From cc57c3dbc944abfc188711254bc6ebb53970e5f2 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Tue, 28 Sep 2021 11:27:11 +0200 Subject: [PATCH 01/18] [godot] Initial commit --- .gitignore | 5 +- spine-godot/README.md | 38 + spine-godot/example/default_env.tres | 7 + spine-godot/example/icon.png | Bin 0 -> 3305 bytes spine-godot/example/icon.png.import | 34 + spine-godot/example/project.godot | 25 + spine-godot/setup.sh | 9 + .../spine_godot/GodotSpineExtension.cpp | 76 ++ spine-godot/spine_godot/GodotSpineExtension.h | 57 + .../spine_godot/PackedSpineSkinResource.cpp | 61 + .../spine_godot/PackedSpineSkinResource.h | 59 + .../spine_godot/RaiixSpineExtension.cpp | 80 ++ .../ResourceFormatLoaderSpineAtlas.cpp | 56 + .../ResourceFormatLoaderSpineAtlas.h | 45 + ...ourceFormatLoaderSpineSkeletonJsonData.cpp | 56 + ...esourceFormatLoaderSpineSkeletonJsonData.h | 44 + .../ResourceFormatSaverSpineAtlas.cpp | 48 + .../ResourceFormatSaverSpineAtlas.h | 44 + ...sourceFormatSaverSpineSkeletonJsonData.cpp | 48 + ...ResourceFormatSaverSpineSkeletonJsonData.h | 44 + spine-godot/spine_godot/SCsub | 9 + spine-godot/spine_godot/SpineAnimation.cpp | 96 ++ spine-godot/spine_godot/SpineAnimation.h | 74 ++ .../spine_godot/SpineAnimationState.cpp | 190 +++ spine-godot/spine_godot/SpineAnimationState.h | 93 ++ .../SpineAnimationStateDataResource.cpp | 178 +++ .../SpineAnimationStateDataResource.h | 76 ++ .../spine_godot/SpineAtlasResource.cpp | 229 ++++ spine-godot/spine_godot/SpineAtlasResource.h | 79 ++ spine-godot/spine_godot/SpineAttachment.cpp | 55 + spine-godot/spine_godot/SpineAttachment.h | 64 + spine-godot/spine_godot/SpineBone.cpp | 537 +++++++++ spine-godot/spine_godot/SpineBone.h | 174 +++ spine-godot/spine_godot/SpineBoneData.cpp | 163 +++ spine-godot/spine_godot/SpineBoneData.h | 104 ++ .../spine_godot/SpineCollisionShapeProxy.cpp | 204 ++++ .../spine_godot/SpineCollisionShapeProxy.h | 78 ++ spine-godot/spine_godot/SpineConstant.cpp | 62 + spine-godot/spine_godot/SpineConstant.h | 80 ++ .../spine_godot/SpineConstraintData.cpp | 59 + spine-godot/spine_godot/SpineConstraintData.h | 66 ++ spine-godot/spine_godot/SpineEvent.cpp | 110 ++ spine-godot/spine_godot/SpineEvent.h | 89 ++ spine-godot/spine_godot/SpineEventData.cpp | 37 + spine-godot/spine_godot/SpineEventData.h | 56 + spine-godot/spine_godot/SpineIkConstraint.cpp | 146 +++ spine-godot/spine_godot/SpineIkConstraint.h | 95 ++ .../spine_godot/SpineIkConstraintData.cpp | 123 ++ .../spine_godot/SpineIkConstraintData.h | 79 ++ .../spine_godot/SpinePathConstraint.cpp | 145 +++ spine-godot/spine_godot/SpinePathConstraint.h | 94 ++ .../spine_godot/SpinePathConstraintData.cpp | 168 +++ .../spine_godot/SpinePathConstraintData.h | 108 ++ spine-godot/spine_godot/SpineRendererObject.h | 42 + .../spine_godot/SpineRuntimeEditorPlugin.cpp | 100 ++ .../spine_godot/SpineRuntimeEditorPlugin.h | 89 ++ spine-godot/spine_godot/SpineSkeleton.cpp | 430 +++++++ spine-godot/spine_godot/SpineSkeleton.h | 135 +++ .../spine_godot/SpineSkeletonDataResource.cpp | 454 +++++++ .../spine_godot/SpineSkeletonDataResource.h | 140 +++ .../SpineSkeletonJsonDataResource.cpp | 55 + .../SpineSkeletonJsonDataResource.h | 49 + spine-godot/spine_godot/SpineSkin.cpp | 162 +++ spine-godot/spine_godot/SpineSkin.h | 85 ++ .../SpineSkinAttachmentMapEntries.cpp | 93 ++ .../SpineSkinAttachmentMapEntries.h | 93 ++ spine-godot/spine_godot/SpineSlot.cpp | 148 +++ spine-godot/spine_godot/SpineSlot.h | 93 ++ spine-godot/spine_godot/SpineSlotData.cpp | 114 ++ spine-godot/spine_godot/SpineSlotData.h | 88 ++ spine-godot/spine_godot/SpineSprite.cpp | 1039 +++++++++++++++++ spine-godot/spine_godot/SpineSprite.h | 162 +++ .../spine_godot/SpineSpriteAnimateDialog.cpp | 350 ++++++ .../spine_godot/SpineSpriteAnimateDialog.h | 86 ++ .../spine_godot/SpineSpriteMeshInstance2D.cpp | 48 + .../spine_godot/SpineSpriteMeshInstance2D.h | 56 + spine-godot/spine_godot/SpineTimeline.cpp | 103 ++ spine-godot/spine_godot/SpineTimeline.h | 72 ++ spine-godot/spine_godot/SpineTrackEntry.cpp | 265 +++++ spine-godot/spine_godot/SpineTrackEntry.h | 131 +++ .../spine_godot/SpineTransformConstraint.cpp | 148 +++ .../spine_godot/SpineTransformConstraint.h | 93 ++ .../SpineTransformConstraintData.cpp | 118 ++ .../SpineTransformConstraintData.h | 74 ++ spine-godot/spine_godot/config.py | 5 + spine-godot/spine_godot/register_types.cpp | 151 +++ spine-godot/spine_godot/register_types.h | 32 + 87 files changed, 10058 insertions(+), 1 deletion(-) create mode 100644 spine-godot/README.md create mode 100644 spine-godot/example/default_env.tres create mode 100644 spine-godot/example/icon.png create mode 100644 spine-godot/example/icon.png.import create mode 100644 spine-godot/example/project.godot create mode 100755 spine-godot/setup.sh create mode 100644 spine-godot/spine_godot/GodotSpineExtension.cpp create mode 100644 spine-godot/spine_godot/GodotSpineExtension.h create mode 100644 spine-godot/spine_godot/PackedSpineSkinResource.cpp create mode 100644 spine-godot/spine_godot/PackedSpineSkinResource.h create mode 100644 spine-godot/spine_godot/RaiixSpineExtension.cpp create mode 100644 spine-godot/spine_godot/ResourceFormatLoaderSpineAtlas.cpp create mode 100644 spine-godot/spine_godot/ResourceFormatLoaderSpineAtlas.h create mode 100644 spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.cpp create mode 100644 spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.h create mode 100644 spine-godot/spine_godot/ResourceFormatSaverSpineAtlas.cpp create mode 100644 spine-godot/spine_godot/ResourceFormatSaverSpineAtlas.h create mode 100644 spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.cpp create mode 100644 spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.h create mode 100644 spine-godot/spine_godot/SCsub create mode 100644 spine-godot/spine_godot/SpineAnimation.cpp create mode 100644 spine-godot/spine_godot/SpineAnimation.h create mode 100644 spine-godot/spine_godot/SpineAnimationState.cpp create mode 100644 spine-godot/spine_godot/SpineAnimationState.h create mode 100644 spine-godot/spine_godot/SpineAnimationStateDataResource.cpp create mode 100644 spine-godot/spine_godot/SpineAnimationStateDataResource.h create mode 100644 spine-godot/spine_godot/SpineAtlasResource.cpp create mode 100644 spine-godot/spine_godot/SpineAtlasResource.h create mode 100644 spine-godot/spine_godot/SpineAttachment.cpp create mode 100644 spine-godot/spine_godot/SpineAttachment.h create mode 100644 spine-godot/spine_godot/SpineBone.cpp create mode 100644 spine-godot/spine_godot/SpineBone.h create mode 100644 spine-godot/spine_godot/SpineBoneData.cpp create mode 100644 spine-godot/spine_godot/SpineBoneData.h create mode 100644 spine-godot/spine_godot/SpineCollisionShapeProxy.cpp create mode 100644 spine-godot/spine_godot/SpineCollisionShapeProxy.h create mode 100644 spine-godot/spine_godot/SpineConstant.cpp create mode 100644 spine-godot/spine_godot/SpineConstant.h create mode 100644 spine-godot/spine_godot/SpineConstraintData.cpp create mode 100644 spine-godot/spine_godot/SpineConstraintData.h create mode 100644 spine-godot/spine_godot/SpineEvent.cpp create mode 100644 spine-godot/spine_godot/SpineEvent.h create mode 100644 spine-godot/spine_godot/SpineEventData.cpp create mode 100644 spine-godot/spine_godot/SpineEventData.h create mode 100644 spine-godot/spine_godot/SpineIkConstraint.cpp create mode 100644 spine-godot/spine_godot/SpineIkConstraint.h create mode 100644 spine-godot/spine_godot/SpineIkConstraintData.cpp create mode 100644 spine-godot/spine_godot/SpineIkConstraintData.h create mode 100644 spine-godot/spine_godot/SpinePathConstraint.cpp create mode 100644 spine-godot/spine_godot/SpinePathConstraint.h create mode 100644 spine-godot/spine_godot/SpinePathConstraintData.cpp create mode 100644 spine-godot/spine_godot/SpinePathConstraintData.h create mode 100644 spine-godot/spine_godot/SpineRendererObject.h create mode 100644 spine-godot/spine_godot/SpineRuntimeEditorPlugin.cpp create mode 100644 spine-godot/spine_godot/SpineRuntimeEditorPlugin.h create mode 100644 spine-godot/spine_godot/SpineSkeleton.cpp create mode 100644 spine-godot/spine_godot/SpineSkeleton.h create mode 100644 spine-godot/spine_godot/SpineSkeletonDataResource.cpp create mode 100644 spine-godot/spine_godot/SpineSkeletonDataResource.h create mode 100644 spine-godot/spine_godot/SpineSkeletonJsonDataResource.cpp create mode 100644 spine-godot/spine_godot/SpineSkeletonJsonDataResource.h create mode 100644 spine-godot/spine_godot/SpineSkin.cpp create mode 100644 spine-godot/spine_godot/SpineSkin.h create mode 100644 spine-godot/spine_godot/SpineSkinAttachmentMapEntries.cpp create mode 100644 spine-godot/spine_godot/SpineSkinAttachmentMapEntries.h create mode 100644 spine-godot/spine_godot/SpineSlot.cpp create mode 100644 spine-godot/spine_godot/SpineSlot.h create mode 100644 spine-godot/spine_godot/SpineSlotData.cpp create mode 100644 spine-godot/spine_godot/SpineSlotData.h create mode 100644 spine-godot/spine_godot/SpineSprite.cpp create mode 100644 spine-godot/spine_godot/SpineSprite.h create mode 100644 spine-godot/spine_godot/SpineSpriteAnimateDialog.cpp create mode 100644 spine-godot/spine_godot/SpineSpriteAnimateDialog.h create mode 100644 spine-godot/spine_godot/SpineSpriteMeshInstance2D.cpp create mode 100644 spine-godot/spine_godot/SpineSpriteMeshInstance2D.h create mode 100644 spine-godot/spine_godot/SpineTimeline.cpp create mode 100644 spine-godot/spine_godot/SpineTimeline.h create mode 100644 spine-godot/spine_godot/SpineTrackEntry.cpp create mode 100644 spine-godot/spine_godot/SpineTrackEntry.h create mode 100644 spine-godot/spine_godot/SpineTransformConstraint.cpp create mode 100644 spine-godot/spine_godot/SpineTransformConstraint.h create mode 100644 spine-godot/spine_godot/SpineTransformConstraintData.cpp create mode 100644 spine-godot/spine_godot/SpineTransformConstraintData.h create mode 100644 spine-godot/spine_godot/config.py create mode 100644 spine-godot/spine_godot/register_types.cpp create mode 100644 spine-godot/spine_godot/register_types.h diff --git a/.gitignore b/.gitignore index 5baaffea6..444577872 100644 --- a/.gitignore +++ b/.gitignore @@ -151,4 +151,7 @@ spine-ts/spine-core/dist spine-ts/spine-canvas/dist spine-ts/spine-webgl/dist spine-ts/spine-player/dist -spine-ts/spine-threejs/dist \ No newline at end of file +spine-ts/spine-threejs/dist +spine-godot/godot +spine-godot/spine_godot/spine-cpp +spine-godot/spine_godot/__pycache__ diff --git a/spine-godot/README.md b/spine-godot/README.md new file mode 100644 index 000000000..d01a47d9d --- /dev/null +++ b/spine-godot/README.md @@ -0,0 +1,38 @@ +# spine-godot + +The spine-godot runtime provides functionality to load, manipulate and render [Spine](http://esotericsoftware.com) skeletal animation data using [Godot](https://godotengine.org/). spine-godot is based on [spine-cpp](../spine-cpp). + +## 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-godot works with data exported from Spine 4.0.xx. + +spine-godot supports all Spine features. + +## Setup + +spine-godot works with the latest stable Godot 3.3 release. It requires compilation of Godot, as spine-godot is implemented as a module. + +To integrate spine-godot into your project: + +1. Follow the [instructions on how to compilation of Godot](https://docs.godotengine.org/en/stable/development/compiling/index.html) +2. Copy the `spine-runtimes/spine-godot` folder into the folder `modules/spine-godot` in your Godot source tree. +3. Copy the `spine-cpp/spine-cpp`folder into the folder `modules/spine-godot/spine-cpp` in your Godot source tree. +4. Compile Godot via scons for your platform as per the Godot documentation. + +The resulting Godot engine binary will include the spine-godot runtime. + +## Example +The Spine Godot example work on all platforms supported by Godot. + + + diff --git a/spine-godot/example/default_env.tres b/spine-godot/example/default_env.tres new file mode 100644 index 000000000..20207a4aa --- /dev/null +++ b/spine-godot/example/default_env.tres @@ -0,0 +1,7 @@ +[gd_resource type="Environment" load_steps=2 format=2] + +[sub_resource type="ProceduralSky" id=1] + +[resource] +background_mode = 2 +background_sky = SubResource( 1 ) diff --git a/spine-godot/example/icon.png b/spine-godot/example/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..c98fbb601c83c81ec8c22b1dba7d1d57c62b323c GIT binary patch literal 3305 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 literal 0 HcmV?d00001 diff --git a/spine-godot/example/icon.png.import b/spine-godot/example/icon.png.import new file mode 100644 index 000000000..96cbf4629 --- /dev/null +++ b/spine-godot/example/icon.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.png" +dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/spine-godot/example/project.godot b/spine-godot/example/project.godot new file mode 100644 index 000000000..0ce873e45 --- /dev/null +++ b/spine-godot/example/project.godot @@ -0,0 +1,25 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=4 + +[application] + +config/name="spine-godot-examples" +config/icon="res://icon.png" + +[physics] + +common/enable_pause_aware_picking=true + +[rendering] + +quality/driver/driver_name="GLES2" +vram_compression/import_etc=true +vram_compression/import_etc2=false +environment/default_environment="res://default_env.tres" diff --git a/spine-godot/setup.sh b/spine-godot/setup.sh new file mode 100755 index 000000000..2c28a4146 --- /dev/null +++ b/spine-godot/setup.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e +rm -rf godot +cp -r ../spine-cpp/spine-cpp spine-godot +git clone --depth 1 https://github.com/godotengine/godot.git -b 3.3.3-stable +ln -s $(pwd)/spine_godot godot/modules/spine_godot +pushd godot +scons --jobs=$(sysctl -n hw.logicalcpu) +popd \ No newline at end of file diff --git a/spine-godot/spine_godot/GodotSpineExtension.cpp b/spine-godot/spine_godot/GodotSpineExtension.cpp new file mode 100644 index 000000000..87ce758a1 --- /dev/null +++ b/spine-godot/spine_godot/GodotSpineExtension.cpp @@ -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. + *****************************************************************************/ + +#include "GodotSpineExtension.h" + +#include "core/variant_parser.h" +#include + +#include + +spine::SpineExtension *spine::getDefaultExtension() { + return new GodotSpineExtension(); +} + +GodotSpineExtension::GodotSpineExtension(){} +GodotSpineExtension::~GodotSpineExtension(){} + +void *GodotSpineExtension::_alloc(size_t size, const char *file, int line){ + return memalloc(size); +} + +void *GodotSpineExtension::_calloc(size_t size, const char *file, int line){ + auto p = memalloc(size); + memset(p, 0, size); + return p; +} + +void *GodotSpineExtension::_realloc(void *ptr, size_t size, const char *file, int line){ + return memrealloc(ptr, size); +} + +void GodotSpineExtension::_free(void *mem, const char *file, int line){ + memfree(mem); +} + +char *GodotSpineExtension::_readFile(const spine::String &path, int *length){ + Error error; + auto res = FileAccess::get_file_as_array(String(path.buffer()), &error); + + if (error != OK){ + if(length) *length = 0; + return NULL; + } + + if(length) *length = res.size(); + auto r = alloc(res.size(), __FILE__, __LINE__); + for(size_t i=0;i +class GodotSpineExtension : public spine::SpineExtension { +public: + GodotSpineExtension(); + + virtual ~GodotSpineExtension(); + +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 spine::String &path, int *length); +}; + + + + + +#endif //GODOT_SPINEEXTENSION_H diff --git a/spine-godot/spine_godot/PackedSpineSkinResource.cpp b/spine-godot/spine_godot/PackedSpineSkinResource.cpp new file mode 100644 index 000000000..34bababcb --- /dev/null +++ b/spine-godot/spine_godot/PackedSpineSkinResource.cpp @@ -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. + *****************************************************************************/ + +#include "PackedSpineSkinResource.h" + +void PackedSpineSkinResource::_bind_methods(){ + ClassDB::bind_method(D_METHOD("set_skin_name", "v"), &PackedSpineSkinResource::set_skin_name); + ClassDB::bind_method(D_METHOD("get_skin_name"), &PackedSpineSkinResource::get_skin_name); + ClassDB::bind_method(D_METHOD("set_sub_skin_names", "v"), &PackedSpineSkinResource::set_sub_skin_names); + ClassDB::bind_method(D_METHOD("get_sub_skin_names"), &PackedSpineSkinResource::get_sub_skin_names); + + ADD_SIGNAL(MethodInfo("property_changed")); + + ADD_PROPERTY(PropertyInfo(Variant::STRING, "skin_name"), "set_skin_name", "get_skin_name"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "sub_skin_names"), "set_sub_skin_names", "get_sub_skin_names"); +} + +PackedSpineSkinResource::PackedSpineSkinResource():skin_name("custom_skin_name"){} +PackedSpineSkinResource::~PackedSpineSkinResource(){} + +void PackedSpineSkinResource::set_skin_name(const String &v){ + skin_name = v; + emit_signal("property_changed"); +} +String PackedSpineSkinResource::get_skin_name(){ + return skin_name; +} + +void PackedSpineSkinResource::set_sub_skin_names(Array v){ + sub_skin_names = v; + emit_signal("property_changed"); +} +Array PackedSpineSkinResource::get_sub_skin_names(){ + return sub_skin_names; +} diff --git a/spine-godot/spine_godot/PackedSpineSkinResource.h b/spine-godot/spine_godot/PackedSpineSkinResource.h new file mode 100644 index 000000000..a4cc5ff3f --- /dev/null +++ b/spine-godot/spine_godot/PackedSpineSkinResource.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 GODOT_PACKEDSPINESKINRESOURCE_H +#define GODOT_PACKEDSPINESKINRESOURCE_H + +#include "core/variant_parser.h" + +#include "SpineSkin.h" + +class PackedSpineSkinResource : public Resource{ + GDCLASS(PackedSpineSkinResource, Resource); + +protected: + static void _bind_methods(); + +private: + String skin_name; + Array sub_skin_names; + +public: + PackedSpineSkinResource(); + virtual ~PackedSpineSkinResource(); + + void set_skin_name(const String &v); + String get_skin_name(); + + void set_sub_skin_names(Array v); + Array get_sub_skin_names(); + +}; + +#endif //GODOT_PACKEDSPINESKINRESOURCE_H diff --git a/spine-godot/spine_godot/RaiixSpineExtension.cpp b/spine-godot/spine_godot/RaiixSpineExtension.cpp new file mode 100644 index 000000000..f4b92781d --- /dev/null +++ b/spine-godot/spine_godot/RaiixSpineExtension.cpp @@ -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. + *****************************************************************************/ + +#include "GodotSpineExtension.h" + +#include "core/variant_parser.h" +#include + +#include + +spine::SpineExtension *spine::getDefaultExtension() { + return new GodotSpineExtension(); +} + +GodotSpineExtension::GodotSpineExtension(){} +GodotSpineExtension::~GodotSpineExtension(){} + +void *GodotSpineExtension::_alloc(size_t size, const char *file, int line){ +// std::cout<<"_alloc "<(res.size(), __FILE__, __LINE__); + for(size_t i=0;i atlas = memnew(SpineAtlasResource); + atlas->load_from_file(p_path); + + if(r_error){ + *r_error = OK; + } + return atlas; +} + +void ResourceFormatLoaderSpineAtlas::get_recognized_extensions(List *r_extensions) const { + const char atlas_ext[] = "spatlas"; + if(!r_extensions->find(atlas_ext)) { + r_extensions->push_back(atlas_ext); + } +} + +String ResourceFormatLoaderSpineAtlas::get_resource_type(const String &p_path) const { + return "SpineAtlasResource"; +} + +bool ResourceFormatLoaderSpineAtlas::handles_type(const String &p_type) const { + return p_type == "SpineAtlasResource" || ClassDB::is_parent_class(p_type, "SpineAtlasResource"); +} \ No newline at end of file diff --git a/spine-godot/spine_godot/ResourceFormatLoaderSpineAtlas.h b/spine-godot/spine_godot/ResourceFormatLoaderSpineAtlas.h new file mode 100644 index 000000000..e6d1610da --- /dev/null +++ b/spine-godot/spine_godot/ResourceFormatLoaderSpineAtlas.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 GODOT_RESOURCEFORMATLOADERSPINEATLAS_H +#define GODOT_RESOURCEFORMATLOADERSPINEATLAS_H + +#include "core/io/resource_loader.h" + +class ResourceFormatLoaderSpineAtlas : public ResourceFormatLoader{ + GDCLASS(ResourceFormatLoaderSpineAtlas, ResourceFormatLoader); +public: + virtual RES load(const String &p_path, const String &p_original_path, Error *r_error = NULL); + virtual void get_recognized_extensions(List *r_extensions) const; + virtual bool handles_type(const String &p_type) const; + virtual String get_resource_type(const String &p_path) const; +}; + + +#endif //GODOT_RESOURCEFORMATLOADERSPINEATLAS_H diff --git a/spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.cpp b/spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.cpp new file mode 100644 index 000000000..34a7a7ae2 --- /dev/null +++ b/spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.cpp @@ -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. + *****************************************************************************/ + +#include "ResourceFormatLoaderSpineSkeletonJsonData.h" +#include "SpineSkeletonJsonDataResource.h" + +RES ResourceFormatLoaderSpineSkeletonJsonData::load(const String &p_path, const String &p_original_path, Error *r_error) { + Ref skeleton = memnew(SpineSkeletonJsonDataResource); + skeleton->load_from_file(p_path); + + if(r_error){ + *r_error = OK; + } + return skeleton; +} + +void ResourceFormatLoaderSpineSkeletonJsonData::get_recognized_extensions(List *r_extensions) const { + const char json_ext[] = "spjson"; + if(!r_extensions->find(json_ext)) { + r_extensions->push_back(json_ext); + } +} + +String ResourceFormatLoaderSpineSkeletonJsonData::get_resource_type(const String &p_path) const { + return "SpineSkeletonJsonDataResource"; +} + +bool ResourceFormatLoaderSpineSkeletonJsonData::handles_type(const String &p_type) const { + return p_type == "SpineSkeletonJsonDataResource" || ClassDB::is_parent_class(p_type, "SpineSkeletonJsonDataResource"); +} \ No newline at end of file diff --git a/spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.h b/spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.h new file mode 100644 index 000000000..13509ba21 --- /dev/null +++ b/spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.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 GODOT_RESOURCEFORMATLOADERSPINESKELETONJSONDATA_H +#define GODOT_RESOURCEFORMATLOADERSPINESKELETONJSONDATA_H + +#include "core/io/resource_loader.h" + +class ResourceFormatLoaderSpineSkeletonJsonData : public ResourceFormatLoader { + GDCLASS(ResourceFormatLoaderSpineSkeletonJsonData, ResourceFormatLoader); +public: + virtual RES load(const String &p_path, const String &p_original_path, Error *r_error = NULL); + virtual void get_recognized_extensions(List *r_extensions) const; + virtual bool handles_type(const String &p_type) const; + virtual String get_resource_type(const String &p_path) const; +}; + +#endif //GODOT_RESOURCEFORMATLOADERSPINESKELETONJSONDATA_H diff --git a/spine-godot/spine_godot/ResourceFormatSaverSpineAtlas.cpp b/spine-godot/spine_godot/ResourceFormatSaverSpineAtlas.cpp new file mode 100644 index 000000000..d976133a1 --- /dev/null +++ b/spine-godot/spine_godot/ResourceFormatSaverSpineAtlas.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. + *****************************************************************************/ + +#include "ResourceFormatSaverSpineAtlas.h" + +#include "SpineAtlasResource.h" + +Error ResourceFormatSaverSpineAtlas::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { + Ref res = p_resource.get_ref_ptr(); + Error error = res->save_to_file(p_path); + return error; +} + +void ResourceFormatSaverSpineAtlas::get_recognized_extensions(const RES &p_resource, List *p_extensions) const { + if (Object::cast_to(*p_resource)) { + p_extensions->push_back("spatlas"); + } +} + +bool ResourceFormatSaverSpineAtlas::recognize(const RES &p_resource) const { + return Object::cast_to(*p_resource) != nullptr; +} diff --git a/spine-godot/spine_godot/ResourceFormatSaverSpineAtlas.h b/spine-godot/spine_godot/ResourceFormatSaverSpineAtlas.h new file mode 100644 index 000000000..4feb076fc --- /dev/null +++ b/spine-godot/spine_godot/ResourceFormatSaverSpineAtlas.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 GODOT_RESOURCEFORMATSAVERSPINEATLAS_H +#define GODOT_RESOURCEFORMATSAVERSPINEATLAS_H + +#include "core/io/resource_saver.h" + +class ResourceFormatSaverSpineAtlas : public ResourceFormatSaver{ + GDCLASS(ResourceFormatSaverSpineAtlas, ResourceFormatSaver); +public: + Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0) override; + void get_recognized_extensions(const RES &p_resource, List *p_extensions) const override; + bool recognize(const RES &p_resource) const override; +}; + + +#endif //GODOT_RESOURCEFORMATSAVERSPINEATLAS_H diff --git a/spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.cpp b/spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.cpp new file mode 100644 index 000000000..01c4b7e1c --- /dev/null +++ b/spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.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. + *****************************************************************************/ + +#include "ResourceFormatSaverSpineSkeletonJsonData.h" + +#include "SpineSkeletonJsonDataResource.h" + +Error ResourceFormatSaverSpineSkeletonJsonData::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { + Ref res = p_resource.get_ref_ptr(); + Error error = res->save_to_file(p_path); + return error; +} + +void ResourceFormatSaverSpineSkeletonJsonData::get_recognized_extensions(const RES &p_resource, List *p_extensions) const { + if (Object::cast_to(*p_resource)) { + p_extensions->push_back("spjson"); + } +} + +bool ResourceFormatSaverSpineSkeletonJsonData::recognize(const RES &p_resource) const { + return Object::cast_to(*p_resource) != nullptr; +} diff --git a/spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.h b/spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.h new file mode 100644 index 000000000..e63993125 --- /dev/null +++ b/spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.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 GODOT_RESOURCEFORMATSAVERSPINESKELETONJSONDATA_H +#define GODOT_RESOURCEFORMATSAVERSPINESKELETONJSONDATA_H + +#include "core/io/resource_saver.h" + +class ResourceFormatSaverSpineSkeletonJsonData : public ResourceFormatSaver{ + GDCLASS(ResourceFormatSaverSpineSkeletonJsonData, ResourceFormatSaver); +public: + Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0) override; + void get_recognized_extensions(const RES &p_resource, List *p_extensions) const override; + bool recognize(const RES &p_resource) const override; +}; + + +#endif //GODOT_RESOURCEFORMATSAVERSPINESKELETONJSONDATA_H diff --git a/spine-godot/spine_godot/SCsub b/spine-godot/spine_godot/SCsub new file mode 100644 index 000000000..0d5573c77 --- /dev/null +++ b/spine-godot/spine_godot/SCsub @@ -0,0 +1,9 @@ +Import('env') + +env_spine_runtime = env.Clone() + +env_spine_runtime.Append(CPPPATH=["spine-cpp/include"]) +env_spine_runtime.Append(CCFLAGS=['-O2']) + +env_spine_runtime.add_source_files(env.modules_sources, "spine-cpp/src/spine/*.cpp") +env_spine_runtime.add_source_files(env.modules_sources, "*.cpp") diff --git a/spine-godot/spine_godot/SpineAnimation.cpp b/spine-godot/spine_godot/SpineAnimation.cpp new file mode 100644 index 000000000..d0e76d54e --- /dev/null +++ b/spine-godot/spine_godot/SpineAnimation.cpp @@ -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. + *****************************************************************************/ + +#include "SpineAnimation.h" + +#include "SpineSkeleton.h" +#include "SpineEvent.h" +#include "SpineTimeline.h" + +// enable more than 5 arguments of a method bind function +#include "core/method_bind_ext.gen.inc" + +void SpineAnimation::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_anim_name"), &SpineAnimation::get_anim_name); + ClassDB::bind_method(D_METHOD("get_duration"), &SpineAnimation::get_duration); + ClassDB::bind_method(D_METHOD("set_duration", "v"), &SpineAnimation::set_duration); + + ClassDB::bind_method(D_METHOD("apply", "skeleton", "last_time", "time", "loop", "events", "alpha", "blend", "direction"), &SpineAnimation::apply); + ClassDB::bind_method(D_METHOD("get_timelines"), &SpineAnimation::get_timelines); + ClassDB::bind_method(D_METHOD("has_timeline", "ids"), &SpineAnimation::has_timeline); +} + +SpineAnimation::SpineAnimation():animation(NULL) {} +SpineAnimation::~SpineAnimation(){} + +String SpineAnimation::get_anim_name() { + return animation->getName().buffer(); +} + +float SpineAnimation::get_duration() { + return animation->getDuration(); +} +void SpineAnimation::set_duration(float v) { + animation->setDuration(v); +} + +void SpineAnimation::apply(Ref skeleton, float lastTime, float time, bool loop, + Array pEvents, float alpha, SpineConstant::MixBlend blend, + SpineConstant::MixDirection direction) { + spine::Vector events; + events.setSize(pEvents.size(), nullptr); + for (size_t i=0; i)(pEvents[i]))->get_spine_object(); + } + animation->apply(*(skeleton->get_spine_object()), lastTime, time, loop, &events, alpha, (spine::MixBlend) blend, (spine::MixDirection) direction); +} + +Array SpineAnimation::get_timelines() { + auto &timelines = animation->getTimelines(); + Array res; + res.resize(timelines.size()); + + for (size_t i=0; i(memnew(SpineTimeline)); + a->set_spine_object(timelines[i]); + res.set(i, a); + } + + return res; +} + +bool SpineAnimation::has_timeline(Array ids) { + spine::Vector list; + list.setSize(ids.size(), 0); + + for (size_t i=0; ihasTimeline(list); +} diff --git a/spine-godot/spine_godot/SpineAnimation.h b/spine-godot/spine_godot/SpineAnimation.h new file mode 100644 index 000000000..22b330f8b --- /dev/null +++ b/spine-godot/spine_godot/SpineAnimation.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 GODOT_SPINEANIMATION_H +#define GODOT_SPINEANIMATION_H + +#include "core/variant_parser.h" + +#include "SpineConstant.h" + +#include + +class SpineEvent; +class SpineSkeleton; +class SpineTimeline; + +class SpineAnimation : public Reference{ + GDCLASS(SpineAnimation, Reference); + +private: + spine::Animation *animation; + +protected: + static void _bind_methods(); + +public: + SpineAnimation(); + ~SpineAnimation(); + + inline void set_spine_object(spine::Animation *a){ + animation = a; + } + inline spine::Animation *get_spine_object(){ + return animation; + } + + // Vector> pEvents + void apply(Ref skeleton, float lastTime, float time, bool loop, Array pEvents, float alpha, SpineConstant::MixBlend blend, SpineConstant::MixDirection direction); + + Array get_timelines(); // Vector> + bool has_timeline(Array ids); // Vector + + String get_anim_name(); + float get_duration(); + void set_duration(float v); +}; + +#endif //GODOT_SPINEANIMATION_H diff --git a/spine-godot/spine_godot/SpineAnimationState.cpp b/spine-godot/spine_godot/SpineAnimationState.cpp new file mode 100644 index 000000000..0dcbaa107 --- /dev/null +++ b/spine-godot/spine_godot/SpineAnimationState.cpp @@ -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. + *****************************************************************************/ + +#include "SpineAnimationState.h" + +void SpineAnimationState::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_animation", "anim_name", "loop", "track_id"), &SpineAnimationState::set_animation, DEFVAL(true), DEFVAL(0)); + ClassDB::bind_method(D_METHOD("update", "delta"), &SpineAnimationState::update, DEFVAL(0)); + ClassDB::bind_method(D_METHOD("apply", "skeleton"), &SpineAnimationState::apply); + ClassDB::bind_method(D_METHOD("clear_tracks"), &SpineAnimationState::clear_tracks); + ClassDB::bind_method(D_METHOD("clear_track"), &SpineAnimationState::clear_track); + ClassDB::bind_method(D_METHOD("add_animation", "anim_name", "delay", "loop", "track_id"), &SpineAnimationState::add_animation, DEFVAL(0), DEFVAL(true), DEFVAL(0)); + ClassDB::bind_method(D_METHOD("set_empty_animation", "track_id", "mix_duration"), &SpineAnimationState::set_empty_animation); + ClassDB::bind_method(D_METHOD("add_empty_animation", "track_id", "mix_duration", "delay"), &SpineAnimationState::add_empty_animation); + ClassDB::bind_method(D_METHOD("set_empty_animations", "mix_duration"), &SpineAnimationState::set_empty_animations); + ClassDB::bind_method(D_METHOD("get_data"), &SpineAnimationState::get_data); + ClassDB::bind_method(D_METHOD("get_time_scale"), &SpineAnimationState::get_time_scale); + ClassDB::bind_method(D_METHOD("set_time_scale", "time_scale"), &SpineAnimationState::set_time_scale); + ClassDB::bind_method(D_METHOD("disable_queue"), &SpineAnimationState::disable_queue); + ClassDB::bind_method(D_METHOD("enable_queue"), &SpineAnimationState::enable_queue); +// ClassDB::bind_method(D_METHOD("reload"), &SpineAnimationState::reload_animation_state); + ClassDB::bind_method(D_METHOD("get_current", "track_id"), &SpineAnimationState::get_current); +} + +SpineAnimationState::SpineAnimationState():animation_state(NULL) { + +} + +SpineAnimationState::~SpineAnimationState() { + if(animation_state) + { + delete animation_state; + animation_state = NULL; + } +} + +void SpineAnimationState::load_animation_state(Ref ad) { + if(animation_state) + { + delete animation_state; + animation_state = NULL; + } + animation_state = new spine::AnimationState(ad->get_animation_state_data()); + anim_state_data_res = ad; +} + +void SpineAnimationState::reload_animation_state() { + if(!anim_state_data_res.is_valid()) + { + ERR_PRINT(" Reload animation state fail, because anim_state_data_res not set!"); + return; + } + if(animation_state) + { + delete animation_state; + animation_state = NULL; + } + animation_state = new spine::AnimationState(anim_state_data_res->get_animation_state_data()); +} + +#define CHECK_V if(!animation_state){ERR_PRINT("The animation state is not loaded yet!");return;} +#define CHECK_X(x) if(!animation_state){ERR_PRINT("The animation state is not loaded yet!");return x;} +#define S_T(x) (spine::String(x.utf8())) +Ref SpineAnimationState::set_animation(const String &anim_name, bool loop, uint64_t track) { + CHECK_X(NULL); + auto skeleton_data = anim_state_data_res->get_skeleton(); + auto anim = skeleton_data->find_animation(anim_name); + if(!anim.is_valid() || anim->get_spine_object() == NULL) + { + ERR_PRINT(String("Can not find animation: ") + anim_name) + return NULL; + } + auto entry = animation_state->setAnimation(track, anim->get_spine_object(), loop); + Ref gd_entry(memnew(SpineTrackEntry)); + gd_entry->set_spine_object(entry); + return gd_entry; +} +Ref SpineAnimationState::add_animation(const String &anim_name, float delay, bool loop, uint64_t track) { + CHECK_X(NULL); + auto skeleton_data = anim_state_data_res->get_skeleton(); + auto anim = skeleton_data->find_animation(anim_name); + if(!anim.is_valid() || anim->get_spine_object() == NULL) + { + ERR_PRINT(String("Can not find animation: ") + anim_name) + return NULL; + } + auto entry = animation_state->addAnimation(track, anim->get_spine_object(), loop, delay); + Ref gd_entry(memnew(SpineTrackEntry)); + gd_entry->set_spine_object(entry); + return gd_entry; +} + +Ref SpineAnimationState::set_empty_animation(uint64_t track_id, float mix_duration) { + CHECK_X(NULL); + auto entry = animation_state->setEmptyAnimation(track_id, mix_duration); + Ref gd_entry(memnew(SpineTrackEntry)); + gd_entry->set_spine_object(entry); + return gd_entry; +} +Ref SpineAnimationState::add_empty_animation(uint64_t track_id, float mix_duration, float delay) { + CHECK_X(NULL); + auto entry = animation_state->addEmptyAnimation(track_id, mix_duration, delay); + Ref gd_entry(memnew(SpineTrackEntry)); + gd_entry->set_spine_object(entry); + return gd_entry; +} +void SpineAnimationState::set_empty_animations(float mix_duration) { + CHECK_V; + animation_state->setEmptyAnimations(mix_duration); +} + +void SpineAnimationState::update(float delta){ + CHECK_V; + animation_state->update(delta); +} +bool SpineAnimationState::apply(Ref skeleton){ + CHECK_X(false); + return animation_state->apply(*(skeleton->get_spine_object())); +} + + +void SpineAnimationState::clear_tracks() { + CHECK_V; + animation_state->clearTracks(); +} +void SpineAnimationState::clear_track(uint64_t track_id) { + CHECK_V; + animation_state->clearTrack(track_id); +} + +Ref SpineAnimationState::get_data() { + CHECK_X(NULL); + return anim_state_data_res; +} + +float SpineAnimationState::get_time_scale() { + CHECK_X(0); + return animation_state->getTimeScale(); +} +void SpineAnimationState::set_time_scale(float v) { + CHECK_V; + animation_state->setTimeScale(v); +} + +void SpineAnimationState::disable_queue() { + CHECK_V; + animation_state->disableQueue(); +} +void SpineAnimationState::enable_queue() { + CHECK_V; + animation_state->enableQueue(); +} + +Ref SpineAnimationState::get_current(uint64_t track_index) { + CHECK_X(NULL); + Ref gd_entry(memnew(SpineTrackEntry)); + auto entry = animation_state->getCurrent(track_index); + if(entry == NULL) return NULL; + gd_entry->set_spine_object(entry); + return gd_entry; +} + +#undef CHECK_V +#undef CHECK_X diff --git a/spine-godot/spine_godot/SpineAnimationState.h b/spine-godot/spine_godot/SpineAnimationState.h new file mode 100644 index 000000000..531a63472 --- /dev/null +++ b/spine-godot/spine_godot/SpineAnimationState.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 GODOT_SPINEANIMATIONSTATE_H +#define GODOT_SPINEANIMATIONSTATE_H + +#include "core/variant_parser.h" + +#include "SpineAnimationStateDataResource.h" +#include "SpineSkeleton.h" +#include "SpineTrackEntry.h" + +class SpineAnimationState : public Reference{ + GDCLASS(SpineAnimationState, Reference); + +protected: + static void _bind_methods(); + +private: + spine::AnimationState *animation_state; + + Ref anim_state_data_res; +public: + void load_animation_state(Ref ad); + + inline void set_animation_state(spine::AnimationState *a){ + animation_state = a; + } + inline spine::AnimationState *get_animation_state(){ + return animation_state; + } + + void reload_animation_state(); + + Ref set_animation(const String &anim_name, bool loop, uint64_t track_id); + inline void set_animation_by_ref(Ref anim, bool loop, uint64_t track_id){ + if(anim.is_valid()){ + animation_state->setAnimation(track_id, anim->get_spine_object(), loop); + } + } + Ref add_animation(const String &anim_name, float delay, bool loop, uint64_t track_id); + + Ref set_empty_animation(uint64_t track_id, float mix_duration); + Ref add_empty_animation(uint64_t track_id, float mix_duration, float delay); + void set_empty_animations(float mix_duration); + + Ref get_data(); + + float get_time_scale(); + void set_time_scale(float v); + + void disable_queue(); + void enable_queue(); + + void update(float delta); + bool apply(Ref skeleton); + + void clear_tracks(); + void clear_track(uint64_t track_id); + + Ref get_current(uint64_t track_index); + + SpineAnimationState(); + ~SpineAnimationState(); +}; + +#endif //GODOT_SPINEANIMATIONSTATE_H diff --git a/spine-godot/spine_godot/SpineAnimationStateDataResource.cpp b/spine-godot/spine_godot/SpineAnimationStateDataResource.cpp new file mode 100644 index 000000000..c17a1d585 --- /dev/null +++ b/spine-godot/spine_godot/SpineAnimationStateDataResource.cpp @@ -0,0 +1,178 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineAnimationStateDataResource.h" + +SpineAnimationStateDataResource::SpineAnimationStateDataResource():animation_state_data(NULL),animation_state_data_created(false),default_mix(0.5f) { + +} +SpineAnimationStateDataResource::~SpineAnimationStateDataResource() { + if(animation_state_data) + { + delete animation_state_data; + animation_state_data = NULL; + } +} + +void SpineAnimationStateDataResource::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_skeleton", "skeleton"), &SpineAnimationStateDataResource::set_skeleton); + ClassDB::bind_method(D_METHOD("get_spine_object"), &SpineAnimationStateDataResource::get_skeleton); + ClassDB::bind_method(D_METHOD("_on_skeleton_data_loaded"), &SpineAnimationStateDataResource::_on_skeleton_data_loaded); + ClassDB::bind_method(D_METHOD("is_animation_state_data_created"), &SpineAnimationStateDataResource::is_animation_state_data_created); + ClassDB::bind_method(D_METHOD("_on_skeleton_data_changed"), &SpineAnimationStateDataResource::_on_skeleton_data_changed); + ClassDB::bind_method(D_METHOD("set_default_mix", "mix"), &SpineAnimationStateDataResource::set_default_mix); + ClassDB::bind_method(D_METHOD("get_default_mix"), &SpineAnimationStateDataResource::get_default_mix); + ClassDB::bind_method(D_METHOD("get_mix", "from", "to"), &SpineAnimationStateDataResource::get_mix); + ClassDB::bind_method(D_METHOD("set_mix", "from", "to", "mix"), &SpineAnimationStateDataResource::set_mix); + + ADD_SIGNAL(MethodInfo("animation_state_data_created")); + ADD_SIGNAL(MethodInfo("skeleton_data_res_changed")); + ADD_SIGNAL(MethodInfo("animation_state_data_changed")); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "skeleton", PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "SpineSkeletonDataResource"), "set_skeleton", "get_spine_object"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "default_mix", PropertyHint::PROPERTY_HINT_EXP_RANGE, "0,1,0.01"), "set_default_mix", "get_default_mix"); +} + +void SpineAnimationStateDataResource::set_skeleton(const Ref &s) { + skeleton = s; + + _on_skeleton_data_changed(); + if(skeleton.is_valid()) + { + skeleton->connect("skeleton_data_loaded", this, "_on_skeleton_data_loaded"); + skeleton->connect("atlas_res_changed", this, "_on_skeleton_data_changed"); + skeleton->connect("skeleton_json_res_changed", this, "_on_skeleton_data_changed"); + + if(skeleton->is_skeleton_data_loaded()) + { + _on_skeleton_data_loaded(); + } + }else{ + if(animation_state_data) + { + delete animation_state_data; + animation_state_data = NULL; + animation_state_data_created = false; +// print_line("Animation state data deleted."); + } + } + + +} +Ref SpineAnimationStateDataResource::get_skeleton() { + return skeleton; +} + +void SpineAnimationStateDataResource::set_default_mix(float m) { + default_mix = m; + if(!is_animation_state_data_created()) + { +// ERR_PRINT("'set_default_mix' fail. Animation state data is not created!"); + return; + } + animation_state_data->setDefaultMix(((m >= 0 && m <= 1) ? m : m <= 0 ? 0 : 1)); +// emit_signal("animation_state_data_changed"); +} +float SpineAnimationStateDataResource::get_default_mix() { + if(!is_animation_state_data_created()) + { +// ERR_PRINT("'get_default_mix' fail. Animation state data is not created!"); + return default_mix; + } + default_mix = animation_state_data->getDefaultMix(); + return default_mix; +} + +void SpineAnimationStateDataResource::set_mix(const String &from, const String &to, float mix_duration) { + if(!is_animation_state_data_created()) + { + ERR_PRINT("'set_mix' fail. Animation state data is not created!"); + return; + } + auto anim_from = get_skeleton()->find_animation(from); + auto anim_to = get_skeleton()->find_animation(to); + if(!anim_from.is_valid()) + { + ERR_PRINT("'set_mix' fail. From animation animation not found!"); + return; + } + if(!anim_to.is_valid()) + { + ERR_PRINT("'set_mix' fail. To animation animation not found!"); + return; + } + animation_state_data->setMix(anim_from->get_spine_object(), anim_to->get_spine_object(), mix_duration); +} +float SpineAnimationStateDataResource::get_mix(const String &from, const String &to) { + if(!is_animation_state_data_created()) + { + ERR_PRINT("'set_mix' fail. Animation state data is not created!"); + return 0; + } + auto anim_from = get_skeleton()->find_animation(from); + auto anim_to = get_skeleton()->find_animation(to); + if(!anim_from.is_valid()) + { + ERR_PRINT("'set_mix' fail. From animation animation not found!"); + return 0; + } + if(!anim_to.is_valid()) + { + ERR_PRINT("'set_mix' fail. To animation animation not found!"); + return 0; + } + return animation_state_data->getMix(anim_from->get_spine_object(), anim_to->get_spine_object()); +} + +void SpineAnimationStateDataResource::_on_skeleton_data_loaded() { + animation_state_data = new spine::AnimationStateData(skeleton->get_skeleton_data()); +// print_line("Animation state data created."); + + + emit_signal("animation_state_data_created"); + animation_state_data->setDefaultMix(default_mix); + animation_state_data_created = true; +} + +void SpineAnimationStateDataResource::_on_skeleton_data_changed() { + animation_state_data_created = false; + if(animation_state_data) + { + delete animation_state_data; + animation_state_data = NULL; +// print_line("Animation state data deleted."); + } + +// print_line("skeleton_data_res_changed emitted"); + emit_signal("skeleton_data_res_changed"); +} + +bool SpineAnimationStateDataResource::is_animation_state_data_created(){ + return animation_state_data_created; +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineAnimationStateDataResource.h b/spine-godot/spine_godot/SpineAnimationStateDataResource.h new file mode 100644 index 000000000..9da9f8fe2 --- /dev/null +++ b/spine-godot/spine_godot/SpineAnimationStateDataResource.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 GODOT_SPINEANIMATIONSTATEDATARESOURCE_H +#define GODOT_SPINEANIMATIONSTATEDATARESOURCE_H + +#include "core/variant_parser.h" + +#include "SpineSkeletonDataResource.h" + +class SpineAnimationStateDataResource : public Resource{ + GDCLASS(SpineAnimationStateDataResource, Resource); + +protected: + static void _bind_methods(); + +private: + Ref skeleton; + + spine::AnimationStateData *animation_state_data; + + bool animation_state_data_created; + + float default_mix; +public: + + void set_skeleton(const Ref &s); + Ref get_skeleton(); + + inline spine::AnimationStateData *get_animation_state_data(){ + return animation_state_data; + } + + void set_default_mix(float m); + float get_default_mix(); + + void set_mix(const String &from, const String &to, float mix_duration); + float get_mix(const String &from, const String &to); + + + void _on_skeleton_data_loaded(); + void _on_skeleton_data_changed(); + + bool is_animation_state_data_created(); + + SpineAnimationStateDataResource(); + ~SpineAnimationStateDataResource(); +}; + +#endif //GODOT_SPINEANIMATIONSTATEDATARESOURCE_H diff --git a/spine-godot/spine_godot/SpineAtlasResource.cpp b/spine-godot/spine_godot/SpineAtlasResource.cpp new file mode 100644 index 000000000..08177ac2c --- /dev/null +++ b/spine-godot/spine_godot/SpineAtlasResource.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. + *****************************************************************************/ + +#include "SpineAtlasResource.h" +#include "core/io/json.h" + +#include + +class GodotSpineTextureLoader : public spine::TextureLoader { +private: + Array *tex_list, *ntex_list; + String normal_tex_prefix; +public: + + GodotSpineTextureLoader(Array *t, Array *nt, const String &p):tex_list(t), ntex_list(nt), normal_tex_prefix(p){ + if (tex_list) tex_list->clear(); + if (ntex_list) ntex_list->clear(); + } + + String fixPathIssue(const String &path){ + if(path.size() > 5 && path[4] == '/' && path[5] == '/') return path; + const String prefix = "res:/"; + auto i = path.find(prefix); +// print_line(String("Found i at ") + String(Variant(i))); + auto sub_str_pos = i+prefix.size()-1; + if(sub_str_pos < 0) return path; + auto res = path.substr(sub_str_pos); +// print_line(String("rest of it: ") + res); + if(res.size() > 0) + { + if(res[0] != '/') + { + return prefix + "/" + res; + } else + { + return prefix + res; + } + } + return path; + } + + virtual void load(spine::AtlasPage &page, const spine::String &path){ + Error err = OK; + +// print_line(String("Spine is loading texture: ") + String(path.buffer())); + auto fixed_path = fixPathIssue(String(path.buffer())); +// print_line("Fixed path: " + fixed_path); + + // Load texture (e.g. tex.png) + Ref tex = ResourceLoader::load(fixed_path, "", false, &err); + if (err != OK) { + print_error(vformat("Can't load texture: \"%s\"", String(path.buffer()))); + page.setRendererObject((void*)memnew(SpineRendererObject {nullptr})); + return; + } + + if (tex_list) tex_list->append(tex); + auto p_spine_renderer_object = memnew(SpineRendererObject); + p_spine_renderer_object->tex = tex; + + // Load normal texture (e.g. n_tex.png) + String temppath = fixed_path; + String newpath = vformat("%s/%s_%s", temppath.get_base_dir(), normal_tex_prefix, temppath.get_file()); +// print_line(vformat("try n tex: %s", newpath)); + if (ResourceLoader::exists(newpath)){ + Ref normal_tex = ResourceLoader::load(newpath); + if (ntex_list) ntex_list->append(normal_tex); + p_spine_renderer_object->normal_tex = normal_tex; + + // print_line(String("From atlas resource load: ") + String(" ro ") + String(Variant((long long) p_spine_renderer_object))); + // print_line(String("From atlas resource load: ") + String(Variant(p_spine_renderer_object->tex)) + String(", ") + String(Variant(p_spine_renderer_object->normal_tex))); + } + + page.setRendererObject((void*)p_spine_renderer_object); + + page.width = tex->get_width(); + page.height = tex->get_height(); + } + + virtual void unload(void *p){ + // print_line("I'm out."); + auto p_spine_renderer_object = (SpineRendererObject*) p; + Ref &tex = p_spine_renderer_object->tex; + Ref &normal_tex = p_spine_renderer_object->normal_tex; + + if (tex.is_valid()) tex.unref(); + if (normal_tex.is_valid()) normal_tex.unref(); + + memdelete(p_spine_renderer_object); + } +}; + +SpineAtlasResource::SpineAtlasResource():atlas(nullptr), normal_texture_prefix("n"){} +SpineAtlasResource::~SpineAtlasResource(){ + if (atlas) delete atlas; +} + +void SpineAtlasResource::_bind_methods(){ + ClassDB::bind_method(D_METHOD("load_from_atlas_file", "path"), &SpineAtlasResource::load_from_atlas_file); + + ClassDB::bind_method(D_METHOD("get_source_path"), &SpineAtlasResource::get_source_path); + + ClassDB::bind_method(D_METHOD("get_textures"), &SpineAtlasResource::get_textures); + ClassDB::bind_method(D_METHOD("get_normal_textures"), &SpineAtlasResource::get_normal_textures); + + ADD_PROPERTY(PropertyInfo(Variant::STRING, "source_path"), "", "get_source_path"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "textures"), "", "get_textures"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "normal_textures"), "", "get_normal_textures"); +} + + +Array SpineAtlasResource::get_textures() { + return tex_list; +} + +Array SpineAtlasResource::get_normal_textures() { + return ntex_list; +} + +String SpineAtlasResource::get_source_path() { + return source_path; +} + +Error SpineAtlasResource::load_from_atlas_file(const String &p_path) { +// print_line(vformat("Importing atlas file: %s", p_path)); + source_path = p_path; + + Error err; + + atlas_data = FileAccess::get_file_as_string(p_path, &err); + if (err != OK) return err; + + if (atlas) delete atlas; + tex_list.clear(); + ntex_list.clear(); + atlas = new spine::Atlas(atlas_data.utf8(), atlas_data.size(), source_path.get_base_dir().utf8(), new GodotSpineTextureLoader(&tex_list, &ntex_list, normal_texture_prefix)); + +// print_line(vformat("atlas loaded!")); + + if (atlas) + return OK; + + tex_list.clear(); + ntex_list.clear(); + + return ERR_FILE_UNRECOGNIZED; +} + +Error SpineAtlasResource::load_from_file(const String &p_path) { + Error err; + + String json_string = FileAccess::get_file_as_string(p_path, &err); + if (err != OK) return err; + + String error_string; + int error_line; + JSON json; + Variant result; + err = json.parse(json_string, result, error_string, error_line); + if (err != OK) { + return err; + } + + Dictionary content = Dictionary(result); + + source_path = content["source_path"]; + atlas_data = content["atlas_data"]; + normal_texture_prefix = content["normal_texture_prefix"]; + + if (atlas) delete atlas; + tex_list.clear(); + ntex_list.clear(); + atlas = new spine::Atlas(atlas_data.utf8(), atlas_data.size(), source_path.get_base_dir().utf8(), new GodotSpineTextureLoader(&tex_list, &ntex_list, normal_texture_prefix)); + + if (atlas) + return OK; + + tex_list.clear(); + ntex_list.clear(); + return ERR_FILE_UNRECOGNIZED; +} + +Error SpineAtlasResource::save_to_file(const String &p_path) { + Error err; + FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &err); + if (err != OK) { +// print_line(vformat("save file err: %d", err)); + if (file) file->close(); + return err; + } + + Dictionary content; + content["source_path"] = source_path; + content["atlas_data"] = atlas_data; + content["normal_texture_prefix"] = normal_texture_prefix; + +// print_line(vformat("storing source_path: %s", source_path)); + + file->store_string(JSON::print(content)); + file->close(); + + return OK; +} diff --git a/spine-godot/spine_godot/SpineAtlasResource.h b/spine-godot/spine_godot/SpineAtlasResource.h new file mode 100644 index 000000000..862f554ef --- /dev/null +++ b/spine-godot/spine_godot/SpineAtlasResource.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 GODOT_SPINEATLASRESOURCE_H +#define GODOT_SPINEATLASRESOURCE_H + + + +#include "core/variant_parser.h" + +#include +#include +#include +#include +#include +#include "SpineRendererObject.h" + +class SpineAtlasResource : public Resource{ + GDCLASS(SpineAtlasResource, Resource); + +protected: + static void _bind_methods(); + + spine::Atlas *atlas; + + String source_path; + String atlas_data; + String normal_texture_prefix; + + Array tex_list; + Array ntex_list; +public: + inline String &get_atlas_data() {return atlas_data;} + + inline spine::Atlas *get_spine_atlas() {return atlas;} + + inline void set_normal_texture_prefix(const String &p) {normal_texture_prefix = p;} + + Error load_from_atlas_file(const String &p_path); // .atlas + + Error load_from_file(const String &p_path); // .spatlas + Error save_to_file(const String &p_path); // .spatlas + + String get_source_path(); + Array get_textures(); + Array get_normal_textures(); + + SpineAtlasResource(); + virtual ~SpineAtlasResource(); +}; + + +#endif //GODOT_SPINEATLASRESOURCE_H diff --git a/spine-godot/spine_godot/SpineAttachment.cpp b/spine-godot/spine_godot/SpineAttachment.cpp new file mode 100644 index 000000000..319cae442 --- /dev/null +++ b/spine-godot/spine_godot/SpineAttachment.cpp @@ -0,0 +1,55 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineAttachment.h" + +void SpineAttachment::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_attachment_name"), &SpineAttachment::get_attachment_name); + ClassDB::bind_method(D_METHOD("copy"), &SpineAttachment::copy); +} + +SpineAttachment::SpineAttachment():attachment(NULL) {} +SpineAttachment::~SpineAttachment() { + if(attachment){ + attachment->dereference(); + attachment = NULL; + } +} + +String SpineAttachment::get_attachment_name(){ + return attachment->getName().buffer(); +} + +Ref SpineAttachment::copy(){ + auto a = attachment->copy(); + if(a == NULL) return NULL; + Ref gd_attachment(memnew(SpineAttachment)); + gd_attachment->set_spine_object(a); + return gd_attachment; +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineAttachment.h b/spine-godot/spine_godot/SpineAttachment.h new file mode 100644 index 000000000..4575a50d1 --- /dev/null +++ b/spine-godot/spine_godot/SpineAttachment.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 GODOT_SPINEATTACHMENT_H +#define GODOT_SPINEATTACHMENT_H + +#include "core/variant_parser.h" + +#include + +class SpineAttachment : public Reference { + GDCLASS(SpineAttachment, Reference); + +protected: + static void _bind_methods(); + +private: + spine::Attachment *attachment; + +public: + SpineAttachment(); + ~SpineAttachment(); + + inline void set_spine_object(spine::Attachment *a){ + attachment = a; + if(attachment) + attachment->reference(); + } + inline spine::Attachment *get_spine_object(){ + return attachment; + } + + String get_attachment_name(); + + Ref copy(); +}; + +#endif //GODOT_SPINEATTACHMENT_H diff --git a/spine-godot/spine_godot/SpineBone.cpp b/spine-godot/spine_godot/SpineBone.cpp new file mode 100644 index 000000000..59f495aa3 --- /dev/null +++ b/spine-godot/spine_godot/SpineBone.cpp @@ -0,0 +1,537 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineBone.h" + +#include "SpineSprite.h" +#include "SpineSkeleton.h" + +void SpineBone::_bind_methods() { + ClassDB::bind_method(D_METHOD("update_world_transform"), &SpineBone::update_world_transform); +// void set_to_setup_pose(); +// +// Vector2 world_to_local(Vector2 world_position); +// +// Vector2 local_to_world(Vector2 local_position); +// +// float world_to_local_rotation(float world_rotation); +// +// float local_to_world_rotation(float local_rotation); +// +// void rotate_world(float degrees); + ClassDB::bind_method(D_METHOD("set_to_setup_pose"), &SpineBone::set_to_setup_pose); + ClassDB::bind_method(D_METHOD("world_to_local", "world_position"), &SpineBone::world_to_local); + ClassDB::bind_method(D_METHOD("local_to_world", "local_position"), &SpineBone::local_to_world); + ClassDB::bind_method(D_METHOD("world_to_local_rotation", "world_rotation"), &SpineBone::world_to_local_rotation); + ClassDB::bind_method(D_METHOD("local_to_world_rotation", "local_rotation"), &SpineBone::local_to_world_rotation); + ClassDB::bind_method(D_METHOD("rotate_world"), &SpineBone::rotate_world); +// +// float get_world_to_local_rotation_x(); +// float get_world_to_local_rotation_y(); +// +// Ref get_data(); +// +// Ref get_skeleton(); +// +// Ref get_parent(); +// +// Array get_children(); + ClassDB::bind_method(D_METHOD("get_world_to_local_rotation_x"), &SpineBone::get_world_to_local_rotation_x); + ClassDB::bind_method(D_METHOD("get_world_to_local_rotation_y"), &SpineBone::get_world_to_local_rotation_y); + ClassDB::bind_method(D_METHOD("get_data"), &SpineBone::get_data); + ClassDB::bind_method(D_METHOD("get_skeleton"), &SpineBone::get_skeleton); + ClassDB::bind_method(D_METHOD("get_parent"), &SpineBone::get_parent); + ClassDB::bind_method(D_METHOD("get_children"), &SpineBone::get_children); +// +// float get_x(); +// void set_x(float v); +// +// float get_y(); +// void set_y(float v); +// +// float get_rotation(); +// void set_rotation(float v); +// +// float get_scale_x(); +// void set_scale_x(float v); + ClassDB::bind_method(D_METHOD("get_x"), &SpineBone::get_x); + ClassDB::bind_method(D_METHOD("set_x", "v"), &SpineBone::set_x); + ClassDB::bind_method(D_METHOD("get_y"), &SpineBone::get_y); + ClassDB::bind_method(D_METHOD("set_y", "v"), &SpineBone::set_y); + ClassDB::bind_method(D_METHOD("get_rotation"), &SpineBone::get_rotation); + ClassDB::bind_method(D_METHOD("set_rotation", "v"), &SpineBone::set_rotation); + ClassDB::bind_method(D_METHOD("get_scale_x"), &SpineBone::get_scale_x); + ClassDB::bind_method(D_METHOD("set_scale_x", "v"), &SpineBone::set_scale_x); +// +// float get_scale_y(); +// void set_scale_y(float v); +// +// float get_shear_x(); +// void set_shear_x(float v); +// +// float get_shear_y(); +// void set_shear_y(float v); +// +// float get_applied_rotation(); +// void set_applied_rotation(float v); + ClassDB::bind_method(D_METHOD("get_scale_y"), &SpineBone::get_scale_y); + ClassDB::bind_method(D_METHOD("set_scale_y", "v"), &SpineBone::set_scale_y); + ClassDB::bind_method(D_METHOD("get_shear_x"), &SpineBone::get_shear_x); + ClassDB::bind_method(D_METHOD("set_shear_x", "v"), &SpineBone::set_shear_x); + ClassDB::bind_method(D_METHOD("get_shear_y"), &SpineBone::get_shear_y); + ClassDB::bind_method(D_METHOD("set_shear_y", "v"), &SpineBone::set_shear_y); + ClassDB::bind_method(D_METHOD("get_applied_rotation"), &SpineBone::get_applied_rotation); + ClassDB::bind_method(D_METHOD("set_applied_rotation", "v"), &SpineBone::set_applied_rotation); +// +// float get_a_x(); +// void set_a_x(float v); +// +// float get_a_y(); +// void set_a_y(float v); +// +// float get_a_scale_x(); +// void set_a_scale_x(float v); +// +// float get_a_scale_y(); +// void set_a_scale_y(float v); + ClassDB::bind_method(D_METHOD("get_a_x"), &SpineBone::get_a_x); + ClassDB::bind_method(D_METHOD("set_a_x", "v"), &SpineBone::set_a_x); + ClassDB::bind_method(D_METHOD("get_a_y"), &SpineBone::get_a_y); + ClassDB::bind_method(D_METHOD("set_a_y", "v"), &SpineBone::set_a_y); + ClassDB::bind_method(D_METHOD("get_a_scale_x"), &SpineBone::get_a_scale_x); + ClassDB::bind_method(D_METHOD("set_a_scale_x", "v"), &SpineBone::set_a_scale_x); + ClassDB::bind_method(D_METHOD("get_a_scale_y"), &SpineBone::get_a_scale_y); + ClassDB::bind_method(D_METHOD("set_a_scale_y", "v"), &SpineBone::set_a_scale_y); +// +// float get_a_shear_x(); +// void set_a_shear_x(float v); +// +// float get_a_shear_y(); +// void set_a_shear_y(float v); +// +// float get_a(); +// void set_a(float v); +// +// float get_b(); +// void set_b(float v); + ClassDB::bind_method(D_METHOD("get_a_shear_x"), &SpineBone::get_a_shear_x); + ClassDB::bind_method(D_METHOD("set_a_shear_x", "v"), &SpineBone::set_a_shear_x); + ClassDB::bind_method(D_METHOD("get_a_shear_y"), &SpineBone::get_a_shear_y); + ClassDB::bind_method(D_METHOD("set_a_shear_y", "v"), &SpineBone::set_a_shear_y); + ClassDB::bind_method(D_METHOD("get_a"), &SpineBone::get_a); + ClassDB::bind_method(D_METHOD("set_a", "v"), &SpineBone::set_a); + ClassDB::bind_method(D_METHOD("get_b"), &SpineBone::get_b); + ClassDB::bind_method(D_METHOD("set_b", "v"), &SpineBone::set_b); +// +// float get_c(); +// void set_c(float v); +// +// float get_d(); +// void set_d(float v); +// +// float get_world_x(); +// void set_world_x(float v); +// +// float get_world_y(); +// void set_world_y(float v); + ClassDB::bind_method(D_METHOD("get_c"), &SpineBone::get_c); + ClassDB::bind_method(D_METHOD("set_c", "v"), &SpineBone::set_c); + ClassDB::bind_method(D_METHOD("get_d"), &SpineBone::get_d); + ClassDB::bind_method(D_METHOD("set_d", "v"), &SpineBone::set_d); + ClassDB::bind_method(D_METHOD("get_world_x"), &SpineBone::get_world_x); + ClassDB::bind_method(D_METHOD("set_world_x", "v"), &SpineBone::set_world_x); + ClassDB::bind_method(D_METHOD("get_world_y"), &SpineBone::get_world_y); + ClassDB::bind_method(D_METHOD("set_world_y", "v"), &SpineBone::set_world_y); +// +// float get_world_rotation_x(); +// float get_world_rotation_y(); +// +// float get_world_scale_x(); +// float get_world_scale_y(); +// +// bool is_applied_valid(); +// void set_applied_valid(bool v); +// +// bool is_active(); +// void set_active(bool v); + ClassDB::bind_method(D_METHOD("get_world_rotation_x"), &SpineBone::get_world_rotation_x); + ClassDB::bind_method(D_METHOD("get_world_rotation_y"), &SpineBone::get_world_rotation_y); + ClassDB::bind_method(D_METHOD("get_world_scale_x"), &SpineBone::get_world_scale_x); + ClassDB::bind_method(D_METHOD("get_world_scale_y"), &SpineBone::get_world_scale_y); + ClassDB::bind_method(D_METHOD("is_active"), &SpineBone::is_active); + ClassDB::bind_method(D_METHOD("set_active", "v"), &SpineBone::set_active); + + ClassDB::bind_method(D_METHOD("get_godot_transform"), &SpineBone::get_godot_transform); + ClassDB::bind_method(D_METHOD("set_godot_transform", "local_transform"), &SpineBone::set_godot_transform); + ClassDB::bind_method(D_METHOD("get_godot_global_transform"), &SpineBone::get_godot_global_transform); + ClassDB::bind_method(D_METHOD("set_godot_global_transform", "global_transform"), &SpineBone::set_godot_global_transform); + + ClassDB::bind_method(D_METHOD("apply_world_transform_2d", "node2d"), &SpineBone::apply_world_transform_2d); +} + +SpineBone::SpineBone():bone(NULL), the_sprite(nullptr) {} +SpineBone::~SpineBone() {} + +void SpineBone::update_world_transform(){ + bone->updateWorldTransform(); +} + +void SpineBone::set_to_setup_pose(){ + bone->setToSetupPose(); +} + +Vector2 SpineBone::world_to_local(Vector2 world_position){ + float x, y; + bone->worldToLocal(world_position.x, world_position.y, x, y); + return Vector2(x, y); +} + +Vector2 SpineBone::local_to_world(Vector2 local_position){ + float x, y; + bone->localToWorld(local_position.x, local_position.y, x, y); + return Vector2(x, y); +} + +float SpineBone::world_to_local_rotation(float world_rotation){ + return bone->worldToLocalRotation(world_rotation); +} + +float SpineBone::local_to_world_rotation(float local_rotation){ + return bone->localToWorldRotation(local_rotation); +} + +void SpineBone::rotate_world(float degrees){ + bone->rotateWorld(degrees); +} + +float SpineBone::get_world_to_local_rotation_x(){ + return bone->getWorldToLocalRotationX(); +} +float SpineBone::get_world_to_local_rotation_y(){ + return bone->getWorldToLocalRotationY(); +} + +Ref SpineBone::get_data(){ + auto &bd = bone->getData(); + Ref gd_bd(memnew(SpineBoneData)); + gd_bd->set_spine_object(&bd); + return gd_bd; +} + +Ref SpineBone::get_skeleton(){ + auto &s = bone->getSkeleton(); + Ref gd_s(memnew(SpineSkeleton)); + gd_s->set_spine_object(&s); + gd_s->set_spine_sprite(the_sprite); + return gd_s; +} + +Ref SpineBone::get_parent(){ + auto b = bone->getParent(); + if(b == NULL) return NULL; + Ref gd_b(memnew(SpineBone)); + gd_b->set_spine_object(b); + gd_b->set_spine_sprite(the_sprite); + return gd_b; +} + +Array SpineBone::get_children(){ + auto bs = bone->getChildren(); + Array gd_bs; + gd_bs.resize(bs.size()); + for(size_t i=0; i < bs.size(); ++i){ + auto b = bs[i]; + if(b == NULL) gd_bs[i] = Ref(NULL); + Ref gd_b(memnew(SpineBone)); + gd_b->set_spine_object(b); + gd_b->set_spine_sprite(the_sprite); + gd_bs[i] = gd_b; + } + return gd_bs; +} + +float SpineBone::get_x(){ + return bone->getX(); +} +void SpineBone::set_x(float v){ + bone->setX(v); +} + +float SpineBone::get_y(){ + return bone->getY(); +} +void SpineBone::set_y(float v){ + bone->setY(v); +} + +float SpineBone::get_rotation(){ + return bone->getRotation(); +} +void SpineBone::set_rotation(float v){ + bone->setRotation(v); +} + +float SpineBone::get_scale_x(){ + return bone->getScaleX(); +} +void SpineBone::set_scale_x(float v){ + bone->setScaleX(v); +} + +float SpineBone::get_scale_y(){ + return bone->getScaleY(); +} +void SpineBone::set_scale_y(float v){ + bone->setScaleY(v); +} + +float SpineBone::get_shear_x(){ + return bone->getShearX(); +} +void SpineBone::set_shear_x(float v){ + bone->setShearX(v); +} + +float SpineBone::get_shear_y(){ + return bone->getShearY(); +} +void SpineBone::set_shear_y(float v){ + bone->setShearY(v); +} + +float SpineBone::get_applied_rotation(){ + return bone->getAppliedRotation(); +} +void SpineBone::set_applied_rotation(float v){ + bone->setAppliedRotation(v); +} + +float SpineBone::get_a_x(){ + return bone->getAX(); +} +void SpineBone::set_a_x(float v){ + bone->setAX(v); +} + +float SpineBone::get_a_y(){ + return bone->getAY(); +} +void SpineBone::set_a_y(float v){ + bone->setAY(v); +} + +float SpineBone::get_a_scale_x(){ + return bone->getAScaleX(); +} +void SpineBone::set_a_scale_x(float v){ + bone->setAScaleX(v); +} + +float SpineBone::get_a_scale_y(){ + return bone->getAScaleY(); +} +void SpineBone::set_a_scale_y(float v){ + bone->setAScaleY(v); +} + +float SpineBone::get_a_shear_x(){ + return bone->getAShearX(); +} +void SpineBone::set_a_shear_x(float v){ + bone->setAShearX(v); +} + +float SpineBone::get_a_shear_y(){ + return bone->getAShearY(); +} +void SpineBone::set_a_shear_y(float v){ + bone->setAShearY(v); +} + +float SpineBone::get_a(){ + return bone->getA(); +} +void SpineBone::set_a(float v){ + bone->setA(v); +} + +float SpineBone::get_b(){ + return bone->getB(); +} +void SpineBone::set_b(float v){ + bone->setB(v); +} + +float SpineBone::get_c(){ + return bone->getC(); +} +void SpineBone::set_c(float v){ + bone->setC(v); +} + +float SpineBone::get_d(){ + return bone->getD(); +} +void SpineBone::set_d(float v){ + bone->setD(v); +} + +float SpineBone::get_world_x(){ + return bone->getWorldX(); +} +void SpineBone::set_world_x(float v){ + bone->setWorldX(v); +} + +float SpineBone::get_world_y(){ + return bone->getWorldY(); +} +void SpineBone::set_world_y(float v){ + bone->setWorldY(v); +} + +float SpineBone::get_world_rotation_x(){ + return bone->getWorldRotationX(); +} +float SpineBone::get_world_rotation_y(){ + return bone->getWorldRotationY(); +} + +float SpineBone::get_world_scale_x(){ + return bone->getWorldScaleX(); +} +float SpineBone::get_world_scale_y(){ + return bone->getWorldScaleY(); +} + +bool SpineBone::is_active(){ + return bone->isActive(); +} +void SpineBone::set_active(bool v){ + bone->setActive(v); +} + +// External feature functions +void SpineBone::apply_world_transform_2d(Variant o){ + if(o.get_type() == Variant::OBJECT){ + auto node = (Node*) o; + if(node->is_class("Node2D")){ + auto node2d = (Node2D*) node; + // In godot the y-axis is nag to spine + node2d->set_transform(Transform2D( + get_a(), get_c(), + get_b(), get_d(), + get_world_x(), -get_world_y()) + ); + // Fix the rotation + auto pos = node2d->get_position(); + node2d->translate(-pos); + node2d->set_rotation(-node2d->get_rotation()); + node2d->translate(pos); + } + } +} + +Transform2D SpineBone::get_godot_transform() { + if (get_spine_object() == nullptr) + return Transform2D(); + Transform2D trans; + trans.translate(get_x(), -get_y()); + // It seems that spine uses degree for rotation + trans.rotate(Math::deg2rad(-get_rotation())); + trans.scale(Size2(get_scale_x(), get_scale_y())); + return trans; +} + +void SpineBone::set_godot_transform(Transform2D trans) { + if (get_spine_object() == nullptr) + return; + Vector2 position = trans.get_origin(); + position.y *= -1; + real_t rotation = trans.get_rotation(); + rotation = Math::rad2deg(-rotation); + Vector2 scale = trans.get_scale(); + + set_x(position.x); + set_y(position.y); + set_rotation(rotation); + set_scale_x(scale.x); + set_scale_y(scale.y); +} + +Transform2D SpineBone::get_godot_global_transform() { + if (get_spine_object() == nullptr) + return Transform2D(); + if (the_sprite == nullptr) + return get_godot_transform(); + Transform2D res = the_sprite->get_transform(); + res.translate(get_world_x(), -get_world_y()); + res.rotate(Math::deg2rad(-get_world_rotation_x())); + res.scale(Vector2(get_world_scale_x(), get_world_scale_y())); + auto p = the_sprite->get_parent() ? Object::cast_to(the_sprite->get_parent()) : nullptr; + if (p) { + return p->get_global_transform() * res; + } + return res; +} + +void SpineBone::set_godot_global_transform(Transform2D transform) { + if (get_spine_object() == nullptr) + return; + if (the_sprite == nullptr) + set_godot_transform(transform); + transform = the_sprite->get_global_transform().affine_inverse() * transform; + Vector2 position = transform.get_origin(); + real_t rotation = transform.get_rotation(); + Vector2 scale = transform.get_scale(); + position.y *= -1; + auto parent = get_parent(); + if (parent.is_valid()) { + position = parent->world_to_local(position); + if (parent->get_world_scale_x() != 0) + scale.x /= parent->get_world_scale_x(); + else + print_error("The parent scale.x is zero."); + if (parent->get_world_scale_y() != 0) + scale.y /= parent->get_world_scale_y(); + else + print_error("The parent scale.y is zero."); + } + rotation = world_to_local_rotation(Math::rad2deg(-rotation)); + + set_x(position.x); + set_y(position.y); + set_rotation(rotation); + set_scale_x(scale.x); + set_scale_y(scale.y); +} + +void SpineBone::set_spine_sprite(SpineSprite *s) { + the_sprite = s; +} diff --git a/spine-godot/spine_godot/SpineBone.h b/spine-godot/spine_godot/SpineBone.h new file mode 100644 index 000000000..1661d751b --- /dev/null +++ b/spine-godot/spine_godot/SpineBone.h @@ -0,0 +1,174 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef GODOT_SPINEBONE_H +#define GODOT_SPINEBONE_H + +#include "core/variant_parser.h" +#include + +#include +#include + +#include "SpineBoneData.h" +#include "SpineIkConstraint.h" +#include "SpinePathConstraint.h" +#include "SpineTransformConstraint.h" + +class SpineSkeleton; +class SpineSprite; + +class SpineBone : public Reference { + GDCLASS(SpineBone, Reference); + +protected: + static void _bind_methods(); + +private: + spine::Bone *bone; + + SpineSprite *the_sprite; +public: + SpineBone(); + ~SpineBone(); + + inline void set_spine_object(spine::Bone *b){ + bone = b; + } + inline spine::Bone *get_spine_object(){ + return bone; + } + + void set_spine_sprite(SpineSprite *s); + + void update_world_transform(); + + void set_to_setup_pose(); + + Vector2 world_to_local(Vector2 world_position); + + Vector2 local_to_world(Vector2 local_position); + + float world_to_local_rotation(float world_rotation); + + float local_to_world_rotation(float local_rotation); + + void rotate_world(float degrees); + + float get_world_to_local_rotation_x(); + float get_world_to_local_rotation_y(); + + Ref get_data(); + + Ref get_skeleton(); + + Ref get_parent(); + + Array get_children(); + + float get_x(); + void set_x(float v); + + float get_y(); + void set_y(float v); + + float get_rotation(); + void set_rotation(float v); + + float get_scale_x(); + void set_scale_x(float v); + + float get_scale_y(); + void set_scale_y(float v); + + float get_shear_x(); + void set_shear_x(float v); + + float get_shear_y(); + void set_shear_y(float v); + + float get_applied_rotation(); + void set_applied_rotation(float v); + + float get_a_x(); + void set_a_x(float v); + + float get_a_y(); + void set_a_y(float v); + + float get_a_scale_x(); + void set_a_scale_x(float v); + + float get_a_scale_y(); + void set_a_scale_y(float v); + + float get_a_shear_x(); + void set_a_shear_x(float v); + + float get_a_shear_y(); + void set_a_shear_y(float v); + + float get_a(); + void set_a(float v); + + float get_b(); + void set_b(float v); + + float get_c(); + void set_c(float v); + + float get_d(); + void set_d(float v); + + float get_world_x(); + void set_world_x(float v); + + float get_world_y(); + void set_world_y(float v); + + float get_world_rotation_x(); + float get_world_rotation_y(); + + float get_world_scale_x(); + float get_world_scale_y(); + + bool is_active(); + void set_active(bool v); + + // External feature functions + void apply_world_transform_2d(Variant o); + + Transform2D get_godot_transform(); + void set_godot_transform(Transform2D trans); + + Transform2D get_godot_global_transform(); + void set_godot_global_transform(Transform2D trans); +}; + +#endif //GODOT_SPINEBONE_H diff --git a/spine-godot/spine_godot/SpineBoneData.cpp b/spine-godot/spine_godot/SpineBoneData.cpp new file mode 100644 index 000000000..e46ade5a2 --- /dev/null +++ b/spine-godot/spine_godot/SpineBoneData.cpp @@ -0,0 +1,163 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineBoneData.h" + +void SpineBoneData::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_index"), &SpineBoneData::get_index); + ClassDB::bind_method(D_METHOD("get_bone_name"), &SpineBoneData::get_bone_name); + ClassDB::bind_method(D_METHOD("get_parent"), &SpineBoneData::get_parent); + + ClassDB::bind_method(D_METHOD("get_length"), &SpineBoneData::get_length); + ClassDB::bind_method(D_METHOD("set_length", "v"), &SpineBoneData::set_length); + + ClassDB::bind_method(D_METHOD("get_x"), &SpineBoneData::get_x); + ClassDB::bind_method(D_METHOD("set_x", "v"), &SpineBoneData::set_x); + + ClassDB::bind_method(D_METHOD("get_y"), &SpineBoneData::get_y); + ClassDB::bind_method(D_METHOD("set_y", "v"), &SpineBoneData::set_y); + + ClassDB::bind_method(D_METHOD("get_rotation"), &SpineBoneData::get_rotation); + ClassDB::bind_method(D_METHOD("set_rotation", "v"), &SpineBoneData::set_rotation); + + ClassDB::bind_method(D_METHOD("get_scale_x"), &SpineBoneData::get_scale_x); + ClassDB::bind_method(D_METHOD("set_scale_x", "v"), &SpineBoneData::set_scale_x); + + ClassDB::bind_method(D_METHOD("get_scale_y"), &SpineBoneData::get_scale_y); + ClassDB::bind_method(D_METHOD("set_scale_y", "v"), &SpineBoneData::set_scale_y); + + ClassDB::bind_method(D_METHOD("get_shear_x"), &SpineBoneData::get_shear_x); + ClassDB::bind_method(D_METHOD("set_shear_x", "v"), &SpineBoneData::set_shear_x); + + ClassDB::bind_method(D_METHOD("get_shear_y"), &SpineBoneData::get_shear_y); + ClassDB::bind_method(D_METHOD("set_shear_y", "v"), &SpineBoneData::set_shear_y); + + ClassDB::bind_method(D_METHOD("get_transform_mode"), &SpineBoneData::get_transform_mode); + ClassDB::bind_method(D_METHOD("set_transform_mode", "v"), &SpineBoneData::set_transform_mode); + + ClassDB::bind_method(D_METHOD("is_skin_required"), &SpineBoneData::is_skin_required); + ClassDB::bind_method(D_METHOD("set_skin_required", "v"), &SpineBoneData::set_skin_required); + + BIND_ENUM_CONSTANT(TRANSFORMMODE_NORMAL); + BIND_ENUM_CONSTANT(TRANSFORMMODE_ONLYTRANSLATION); + BIND_ENUM_CONSTANT(TRANSFORMMODE_NOROTATIONORREFLECTION); + BIND_ENUM_CONSTANT(TRANSFORMMODE_NOSCALE); + BIND_ENUM_CONSTANT(TRANSFORMMODE_NOSCALEORREFLECTION); +} + +SpineBoneData::SpineBoneData():bone_data(NULL) {} +SpineBoneData::~SpineBoneData() {} + +int SpineBoneData::get_index(){ + return bone_data->getIndex(); +} + +String SpineBoneData::get_bone_name(){ + return bone_data->getName().buffer(); +} + +Ref SpineBoneData::get_parent(){ + auto p = bone_data->getParent(); + if(p == NULL) return NULL; + Ref gd_bone_data(memnew(SpineBoneData)); + gd_bone_data->set_spine_object(p); + return gd_bone_data; +} + +float SpineBoneData::get_length(){ + return bone_data->getLength(); +} +void SpineBoneData::set_length(float v){ + bone_data->setLength(v); +} + +float SpineBoneData::get_x(){ + return bone_data->getX(); +} +void SpineBoneData::set_x(float v){ + bone_data->setX(v); +} + +float SpineBoneData::get_y(){ + return bone_data->getY(); +} +void SpineBoneData::set_y(float v){ + bone_data->setY(v); +} + +float SpineBoneData::get_rotation(){ + return bone_data->getRotation(); +} +void SpineBoneData::set_rotation(float v){ + bone_data->setRotation(v); +} + +float SpineBoneData::get_scale_x(){ + return bone_data->getScaleX(); +} +void SpineBoneData::set_scale_x(float v){ + bone_data->setScaleX(v); +} + +float SpineBoneData::get_scale_y(){ + return bone_data->getScaleY(); +} +void SpineBoneData::set_scale_y(float v){ + bone_data->setScaleY(v); +} + +float SpineBoneData::get_shear_x(){ + return bone_data->getShearX(); +} +void SpineBoneData::set_shear_x(float v){ + bone_data->setShearX(v); +} + +float SpineBoneData::get_shear_y(){ + return bone_data->getShearY(); +} +void SpineBoneData::set_shear_y(float v){ + bone_data->setShearY(v); +} + +SpineBoneData::TransformMode SpineBoneData::get_transform_mode(){ + auto tm = (int)bone_data->getTransformMode(); + return (TransformMode) tm; +} +void SpineBoneData::set_transform_mode(TransformMode v){ + auto tm = (int) v; + bone_data->setTransformMode((spine::TransformMode)tm); +} + +bool SpineBoneData::is_skin_required(){ + return bone_data->isSkinRequired(); +} +void SpineBoneData::set_skin_required(bool v){ + bone_data->setSkinRequired(v); +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineBoneData.h b/spine-godot/spine_godot/SpineBoneData.h new file mode 100644 index 000000000..3bef4c023 --- /dev/null +++ b/spine-godot/spine_godot/SpineBoneData.h @@ -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. + *****************************************************************************/ + +#ifndef GODOT_SPINEBONEDATA_H +#define GODOT_SPINEBONEDATA_H + +#include "core/variant_parser.h" + +#include + +class SpineBoneData : public Reference { + GDCLASS(SpineBoneData, Reference); + +protected: + static void _bind_methods(); + +private: + spine::BoneData *bone_data; + +public: + SpineBoneData(); + ~SpineBoneData(); + + inline void set_spine_object(spine::BoneData *b){ + bone_data = b; + } + inline spine::BoneData *get_spine_object(){ + return bone_data; + } + + enum TransformMode { + TRANSFORMMODE_NORMAL = 0, + TRANSFORMMODE_ONLYTRANSLATION, + TRANSFORMMODE_NOROTATIONORREFLECTION, + TRANSFORMMODE_NOSCALE, + TRANSFORMMODE_NOSCALEORREFLECTION + }; + + int get_index(); + + String get_bone_name(); + + Ref get_parent(); + + float get_length(); + void set_length(float v); + + float get_x(); + void set_x(float v); + + float get_y(); + void set_y(float v); + + float get_rotation(); + void set_rotation(float v); + + float get_scale_x(); + void set_scale_x(float v); + + float get_scale_y(); + void set_scale_y(float v); + + float get_shear_x(); + void set_shear_x(float v); + + float get_shear_y(); + void set_shear_y(float v); + + TransformMode get_transform_mode(); + void set_transform_mode(TransformMode v); + + bool is_skin_required(); + void set_skin_required(bool v); + +}; + +VARIANT_ENUM_CAST(SpineBoneData::TransformMode); +#endif //GODOT_SPINEBONEDATA_H diff --git a/spine-godot/spine_godot/SpineCollisionShapeProxy.cpp b/spine-godot/spine_godot/SpineCollisionShapeProxy.cpp new file mode 100644 index 000000000..e41b28faf --- /dev/null +++ b/spine-godot/spine_godot/SpineCollisionShapeProxy.cpp @@ -0,0 +1,204 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineCollisionShapeProxy.h" + +#include "SpineSprite.h" + +void SpineCollisionShapeProxy::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_spine_sprite_path"), &SpineCollisionShapeProxy::get_spine_sprite_path); + ClassDB::bind_method(D_METHOD("set_spine_sprite_path", "v"), &SpineCollisionShapeProxy::set_spine_sprite_path); + + ClassDB::bind_method(D_METHOD("get_slot"), &SpineCollisionShapeProxy::get_slot); + ClassDB::bind_method(D_METHOD("set_slot", "v"), &SpineCollisionShapeProxy::set_slot); + + ClassDB::bind_method(D_METHOD("get_sync_transform"), &SpineCollisionShapeProxy::get_sync_transform); + ClassDB::bind_method(D_METHOD("set_sync_transform", "v"), &SpineCollisionShapeProxy::set_sync_transform); + + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "spine_sprite_path"), "set_spine_sprite_path", "get_spine_sprite_path"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync_transform"), "set_sync_transform", "get_sync_transform"); +} + +SpineCollisionShapeProxy::SpineCollisionShapeProxy():sync_transform(true) { + +} + +SpineCollisionShapeProxy::~SpineCollisionShapeProxy() { + +} + +void SpineCollisionShapeProxy::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_READY: { + set_process_internal(true); + } break; + case NOTIFICATION_INTERNAL_PROCESS: { + if (!disabled) { + if (sync_transform) _sync_transform(get_spine_sprite()); + _update_polygon_from_spine_sprite(get_spine_sprite()); + if (is_visible()) update(); + } + } break; + } +} + +SpineSprite *SpineCollisionShapeProxy::get_spine_sprite() const { + return (SpineSprite*) get_node_or_null(spine_sprite_path); +} + +NodePath SpineCollisionShapeProxy::get_spine_sprite_path() { + return spine_sprite_path; +} + +void SpineCollisionShapeProxy::set_spine_sprite_path(NodePath v) { + spine_sprite_path = v; + + _update_polygon_from_spine_sprite(get_spine_sprite()); +} + +String SpineCollisionShapeProxy::get_slot() const { + return slot; +} + +void SpineCollisionShapeProxy::set_slot(const String &v) { + slot = v; + _update_polygon_from_spine_sprite(get_spine_sprite()); +} + +void SpineCollisionShapeProxy::_update_polygon_from_spine_sprite(SpineSprite *sprite) { + _clear_polygon(); + if (sprite == nullptr || slot.empty()) { + return; + } + + if (!sprite->get_skeleton().is_valid()) { + return; + } + + auto sk = sprite->get_skeleton()->get_spine_object(); + + spine::Vector vertices; + + spine::Slot *s = sk->findSlot(spine::String(slot.utf8())); + if (!s) { + return; + } + spine::Attachment *attachment = s->getAttachment(); + if(!attachment){ + return; + } + + if (attachment->getRTTI().isExactly(spine::BoundingBoxAttachment::rtti)) { + auto *box = (spine::BoundingBoxAttachment*) attachment; + + vertices.setSize(box->getWorldVerticesLength(), 0); + box->computeWorldVertices(*s, vertices); + } else { + return; + } + + polygon.resize(vertices.size()/2); + for (size_t j=0; j < vertices.size(); j+=2) { + polygon.set(j/2, Vector2(vertices[j], -vertices[j + 1])); + } + + set_polygon(polygon); +} + +void SpineCollisionShapeProxy::_clear_polygon() { + polygon.clear(); + set_polygon(polygon); +} + +void SpineCollisionShapeProxy::_sync_transform(SpineSprite *sprite) { + if (sprite == nullptr) return; + set_global_transform(sprite->get_global_transform()); +} + +bool SpineCollisionShapeProxy::get_sync_transform() { + return sync_transform; +} + +void SpineCollisionShapeProxy::set_sync_transform(bool v) { + sync_transform = v; +} + +void SpineCollisionShapeProxy::_get_property_list(List *p_list) const { + PropertyInfo p; + Vector res; + + p.name = "slot"; + p.type = Variant::STRING; + _get_slot_list(res); + if (res.empty()) res.push_back("No Slot"); + p.hint_string = String(",").join(res); + p.hint = PROPERTY_HINT_ENUM; + p_list->push_back(p); +} + +bool SpineCollisionShapeProxy::_get(const StringName &p_property, Variant &r_value) const { + if (p_property == "slot") { + r_value = get_slot(); + return true; + } + return false; +} + +bool SpineCollisionShapeProxy::_set(const StringName &p_property, const Variant &p_value) { + if (p_property == "slot") { + set_slot(p_value); + return true; + } + return false; +} + +void SpineCollisionShapeProxy::_get_slot_list(Vector &res) const { + if (get_spine_sprite() == nullptr) { + return; + } + + auto sprite = get_spine_sprite(); + if (!sprite->get_skeleton().is_valid()) { + return; + } + + auto slots = sprite->get_skeleton()->get_slots(); + res.resize(slots.size()); + for (size_t i=0; i < res.size(); ++i) { + auto slot = (Ref)slots[i]; + if (slot.is_valid()) + res.set(i, slot->get_data()->get_slot_name()); + } +} + + + + + + diff --git a/spine-godot/spine_godot/SpineCollisionShapeProxy.h b/spine-godot/spine_godot/SpineCollisionShapeProxy.h new file mode 100644 index 000000000..5dd2dd683 --- /dev/null +++ b/spine-godot/spine_godot/SpineCollisionShapeProxy.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 GODOT_SPINECOLLISIONSHAPEPROXY_H +#define GODOT_SPINECOLLISIONSHAPEPROXY_H + +#include "scene/2d/collision_polygon_2d.h" + +class SpineSprite; +class SpineAnimationState; +class SpineSkeleton; + +class SpineCollisionShapeProxy : public CollisionPolygon2D{ + GDCLASS(SpineCollisionShapeProxy, CollisionPolygon2D) +protected: + static void _bind_methods(); + + NodePath spine_sprite_path; + + String slot; + + bool sync_transform; +protected: + void _notification(int p_what); + void _get_property_list(List *p_list) const; + bool _get(const StringName &p_property, Variant &r_value) const; + bool _set(const StringName &p_property, const Variant &p_value); + + + SpineSprite *get_spine_sprite() const; + + void _update_polygon_from_spine_sprite(SpineSprite *sprite); + void _clear_polygon(); + void _sync_transform(SpineSprite *sprite); + + void _get_slot_list(Vector &res) const; +public: + SpineCollisionShapeProxy(); + ~SpineCollisionShapeProxy(); + + NodePath get_spine_sprite_path(); + void set_spine_sprite_path(NodePath v); + + String get_slot() const; + void set_slot(const String &v); + + bool get_sync_transform(); + void set_sync_transform(bool v); +}; + + +#endif //GODOT_SPINECOLLISIONSHAPEPROXY_H diff --git a/spine-godot/spine_godot/SpineConstant.cpp b/spine-godot/spine_godot/SpineConstant.cpp new file mode 100644 index 000000000..9e0406103 --- /dev/null +++ b/spine-godot/spine_godot/SpineConstant.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. + *****************************************************************************/ + +#include "SpineConstant.h" + +void SpineConstant::_bind_methods() { + BIND_ENUM_CONSTANT(MixBlend_Setup); + BIND_ENUM_CONSTANT(MixBlend_First); + BIND_ENUM_CONSTANT(MixBlend_Replace); + BIND_ENUM_CONSTANT(MixBlend_Add); + + BIND_ENUM_CONSTANT(MixDirection_In); + BIND_ENUM_CONSTANT(MixDirection_Out); + + BIND_ENUM_CONSTANT(Property_Rotate); + BIND_ENUM_CONSTANT(Property_X); + BIND_ENUM_CONSTANT(Property_Y); + BIND_ENUM_CONSTANT(Property_ScaleX); + BIND_ENUM_CONSTANT( Property_ScaleY); + BIND_ENUM_CONSTANT(Property_ShearX); + BIND_ENUM_CONSTANT(Property_ShearY); + BIND_ENUM_CONSTANT(Property_Rgb); + BIND_ENUM_CONSTANT(Property_Alpha); + BIND_ENUM_CONSTANT(Property_Rgb2); + BIND_ENUM_CONSTANT(Property_Attachment); + BIND_ENUM_CONSTANT(Property_Deform); + BIND_ENUM_CONSTANT(Property_Event); + BIND_ENUM_CONSTANT(Property_DrawOrder); + BIND_ENUM_CONSTANT(Property_IkConstraint); + BIND_ENUM_CONSTANT(Property_TransformConstraint); + BIND_ENUM_CONSTANT(Property_PathConstraintPosition); + BIND_ENUM_CONSTANT(Property_PathConstraintSpacing); + BIND_ENUM_CONSTANT(Property_PathConstraintMix); + + +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineConstant.h b/spine-godot/spine_godot/SpineConstant.h new file mode 100644 index 000000000..fb2d01ece --- /dev/null +++ b/spine-godot/spine_godot/SpineConstant.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 GODOT_SPINECONSTANT_H +#define GODOT_SPINECONSTANT_H + +#include "core/variant_parser.h" + +class SpineConstant : public Object{ + GDCLASS(SpineConstant, Object); + +protected: + static void _bind_methods(); +public: + enum MixBlend { + MixBlend_Setup = 0, + MixBlend_First, + MixBlend_Replace, + MixBlend_Add + }; + + enum MixDirection { + MixDirection_In = 0, + MixDirection_Out + }; + + enum PropertyId { + 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 + }; +}; + +VARIANT_ENUM_CAST(SpineConstant::MixBlend); +VARIANT_ENUM_CAST(SpineConstant::MixDirection); +VARIANT_ENUM_CAST(SpineConstant::PropertyId); + +#endif //GODOT_SPINECONSTANT_H diff --git a/spine-godot/spine_godot/SpineConstraintData.cpp b/spine-godot/spine_godot/SpineConstraintData.cpp new file mode 100644 index 000000000..52d054efe --- /dev/null +++ b/spine-godot/spine_godot/SpineConstraintData.cpp @@ -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. + *****************************************************************************/ + +#include "SpineConstraintData.h" + +void SpineConstraintData::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_constraint_data_name"), &SpineConstraintData::get_constraint_data_name); + ClassDB::bind_method(D_METHOD("get_order"), &SpineConstraintData::get_order); + ClassDB::bind_method(D_METHOD("set_order", "v"), &SpineConstraintData::set_order); + ClassDB::bind_method(D_METHOD("is_skin_required"), &SpineConstraintData::is_skin_required); + ClassDB::bind_method(D_METHOD("set_skin_required", "v"), &SpineConstraintData::set_skin_required); +} + +SpineConstraintData::SpineConstraintData():constraint_data(NULL) {} +SpineConstraintData::~SpineConstraintData() {} + +String SpineConstraintData::get_constraint_data_name(){ + return constraint_data->getName().buffer(); +} + +uint64_t SpineConstraintData::get_order(){ + return constraint_data->getOrder(); +} +void SpineConstraintData::set_order(uint64_t v){ + constraint_data->setOrder(v); +} + +bool SpineConstraintData::is_skin_required(){ + return constraint_data->isSkinRequired(); +} +void SpineConstraintData::set_skin_required(bool v){ + constraint_data->setSkinRequired(v); +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineConstraintData.h b/spine-godot/spine_godot/SpineConstraintData.h new file mode 100644 index 000000000..ff0517a46 --- /dev/null +++ b/spine-godot/spine_godot/SpineConstraintData.h @@ -0,0 +1,66 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef GODOT_SPINECONSTRAINTDATA_H +#define GODOT_SPINECONSTRAINTDATA_H + +#include "core/variant_parser.h" + +#include + +class SpineConstraintData : public Reference { + GDCLASS(SpineConstraintData, Reference); + +protected: + static void _bind_methods(); + +private: + spine::ConstraintData *constraint_data; + +public: + SpineConstraintData(); + ~SpineConstraintData(); + + inline void set_spine_object(spine::ConstraintData *c){ + constraint_data = c; + } + virtual inline spine::ConstraintData *get_spine_object(){ + return constraint_data; + } + + String get_constraint_data_name(); + + uint64_t get_order(); + void set_order(uint64_t v); + + bool is_skin_required(); + void set_skin_required(bool v); +}; + +#endif //GODOT_SPINECONSTRAINTDATA_H diff --git a/spine-godot/spine_godot/SpineEvent.cpp b/spine-godot/spine_godot/SpineEvent.cpp new file mode 100644 index 000000000..f33582045 --- /dev/null +++ b/spine-godot/spine_godot/SpineEvent.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. + *****************************************************************************/ + +#include "SpineEvent.h" + +void SpineEvent::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_data"), &SpineEvent::get_data); + ClassDB::bind_method(D_METHOD("get_event_name"), &SpineEvent::get_event_name); + ClassDB::bind_method(D_METHOD("get_time"), &SpineEvent::get_time); + ClassDB::bind_method(D_METHOD("get_int_value"), &SpineEvent::get_int_value); + ClassDB::bind_method(D_METHOD("set_int_value", "v"), &SpineEvent::set_int_value); + ClassDB::bind_method(D_METHOD("get_float_value"), &SpineEvent::get_float_value); + ClassDB::bind_method(D_METHOD("set_float_value", "v"), &SpineEvent::set_float_value); + ClassDB::bind_method(D_METHOD("get_string_value"), &SpineEvent::get_string_value); + ClassDB::bind_method(D_METHOD("set_string_value", "v"), &SpineEvent::set_string_value); + ClassDB::bind_method(D_METHOD("get_volume"), &SpineEvent::get_volume); + ClassDB::bind_method(D_METHOD("set_volume", "v"), &SpineEvent::set_volume); + ClassDB::bind_method(D_METHOD("get_balance"), &SpineEvent::get_balance); + ClassDB::bind_method(D_METHOD("set_balance", "v"), &SpineEvent::set_balance); +// +// BIND_ENUM_CONSTANT(EVENTTYPE_START); +// BIND_ENUM_CONSTANT(EVENTTYPE_INTERRUPT); +// BIND_ENUM_CONSTANT(EVENTTYPE_END); +// BIND_ENUM_CONSTANT(EVENTTYPE_COMPLETE); +// BIND_ENUM_CONSTANT(EVENTTYPE_DISPOSE); +// BIND_ENUM_CONSTANT(EVENTTYPE_EVENT); +} + +SpineEvent::SpineEvent():event(NULL) {} +SpineEvent::~SpineEvent(){} + +Ref SpineEvent::get_data(){ + Ref event_data(memnew(SpineEventData)); + event_data->set_spine_object(&(event->getData())); + return event_data; +} + +String SpineEvent::get_event_name() { + return event->getData().getName().buffer(); +} + +float SpineEvent::get_time(){ + return event->getTime(); +} + +int SpineEvent::get_int_value(){ + return event->getIntValue(); +} + +void SpineEvent::set_int_value(int v){ + event->setIntValue(v); +} + +float SpineEvent::get_float_value(){ + return event->getFloatValue(); +} + +void SpineEvent::set_float_value(float v){ + event->setFloatValue(v); +} + +String SpineEvent::get_string_value(){ + return event->getStringValue().buffer(); +} + +void SpineEvent::set_string_value(const String &v){ + event->setStringValue(spine::String(v.utf8())); +} + +float SpineEvent::get_volume(){ + return event->getVolume(); +} + +void SpineEvent::set_volume(float v){ + event->setVolume(v); +} + +float SpineEvent::get_balance(){ + return event->getBalance(); +} + +void SpineEvent::set_balance(float v){ + event->setBalance(v); +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineEvent.h b/spine-godot/spine_godot/SpineEvent.h new file mode 100644 index 000000000..4824eeaff --- /dev/null +++ b/spine-godot/spine_godot/SpineEvent.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 GODOT_SPINEEVENT_H +#define GODOT_SPINEEVENT_H + +#include "core/variant_parser.h" + +#include + +#include "SpineEventData.h" + +class SpineEvent : public Reference{ + GDCLASS(SpineEvent, Reference); + +protected: + static void _bind_methods(); +private: + spine::Event *event; +public: + SpineEvent(); + ~SpineEvent(); + + inline void set_spine_object(spine::Event *e){ + event = e; + } + inline spine::Event *get_spine_object() const{ + return event; + } + + enum EventType{ + EVENTTYPE_START = spine::EventType_Start, + EVENTTYPE_INTERRUPT = spine::EventType_Interrupt, + EVENTTYPE_END = spine::EventType_End, + EVENTTYPE_COMPLETE = spine::EventType_Complete, + EVENTTYPE_DISPOSE = spine::EventType_Dispose, + EVENTTYPE_EVENT = spine::EventType_Event + }; + + + Ref get_data(); + + String get_event_name(); + + float get_time(); + + int get_int_value(); + void set_int_value(int inValue); + + float get_float_value(); + void set_float_value(float inValue); + + String get_string_value(); + void set_string_value(const String &inValue); + + float get_volume(); + void set_volume(float inValue); + + float get_balance(); + void set_balance(float inValue); +}; + +#endif //GODOT_SPINEEVENT_H diff --git a/spine-godot/spine_godot/SpineEventData.cpp b/spine-godot/spine_godot/SpineEventData.cpp new file mode 100644 index 000000000..a1367ce96 --- /dev/null +++ b/spine-godot/spine_godot/SpineEventData.cpp @@ -0,0 +1,37 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineEventData.h" + +void SpineEventData::_bind_methods() { + +} + +SpineEventData::SpineEventData():event_data(NULL) {} +SpineEventData::~SpineEventData(){} diff --git a/spine-godot/spine_godot/SpineEventData.h b/spine-godot/spine_godot/SpineEventData.h new file mode 100644 index 000000000..eb6279717 --- /dev/null +++ b/spine-godot/spine_godot/SpineEventData.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 GODOT_SPINEEVENTDATA_H +#define GODOT_SPINEEVENTDATA_H + +#include "core/variant_parser.h" + +#include + +class SpineEventData : public Reference{ + GDCLASS(SpineEventData, Reference); + +protected: + static void _bind_methods(); +private: + const spine::EventData *event_data; +public: + SpineEventData(); + ~SpineEventData(); + + inline void set_spine_object(const spine::EventData *e){ + event_data = e; + } + inline const spine::EventData *get_spine_object(){ + return event_data; + } +}; + +#endif //GODOT_SPINEEVENTDATA_H diff --git a/spine-godot/spine_godot/SpineIkConstraint.cpp b/spine-godot/spine_godot/SpineIkConstraint.cpp new file mode 100644 index 000000000..2c613ee90 --- /dev/null +++ b/spine-godot/spine_godot/SpineIkConstraint.cpp @@ -0,0 +1,146 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineIkConstraint.h" +#include "SpineBone.h" + +void SpineIkConstraint::_bind_methods() { + // ClassDB::bind_method(D_METHOD("apply"), &SpineIkConstraint::apply); + ClassDB::bind_method(D_METHOD("update"), &SpineIkConstraint::update); + ClassDB::bind_method(D_METHOD("get_order"), &SpineIkConstraint::get_order); + ClassDB::bind_method(D_METHOD("get_data"), &SpineIkConstraint::get_data); + ClassDB::bind_method(D_METHOD("get_bones"), &SpineIkConstraint::get_bones); + ClassDB::bind_method(D_METHOD("get_target"), &SpineIkConstraint::get_target); + ClassDB::bind_method(D_METHOD("set_target", "v"), &SpineIkConstraint::set_target); + ClassDB::bind_method(D_METHOD("get_bend_direction"), &SpineIkConstraint::get_bend_direction); + ClassDB::bind_method(D_METHOD("set_bend_direction", "v"), &SpineIkConstraint::set_bend_direction); + ClassDB::bind_method(D_METHOD("get_compress"), &SpineIkConstraint::get_compress); + ClassDB::bind_method(D_METHOD("set_compress", "v"), &SpineIkConstraint::set_compress); + ClassDB::bind_method(D_METHOD("get_stretch"), &SpineIkConstraint::get_stretch); + ClassDB::bind_method(D_METHOD("set_stretch", "v"), &SpineIkConstraint::set_stretch); + ClassDB::bind_method(D_METHOD("get_mix"), &SpineIkConstraint::get_mix); + ClassDB::bind_method(D_METHOD("set_mix", "v"), &SpineIkConstraint::set_mix); + ClassDB::bind_method(D_METHOD("get_softness"), &SpineIkConstraint::get_softness); + ClassDB::bind_method(D_METHOD("set_softness", "v"), &SpineIkConstraint::set_softness); + ClassDB::bind_method(D_METHOD("is_active"), &SpineIkConstraint::is_active); + ClassDB::bind_method(D_METHOD("set_active", "v"), &SpineIkConstraint::set_active); +} + +SpineIkConstraint::SpineIkConstraint():ik_constraint(NULL) {} +SpineIkConstraint::~SpineIkConstraint() {} + +// void SpineIkConstraint::apply(){ +// ik_constraint->apply(); +// } + +void SpineIkConstraint::update(){ + ik_constraint->update(); +} + +int SpineIkConstraint::get_order(){ + return ik_constraint->getOrder(); +} + +Ref SpineIkConstraint::get_data(){ + auto &ikc = ik_constraint->getData(); + Ref gd_ikc(memnew(SpineIkConstraintData)); + gd_ikc->set_spine_object(&ikc); + return gd_ikc; +} + +Array SpineIkConstraint::get_bones(){ + auto &bs = ik_constraint->getBones(); + Array gd_bs; + gd_bs.resize(bs.size()); + for(size_t i=0; i(NULL); + Ref gd_b(memnew(SpineBone)); + gd_b->set_spine_object(b); + gd_bs[i] = gd_b; + } + return gd_bs; +} + +Ref SpineIkConstraint::get_target(){ + auto b = ik_constraint->getTarget(); + if(b == NULL) return NULL; + Ref gd_b(memnew(SpineBone)); + gd_b->set_spine_object(b); + return gd_b; +} +void SpineIkConstraint::set_target(Ref v){ + if(v.is_valid()){ + ik_constraint->setTarget(v->get_spine_object()); + } else{ + ik_constraint->setTarget(NULL); + } +} + +int SpineIkConstraint::get_bend_direction(){ + return ik_constraint->getBendDirection(); +} +void SpineIkConstraint::set_bend_direction(int v){ + ik_constraint->setBendDirection(v); +} + +bool SpineIkConstraint::get_compress(){ + return ik_constraint->getCompress(); +} +void SpineIkConstraint::set_compress(bool v){ + ik_constraint->setCompress(v); +} + +bool SpineIkConstraint::get_stretch(){ + return ik_constraint->getStretch(); +} +void SpineIkConstraint::set_stretch(bool v){ + ik_constraint->setStretch(v); +} + +float SpineIkConstraint::get_mix(){ + return ik_constraint->getMix(); +} +void SpineIkConstraint::set_mix(float v){ + ik_constraint->setMix(v); +} + +float SpineIkConstraint::get_softness(){ + return ik_constraint->getSoftness(); +} +void SpineIkConstraint::set_softness(float v){ + ik_constraint->setSoftness(v); +} + +bool SpineIkConstraint::is_active(){ + return ik_constraint->isActive(); +} +void SpineIkConstraint::set_active(bool v){ + ik_constraint->setActive(v); +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineIkConstraint.h b/spine-godot/spine_godot/SpineIkConstraint.h new file mode 100644 index 000000000..2be633115 --- /dev/null +++ b/spine-godot/spine_godot/SpineIkConstraint.h @@ -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. + *****************************************************************************/ + +#ifndef GODOT_SPINEIKCONSTRAINT_H +#define GODOT_SPINEIKCONSTRAINT_H + +#include "core/variant_parser.h" + +#include + +#include "SpineIkConstraintData.h" + +class SpineBone; + +class SpineIkConstraint : public Reference { + GDCLASS(SpineIkConstraint, Reference); + +protected: + static void _bind_methods(); + +private: + spine::IkConstraint *ik_constraint; + +public: + SpineIkConstraint(); + ~SpineIkConstraint(); + + inline void set_spine_object(spine::IkConstraint * ic){ + ik_constraint = ic; + } + inline spine::IkConstraint *get_spine_object(){ + return ik_constraint; + } + + // The spine-runtime-cpp 4.0 seems to not have a apply function implementation. + // void apply(); + + void update(); + + int get_order(); + + Ref get_data(); + + Array get_bones(); + + Ref get_target(); + void set_target(Ref v); + + int get_bend_direction(); + void set_bend_direction(int v); + + bool get_compress(); + void set_compress(bool v); + + bool get_stretch(); + void set_stretch(bool v); + + float get_mix(); + void set_mix(float v); + + float get_softness(); + void set_softness(float v); + + bool is_active(); + void set_active(bool v); + +}; + +#endif //GODOT_SPINEIKCONSTRAINT_H diff --git a/spine-godot/spine_godot/SpineIkConstraintData.cpp b/spine-godot/spine_godot/SpineIkConstraintData.cpp new file mode 100644 index 000000000..be9dfe080 --- /dev/null +++ b/spine-godot/spine_godot/SpineIkConstraintData.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 "SpineIkConstraintData.h" + +void SpineIkConstraintData::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_all_bone_data"), &SpineIkConstraintData::get_bones); + ClassDB::bind_method(D_METHOD("get_target"), &SpineIkConstraintData::get_target); + ClassDB::bind_method(D_METHOD("set_target", "v"), &SpineIkConstraintData::set_target); + ClassDB::bind_method(D_METHOD("get_bend_direction"), &SpineIkConstraintData::get_bend_direction); + ClassDB::bind_method(D_METHOD("set_bend_direction", "v"), &SpineIkConstraintData::set_bend_direction); + ClassDB::bind_method(D_METHOD("get_compress"), &SpineIkConstraintData::get_compress); + ClassDB::bind_method(D_METHOD("set_compress", "v"), &SpineIkConstraintData::set_compress); + ClassDB::bind_method(D_METHOD("get_stretch"), &SpineIkConstraintData::get_stretch); + ClassDB::bind_method(D_METHOD("set_stretch", "v"), &SpineIkConstraintData::set_stretch); + ClassDB::bind_method(D_METHOD("get_uniform"), &SpineIkConstraintData::get_uniform); + ClassDB::bind_method(D_METHOD("set_uniform", "v"), &SpineIkConstraintData::set_uniform); + ClassDB::bind_method(D_METHOD("get_mix"), &SpineIkConstraintData::get_mix); + ClassDB::bind_method(D_METHOD("set_mix", "v"), &SpineIkConstraintData::set_mix); + ClassDB::bind_method(D_METHOD("get_softness"), &SpineIkConstraintData::get_softness); + ClassDB::bind_method(D_METHOD("set_softness", "v"), &SpineIkConstraintData::set_softness); +} + +SpineIkConstraintData::SpineIkConstraintData() {} +SpineIkConstraintData::~SpineIkConstraintData() {} + +Array SpineIkConstraintData::get_bones(){ + auto bs = get_spine_data()->getBones(); + Array gd_bs; + gd_bs.resize(bs.size()); + for(size_t i=0; i < bs.size(); ++i){ + if(bs[i] == NULL) gd_bs[i] = Ref(NULL); + else { + Ref gd_b(memnew(SpineBoneData)); + gd_b->set_spine_object(bs[i]); + gd_bs[i] = gd_b; + } + } + return gd_bs; +} + +Ref SpineIkConstraintData::get_target(){ + auto b = get_spine_data()->getTarget(); + if(b == NULL) return NULL; + Ref gd_b(memnew(SpineBoneData)); + gd_b->set_spine_object(b); + return gd_b; +} +void SpineIkConstraintData::set_target(Ref v){ + if(v.is_valid()){ + get_spine_data()->setTarget(v->get_spine_object()); + }else{ + get_spine_data()->setTarget(NULL); + } +} + +int SpineIkConstraintData::get_bend_direction(){ + return get_spine_data()->getBendDirection(); +} +void SpineIkConstraintData::set_bend_direction(int v){ + get_spine_data()->setBendDirection(v); +} + +bool SpineIkConstraintData::get_compress(){ + return get_spine_data()->getCompress(); +} +void SpineIkConstraintData::set_compress(bool v){ + get_spine_data()->setCompress(v); +} + +bool SpineIkConstraintData::get_stretch(){ + return get_spine_data()->getStretch(); +} +void SpineIkConstraintData::set_stretch(bool v){ + get_spine_data()->setStretch(v); +} + +bool SpineIkConstraintData::get_uniform(){ + return get_spine_data()->getUniform(); +} +void SpineIkConstraintData::set_uniform(bool v){ + get_spine_data()->setUniform(v); +} + +float SpineIkConstraintData::get_mix(){ + return get_spine_data()->getMix(); +} +void SpineIkConstraintData::set_mix(float v){ + get_spine_data()->setMix(v); +} + +float SpineIkConstraintData::get_softness(){ + return get_spine_data()->getSoftness(); +} +void SpineIkConstraintData::set_softness(float v){ + get_spine_data()->setSoftness(v); +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineIkConstraintData.h b/spine-godot/spine_godot/SpineIkConstraintData.h new file mode 100644 index 000000000..97ecac686 --- /dev/null +++ b/spine-godot/spine_godot/SpineIkConstraintData.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 GODOT_SPINEIKCONSTRAINTDATA_H +#define GODOT_SPINEIKCONSTRAINTDATA_H + +#include "core/variant_parser.h" + +#include + +#include "SpineConstraintData.h" +#include "SpineBoneData.h" + +class SpineIkConstraintData : public SpineConstraintData { + GDCLASS(SpineIkConstraintData, SpineConstraintData); + +protected: + static void _bind_methods(); + +public: + SpineIkConstraintData(); + ~SpineIkConstraintData(); + + virtual inline spine::IkConstraintData *get_spine_data(){ + return (spine::IkConstraintData*) SpineConstraintData::get_spine_object(); + } + + Array get_bones(); + + Ref get_target(); + void set_target(Ref v); + + int get_bend_direction(); + void set_bend_direction(int v); + + bool get_compress(); + void set_compress(bool v); + + bool get_stretch(); + void set_stretch(bool v); + + bool get_uniform(); + void set_uniform(bool v); + + float get_mix(); + void set_mix(float v); + + float get_softness(); + void set_softness(float v); + +}; + +#endif //GODOT_SPINEIKCONSTRAINTDATA_H diff --git a/spine-godot/spine_godot/SpinePathConstraint.cpp b/spine-godot/spine_godot/SpinePathConstraint.cpp new file mode 100644 index 000000000..4db07fb45 --- /dev/null +++ b/spine-godot/spine_godot/SpinePathConstraint.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. + *****************************************************************************/ + +#include "SpinePathConstraint.h" + +void SpinePathConstraint::_bind_methods(){ + // ClassDB::bind_method(D_METHOD("apply"), &SpinePathConstraint::apply); + ClassDB::bind_method(D_METHOD("update"), &SpinePathConstraint::update); + ClassDB::bind_method(D_METHOD("get_order"), &SpinePathConstraint::get_order); + ClassDB::bind_method(D_METHOD("get_position"), &SpinePathConstraint::get_position); + ClassDB::bind_method(D_METHOD("set_position", "v"), &SpinePathConstraint::set_position); + ClassDB::bind_method(D_METHOD("get_spacing"), &SpinePathConstraint::get_spacing); + ClassDB::bind_method(D_METHOD("set_spacing", "v"), &SpinePathConstraint::set_spacing); + ClassDB::bind_method(D_METHOD("get_mix_rotate"), &SpinePathConstraint::get_mix_rotate); + ClassDB::bind_method(D_METHOD("set_mix_rotate", "v"), &SpinePathConstraint::set_mix_rotate); + ClassDB::bind_method(D_METHOD("get_mix_x"), &SpinePathConstraint::get_mix_x); + ClassDB::bind_method(D_METHOD("set_mix_x", "v"), &SpinePathConstraint::set_mix_x); + ClassDB::bind_method(D_METHOD("get_mix_y"), &SpinePathConstraint::get_mix_y); + ClassDB::bind_method(D_METHOD("set_mix_y", "v"), &SpinePathConstraint::set_mix_y); + ClassDB::bind_method(D_METHOD("get_bones"), &SpinePathConstraint::get_bones); + ClassDB::bind_method(D_METHOD("get_target"), &SpinePathConstraint::get_target); + ClassDB::bind_method(D_METHOD("set_target", "v"), &SpinePathConstraint::set_target); + ClassDB::bind_method(D_METHOD("get_data"), &SpinePathConstraint::get_data); + ClassDB::bind_method(D_METHOD("is_active"), &SpinePathConstraint::is_active); + ClassDB::bind_method(D_METHOD("set_active", "v"), &SpinePathConstraint::set_active); +} + +SpinePathConstraint::SpinePathConstraint():path_constraint(NULL) {} +SpinePathConstraint::~SpinePathConstraint() {} + +// void SpinePathConstraint::apply(){ +// path_constraint->apply(); +// } + +void SpinePathConstraint::update(){ + path_constraint->update(); +} + +int SpinePathConstraint::get_order(){ + return path_constraint->getOrder(); +} + +float SpinePathConstraint::get_position(){ + return path_constraint->getPosition(); +} +void SpinePathConstraint::set_position(float v){ + path_constraint->setPosition(v); +} + +float SpinePathConstraint::get_spacing(){ + return path_constraint->getSpacing(); +} +void SpinePathConstraint::set_spacing(float v){ + path_constraint->setSpacing(v); +} + +float SpinePathConstraint::get_mix_rotate(){ + return path_constraint->getMixRotate(); +} +void SpinePathConstraint::set_mix_rotate(float v){ + path_constraint->setMixRotate(v); +} + +float SpinePathConstraint::get_mix_x(){ + return path_constraint->getMixX(); +} +void SpinePathConstraint::set_mix_x(float v){ + path_constraint->setMixX(v); +} + +float SpinePathConstraint::get_mix_y(){ + return path_constraint->getMixY(); +} +void SpinePathConstraint::set_mix_y(float v){ + path_constraint->setMixY(v); +} + +Array SpinePathConstraint::get_bones(){ + auto &bs = path_constraint->getBones(); + Array gd_bs; + gd_bs.resize(bs.size()); + for(size_t i=0; i(NULL); + Ref gd_b(memnew(SpineBone)); + gd_b->set_spine_object(b); + gd_bs[i] = gd_b; + } + return gd_bs; +} + +Ref SpinePathConstraint::get_target(){ + auto s = path_constraint->getTarget(); + if(s == NULL) return NULL; + Ref gd_s(memnew(SpineSlot)); + gd_s->set_spine_object(s); + return gd_s; +} +void SpinePathConstraint::set_target(Ref v){ + if(v.is_valid()){ + path_constraint->setTarget(v->get_spine_object()); + }else{ + path_constraint->setTarget(NULL); + } +} + +Ref SpinePathConstraint::get_data(){ + auto &sd = path_constraint->getData(); + Ref gd_sd(memnew(SpinePathConstraintData)); + gd_sd->set_spine_object(&sd); + return gd_sd; +} + +bool SpinePathConstraint::is_active(){ + return path_constraint->isActive(); +} +void SpinePathConstraint::set_active(bool v){ + path_constraint->setActive(v); +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpinePathConstraint.h b/spine-godot/spine_godot/SpinePathConstraint.h new file mode 100644 index 000000000..8ab822f12 --- /dev/null +++ b/spine-godot/spine_godot/SpinePathConstraint.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 GODOT_SPINEPATHCONSTRAINT_H +#define GODOT_SPINEPATHCONSTRAINT_H + +#include "core/variant_parser.h" + +#include + +#include "SpineBone.h" +#include "SpineSlot.h" +#include "SpinePathConstraintData.h" + +class SpinePathConstraint : public Reference{ + GDCLASS(SpinePathConstraint, Reference); + +protected: + static void _bind_methods(); + +private: + spine::PathConstraint *path_constraint; + +public: + SpinePathConstraint(); + ~SpinePathConstraint(); + + inline void set_spine_object(spine::PathConstraint *pc){ + path_constraint = pc; + } + inline spine::PathConstraint *get_spine_object(){ + return path_constraint; + } + + // The spine-runtime-cpp 4.0 seems to not have a apply function implementation. + // void apply(); + + void update(); + + int get_order(); + + float get_position(); + void set_position(float v); + + float get_spacing(); + void set_spacing(float v); + + float get_mix_rotate(); + void set_mix_rotate(float v); + + float get_mix_x(); + void set_mix_x(float v); + + float get_mix_y(); + void set_mix_y(float v); + + Array get_bones(); + + Ref get_target(); + void set_target(Ref v); + + Ref get_data(); + + bool is_active(); + void set_active(bool v); +}; + +#endif //GODOT_SPINEPATHCONSTRAINT_H diff --git a/spine-godot/spine_godot/SpinePathConstraintData.cpp b/spine-godot/spine_godot/SpinePathConstraintData.cpp new file mode 100644 index 000000000..24541eeed --- /dev/null +++ b/spine-godot/spine_godot/SpinePathConstraintData.cpp @@ -0,0 +1,168 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpinePathConstraintData.h" + + +void SpinePathConstraintData::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_all_bone_data"), &SpinePathConstraintData::get_bones); + ClassDB::bind_method(D_METHOD("get_target"), &SpinePathConstraintData::get_target); + ClassDB::bind_method(D_METHOD("set_target", "V"), &SpinePathConstraintData::set_target); + ClassDB::bind_method(D_METHOD("get_position_mode"), &SpinePathConstraintData::get_position_mode); + ClassDB::bind_method(D_METHOD("set_position_mode", "V"), &SpinePathConstraintData::set_position_mode); + ClassDB::bind_method(D_METHOD("get_spacing_mode"), &SpinePathConstraintData::get_spacing_mode); + ClassDB::bind_method(D_METHOD("set_spacing_mode", "V"), &SpinePathConstraintData::set_spacing_mode); + ClassDB::bind_method(D_METHOD("get_rotate_mode"), &SpinePathConstraintData::get_rotate_mode); + ClassDB::bind_method(D_METHOD("set_rotate_mode", "V"), &SpinePathConstraintData::set_rotate_mode); + ClassDB::bind_method(D_METHOD("get_offset_rotation"), &SpinePathConstraintData::get_offset_rotation); + ClassDB::bind_method(D_METHOD("set_offset_rotation", "V"), &SpinePathConstraintData::set_offset_rotation); + ClassDB::bind_method(D_METHOD("get_position"), &SpinePathConstraintData::get_position); + ClassDB::bind_method(D_METHOD("set_position", "V"), &SpinePathConstraintData::set_position); + ClassDB::bind_method(D_METHOD("get_spacing"), &SpinePathConstraintData::get_spacing); + ClassDB::bind_method(D_METHOD("set_spacing", "V"), &SpinePathConstraintData::set_spacing); + ClassDB::bind_method(D_METHOD("get_mix_rotate"), &SpinePathConstraintData::get_mix_rotate); + ClassDB::bind_method(D_METHOD("set_mix_rotate", "V"), &SpinePathConstraintData::set_mix_rotate); + ClassDB::bind_method(D_METHOD("get_mix_x"), &SpinePathConstraintData::get_mix_x); + ClassDB::bind_method(D_METHOD("set_mix_x", "V"), &SpinePathConstraintData::set_mix_x); + ClassDB::bind_method(D_METHOD("get_mix_y"), &SpinePathConstraintData::get_mix_y); + ClassDB::bind_method(D_METHOD("set_mix_y", "V"), &SpinePathConstraintData::set_mix_y); + + BIND_ENUM_CONSTANT(POSITIONMODE_FIXED); + BIND_ENUM_CONSTANT(POSITIONMODE_PERCENT); + + BIND_ENUM_CONSTANT(SPACINGMODE_LENGTH); + BIND_ENUM_CONSTANT(SPACINGMODE_FIXED); + BIND_ENUM_CONSTANT(SPACINGMODE_PERCENT); + + BIND_ENUM_CONSTANT(ROTATEMODE_TANGENT); + BIND_ENUM_CONSTANT(ROTATEMODE_CHAIN); + BIND_ENUM_CONSTANT(ROTATEMODE_CHAINSCALE); +} + +SpinePathConstraintData::SpinePathConstraintData() {} +SpinePathConstraintData::~SpinePathConstraintData() {} + +Array SpinePathConstraintData::get_bones(){ + auto bs = get_spine_data()->getBones(); + Array gd_bs; + gd_bs.resize(bs.size()); + for(size_t i=0; i < bs.size(); ++i){ + if(bs[i] == NULL) gd_bs[i] = Ref(NULL); + else { + Ref gd_b(memnew(SpineBoneData)); + gd_b->set_spine_object(bs[i]); + gd_bs[i] = gd_b; + } + } + return gd_bs; +} + +Ref SpinePathConstraintData::get_target(){ + auto s = get_spine_data()->getTarget(); + if(s == NULL) return NULL; + Ref gd_s(memnew(SpineSlotData)); + gd_s->set_spine_object(s); + return gd_s; +} +void SpinePathConstraintData::set_target(Ref v){ + if(v.is_valid()){ + get_spine_data()->setTarget(v->get_spine_object()); + }else{ + get_spine_data()->setTarget(NULL); + } +} + +SpinePathConstraintData::PositionMode SpinePathConstraintData::get_position_mode(){ + auto m = (int) get_spine_data()->getPositionMode(); + return (PositionMode) m; +} +void SpinePathConstraintData::set_position_mode(PositionMode v){ + auto m = (int) v; + get_spine_data()->setPositionMode((spine::PositionMode)m); +} + +SpinePathConstraintData::SpacingMode SpinePathConstraintData::get_spacing_mode(){ + auto m = (int) get_spine_data()->getSpacingMode(); + return (SpacingMode) m; +} +void SpinePathConstraintData::set_spacing_mode(SpacingMode v){ + auto m = (int) v; + get_spine_data()->setSpacingMode((spine::SpacingMode)m); +} + +SpinePathConstraintData::RotateMode SpinePathConstraintData::get_rotate_mode(){ + auto m = (int) get_spine_data()->getRotateMode(); + return (RotateMode) m; +} +void SpinePathConstraintData::set_rotate_mode(RotateMode v){ + auto m = (int) v; + get_spine_data()->setRotateMode((spine::RotateMode)m); +} + +float SpinePathConstraintData::get_offset_rotation(){ + return get_spine_data()->getOffsetRotation(); +} +void SpinePathConstraintData::set_offset_rotation(float v){ + get_spine_data()->setOffsetRotation(v); +} + +float SpinePathConstraintData::get_position(){ + return get_spine_data()->getPosition(); +} +void SpinePathConstraintData::set_position(float v){ + get_spine_data()->setPosition(v); +} + +float SpinePathConstraintData::get_spacing(){ + return get_spine_data()->getSpacing(); +} +void SpinePathConstraintData::set_spacing(float v){ + get_spine_data()->setSpacing(v); +} + +float SpinePathConstraintData::get_mix_rotate(){ + return get_spine_data()->getMixRotate(); +} +void SpinePathConstraintData::set_mix_rotate(float v){ + get_spine_data()->setMixRotate(v); +} + +float SpinePathConstraintData::get_mix_x(){ + return get_spine_data()->getMixX(); +} +void SpinePathConstraintData::set_mix_x(float v){ + get_spine_data()->setMixX(v); +} + +float SpinePathConstraintData::get_mix_y(){ + return get_spine_data()->getMixY(); +} +void SpinePathConstraintData::set_mix_y(float v){ + get_spine_data()->setMixY(v); +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpinePathConstraintData.h b/spine-godot/spine_godot/SpinePathConstraintData.h new file mode 100644 index 000000000..1152998a4 --- /dev/null +++ b/spine-godot/spine_godot/SpinePathConstraintData.h @@ -0,0 +1,108 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef GODOT_SPINEPATHCONSTRAINTDATA_H +#define GODOT_SPINEPATHCONSTRAINTDATA_H + +#include "core/variant_parser.h" + +#include + +#include "SpineConstraintData.h" +#include "SpineBoneData.h" +#include "SpineSlotData.h" + +class SpinePathConstraintData : public SpineConstraintData { + GDCLASS(SpinePathConstraintData, SpineConstraintData); + +protected: + static void _bind_methods(); + +public: + SpinePathConstraintData(); + ~SpinePathConstraintData(); + + virtual inline spine::PathConstraintData *get_spine_data(){ + return (spine::PathConstraintData*) SpineConstraintData::get_spine_object(); + } + + enum PositionMode { + POSITIONMODE_FIXED = 0, + POSITIONMODE_PERCENT + }; + + enum SpacingMode { + SPACINGMODE_LENGTH = 0, + SPACINGMODE_FIXED, + SPACINGMODE_PERCENT + }; + + enum RotateMode { + ROTATEMODE_TANGENT = 0, + ROTATEMODE_CHAIN, + ROTATEMODE_CHAINSCALE + }; + + Array get_bones(); + + Ref get_target(); + void set_target(Ref v); + + PositionMode get_position_mode(); + void set_position_mode(PositionMode v); + + SpacingMode get_spacing_mode(); + void set_spacing_mode(SpacingMode v); + + RotateMode get_rotate_mode(); + void set_rotate_mode(RotateMode v); + + float get_offset_rotation(); + void set_offset_rotation(float v); + + float get_position(); + void set_position(float v); + + float get_spacing(); + void set_spacing(float v); + + float get_mix_rotate(); + void set_mix_rotate(float v); + + float get_mix_x(); + void set_mix_x(float v); + + float get_mix_y(); + void set_mix_y(float v); +}; + +VARIANT_ENUM_CAST(SpinePathConstraintData::PositionMode); +VARIANT_ENUM_CAST(SpinePathConstraintData::SpacingMode); +VARIANT_ENUM_CAST(SpinePathConstraintData::RotateMode); +#endif //GODOT_SPINEPATHCONSTRAINTDATA_H diff --git a/spine-godot/spine_godot/SpineRendererObject.h b/spine-godot/spine_godot/SpineRendererObject.h new file mode 100644 index 000000000..e8cb3b333 --- /dev/null +++ b/spine-godot/spine_godot/SpineRendererObject.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 GODOT_SPINERENDEREROBJECT_H +#define GODOT_SPINERENDEREROBJECT_H + +#include + + +struct SpineRendererObject { + Ref tex; + Ref normal_tex; +}; + + +#endif diff --git a/spine-godot/spine_godot/SpineRuntimeEditorPlugin.cpp b/spine-godot/spine_godot/SpineRuntimeEditorPlugin.cpp new file mode 100644 index 000000000..773e199c7 --- /dev/null +++ b/spine-godot/spine_godot/SpineRuntimeEditorPlugin.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 TOOLS_ENABLED +#include "SpineRuntimeEditorPlugin.h" + +#include "SpineAtlasResource.h" +#include "SpineSkeletonJsonDataResource.h" +#include "SpineSpriteAnimateDialog.h" + +#include "SpineSprite.h" + +Error SpineAtlasResourceImportPlugin::import(const String &p_source_file, const String &p_save_path, const Map &p_options, List *r_platform_variants, List *r_gen_files, Variant *r_metadata){ + Ref res(memnew(SpineAtlasResource)); + res->set_normal_texture_prefix(p_options["normal_texture_prefix"]); + res->load_from_atlas_file(p_source_file); + + String file_name = vformat("%s.%s", p_save_path, get_save_extension()); + auto err = ResourceSaver::save(file_name, res); + return err; +} + +void SpineAtlasResourceImportPlugin::get_import_options(List *r_options, int p_preset) const { + if (p_preset == 0) { + ImportOption op; + op.option.name = "normal_texture_prefix"; + op.option.type = Variant::STRING; + op.option.hint_string = "String"; + op.default_value = String("n"); + r_options->push_back(op); + } +} + +Error SpineJsonResourceImportPlugin::import(const String &p_source_file, const String &p_save_path, const Map &p_options, List *r_platform_variants, List *r_gen_files, Variant *r_metadata){ + Ref res(memnew(SpineSkeletonJsonDataResource)); + res->load_from_file(p_source_file); + + String file_name = vformat("%s.%s", p_save_path, get_save_extension()); + auto err = ResourceSaver::save(file_name, res); + return err; +} + +//=======================| SpineRuntimeEditorPlugin |============================ +SpineRuntimeEditorPlugin::SpineRuntimeEditorPlugin(EditorNode *p_node) { + add_import_plugin(memnew(SpineAtlasResourceImportPlugin)); + add_import_plugin(memnew(SpineJsonResourceImportPlugin)); + + auto animate_button = memnew(ToolButton); + animate_button->set_text("Animate"); + add_control_to_container(CONTAINER_CANVAS_EDITOR_MENU, animate_button); + + animate_dialog = memnew(SpineSpriteAnimateDialog); + get_editor_interface()->get_base_control()->add_child(animate_dialog); + animate_dialog->set_animate_button(animate_button); + animate_dialog->set_plugin(this); +} + +SpineRuntimeEditorPlugin::~SpineRuntimeEditorPlugin() { + +} + +bool SpineRuntimeEditorPlugin::handles(Object *p_object) const { + return p_object->is_class("SpineSprite"); +} + +void SpineRuntimeEditorPlugin::make_visible(bool p_visible) { + if (get_editor_interface()->get_selection()->get_selected_node_list().size() != 1) { + p_visible = false; + } + animate_dialog->get_animate_button()->set_visible(p_visible); +} + + +#endif \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineRuntimeEditorPlugin.h b/spine-godot/spine_godot/SpineRuntimeEditorPlugin.h new file mode 100644 index 000000000..e5233a00c --- /dev/null +++ b/spine-godot/spine_godot/SpineRuntimeEditorPlugin.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 GODOT_SPINERUNTIMEEDITORPLUGIN_H +#define GODOT_SPINERUNTIMEEDITORPLUGIN_H + +#ifdef TOOLS_ENABLED +#include "editor/editor_node.h" + +class SpineAtlasResourceImportPlugin : public EditorImportPlugin { + GDCLASS(SpineAtlasResourceImportPlugin, EditorImportPlugin); + +public: + String get_importer_name() const override {return "spine.atlas";} + String get_visible_name() const override {return "Spine Runtime Atlas";} + void get_recognized_extensions(List *p_extensions) const override {p_extensions->push_back("atlas");} + String get_preset_name(int p_idx) const override {if (p_idx == 0) return "Default"; else return "Unknown";} + int get_preset_count() const override {return 1;} + String get_save_extension() const override {return "spatlas";} + String get_resource_type() const override {return "SpineAtlasResource";} + void get_import_options(List *r_options, int p_preset) const override; + bool get_option_visibility(const String &p_option, const Map &p_options) const override {return true;} + Error import(const String &p_source_file, const String &p_save_path, const Map &p_options, List *r_platform_variants, List *r_gen_files, Variant *r_metadata) override; +}; + +class SpineJsonResourceImportPlugin : public EditorImportPlugin { +GDCLASS(SpineJsonResourceImportPlugin, EditorImportPlugin); + +public: + String get_importer_name() const override {return "spine.json";} + String get_visible_name() const override {return "Spine Runtime Json";} + void get_recognized_extensions(List *p_extensions) const override {p_extensions->push_back("json");} + String get_preset_name(int p_idx) const override {if (p_idx == 0) return "Default"; else return "Unknown";} + int get_preset_count() const override {return 1;} + String get_save_extension() const override {return "spjson";} + String get_resource_type() const override {return "SpineSkeletonJsonDataResource";} + void get_import_options(List *r_options, int p_preset) const override {} + bool get_option_visibility(const String &p_option, const Map &p_options) const override {return true;} + Error import(const String &p_source_file, const String &p_save_path, const Map &p_options, List *r_platform_variants, List *r_gen_files, Variant *r_metadata) override; +}; + +class SpineSpriteAnimateDialog; + +class SpineRuntimeEditorPlugin : public EditorPlugin { + GDCLASS(SpineRuntimeEditorPlugin, EditorPlugin); + +protected: + SpineSpriteAnimateDialog *animate_dialog; +public: + SpineRuntimeEditorPlugin(EditorNode *p_node); + ~SpineRuntimeEditorPlugin(); + + String get_name() const override { return "SpineRuntimeEditorPlugin"; } + bool has_main_screen() const { return false; } + + bool handles(Object *p_object) const override; + void make_visible(bool p_visible) override; + + void _on_animate_button_pressed(); +}; +#endif + +#endif //GODOT_SPINERUNTIMEEDITORPLUGIN_H diff --git a/spine-godot/spine_godot/SpineSkeleton.cpp b/spine-godot/spine_godot/SpineSkeleton.cpp new file mode 100644 index 000000000..c8d207ea1 --- /dev/null +++ b/spine-godot/spine_godot/SpineSkeleton.cpp @@ -0,0 +1,430 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineSkeleton.h" + +void SpineSkeleton::_bind_methods() { +//void update_world_transform(); +// +// void set_to_setup_pose(); +// +// void set_bones_to_setup_pose(); +// +// void set_slots_to_setup_pose(); + ClassDB::bind_method(D_METHOD("update_world_transform"), &SpineSkeleton::update_world_transform); + ClassDB::bind_method(D_METHOD("set_to_setup_pose"), &SpineSkeleton::set_to_setup_pose); + ClassDB::bind_method(D_METHOD("set_bones_to_setup_pose"), &SpineSkeleton::set_bones_to_setup_pose); + ClassDB::bind_method(D_METHOD("set_slots_to_setup_pose"), &SpineSkeleton::set_slots_to_setup_pose); +// +// Ref find_bone(const String &name); +// int find_bone_index(const String &name); +// +// Ref find_slot(const String &name); +// int find_slot_index(const String &name); +// +// void set_skin_by_name(const String &skin_name); +// void set_skin(Ref new_skin); +// +// Ref get_attachment_by_slot_name(const String &slot_name, const String &attachment_name); +// Ref get_attachment_by_slot_index(int slot_index, const String &attachment_name); + ClassDB::bind_method(D_METHOD("find_bone", "bone_name"), &SpineSkeleton::find_bone); + ClassDB::bind_method(D_METHOD("find_slot", "slot_name"), &SpineSkeleton::find_slot); + ClassDB::bind_method(D_METHOD("set_skin_by_name", "skin_name"), &SpineSkeleton::set_skin_by_name); + ClassDB::bind_method(D_METHOD("set_skin", "new_skin"), &SpineSkeleton::set_skin); + ClassDB::bind_method(D_METHOD("get_attachment_by_slot_name", "slot_name", "attachment_name"), &SpineSkeleton::get_attachment_by_slot_name); + ClassDB::bind_method(D_METHOD("get_attachment_by_slot_index", "slot_index", "attachment_name"), &SpineSkeleton::get_attachment_by_slot_index); +// +// void set_attachment(const String &slot_name, const String &attachment_name); +// +// Ref find_ik_constraint(const String &constraint_name); +// Ref find_transform_constraint(const String &constraint_name); +// Ref find_path_constraint(const String &constraint_name); +// +// void update(float delta); +// +// Dictionary get_bounds(); +// +// Ref get_root_bone(); +// +// Ref get_data(); + ClassDB::bind_method(D_METHOD("set_attachment", "slot_name", "attachment_name"), &SpineSkeleton::set_attachment); + ClassDB::bind_method(D_METHOD("find_ik_constraint", "constraint_name"), &SpineSkeleton::find_ik_constraint); + ClassDB::bind_method(D_METHOD("find_transform_constraint", "constraint_name"), &SpineSkeleton::find_transform_constraint); + ClassDB::bind_method(D_METHOD("find_path_constraint", "constraint_name"), &SpineSkeleton::find_path_constraint); + ClassDB::bind_method(D_METHOD("update", "delta"), &SpineSkeleton::update); + ClassDB::bind_method(D_METHOD("get_bounds"), &SpineSkeleton::get_bounds); + ClassDB::bind_method(D_METHOD("get_root_bone"), &SpineSkeleton::get_root_bone); + ClassDB::bind_method(D_METHOD("get_data"), &SpineSkeleton::get_data); +// +// Array get_bones(); +// Array get_slots(); +// Array get_draw_orders(); +// Array get_ik_constraints(); +// Array get_path_constraints(); +// Array get_transform_constraints(); +// +// Ref get_skin(); + ClassDB::bind_method(D_METHOD("get_bones"), &SpineSkeleton::get_bones); + ClassDB::bind_method(D_METHOD("get_slots"), &SpineSkeleton::get_slots); + ClassDB::bind_method(D_METHOD("get_draw_orders"), &SpineSkeleton::get_draw_orders); + ClassDB::bind_method(D_METHOD("get_ik_constraints"), &SpineSkeleton::get_ik_constraints); + ClassDB::bind_method(D_METHOD("get_path_constraints"), &SpineSkeleton::get_path_constraints); + ClassDB::bind_method(D_METHOD("get_transform_constraints"), &SpineSkeleton::get_transform_constraints); + ClassDB::bind_method(D_METHOD("get_skin"), &SpineSkeleton::get_skin); +// +// Color get_color(); +// void set_color(Color v); +// +// float get_time(); +// void set_time(float v); +// +// void set_position(Vector2 pos); + ClassDB::bind_method(D_METHOD("get_color"), &SpineSkeleton::get_color); + ClassDB::bind_method(D_METHOD("set_color", "v"), &SpineSkeleton::set_color); + ClassDB::bind_method(D_METHOD("get_time"), &SpineSkeleton::get_time); + ClassDB::bind_method(D_METHOD("set_time", "v"), &SpineSkeleton::set_time); + ClassDB::bind_method(D_METHOD("set_position", "pos"), &SpineSkeleton::set_position); +// +// float get_x(); +// void set_x(float v); +// +// float get_y(); +// void set_y(float v); +// +// float get_scale_x(); +// void set_scale_x(float v); +// +// float get_scale_y(); +// void set_scale_y(float v); + ClassDB::bind_method(D_METHOD("get_x"), &SpineSkeleton::get_x); + ClassDB::bind_method(D_METHOD("set_x", "v"), &SpineSkeleton::set_x); + ClassDB::bind_method(D_METHOD("get_y"), &SpineSkeleton::get_y); + ClassDB::bind_method(D_METHOD("set_y", "v"), &SpineSkeleton::set_y); + ClassDB::bind_method(D_METHOD("get_scale_x"), &SpineSkeleton::get_scale_x); + ClassDB::bind_method(D_METHOD("set_scale_x", "v"), &SpineSkeleton::set_scale_x); + ClassDB::bind_method(D_METHOD("get_scale_y"), &SpineSkeleton::get_scale_y); + ClassDB::bind_method(D_METHOD("set_scale_y", "v"), &SpineSkeleton::set_scale_y); +} + +SpineSkeleton::SpineSkeleton():skeleton(NULL),spine_object(false),the_sprite(nullptr) { + +} + +SpineSkeleton::~SpineSkeleton() { + if(skeleton && !spine_object) + { + delete skeleton; + skeleton = NULL; + } +} + +void SpineSkeleton::load_skeleton(Ref sd) { + if(skeleton && !spine_object) + { + delete skeleton; + skeleton = NULL; + } + skeleton = new spine::Skeleton(sd->get_skeleton_data()); + spine_object = false; +} + +#define S_T(x) (spine::String(x.utf8())) +void SpineSkeleton::update_world_transform(){ + skeleton->updateWorldTransform(); +} + +void SpineSkeleton::set_to_setup_pose(){ + skeleton->setToSetupPose(); +} + +void SpineSkeleton::set_bones_to_setup_pose(){ + skeleton->setBonesToSetupPose(); +} + +void SpineSkeleton::set_slots_to_setup_pose(){ + skeleton->setSlotsToSetupPose(); +} + +Ref SpineSkeleton::find_bone(const String &name){ + if(name.empty()) return NULL; + auto b = skeleton->findBone(S_T(name)); + if(b == NULL) return NULL; + Ref gd_b(memnew(SpineBone)); + gd_b->set_spine_object(b); + gd_b->set_spine_sprite(the_sprite); + return gd_b; +} + +Ref SpineSkeleton::find_slot(const String &name){ + if(name.empty()) return NULL; + auto s = skeleton->findSlot(S_T(name)); + if(s == NULL) return NULL; + Ref gd_s(memnew(SpineSlot)); + gd_s->set_spine_object(s); + return gd_s; +} + +void SpineSkeleton::set_skin_by_name(const String &skin_name){ + skeleton->setSkin(S_T(skin_name)); +} +void SpineSkeleton::set_skin(Ref new_skin){ + if(new_skin.is_valid()){ + skeleton->setSkin(new_skin->get_spine_object()); + }else{ + skeleton->setSkin(NULL); + } +} + +Ref SpineSkeleton::get_attachment_by_slot_name(const String &slot_name, const String &attachment_name){ + auto a = skeleton->getAttachment(S_T(slot_name), S_T(attachment_name)); + if(a == NULL) return NULL; + Ref gd_a(memnew(SpineAttachment)); + gd_a->set_spine_object(a); + return gd_a; +} +Ref SpineSkeleton::get_attachment_by_slot_index(int slot_index, const String &attachment_name){ + auto a = skeleton->getAttachment(slot_index, S_T(attachment_name)); + if(a == NULL) return NULL; + Ref gd_a(memnew(SpineAttachment)); + gd_a->set_spine_object(a); + return gd_a; +} + +void SpineSkeleton::set_attachment(const String &slot_name, const String &attachment_name){ + ERR_FAIL_COND(slot_name.empty()); + ERR_FAIL_COND(get_attachment_by_slot_name(slot_name, attachment_name) == NULL); + skeleton->setAttachment(S_T(slot_name), S_T(attachment_name)); +} + +Ref SpineSkeleton::find_ik_constraint(const String &constraint_name){ + if(constraint_name.empty()) return NULL; + auto c = skeleton->findIkConstraint(S_T(constraint_name)); + if(c == NULL) return NULL; + Ref gd_c(memnew(SpineIkConstraint)); + gd_c->set_spine_object(c); + return gd_c; +} +Ref SpineSkeleton::find_transform_constraint(const String &constraint_name){ + if(constraint_name.empty()) return NULL; + auto c = skeleton->findTransformConstraint(S_T(constraint_name)); + if(c == NULL) return NULL; + Ref gd_c(memnew(SpineTransformConstraint)); + gd_c->set_spine_object(c); + return gd_c; +} +Ref SpineSkeleton::find_path_constraint(const String &constraint_name){ + if(constraint_name.empty()) return NULL; + auto c = skeleton->findPathConstraint(S_T(constraint_name)); + if(c == NULL) return NULL; + Ref gd_c(memnew(SpinePathConstraint)); + gd_c->set_spine_object(c); + return gd_c; +} + +void SpineSkeleton::update(float delta){ + skeleton->update(delta); +} + +Dictionary SpineSkeleton::get_bounds(){ + float x, y, w, h; + spine::Vector vertex_buffer; + skeleton->getBounds(x, y, w, h, vertex_buffer); + + Dictionary res; + res["x"] = x; + res["y"] = y; + res["w"] = w; + res["h"] = h; + + Array gd_a; + gd_a.resize(vertex_buffer.size()); + for(size_t i=0; i SpineSkeleton::get_root_bone(){ + auto b = skeleton->getRootBone(); + if(b == NULL) return NULL; + Ref gd_b(memnew(SpineBone)); + gd_b->set_spine_object(b); + gd_b->set_spine_sprite(the_sprite); + return gd_b; +} + +Ref SpineSkeleton::get_data() const { + auto sd = skeleton->getData(); + if(sd == NULL) return NULL; + Ref gd_sd(memnew(SpineSkeletonDataResource)); + gd_sd->set_spine_object(sd); + return gd_sd; +} + +Array SpineSkeleton::get_bones(){ + auto &as = skeleton->getBones(); + Array gd_as; + gd_as.resize(as.size()); + for(size_t i=0; i(NULL); + Ref gd_a(memnew(SpineBone)); + gd_a->set_spine_object(b); + gd_a->set_spine_sprite(the_sprite); + gd_as[i] = gd_a; + } + return gd_as; +} +Array SpineSkeleton::get_slots(){ + auto &as = skeleton->getSlots(); + Array gd_as; + gd_as.resize(as.size()); + for(size_t i=0; i(NULL); + Ref gd_a(memnew(SpineSlot)); + gd_a->set_spine_object(b); + gd_as[i] = gd_a; + } + return gd_as; +} +Array SpineSkeleton::get_draw_orders(){ + auto &as = skeleton->getDrawOrder(); + Array gd_as; + gd_as.resize(as.size()); + for(size_t i=0; i(NULL); + Ref gd_a(memnew(SpineSlot)); + gd_a->set_spine_object(b); + gd_as[i] = gd_a; + } + return gd_as; +} +Array SpineSkeleton::get_ik_constraints(){ + auto &as = skeleton->getIkConstraints(); + Array gd_as; + gd_as.resize(as.size()); + for(size_t i=0; i(NULL); + Ref gd_a(memnew(SpineIkConstraint)); + gd_a->set_spine_object(b); + gd_as[i] = gd_a; + } + return gd_as; +} +Array SpineSkeleton::get_path_constraints(){ + auto &as = skeleton->getPathConstraints(); + Array gd_as; + gd_as.resize(as.size()); + for(size_t i=0; i(NULL); + Ref gd_a(memnew(SpinePathConstraint)); + gd_a->set_spine_object(b); + gd_as[i] = gd_a; + } + return gd_as; +} +Array SpineSkeleton::get_transform_constraints(){ + auto &as = skeleton->getTransformConstraints(); + Array gd_as; + gd_as.resize(as.size()); + for(size_t i=0; i(NULL); + Ref gd_a(memnew(SpineTransformConstraint)); + gd_a->set_spine_object(b); + gd_as[i] = gd_a; + } + return gd_as; +} + +Ref SpineSkeleton::get_skin(){ + auto s = skeleton->getSkin(); + if(s == NULL) return NULL; + Ref gd_s(memnew(SpineSkin)); + gd_s->set_spine_object(s); + return gd_s; +} + +Color SpineSkeleton::get_color(){ + auto &c = skeleton->getColor(); + return Color(c.r, c.g, c.b, c.a); +} +void SpineSkeleton::set_color(Color v){ + auto &c = skeleton->getColor(); + c.set(v.r, v.g, v.b, v.a); +} + +float SpineSkeleton::get_time(){ + return skeleton->getTime(); +} +void SpineSkeleton::set_time(float v){ + skeleton->setTime(v); +} + +void SpineSkeleton::set_position(Vector2 pos){ + skeleton->setPosition(pos.x, pos.y); +} + +float SpineSkeleton::get_x(){ + return skeleton->getX(); +} +void SpineSkeleton::set_x(float v){ + skeleton->setX(v); +} + +float SpineSkeleton::get_y(){ + return skeleton->getY(); +} +void SpineSkeleton::set_y(float v){ + skeleton->setY(v); +} + +float SpineSkeleton::get_scale_x(){ + return skeleton->getScaleX(); +} +void SpineSkeleton::set_scale_x(float v){ + skeleton->setScaleX(v); +} + +float SpineSkeleton::get_scale_y(){ + return skeleton->getScaleY(); +} +void SpineSkeleton::set_scale_y(float v){ + skeleton->setScaleY(v); +} + +void SpineSkeleton::set_spine_sprite(SpineSprite *s) { + the_sprite = s; +} diff --git a/spine-godot/spine_godot/SpineSkeleton.h b/spine-godot/spine_godot/SpineSkeleton.h new file mode 100644 index 000000000..fa488bfa4 --- /dev/null +++ b/spine-godot/spine_godot/SpineSkeleton.h @@ -0,0 +1,135 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef GODOT_SPINESKELETON_H +#define GODOT_SPINESKELETON_H + +#include "core/variant_parser.h" + +#include + +#include "SpineSkeletonDataResource.h" +#include "SpineBone.h" +#include "SpineSlot.h" + +class SpineSprite; + +class SpineSkeleton : public Reference{ + GDCLASS(SpineSkeleton, Reference); + +protected: + static void _bind_methods(); + +private: + spine::Skeleton *skeleton; + bool spine_object; + + SpineSprite *the_sprite; +public: + + SpineSkeleton(); + ~SpineSkeleton(); + + void load_skeleton(Ref sd); + + inline void set_spine_object(spine::Skeleton *s){ + skeleton = s; + spine_object = true; + } + inline spine::Skeleton *get_spine_object(){ + return skeleton; + } + + void set_spine_sprite(SpineSprite *s); + + + void update_world_transform(); + + void set_to_setup_pose(); + + void set_bones_to_setup_pose(); + + void set_slots_to_setup_pose(); + + Ref find_bone(const String &name); + + Ref find_slot(const String &name); + + void set_skin_by_name(const String &skin_name); + void set_skin(Ref new_skin); + + Ref get_attachment_by_slot_name(const String &slot_name, const String &attachment_name); + Ref get_attachment_by_slot_index(int slot_index, const String &attachment_name); + + void set_attachment(const String &slot_name, const String &attachment_name); + + Ref find_ik_constraint(const String &constraint_name); + Ref find_transform_constraint(const String &constraint_name); + Ref find_path_constraint(const String &constraint_name); + + void update(float delta); + + Dictionary get_bounds(); + + Ref get_root_bone(); + + Ref get_data() const; + + Array get_bones(); + Array get_slots(); + Array get_draw_orders(); + Array get_ik_constraints(); + Array get_path_constraints(); + Array get_transform_constraints(); + + Ref get_skin(); + + Color get_color(); + void set_color(Color v); + + float get_time(); + void set_time(float v); + + void set_position(Vector2 pos); + + float get_x(); + void set_x(float v); + + float get_y(); + void set_y(float v); + + float get_scale_x(); + void set_scale_x(float v); + + float get_scale_y(); + void set_scale_y(float v); + +}; + +#endif //GODOT_SPINESKELETON_H diff --git a/spine-godot/spine_godot/SpineSkeletonDataResource.cpp b/spine-godot/spine_godot/SpineSkeletonDataResource.cpp new file mode 100644 index 000000000..d6f5c87a6 --- /dev/null +++ b/spine-godot/spine_godot/SpineSkeletonDataResource.cpp @@ -0,0 +1,454 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineSkeletonDataResource.h" + +void SpineSkeletonDataResource::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_atlas_res", "atlas_res"), &SpineSkeletonDataResource::set_atlas_res); + ClassDB::bind_method(D_METHOD("get_atlas_res"), &SpineSkeletonDataResource::get_atlas_res); + ClassDB::bind_method(D_METHOD("set_skeleton_json_res", "skeleton_json_res"), &SpineSkeletonDataResource::set_skeleton_json_res); + ClassDB::bind_method(D_METHOD("get_skeleton_json_res"), &SpineSkeletonDataResource::get_skeleton_json_res); + ClassDB::bind_method(D_METHOD("is_skeleton_data_loaded"), &SpineSkeletonDataResource::is_skeleton_data_loaded); + ClassDB::bind_method(D_METHOD("find_animation", "animation_name"), &SpineSkeletonDataResource::find_animation); + ClassDB::bind_method(D_METHOD("get_sk_name"), &SpineSkeletonDataResource::get_sk_name); + ClassDB::bind_method(D_METHOD("set_sk_name", "sk_name"), &SpineSkeletonDataResource::set_sk_name); + ClassDB::bind_method(D_METHOD("get_x"), &SpineSkeletonDataResource::get_x); + ClassDB::bind_method(D_METHOD("set_x", "v"), &SpineSkeletonDataResource::set_x); + ClassDB::bind_method(D_METHOD("get_y"), &SpineSkeletonDataResource::get_y); + ClassDB::bind_method(D_METHOD("set_y", "v"), &SpineSkeletonDataResource::set_y); + ClassDB::bind_method(D_METHOD("get_width"), &SpineSkeletonDataResource::get_width); + ClassDB::bind_method(D_METHOD("get_height"), &SpineSkeletonDataResource::get_height); + ClassDB::bind_method(D_METHOD("get_version"), &SpineSkeletonDataResource::get_version); + ClassDB::bind_method(D_METHOD("get_fps"), &SpineSkeletonDataResource::get_fps); + ClassDB::bind_method(D_METHOD("set_fps", "v"), &SpineSkeletonDataResource::set_fps); + + ClassDB::bind_method(D_METHOD("find_bone", "bone_name"), &SpineSkeletonDataResource::find_bone); + ClassDB::bind_method(D_METHOD("find_slot", "slot_name"), &SpineSkeletonDataResource::find_slot); + ClassDB::bind_method(D_METHOD("find_skin", "skin_name"), &SpineSkeletonDataResource::find_skin); + ClassDB::bind_method(D_METHOD("find_event", "event_data_name"), &SpineSkeletonDataResource::find_event); + ClassDB::bind_method(D_METHOD("find_ik_constraint_data", "constraint_name"), &SpineSkeletonDataResource::find_ik_constraint); + ClassDB::bind_method(D_METHOD("find_transform_constraint_data", "constraint_name"), &SpineSkeletonDataResource::find_transform_constraint); + ClassDB::bind_method(D_METHOD("find_path_constraint_data", "constraint_name"), &SpineSkeletonDataResource::find_path_constraint); + ClassDB::bind_method(D_METHOD("get_all_bone_data"), &SpineSkeletonDataResource::get_bones); + ClassDB::bind_method(D_METHOD("get_all_slot_data"), &SpineSkeletonDataResource::get_slots); + ClassDB::bind_method(D_METHOD("get_skins"), &SpineSkeletonDataResource::get_skins); + ClassDB::bind_method(D_METHOD("get_default_skin"), &SpineSkeletonDataResource::get_default_skin); + ClassDB::bind_method(D_METHOD("set_default_skin", "v"), &SpineSkeletonDataResource::set_default_skin); + ClassDB::bind_method(D_METHOD("get_all_event_data"), &SpineSkeletonDataResource::get_events); + ClassDB::bind_method(D_METHOD("get_animations"), &SpineSkeletonDataResource::get_animations); + ClassDB::bind_method(D_METHOD("get_all_ik_constraint_data"), &SpineSkeletonDataResource::get_ik_constraints); + ClassDB::bind_method(D_METHOD("get_all_transform_constraint_data"), &SpineSkeletonDataResource::get_transform_constraints); + ClassDB::bind_method(D_METHOD("get_all_path_constraint_data"), &SpineSkeletonDataResource::get_path_constraints); + + ADD_SIGNAL(MethodInfo("skeleton_data_loaded")); + ADD_SIGNAL(MethodInfo("atlas_res_changed")); + ADD_SIGNAL(MethodInfo("skeleton_json_res_changed")); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "atlas_res", PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "SpineAtlasResource"), "set_atlas_res", "get_atlas_res"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "skeleton_json_res", PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "SpineSkeletonJsonDataResource"), "set_skeleton_json_res", "get_skeleton_json_res"); +} + +SpineSkeletonDataResource::SpineSkeletonDataResource():valid(false),spine_object(false),skeleton_data(NULL) { + +} +SpineSkeletonDataResource::~SpineSkeletonDataResource() { + if(skeleton_data && !spine_object) + { + delete skeleton_data; + skeleton_data = NULL; + } +} + +bool SpineSkeletonDataResource::is_skeleton_data_loaded() const{ + return valid || spine_object; +} + +void SpineSkeletonDataResource::load_res(spine::Atlas *a, const String &json_string) { + if (json_string.empty()) return; + auto path = get_path(); + spine::SkeletonJson json(a); + auto temp_skeleton_data = json.readSkeletonData(json_string.utf8()); + if(!temp_skeleton_data) + { + print_error(String("Error happened while loading skeleton json data: ") + path); + print_error(String("Error msg: ") + json.getError().buffer()); + return; + } + if(skeleton_data) + { + delete skeleton_data; + skeleton_data = NULL; + } + skeleton_data = temp_skeleton_data; + + valid = true; +// print_line("Skeleton json data loaded!"); +} + +void SpineSkeletonDataResource::update_skeleton_data() { + if(atlas_res.is_valid() && skeleton_json_res.is_valid()) + { + load_res(atlas_res->get_spine_atlas(), skeleton_json_res->get_json_string()); + if(valid) + { + emit_signal("skeleton_data_loaded"); + } + } +} + +void SpineSkeletonDataResource::set_atlas_res(const Ref &a) { + atlas_res = a; + valid = false; +// print_line("atlas_res_changed emitted"); + emit_signal("atlas_res_changed"); + update_skeleton_data(); +} +Ref SpineSkeletonDataResource::get_atlas_res() { + if(spine_object){ + print_line("Getting atlas res from a spine_object skeleton! The result may be NULL!"); + } + return atlas_res; +} + +void SpineSkeletonDataResource::set_skeleton_json_res(const Ref &s) { + skeleton_json_res = s; + valid = false; +// print_line("skeleton_json_res_changed emitted"); + emit_signal("skeleton_json_res_changed"); + update_skeleton_data(); +} +Ref SpineSkeletonDataResource::get_skeleton_json_res() { + if(spine_object){ + print_line("Getting atlas res from a spine_object skeleton! The result may be NULL!"); + } + return skeleton_json_res; +} + +#define CHECK_V if(!is_skeleton_data_loaded()){ERR_PRINT("skeleton data has not loaded yet!");return;} +#define CHECK_X(x) if(!is_skeleton_data_loaded()){ERR_PRINT("skeleton data has not loaded yet!");return x;} +#define S_T(x) (spine::String(x.utf8())) +Ref SpineSkeletonDataResource::find_animation(const String &animation_name) { + CHECK_X(NULL); + if(animation_name.empty()){ + return NULL; + } + auto a = skeleton_data->findAnimation(S_T(animation_name)); + if(!a) return NULL; + Ref sa(memnew(SpineAnimation)); + sa->set_spine_object(a); + return sa; +} +String SpineSkeletonDataResource::get_sk_name() { + CHECK_X("error"); + return skeleton_data->getName().buffer(); +} +void SpineSkeletonDataResource::set_sk_name(const String &v) { + CHECK_V; + skeleton_data->setName(S_T(v)); +} +float SpineSkeletonDataResource::get_x() { + CHECK_X(0); + return skeleton_data->getX(); +} +void SpineSkeletonDataResource::set_x(float v) { + CHECK_V; + skeleton_data->setX(v); +} +float SpineSkeletonDataResource::get_y() { + CHECK_X(0); + return skeleton_data->getY(); +} +void SpineSkeletonDataResource::set_y(float v) { + CHECK_V; + skeleton_data->setY(v); +} +float SpineSkeletonDataResource::get_width() { + CHECK_X(0); + return skeleton_data->getWidth(); +} +float SpineSkeletonDataResource::get_height() { + CHECK_X(0); + return skeleton_data->getHeight(); +} +String SpineSkeletonDataResource::get_version() { + CHECK_X("error"); + return skeleton_data->getVersion().buffer(); +} +float SpineSkeletonDataResource::get_fps() { + CHECK_X(0); + return skeleton_data->getFps(); +} +void SpineSkeletonDataResource::set_fps(float v) { + CHECK_V; + skeleton_data->setFps(v); +} + +Ref SpineSkeletonDataResource::find_bone(const String &bone_name){ + if(bone_name.empty()) return NULL; + auto b = skeleton_data->findBone(S_T(bone_name)); + if(b == NULL) return NULL; + Ref gd_b(memnew(SpineBoneData)); + gd_b->set_spine_object(b); + return gd_b; +} + +Ref SpineSkeletonDataResource::find_slot(const String &slot_name){ + if(slot_name.empty()) return NULL; + auto b = skeleton_data->findSlot(S_T(slot_name)); + if(b == NULL) return NULL; + Ref gd_b(memnew(SpineSlotData)); + gd_b->set_spine_object(b); + return gd_b; +} + +Ref SpineSkeletonDataResource::find_skin(const String &skin_name){ + if(skin_name.empty()) return NULL; + auto b = skeleton_data->findSkin(S_T(skin_name)); + if(b == NULL) return NULL; + Ref gd_b(memnew(SpineSkin)); + gd_b->set_spine_object(b); + return gd_b; +} + +Ref SpineSkeletonDataResource::find_event(const String &event_data_name){ + if(event_data_name.empty()) return NULL; + auto b = skeleton_data->findEvent(S_T(event_data_name)); + if(b == NULL) return NULL; + Ref gd_b(memnew(SpineEventData)); + gd_b->set_spine_object(b); + return gd_b; +} + +Ref SpineSkeletonDataResource::find_ik_constraint(const String &constraint_name){ + if(constraint_name.empty()) return NULL; + auto b = skeleton_data->findIkConstraint(S_T(constraint_name)); + if(b == NULL) return NULL; + Ref gd_b(memnew(SpineIkConstraintData)); + gd_b->set_spine_object(b); + return gd_b; +} +Ref SpineSkeletonDataResource::find_transform_constraint(const String &constraint_name){ + if(constraint_name.empty()) return NULL; + auto b = skeleton_data->findTransformConstraint(S_T(constraint_name)); + if(b == NULL) return NULL; + Ref gd_b(memnew(SpineTransformConstraintData)); + gd_b->set_spine_object(b); + return gd_b; +} +Ref SpineSkeletonDataResource::find_path_constraint(const String &constraint_name){ + if(constraint_name.empty()) return NULL; + auto b = skeleton_data->findPathConstraint(S_T(constraint_name)); + if(b == NULL) return NULL; + Ref gd_b(memnew(SpinePathConstraintData)); + gd_b->set_spine_object(b); + return gd_b; +} + +Array SpineSkeletonDataResource::get_bones(){ + auto bs = skeleton_data->getBones(); + Array gd_bs; + gd_bs.resize(bs.size()); + for(size_t i=0; i < bs.size(); ++i){ + if(bs[i] == NULL) gd_bs[i] = Ref(NULL); + else { + Ref gd_b(memnew(SpineBoneData)); + gd_b->set_spine_object(bs[i]); + gd_bs[i] = gd_b; + } + } + return gd_bs; +} +Array SpineSkeletonDataResource::get_slots(){ + auto bs = skeleton_data->getSlots(); + Array gd_bs; + gd_bs.resize(bs.size()); + for(size_t i=0; i < bs.size(); ++i){ + if(bs[i] == NULL) gd_bs[i] = Ref(NULL); + else { + Ref gd_b(memnew(SpineSlotData)); + gd_b->set_spine_object(bs[i]); + gd_bs[i] = gd_b; + } + } + return gd_bs; +} +Array SpineSkeletonDataResource::get_skins() const{ + auto bs = skeleton_data->getSkins(); + Array gd_bs; + gd_bs.resize(bs.size()); + for(size_t i=0; i < bs.size(); ++i){ + if(bs[i] == NULL) gd_bs[i] = Ref(NULL); + else { + Ref gd_b(memnew(SpineSkin)); + gd_b->set_spine_object(bs[i]); + gd_bs[i] = gd_b; + } + } + return gd_bs; +} + +Ref SpineSkeletonDataResource::get_default_skin(){ + auto b = skeleton_data->getDefaultSkin(); + if(b == NULL) return NULL; + Ref gd_b(memnew(SpineSkin)); + gd_b->set_spine_object(b); + return gd_b; +} +void SpineSkeletonDataResource::set_default_skin(Ref v){ + if(v.is_valid()){ + skeleton_data->setDefaultSkin(v->get_spine_object()); + } else + skeleton_data->setDefaultSkin(NULL); +} + +Array SpineSkeletonDataResource::get_events(){ + auto bs = skeleton_data->getEvents(); + Array gd_bs; + gd_bs.resize(bs.size()); + for(size_t i=0; i < bs.size(); ++i){ + if(bs[i] == NULL) gd_bs[i] = Ref(NULL); + else { + Ref gd_b(memnew(SpineEventData)); + gd_b->set_spine_object(bs[i]); + gd_bs[i] = gd_b; + } + } + return gd_bs; +} +Array SpineSkeletonDataResource::get_animations(){ + auto bs = skeleton_data->getAnimations(); + Array gd_bs; + gd_bs.resize(bs.size()); + for(size_t i=0; i < bs.size(); ++i){ + if(bs[i] == NULL) gd_bs[i] = Ref(NULL); + else { + Ref gd_b(memnew(SpineAnimation)); + gd_b->set_spine_object(bs[i]); + gd_bs[i] = gd_b; + } + } + return gd_bs; +} +Array SpineSkeletonDataResource::get_ik_constraints(){ + auto bs = skeleton_data->getIkConstraints(); + Array gd_bs; + gd_bs.resize(bs.size()); + for(size_t i=0; i < bs.size(); ++i){ + if(bs[i] == NULL) gd_bs[i] = Ref(NULL); + else { + Ref gd_b(memnew(SpineIkConstraintData)); + gd_b->set_spine_object(bs[i]); + gd_bs[i] = gd_b; + } + } + return gd_bs; +} +Array SpineSkeletonDataResource::get_transform_constraints(){ + auto bs = skeleton_data->getTransformConstraints(); + Array gd_bs; + gd_bs.resize(bs.size()); + for(size_t i=0; i < bs.size(); ++i){ + if(bs[i] == NULL) gd_bs[i] = Ref(NULL); + else { + Ref gd_b(memnew(SpineTransformConstraintData)); + gd_b->set_spine_object(bs[i]); + gd_bs[i] = gd_b; + } + } + return gd_bs; +} +Array SpineSkeletonDataResource::get_path_constraints(){ + auto bs = skeleton_data->getPathConstraints(); + Array gd_bs; + gd_bs.resize(bs.size()); + for(size_t i=0; i < bs.size(); ++i){ + if(bs[i] == NULL) gd_bs[i] = Ref(NULL); + else { + Ref gd_b(memnew(SpinePathConstraintData)); + gd_b->set_spine_object(bs[i]); + gd_bs[i] = gd_b; + } + } + return gd_bs; +} +#undef S_T +#undef CHECK_V +#undef CHECK_X + +//External feature functions +void SpineSkeletonDataResource::get_animation_names(Vector &res) const{ + res.clear(); + if(!is_skeleton_data_loaded()){ + return; + } + auto as = skeleton_data->getAnimations(); + for(size_t i=0; igetName().buffer()); + }else{ + res.push_back(""); + } + } +} +void SpineSkeletonDataResource::get_skin_names(Vector &res) const{ + res.clear(); + if(!is_skeleton_data_loaded()){ + return; + } + auto as = get_skins(); + res.resize(as.size()); + for(size_t i=0; i(as[i]); + if(a.is_valid()){ + res.push_back(a->get_skin_name()); + }else{ + res.push_back(""); + } + } +} + +void SpineSkeletonDataResource::_get_property_list(List *p_list) const{ + PropertyInfo p; + Vector res; + + p.name = "animations"; + p.type = Variant::STRING; + get_animation_names(res); + p.hint_string = String(",").join(res); + p.hint = PROPERTY_HINT_ENUM; + p_list->push_back(p); + + p.name = "skins"; + p.type = Variant::STRING; + get_skin_names(res); + p.hint_string = String(",").join(res); + p.hint = PROPERTY_HINT_ENUM; + p_list->push_back(p); +} diff --git a/spine-godot/spine_godot/SpineSkeletonDataResource.h b/spine-godot/spine_godot/SpineSkeletonDataResource.h new file mode 100644 index 000000000..14fc17c19 --- /dev/null +++ b/spine-godot/spine_godot/SpineSkeletonDataResource.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 GODOT_SPINESKELETONDATARESOURCE_H +#define GODOT_SPINESKELETONDATARESOURCE_H + +#include "core/variant_parser.h" + +#include + +#include "SpineAtlasResource.h" +#include "SpineSkeletonJsonDataResource.h" +#include "SpineAnimation.h" +#include "SpineBoneData.h" +#include "SpineSlotData.h" +#include "SpineSkin.h" +#include "SpineIkConstraintData.h" +#include "SpineTransformConstraintData.h" +#include "SpinePathConstraintData.h" +#include "SpineEventData.h" + +class SpineSkeletonDataResource : public Resource{ + GDCLASS(SpineSkeletonDataResource, Resource); + +protected: + static void _bind_methods(); + +private: + Ref atlas_res; + Ref skeleton_json_res; + bool valid; + bool spine_object; + + spine::SkeletonData *skeleton_data; + + void update_skeleton_data(); +public: + + inline void set_spine_object(spine::SkeletonData *s){ + skeleton_data = s; + if(s) + spine_object = true; + } + inline spine::SkeletonData *get_spine_object(){ + return skeleton_data; + } + + void load_res(spine::Atlas *a, const String &json_path); + + SpineSkeletonDataResource(); + virtual ~SpineSkeletonDataResource(); + + void _get_property_list(List *p_list) const; + + void set_atlas_res(const Ref &a); + Ref get_atlas_res(); + + void set_skeleton_json_res(const Ref &s); + Ref get_skeleton_json_res(); + + inline spine::SkeletonData *get_skeleton_data(){return skeleton_data;} + + bool is_skeleton_data_loaded() const; + + void get_animation_names(Vector &l) const; + void get_skin_names(Vector &l) const; + + // spine api + Ref find_bone(const String &bone_name); + + Ref find_slot(const String &slot_name); + + Ref find_skin(const String &skin_name); + + Ref find_event(const String &event_data_name); + + Ref find_animation(const String &animation_name); + + Ref find_ik_constraint(const String &constraint_name); + Ref find_transform_constraint(const String &constraint_name); + Ref find_path_constraint(const String &constraint_name); + + Array get_bones(); + Array get_slots(); + Array get_skins() const; + + Ref get_default_skin(); + void set_default_skin(Ref v); + + Array get_events(); + Array get_animations(); + Array get_ik_constraints(); + Array get_transform_constraints(); + Array get_path_constraints(); + + String get_sk_name(); + void set_sk_name(const String &v); + + float get_x(); + void set_x(float v); + + float get_y(); + void set_y(float v); + + float get_width(); + float get_height(); + + String get_version(); + + float get_fps(); + void set_fps(float v); +}; + +#endif //GODOT_SPINESKELETONDATARESOURCE_H diff --git a/spine-godot/spine_godot/SpineSkeletonJsonDataResource.cpp b/spine-godot/spine_godot/SpineSkeletonJsonDataResource.cpp new file mode 100644 index 000000000..ef4c18afb --- /dev/null +++ b/spine-godot/spine_godot/SpineSkeletonJsonDataResource.cpp @@ -0,0 +1,55 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineSkeletonJsonDataResource.h" + + +void SpineSkeletonJsonDataResource::_bind_methods() { +} + +Error SpineSkeletonJsonDataResource::load_from_file(const String &p_path) { + Error err; + + json_string = FileAccess::get_file_as_string(p_path, &err); + return err; +} + +Error SpineSkeletonJsonDataResource::save_to_file(const String &p_path) { + Error err; + FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &err); + if (err != OK) { + if (file) file->close(); + return err; + } + + file->store_string(json_string); + file->close(); + + return OK; +} diff --git a/spine-godot/spine_godot/SpineSkeletonJsonDataResource.h b/spine-godot/spine_godot/SpineSkeletonJsonDataResource.h new file mode 100644 index 000000000..54e2fe650 --- /dev/null +++ b/spine-godot/spine_godot/SpineSkeletonJsonDataResource.h @@ -0,0 +1,49 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef GODOT_SPINESKELETONJSONDATARESOURCE_H +#define GODOT_SPINESKELETONJSONDATARESOURCE_H + +#include "core/variant_parser.h" + +class SpineSkeletonJsonDataResource : public Resource{ + GDCLASS(SpineSkeletonJsonDataResource, Resource); + +protected: + static void _bind_methods(); + + String json_string; +public: + inline const String &get_json_string() {return json_string;} + + Error load_from_file(const String &p_path); + Error save_to_file(const String &p_path); +}; + +#endif //GODOT_SPINESKELETONJSONDATARESOURCE_H diff --git a/spine-godot/spine_godot/SpineSkin.cpp b/spine-godot/spine_godot/SpineSkin.cpp new file mode 100644 index 000000000..92ece10de --- /dev/null +++ b/spine-godot/spine_godot/SpineSkin.cpp @@ -0,0 +1,162 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineSkin.h" + +#include "SpineBoneData.h" +#include "SpineConstraintData.h" + +void SpineSkin::_bind_methods() { + ClassDB::bind_method(D_METHOD("init", "name"), &SpineSkin::init); + ClassDB::bind_method(D_METHOD("set_attachment", "slot_index", "name", "attachment"), &SpineSkin::set_attachment); + ClassDB::bind_method(D_METHOD("get_attachment", "slot_index", "name"), &SpineSkin::get_attachment); + ClassDB::bind_method(D_METHOD("remove_attachment", "slot_index", "name"), &SpineSkin::remove_attachment); + ClassDB::bind_method(D_METHOD("find_names_for_slot", "slot_index"), &SpineSkin::find_names_for_slot); + ClassDB::bind_method(D_METHOD("find_attachments_for_slot", "slot_index"), &SpineSkin::find_attachments_for_slot); + ClassDB::bind_method(D_METHOD("get_skin_name"), &SpineSkin::get_skin_name); + ClassDB::bind_method(D_METHOD("add_skin", "other"), &SpineSkin::add_skin); + ClassDB::bind_method(D_METHOD("copy_skin", "other"), &SpineSkin::copy_skin); + ClassDB::bind_method(D_METHOD("get_attachments"), &SpineSkin::get_attachments); + ClassDB::bind_method(D_METHOD("get_all_bone_data"), &SpineSkin::get_bones); + ClassDB::bind_method(D_METHOD("get_all_constraint_data"), &SpineSkin::get_constraint); +} + +SpineSkin::SpineSkin():skin(NULL) {} +SpineSkin::~SpineSkin() {} + +#define S_T(x) (spine::String(x.utf8())) +Ref SpineSkin::init(const String &name){ + skin = new spine::Skin(S_T(name)); + return this; +} + +void SpineSkin::set_attachment(uint64_t slot_index, const String &name, Ref attachment){ + if(!attachment.is_valid()){ + ERR_PRINT("attachment is invalid!"); + return; + } + skin->setAttachment(slot_index, S_T(name), attachment->get_spine_object()); +} + +Ref SpineSkin::get_attachment(uint64_t slot_index, const String &name){ + auto a = skin->getAttachment(slot_index, S_T(name)); + if(a == NULL) return NULL; + Ref gd_attachment(memnew(SpineAttachment)); + gd_attachment->set_spine_object(a); + return gd_attachment; +} + +void SpineSkin::remove_attachment(uint64_t slot_index, const String &name){ + skin->removeAttachment(slot_index, S_T(name)); +} + +Array SpineSkin::find_names_for_slot(uint64_t slot_index){ + spine::Vector names; + skin->findNamesForSlot(slot_index, names); + Array gd_names; + gd_names.resize(names.size()); + for(size_t i=0; i < names.size(); ++i){ + gd_names[i] = names[i].buffer(); + } + return gd_names; +} + +Array SpineSkin::find_attachments_for_slot(uint64_t slot_index){ + spine::Vector as; + skin->findAttachmentsForSlot(slot_index, as); + Array gd_as; + gd_as.resize(as.size()); + for(size_t i=0; i < as.size(); ++i){ + if(as[i] == NULL) gd_as[i] = Ref(NULL); + else { + Ref gd_a(memnew(SpineAttachment)); + gd_a->set_spine_object(as[i]); + gd_as[i] = gd_a; + } + } + return gd_as; +} + +String SpineSkin::get_skin_name(){ + return skin->getName().buffer(); +} + +void SpineSkin::add_skin(Ref other){ + if(other.is_valid() && other->get_spine_object()){ + skin->addSkin(other->get_spine_object()); + } else{ + ERR_PRINT("other is NULL!"); + } +} + +void SpineSkin::copy_skin(Ref other){ + if(other.is_valid() && other->get_spine_object()){ + skin->copySkin(other->get_spine_object()); + } else{ + ERR_PRINT("other is NULL!"); + } +} + +Ref SpineSkin::get_attachments(){ + auto *es = new spine::Skin::AttachmentMap::Entries(skin->getAttachments()); + Ref gd_es(memnew(SpineSkinAttachmentMapEntries)); + gd_es->set_spine_object(es); + return gd_es; + +} + +Array SpineSkin::get_bones(){ + auto bs = skin->getBones(); + Array gd_bs; + gd_bs.resize(bs.size()); + for(size_t i=0; i < bs.size(); ++i){ + if(bs[i] == NULL) gd_bs[i] = Ref(NULL); + else{ + Ref gd_b(memnew(SpineBoneData)); + gd_b->set_spine_object(bs[i]); + gd_bs[i] = gd_b; + } + } + return gd_bs; +} + +Array SpineSkin::get_constraint(){ + auto cs = skin->getConstraints(); + Array gd_cs; + gd_cs.resize(cs.size()); + for(size_t i=0; i < cs.size(); ++i){ + if(cs[i] == NULL) gd_cs[i] = Ref(NULL); + else{ + Ref gd_c(memnew(SpineConstraintData)); + gd_c->set_spine_object(cs[i]); + gd_cs[i] = gd_c; + } + } + return gd_cs; +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineSkin.h b/spine-godot/spine_godot/SpineSkin.h new file mode 100644 index 000000000..1b6533414 --- /dev/null +++ b/spine-godot/spine_godot/SpineSkin.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 GODOT_SPINESKIN_H +#define GODOT_SPINESKIN_H + +#include "core/variant_parser.h" + +#include + +#include "SpineAttachment.h" +#include "SpineSkinAttachmentMapEntries.h" + +class SpineSkin : public Reference { + GDCLASS(SpineSkin, Reference); + +protected: + static void _bind_methods(); + +private: + spine::Skin *skin; + +public: + SpineSkin(); + ~SpineSkin(); + + inline void set_spine_object(spine::Skin *s){ + skin = s; + } + spine::Skin *get_spine_object(){ + return skin; + } + + Ref init(const String &name); + + void set_attachment(uint64_t slot_index, const String &name, Ref attachment); + + Ref get_attachment(uint64_t slot_index, const String &name); + + void remove_attachment(uint64_t slot_index, const String &name); + + Array find_names_for_slot(uint64_t slot_index); + + Array find_attachments_for_slot(uint64_t slot_index); + + String get_skin_name(); + + void add_skin(Ref other); + + void copy_skin(Ref other); + + Ref get_attachments(); + + Array get_bones(); + + Array get_constraint(); +}; + +#endif //GODOT_SPINESKIN_H diff --git a/spine-godot/spine_godot/SpineSkinAttachmentMapEntries.cpp b/spine-godot/spine_godot/SpineSkinAttachmentMapEntries.cpp new file mode 100644 index 000000000..03e15203f --- /dev/null +++ b/spine-godot/spine_godot/SpineSkinAttachmentMapEntries.cpp @@ -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. + *****************************************************************************/ + +#include "SpineSkinAttachmentMapEntries.h" + +void SpineSkinAttachmentMapEntry::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_slot_index"), &SpineSkinAttachmentMapEntry::get_slot_index); + ClassDB::bind_method(D_METHOD("set_slot_index", "v"), &SpineSkinAttachmentMapEntry::set_slot_index); + ClassDB::bind_method(D_METHOD("get_entry_name"), &SpineSkinAttachmentMapEntry::get_entry_name); + ClassDB::bind_method(D_METHOD("set_entry_name", "v"), &SpineSkinAttachmentMapEntry::set_entry_name); + ClassDB::bind_method(D_METHOD("get_attachment"), &SpineSkinAttachmentMapEntry::get_attachment); + ClassDB::bind_method(D_METHOD("set_attachment", "v"), &SpineSkinAttachmentMapEntry::set_attachment); +} + +SpineSkinAttachmentMapEntry::SpineSkinAttachmentMapEntry():entry(NULL) {} +SpineSkinAttachmentMapEntry::~SpineSkinAttachmentMapEntry() {} + +uint64_t SpineSkinAttachmentMapEntry::get_slot_index(){ + return entry->_slotIndex; +} +void SpineSkinAttachmentMapEntry::set_slot_index(uint64_t v){ + entry->_slotIndex = v; +} + +String SpineSkinAttachmentMapEntry::get_entry_name(){ + return entry->_name.buffer(); +} +void SpineSkinAttachmentMapEntry::set_entry_name(const String &v){ + entry->_name = spine::String(v.utf8()); +} + +Ref SpineSkinAttachmentMapEntry::get_attachment(){ + if(entry->_attachment == NULL) return NULL; + Ref gd_attachment(memnew(SpineAttachment)); + gd_attachment->set_spine_object(entry->_attachment); + return gd_attachment; +} +void SpineSkinAttachmentMapEntry::set_attachment(Ref v){ + if(v.is_valid()){ + entry->_attachment = v->get_spine_object(); + }else{ + entry->_attachment = NULL; + } +} + +void SpineSkinAttachmentMapEntries::_bind_methods() { + ClassDB::bind_method(D_METHOD("has_next"), &SpineSkinAttachmentMapEntries::has_next); + ClassDB::bind_method(D_METHOD("next"), &SpineSkinAttachmentMapEntries::next); +} + +SpineSkinAttachmentMapEntries::SpineSkinAttachmentMapEntries():entries(NULL) {} +SpineSkinAttachmentMapEntries::~SpineSkinAttachmentMapEntries() { + if(entries){ + delete entries; + return; + } +} + +bool SpineSkinAttachmentMapEntries::has_next(){ + return entries->hasNext(); +} +Ref SpineSkinAttachmentMapEntries::next(){ + auto &e = entries->next(); + Ref gd_entry(memnew(SpineSkinAttachmentMapEntry)); + gd_entry->set_spine_object(&e); + return gd_entry; +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineSkinAttachmentMapEntries.h b/spine-godot/spine_godot/SpineSkinAttachmentMapEntries.h new file mode 100644 index 000000000..9f5db61e3 --- /dev/null +++ b/spine-godot/spine_godot/SpineSkinAttachmentMapEntries.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 GODOT_SPINESKINATTACHMENTMAPENTRIES_H +#define GODOT_SPINESKINATTACHMENTMAPENTRIES_H + +#include "core/variant_parser.h" + +#include + +#include "SpineAttachment.h" + +class SpineSkinAttachmentMapEntry : public Reference { + GDCLASS(SpineSkinAttachmentMapEntry, Reference); + +protected: + static void _bind_methods(); + +private: + spine::Skin::AttachmentMap::Entry *entry; + +public: + SpineSkinAttachmentMapEntry(); + ~SpineSkinAttachmentMapEntry(); + + inline void set_spine_object(spine::Skin::AttachmentMap::Entry *e){ + entry = e; + } + inline spine::Skin::AttachmentMap::Entry *get_spine_object(){ + return entry; + } + + uint64_t get_slot_index(); + void set_slot_index(uint64_t v); + + String get_entry_name(); + void set_entry_name(const String &v); + + Ref get_attachment(); + void set_attachment(Ref v); +}; + +class SpineSkinAttachmentMapEntries : public Reference { + GDCLASS(SpineSkinAttachmentMapEntries, Reference); + +protected: + static void _bind_methods(); + +private: + spine::Skin::AttachmentMap::Entries *entries; + +public: + SpineSkinAttachmentMapEntries(); + ~SpineSkinAttachmentMapEntries(); + + inline void set_spine_object(spine::Skin::AttachmentMap::Entries *e){ + entries = e; + } + inline spine::Skin::AttachmentMap::Entries *get_spine_object(){ + return entries; + } + + bool has_next(); + Ref next(); +}; + +#endif //GODOT_SPINESKINATTACHMENTMAPENTRIES_H diff --git a/spine-godot/spine_godot/SpineSlot.cpp b/spine-godot/spine_godot/SpineSlot.cpp new file mode 100644 index 000000000..c26b98448 --- /dev/null +++ b/spine-godot/spine_godot/SpineSlot.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. + *****************************************************************************/ + +#include "SpineSlot.h" + +#include "SpineBone.h" +#include "SpineSkeleton.h" + + +void SpineSlot::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_to_setup_pos"), &SpineSlot::set_to_setup_pos); + ClassDB::bind_method(D_METHOD("get_data"), &SpineSlot::get_data); + ClassDB::bind_method(D_METHOD("get_bone"), &SpineSlot::get_bone); + ClassDB::bind_method(D_METHOD("get_skeleton"), &SpineSlot::get_skeleton); + ClassDB::bind_method(D_METHOD("get_color"), &SpineSlot::get_color); + ClassDB::bind_method(D_METHOD("set_color"), &SpineSlot::set_color); + ClassDB::bind_method(D_METHOD("get_dark_color"), &SpineSlot::get_dark_color); + ClassDB::bind_method(D_METHOD("set_dark_color", "v"), &SpineSlot::set_dark_color); + ClassDB::bind_method(D_METHOD("has_dark_color"), &SpineSlot::has_dark_color); + ClassDB::bind_method(D_METHOD("get_attachment"), &SpineSlot::get_attachment); + ClassDB::bind_method(D_METHOD("set_attachment", "v"), &SpineSlot::set_attachment); + ClassDB::bind_method(D_METHOD("get_attachment_state"), &SpineSlot::get_attachment_state); + ClassDB::bind_method(D_METHOD("set_attachment_state", "v"), &SpineSlot::set_attachment_state); + ClassDB::bind_method(D_METHOD("get_deform"), &SpineSlot::get_deform); + ClassDB::bind_method(D_METHOD("set_deform", "v"), &SpineSlot::set_deform); +} + +SpineSlot::SpineSlot():slot(NULL) {} +SpineSlot::~SpineSlot() {} + +void SpineSlot::set_to_setup_pos(){ + slot->setToSetupPose(); +} + +Ref SpineSlot::get_data(){ + auto &sd = slot->getData(); + Ref gd_sd(memnew(SpineSlotData)); + gd_sd->set_spine_object(&sd); + return gd_sd; +} + +Ref SpineSlot::get_bone(){ + auto &b = slot->getBone(); + Ref gd_b(memnew(SpineBone)); + gd_b->set_spine_object(&b); + return gd_b; +} + +Ref SpineSlot::get_skeleton(){ + auto &s = slot->getSkeleton(); + Ref gd_s(memnew(SpineSkeleton)); + gd_s->set_spine_object(&s); + return gd_s; +} + +Color SpineSlot::get_color(){ + auto &c = slot->getColor(); + return Color(c.r, c.g, c.b, c.a); +} +void SpineSlot::set_color(Color v){ + auto &c = slot->getColor(); + c.set(v.r, v.g, v.b, v.a); +} + +Color SpineSlot::get_dark_color(){ + auto &c = slot->getDarkColor(); + return Color(c.r, c.g, c.b, c.a); +} +void SpineSlot::set_dark_color(Color v){ + auto &c = slot->getDarkColor(); + c.set(v.r, v.g, v.b, v.a); +} + +bool SpineSlot::has_dark_color(){ + return slot->hasDarkColor(); +} + +Ref SpineSlot::get_attachment(){ + auto a = slot->getAttachment(); + if(a == NULL) return NULL; + Ref gd_a(memnew(SpineAttachment)); + gd_a->set_spine_object(a); + return gd_a; +} +void SpineSlot::set_attachment(Ref v){ + if(v.is_valid()){ + slot->setAttachment(v->get_spine_object()); + }else{ + slot->setAttachment(NULL); + } +} + +int SpineSlot::get_attachment_state(){ + return slot->getAttachmentState(); +} +void SpineSlot::set_attachment_state(int v){ + slot->setAttachmentState(v); +} + +float SpineSlot::get_attachment_time(){ + return slot->getAttachmentTime(); +} +void SpineSlot::set_attachment_time(float v){ + slot->setAttachmentTime(v); +} + +Array SpineSlot::get_deform(){ + auto &ds = slot->getDeform(); + Array gd_ds; + gd_ds.resize(ds.size()); + for(size_t i=0; i < ds.size(); ++i){ + gd_ds[i] = ds[i]; + } + return gd_ds; +} +void SpineSlot::set_deform(Array gd_ds){ + auto &ds = slot->getDeform(); + ds.setSize(gd_ds.size(), 0); + for(size_t i=0; i < gd_ds.size(); ++i){ + ds[i] = gd_ds[i]; + } +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineSlot.h b/spine-godot/spine_godot/SpineSlot.h new file mode 100644 index 000000000..dff4cebcf --- /dev/null +++ b/spine-godot/spine_godot/SpineSlot.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 GODOT_SPINESLOT_H +#define GODOT_SPINESLOT_H + +#include "core/variant_parser.h" + +#include + +#include "SpineSlotData.h" +#include "SpineAttachment.h" + +class SpineSkeleton; + +class SpineBone; + +class SpineSlot : public Reference{ + GDCLASS(SpineSlot, Reference); + +protected: + static void _bind_methods(); + +private: + spine::Slot *slot; + +public: + SpineSlot(); + ~SpineSlot(); + + inline void set_spine_object(spine::Slot *s){ + slot = s; + } + inline spine::Slot *get_spine_object(){ + return slot; + } + + void set_to_setup_pos(); + + Ref get_data(); + + Ref get_bone(); + + Ref get_skeleton(); + + Color get_color(); + void set_color(Color v); + + Color get_dark_color(); + void set_dark_color(Color v); + + bool has_dark_color(); + + Ref get_attachment(); + void set_attachment(Ref v); + + int get_attachment_state(); + void set_attachment_state(int v); + + float get_attachment_time(); + void set_attachment_time(float v); + + Array get_deform(); + void set_deform(Array v); +}; + +#endif //GODOT_SPINESLOT_H diff --git a/spine-godot/spine_godot/SpineSlotData.cpp b/spine-godot/spine_godot/SpineSlotData.cpp new file mode 100644 index 000000000..82d77b9e1 --- /dev/null +++ b/spine-godot/spine_godot/SpineSlotData.cpp @@ -0,0 +1,114 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineSlotData.h" + +void SpineSlotData::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_index"), &SpineSlotData::get_index); + ClassDB::bind_method(D_METHOD("get_slot_name"), &SpineSlotData::get_slot_name); + ClassDB::bind_method(D_METHOD("get_bone_data"), &SpineSlotData::get_bone_data); + ClassDB::bind_method(D_METHOD("get_color"), &SpineSlotData::get_color); + ClassDB::bind_method(D_METHOD("get_dark_color"), &SpineSlotData::get_dark_color); + ClassDB::bind_method(D_METHOD("has_dark_color"), &SpineSlotData::has_dark_color); + ClassDB::bind_method(D_METHOD("set_has_dark_color", "v"), &SpineSlotData::set_has_dark_color); + ClassDB::bind_method(D_METHOD("get_attachment_name"), &SpineSlotData::get_attachment_name); + ClassDB::bind_method(D_METHOD("set_attachment_name", "v"), &SpineSlotData::set_attachment_name); + ClassDB::bind_method(D_METHOD("get_blend_mode"), &SpineSlotData::get_blend_mode); + ClassDB::bind_method(D_METHOD("set_blend_mode", "v"), &SpineSlotData::set_blend_mode); + + ClassDB::bind_method(D_METHOD("set_color", "v"), &SpineSlotData::set_color); + ClassDB::bind_method(D_METHOD("set_dark_color", "v"), &SpineSlotData::set_dark_color); + + BIND_ENUM_CONSTANT(BLENDMODE_NORMAL); + BIND_ENUM_CONSTANT(BLENDMODE_ADDITIVE); + BIND_ENUM_CONSTANT(BLENDMODE_MULTIPLY); + BIND_ENUM_CONSTANT(BLENDMODE_SCREEN); +} + +SpineSlotData::SpineSlotData():slot_data(NULL) {} +SpineSlotData::~SpineSlotData() {} + +#define S_T(x) (spine::String(x.utf8())) +int SpineSlotData::get_index(){ + return slot_data->getIndex(); +} + +String SpineSlotData::get_slot_name(){ + return slot_data->getName().buffer(); +} + +Ref SpineSlotData::get_bone_data(){ + auto &bd = slot_data->getBoneData(); + Ref gd_bone_data(memnew(SpineBoneData)); + gd_bone_data->set_spine_object(&bd); + return gd_bone_data; +} + +Color SpineSlotData::get_color(){ + auto &c = slot_data->getColor(); + return Color(c.r, c.g, c.b, c.a); +} +void SpineSlotData::set_color(Color v){ + auto &c = slot_data->getColor(); + c.set(v.r, v.g, v.b, v.a); +} + +Color SpineSlotData::get_dark_color(){ + auto &c = slot_data->getDarkColor(); + return Color(c.r, c.g, c.b, c.a); +} +void SpineSlotData::set_dark_color(Color v){ + auto &c = slot_data->getDarkColor(); + c.set(v.r, v.g, v.b, v.a); +} + +bool SpineSlotData::has_dark_color(){ + return slot_data->hasDarkColor(); +} +void SpineSlotData::set_has_dark_color(bool v){ + slot_data->setHasDarkColor(v); +} + +String SpineSlotData::get_attachment_name(){ + return slot_data->getAttachmentName().buffer(); +} +void SpineSlotData::set_attachment_name(const String &v){ + slot_data->setAttachmentName(S_T(v)); +} + +SpineSlotData::BlendMode SpineSlotData::get_blend_mode(){ + auto bm = (int) slot_data->getBlendMode(); + return (BlendMode) bm; +} +void SpineSlotData::set_blend_mode(BlendMode v){ + auto bm = (int) v; + slot_data->setBlendMode((spine::BlendMode) bm); +} + +#undef S_T \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineSlotData.h b/spine-godot/spine_godot/SpineSlotData.h new file mode 100644 index 000000000..0b2f9abf5 --- /dev/null +++ b/spine-godot/spine_godot/SpineSlotData.h @@ -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. + *****************************************************************************/ + +#ifndef GODOT_SPINESLOTDATA_H +#define GODOT_SPINESLOTDATA_H +#include "core/variant_parser.h" + +#include + +#include "SpineBoneData.h" + +class SpineSlotData : public Reference { + GDCLASS(SpineSlotData, Reference); + +protected: + static void _bind_methods(); + +private: + spine::SlotData *slot_data; + +public: + SpineSlotData(); + ~SpineSlotData(); + + inline void set_spine_object(spine::SlotData *s){ + slot_data = s; + } + inline spine::SlotData *get_spine_object(){ + return slot_data; + } + + enum BlendMode { + BLENDMODE_NORMAL = 0, + BLENDMODE_ADDITIVE, + BLENDMODE_MULTIPLY, + BLENDMODE_SCREEN + }; + + int get_index(); + + String get_slot_name(); + + Ref get_bone_data(); + + Color get_color(); + void set_color(Color c); + + Color get_dark_color(); + void set_dark_color(Color c); + + bool has_dark_color(); + void set_has_dark_color(bool v); + + String get_attachment_name(); + void set_attachment_name(const String &v); + + BlendMode get_blend_mode(); + void set_blend_mode(BlendMode v); +}; + +VARIANT_ENUM_CAST(SpineSlotData::BlendMode); +#endif //GODOT_SPINESLOTDATA_H diff --git a/spine-godot/spine_godot/SpineSprite.cpp b/spine-godot/spine_godot/SpineSprite.cpp new file mode 100644 index 000000000..894545755 --- /dev/null +++ b/spine-godot/spine_godot/SpineSprite.cpp @@ -0,0 +1,1039 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineSprite.h" + +#include "SpineTrackEntry.h" +#include "SpineEvent.h" + +void SpineSprite::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_animation_state_data_res", "animation_state_data_res"), &SpineSprite::set_animation_state_data_res); + ClassDB::bind_method(D_METHOD("get_animation_state_data_res"), &SpineSprite::get_animation_state_data_res); + ClassDB::bind_method(D_METHOD("_on_animation_data_created"), &SpineSprite::_on_animation_data_created); + ClassDB::bind_method(D_METHOD("get_skeleton"), &SpineSprite::get_skeleton); + ClassDB::bind_method(D_METHOD("get_animation_state"), &SpineSprite::get_animation_state); + ClassDB::bind_method(D_METHOD("_on_animation_data_changed"), &SpineSprite::_on_animation_data_changed); + + ClassDB::bind_method(D_METHOD("get_current_animations"), &SpineSprite::get_current_animations); + ClassDB::bind_method(D_METHOD("set_current_animations", "current_animations"), &SpineSprite::set_current_animations); + + ClassDB::bind_method(D_METHOD("get_select_track_id"), &SpineSprite::get_select_track_id); + ClassDB::bind_method(D_METHOD("set_select_track_id", "track_id"), &SpineSprite::set_select_track_id); + ClassDB::bind_method(D_METHOD("get_clear_track"), &SpineSprite::get_clear_track); + ClassDB::bind_method(D_METHOD("set_clear_track", "v"), &SpineSprite::set_clear_track); + ClassDB::bind_method(D_METHOD("get_clear_tracks"), &SpineSprite::get_clear_tracks); + ClassDB::bind_method(D_METHOD("set_clear_tracks", "v"), &SpineSprite::set_clear_tracks); + + ClassDB::bind_method(D_METHOD("get_empty_animation_duration"), &SpineSprite::get_empty_animation_duration); + ClassDB::bind_method(D_METHOD("set_empty_animation_duration", "track_id"), &SpineSprite::set_empty_animation_duration); + ClassDB::bind_method(D_METHOD("get_set_empty_animation"), &SpineSprite::get_set_empty_animation); + ClassDB::bind_method(D_METHOD("set_set_empty_animation", "v"), &SpineSprite::set_set_empty_animation); + ClassDB::bind_method(D_METHOD("get_set_empty_animations"), &SpineSprite::get_set_empty_animations); + ClassDB::bind_method(D_METHOD("set_set_empty_animations", "v"), &SpineSprite::set_set_empty_animations); + + ClassDB::bind_method(D_METHOD("get_bind_slot_nodes"), &SpineSprite::get_bind_slot_nodes); + ClassDB::bind_method(D_METHOD("set_bind_slot_nodes", "v"), &SpineSprite::set_bind_slot_nodes); + ClassDB::bind_method(D_METHOD("get_overlap"), &SpineSprite::get_overlap); + ClassDB::bind_method(D_METHOD("set_overlap", "v"), &SpineSprite::set_overlap); + ClassDB::bind_method(D_METHOD("set_skin", "v"), &SpineSprite::set_skin); + ClassDB::bind_method(D_METHOD("get_skin"), &SpineSprite::get_skin); + ClassDB::bind_method(D_METHOD("_on_skin_property_changed"), &SpineSprite::_on_skin_property_changed); + ClassDB::bind_method(D_METHOD("gen_spine_skin_from_packed_resource", "res"), &SpineSprite::gen_spine_skin_from_packed_resource); + + ClassDB::bind_method(D_METHOD("bone_get_global_transform", "bone_name"), &SpineSprite::bone_get_global_transform); + ClassDB::bind_method(D_METHOD("bone_set_global_transform", "bone_name", "global_transform"), &SpineSprite::bone_set_global_transform); + + ClassDB::bind_method(D_METHOD("set_process_mode", "v"), &SpineSprite::set_process_mode); + ClassDB::bind_method(D_METHOD("get_process_mode"), &SpineSprite::get_process_mode); + + ClassDB::bind_method(D_METHOD("manual_update", "delta"), &SpineSprite::_update_all); + + ADD_SIGNAL(MethodInfo("animation_state_ready", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "skeleton", PROPERTY_HINT_TYPE_STRING, "SpineSkeleton"))); + ADD_SIGNAL(MethodInfo("animation_start", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent"))); + ADD_SIGNAL(MethodInfo("animation_interrupt", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent"))); + ADD_SIGNAL(MethodInfo("animation_end", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent"))); + ADD_SIGNAL(MethodInfo("animation_complete", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent"))); + ADD_SIGNAL(MethodInfo("animation_dispose", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent"))); + ADD_SIGNAL(MethodInfo("animation_event", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent"))); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "animation_state_data_res", PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "SpineAnimationStateDataResource"), "set_animation_state_data_res", "get_animation_state_data_res"); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "overlap"), "set_overlap", "get_overlap"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "bind_slot_nodes"), "set_bind_slot_nodes", "get_bind_slot_nodes"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "packed_skin_resource", PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "PackedSpineSkinResource"), "set_skin", "get_skin"); + + ADD_GROUP("animation", ""); + ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Process,Physics,Manually"), "set_process_mode", "get_process_mode"); + + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "current_animations"), "set_current_animations", "get_current_animations"); + + BIND_ENUM_CONSTANT(ProcessMode::ProcessMode_Process); + BIND_ENUM_CONSTANT(ProcessMode::ProcessMode_Physics); + BIND_ENUM_CONSTANT(ProcessMode::ProcessMode_Manual); +} + +SpineSprite::SpineSprite() : + select_track_id(0), empty_animation_duration(0.2f), skeleton_clipper(NULL), + overlap(false), + process_mode(ProcessMode_Process) + { + skeleton_clipper = new spine::SkeletonClipping(); +} +SpineSprite::~SpineSprite() { + delete skeleton_clipper; +} + +void SpineSprite::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_READY:{ + set_process_internal(process_mode == ProcessMode_Process); + set_physics_process_internal(process_mode == ProcessMode_Physics); + remove_redundant_mesh_instances(); + } break; + case NOTIFICATION_INTERNAL_PROCESS: { + if (process_mode == ProcessMode_Process) + _update_all(get_process_delta_time()); + } break; + case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { + if (process_mode == ProcessMode_Physics) + _update_all(get_physics_process_delta_time()); + } break; + } +} + +void SpineSprite::_update_all(float delta) { + if (!(skeleton.is_valid() && animation_state.is_valid()) || mesh_instances.empty()) + return; + + animation_state->update(delta); + if (!is_visible_in_tree()) + return; + + animation_state->apply(skeleton); + + skeleton->update_world_transform(); + + update_mesh_from_skeleton(skeleton); + + update(); + + update_bind_slot_nodes(); +} + +void SpineSprite::update_bind_slot_nodes(){ + if(animation_state.is_valid() && skeleton.is_valid()){ + for(size_t i=0, n=bind_slot_nodes.size(); iis_class("Node2D")){ + Node2D *node2d = (Node2D*) node; + + String slot_name = d["slot_name"]; + auto slot = skeleton->find_slot(slot_name); + if(slot.is_valid()){ + auto bone = slot->get_bone(); + if(bone.is_valid()) + { + update_bind_slot_node_transform(bone, node2d); + update_bind_slot_node_draw_order(slot_name, node2d); + } + } + + } + } + }else if(a.get_type() == Variant::ARRAY){ + auto as = (Array) a;// 0: slot_name, 1: node_path + if(as.size() >= 2 && as[0].get_type() == Variant::STRING && as[1].get_type() == Variant::NODE_PATH){ + NodePath node_path = as[1]; + Node *node = get_node_or_null(node_path); + if(node && node->is_class("Node2D")){ + Node2D *node2d = (Node2D*) node; + + String slot_name = as[0]; + auto slot = skeleton->find_slot(slot_name); + if(slot.is_valid()){ + auto bone = slot->get_bone(); + if(bone.is_valid()) + { + update_bind_slot_node_transform(bone, node2d); + update_bind_slot_node_draw_order(slot_name, node2d); + } + } + + } + } + } + } + } +} +void SpineSprite::update_bind_slot_node_transform(Ref bone, Node2D *node2d){ + bone->apply_world_transform_2d(node2d); +} +void SpineSprite::update_bind_slot_node_draw_order(const String &slot_name, Node2D *node2d){ + auto mesh_ins = find_node(slot_name); + if(mesh_ins){ + auto pos = mesh_ins->get_index(); + + // get child + auto node = find_child_node_by_node(node2d); + if(node && node->get_index() != pos+1){ + move_child(node, pos+1); + } + } +} +Node *SpineSprite::find_child_node_by_node(Node *node){ + if(node == NULL) return NULL; + while(node && node->get_parent() != this) node = node->get_parent(); + return node; +} + +void SpineSprite::set_animation_state_data_res(const Ref &s) { + animation_state_data_res = s; + + // update run time skeleton and meshes + _on_animation_data_changed(); +} +Ref SpineSprite::get_animation_state_data_res() { + return animation_state_data_res; +} + +void SpineSprite::_on_animation_data_created(){ +// print_line("_on_animation_data_created"); + skeleton = Ref(memnew(SpineSkeleton)); + skeleton->load_skeleton(animation_state_data_res->get_skeleton()); + skeleton->set_spine_sprite(this); +// print_line("Run time skeleton created."); + + animation_state = Ref(memnew(SpineAnimationState)); + animation_state->load_animation_state(animation_state_data_res); + animation_state->get_animation_state()->setListener(this); +// print_line("Run time animation state created."); + + // add mesh instances related by current skeleton + animation_state->update(0); + animation_state->apply(skeleton); + skeleton->update_world_transform(); + gen_mesh_from_skeleton(skeleton); + + if (process_mode == ProcessMode_Process) { + _notification(NOTIFICATION_INTERNAL_PROCESS); + } else if (process_mode == ProcessMode_Physics) { + _notification(NOTIFICATION_INTERNAL_PHYSICS_PROCESS); + } + + emit_signal("animation_state_ready", animation_state, skeleton); +} +void SpineSprite::_on_animation_data_changed() { +// print_line("_on_animation_data_changed"); + remove_mesh_instances(); + skeleton.unref(); + animation_state.unref(); + if(!animation_state_data_res.is_null()) + { + if(!animation_state_data_res->is_connected("animation_state_data_created", this, "_on_animation_data_created")) + animation_state_data_res->connect("animation_state_data_created", this, "_on_animation_data_created"); + if(!animation_state_data_res->is_connected("skeleton_data_res_changed", this, "_on_animation_data_changed")) + animation_state_data_res->connect("skeleton_data_res_changed", this, "_on_animation_data_changed"); + if(!animation_state_data_res->is_connected("animation_state_data_changed", this, "_on_animation_data_changed")) + animation_state_data_res->connect("animation_state_data_changed", this, "_on_animation_data_changed"); + + if(animation_state_data_res->is_animation_state_data_created()) + { + _on_animation_data_created(); + } + } +} + +Ref SpineSprite::get_skeleton() { + return skeleton; +} +Ref SpineSprite::get_animation_state() { + return animation_state; +} + +void SpineSprite::gen_mesh_from_skeleton(Ref s) { + auto sk = s->get_spine_object(); + for(size_t i=0, n = sk->getSlots().size(); i < n; ++i) + { + // creat a mesh instance 2d for every slot + auto mesh_ins = memnew(SpineSpriteMeshInstance2D); + add_child(mesh_ins); + mesh_ins->set_position(Vector2(0, 0)); + mesh_ins->set_owner(this); + mesh_instances.push_back(mesh_ins); + + spine::Slot *slot = sk->getDrawOrder()[i]; + mesh_ins->set_name(slot->getData().getName().buffer()); + Ref gd_slot(memnew(SpineSlot)); + gd_slot->set_spine_object(slot); + mesh_ins->set_slot(gd_slot); + + // creat a material + Ref mat(memnew(CanvasItemMaterial)); + CanvasItemMaterial::BlendMode blend_mode; + switch (slot->getData().getBlendMode()) { + case spine::BlendMode_Normal: + blend_mode = CanvasItemMaterial::BLEND_MODE_MIX; + break; + case spine::BlendMode_Additive: + blend_mode = CanvasItemMaterial::BLEND_MODE_ADD; + break; + case spine::BlendMode_Multiply: + blend_mode = CanvasItemMaterial::BLEND_MODE_MUL; + break; + case spine::BlendMode_Screen: + blend_mode = CanvasItemMaterial::BLEND_MODE_MIX; + break; + default: + blend_mode = CanvasItemMaterial::BLEND_MODE_MIX; + } + mat->set_blend_mode(blend_mode); + mesh_ins->set_material(mat); + } +} + +void SpineSprite::remove_mesh_instances() { + for(size_t i=0;i < mesh_instances.size();++i) + { + remove_child(mesh_instances[i]); + memdelete(mesh_instances[i]); + } + mesh_instances.clear(); +} + +void SpineSprite::remove_redundant_mesh_instances() { + Vector ms; + // remove the redundant mesh instances that added by duplicating +// print_line("start clearing"); + for(size_t i=0, n=get_child_count(); iget_name()); + if(node && node->is_class("SpineSpriteMeshInstance2D")){ + if(mesh_instances.find((SpineSpriteMeshInstance2D*)node) == -1) + { +// print_line("marked clear"); + ms.push_back(node); + } + + } + } + for(size_t i=0, n=ms.size(); i s) { + static const unsigned short VERTEX_STRIDE = 2; + static const unsigned short UV_STRIDE = 2; + static unsigned short quad_indices[] = { 0, 1, 2, 2, 3, 0 }; + + auto sk = s->get_spine_object(); + for(size_t i=0, n = sk->getSlots().size(); i < n; ++i) + { + spine::Vector vertices; + spine::Vector uvs; + spine::Vector indices; + + spine::Slot *slot = sk->getDrawOrder()[i]; + + spine::Attachment *attachment = slot->getAttachment(); + if(!attachment){ + // set invisible to mesh instance + mesh_instances[i]->set_visible(false); + + skeleton_clipper->clipEnd(*slot); + continue; + } + mesh_instances[i]->set_visible(true); + + spine::Color skeleton_color = sk->getColor(); + spine::Color slot_color = slot->getColor(); + spine::Color tint(skeleton_color.r * slot_color.r, skeleton_color.g * slot_color.g, skeleton_color.b * slot_color.b, skeleton_color.a * slot_color.a); + + Ref tex; + Ref normal_tex; + size_t v_num = 0; + + if(attachment->getRTTI().isExactly(spine::RegionAttachment::rtti)) + { + spine::RegionAttachment *region_attachment = (spine::RegionAttachment*)attachment; + + auto p_spine_renderer_object = (SpineRendererObject*) ((spine::AtlasRegion*)region_attachment->getRendererObject())->page->getRendererObject(); + tex = p_spine_renderer_object->tex; + normal_tex = p_spine_renderer_object->normal_tex; + + v_num = 4; + vertices.setSize(v_num * VERTEX_STRIDE, 0); + + region_attachment->computeWorldVertices(slot->getBone(), vertices, 0); + + TEMP_COPY(uvs, region_attachment->getUVs()); + + indices.setSize(sizeof(quad_indices) / sizeof(unsigned short), 0); + for (size_t j = 0, qn = indices.size();jgetColor(); + tint.r *= attachment_color.r; + tint.g *= attachment_color.g; + tint.b *= attachment_color.b; + tint.a *= attachment_color.a; + }else if(attachment->getRTTI().isExactly(spine::MeshAttachment::rtti)) { + spine::MeshAttachment *mesh = (spine::MeshAttachment*) attachment; + + auto p_spine_renderer_object = (SpineRendererObject*) ((spine::AtlasRegion*)mesh->getRendererObject())->page->getRendererObject(); + tex = p_spine_renderer_object->tex; + normal_tex = p_spine_renderer_object->normal_tex; + + v_num = mesh->getWorldVerticesLength()/VERTEX_STRIDE; + vertices.setSize(mesh->getWorldVerticesLength(), 0); + + mesh->computeWorldVertices(*slot, vertices); + +// uvs = mesh->getUVs(); +// indices = mesh->getTriangles(); + TEMP_COPY(uvs, mesh->getUVs()); + TEMP_COPY(indices, mesh->getTriangles()); + + auto attachment_color = mesh->getColor(); + tint.r *= attachment_color.r; + tint.g *= attachment_color.g; + tint.b *= attachment_color.b; + tint.a *= attachment_color.a; + } else if (attachment->getRTTI().isExactly(spine::ClippingAttachment::rtti)) { + auto clip = (spine::ClippingAttachment *) attachment; + skeleton_clipper->clipStart(*slot, clip); + continue; + } else { + skeleton_clipper->clipEnd(*slot); + continue; + } + + auto mesh_ins = mesh_instances[i]; + VisualServer::get_singleton()->canvas_item_clear(mesh_ins->get_canvas_item()); + + if (skeleton_clipper->isClipping()) { + skeleton_clipper->clipTriangles(vertices, indices, uvs, VERTEX_STRIDE); + + if (skeleton_clipper->getClippedTriangles().size() == 0) { + skeleton_clipper->clipEnd(*slot); + continue; + } + + auto &clipped_vertices = skeleton_clipper->getClippedVertices(); + v_num = clipped_vertices.size()/VERTEX_STRIDE; + auto &clipped_uvs = skeleton_clipper->getClippedUVs(); + auto &clipped_indices = skeleton_clipper->getClippedTriangles(); + + if (indices.size() > 0) { + Vector p_points, p_uvs; + Vector p_colors; + Vector p_indices; + p_points.resize(v_num); + p_uvs.resize(v_num); + p_colors.resize(v_num); + for (size_t j = 0; j < v_num; j++) { + p_points.set(j, Vector2(clipped_vertices[j*VERTEX_STRIDE], -clipped_vertices[j*VERTEX_STRIDE+1])); + p_uvs.set(j, Vector2(clipped_uvs[j*VERTEX_STRIDE], clipped_uvs[j*VERTEX_STRIDE+1])); + p_colors.set(j, Color(tint.r, tint.g, tint.b, tint.a)); + } + p_indices.resize(clipped_indices.size()); + for (size_t j = 0; j < clipped_indices.size(); ++j) { + p_indices.set(j, clipped_indices[j]); + } + + VisualServer::get_singleton()->canvas_item_add_triangle_array(mesh_ins->get_canvas_item(), + p_indices, + p_points, + p_colors, + p_uvs, + Vector(), + Vector(), + tex.is_null() ? RID() : tex->get_rid(), + -1, + normal_tex.is_null() ? RID() : normal_tex->get_rid()); + } + }else { + if (indices.size() > 0) { + Vector p_points, p_uvs; + Vector p_colors; + Vector p_indices; + p_points.resize(v_num); + p_uvs.resize(v_num); + p_colors.resize(v_num); + for (size_t j = 0; j < v_num; j++) { + p_points.set(j, Vector2(vertices[j*VERTEX_STRIDE], -vertices[j*VERTEX_STRIDE+1])); + p_uvs.set(j, Vector2(uvs[j*VERTEX_STRIDE], uvs[j*VERTEX_STRIDE+1])); + p_colors.set(j, Color(tint.r, tint.g, tint.b, tint.a)); + } + p_indices.resize(indices.size()); + for (size_t j = 0; j < indices.size(); ++j) { + p_indices.set(j, indices[j]); + } + + VisualServer::get_singleton()->canvas_item_add_triangle_array(mesh_ins->get_canvas_item(), + p_indices, + p_points, + p_colors, + p_uvs, + Vector(), + Vector(), + tex.is_null() ? RID() : tex->get_rid(), + -1, + normal_tex.is_null() ? RID() : normal_tex->get_rid()); + } + } + skeleton_clipper->clipEnd(*slot); + + if (mesh_ins->get_material()->is_class("CanvasItemMaterial")){ + Ref mat = mesh_ins->get_material(); + CanvasItemMaterial::BlendMode blend_mode; + switch (slot->getData().getBlendMode()) { + case spine::BlendMode_Normal: + blend_mode = CanvasItemMaterial::BLEND_MODE_MIX; + break; + case spine::BlendMode_Additive: + blend_mode = CanvasItemMaterial::BLEND_MODE_ADD; + break; + case spine::BlendMode_Multiply: + blend_mode = CanvasItemMaterial::BLEND_MODE_MUL; + break; + case spine::BlendMode_Screen: + blend_mode = CanvasItemMaterial::BLEND_MODE_MIX; + break; + default: + blend_mode = CanvasItemMaterial::BLEND_MODE_MIX; + } + mat->set_blend_mode(blend_mode); + } + } + skeleton_clipper->clipEnd(); +} + +void SpineSprite::callback(spine::AnimationState *state, spine::EventType type, spine::TrackEntry *entry, spine::Event *event) { + Ref gd_entry(NULL); + Ref gd_event(NULL); + + if(entry){ + gd_entry = Ref(memnew(SpineTrackEntry)); + gd_entry->set_spine_object(entry); + } + if(event){ + gd_event = Ref(memnew(SpineEvent)); + gd_event->set_spine_object(event); + } + + switch (type) { + case spine::EventType_Start: + { + emit_signal("animation_start", animation_state, gd_entry, gd_event); + }break; + case spine::EventType_Interrupt: + { + emit_signal("animation_interrupt", animation_state, gd_entry, gd_event); + }break; + case spine::EventType_End: + { + emit_signal("animation_end", animation_state, gd_entry, gd_event); + }break; + case spine::EventType_Complete: + { + emit_signal("animation_complete", animation_state, gd_entry, gd_event); + }break; + case spine::EventType_Dispose: + { + emit_signal("animation_dispose", animation_state, gd_entry, gd_event); + }break; + case spine::EventType_Event: + { + emit_signal("animation_event", animation_state, gd_entry, gd_event); + }break; + } +} + +// External feature functions +Array SpineSprite::get_current_animations() { + return current_animations.duplicate(true); +} +void SpineSprite::set_current_animations(Array as) { + current_animations = as.duplicate(true); + + // validate it then play the animations + _validate_and_play_current_animations(); +} + +int SpineSprite::get_select_track_id(){ + return select_track_id; +} +void SpineSprite::set_select_track_id(int v){ + select_track_id = v; + + if(select_track_id < 0) select_track_id = 0; +} + +bool SpineSprite::get_clear_track(){ + return false; +} +void SpineSprite::set_clear_track(bool v){ + if(v && animation_state.is_valid() && skeleton.is_valid()) + animation_state->clear_track(select_track_id); +} + +bool SpineSprite::get_clear_tracks(){ + return false; +} +void SpineSprite::set_clear_tracks(bool v){ + if(v && animation_state.is_valid() && skeleton.is_valid()) + animation_state->clear_tracks(); +} + +float SpineSprite::get_empty_animation_duration(){ + return empty_animation_duration; +} +void SpineSprite::set_empty_animation_duration(float v){ + empty_animation_duration = v; +} + +bool SpineSprite::get_set_empty_animation(){ + return false; +} +void SpineSprite::set_set_empty_animation(bool v){ + if(v && animation_state.is_valid() && skeleton.is_valid()) + animation_state->set_empty_animation(select_track_id, empty_animation_duration); +} + +bool SpineSprite::get_set_empty_animations(){ + return false; +} +void SpineSprite::set_set_empty_animations(bool v){ + if(v && animation_state.is_valid() && skeleton.is_valid()) + animation_state->set_empty_animations(empty_animation_duration); +} + +Array SpineSprite::get_bind_slot_nodes(){ + return bind_slot_nodes; +} +void SpineSprite::set_bind_slot_nodes(Array v) { + bind_slot_nodes = v; +} + +bool SpineSprite::get_overlap(){ + return overlap; +} +void SpineSprite::set_overlap(bool v){ + overlap = v; +} + +void SpineSprite::set_skin(Ref v) +{ + if(v != skin && skin.is_valid()){ + if(skin->is_connected("property_changed", this, "_on_skin_property_changed")) + skin->disconnect("property_changed", this, "_on_skin_property_changed"); + } + + skin = v; + + if(skin.is_valid()){ + if(!skin->is_connected("property_changed", this, "_on_skin_property_changed")) + skin->connect("property_changed", this, "_on_skin_property_changed"); + update_runtime_skin(); + } +} +Ref SpineSprite::get_skin(){ + return skin; +} +void SpineSprite::update_runtime_skin(){ + auto new_skin = gen_spine_skin_from_packed_resource(skin); + + if(new_skin.is_valid()) + { + skeleton->set_skin(new_skin); + skeleton->set_to_setup_pose(); + } +} +void SpineSprite::_on_skin_property_changed(){ + update_runtime_skin(); +} + +Ref SpineSprite::gen_spine_skin_from_packed_resource(Ref res){ + if(!(animation_state.is_valid() && skeleton.is_valid())) + return NULL; + if(!res.is_valid()) + return NULL; + if(res->get_skin_name().empty()) + return NULL; + auto exist_skin = animation_state_data_res->get_skeleton()->find_skin(res->get_skin_name()); + if(exist_skin.is_valid()) + { + return exist_skin; + } + + auto new_skin = Ref(memnew(SpineSkin))->init(res->get_skin_name()); + auto sub_skin_names = res->get_sub_skin_names(); + for(size_t i=0;iget_skeleton()->find_skin(skin_name); + if(sub_skin.is_valid()) + new_skin->add_skin(sub_skin); + } + return new_skin; +} + +void SpineSprite::bind_slot_with_node_2d(const String &slot_name, Node2D *n){ + auto node_path = n->get_path_to(this); + + // check if has the same binding + for(size_t i=0, size=bind_slot_nodes.size(); i= 2 && as[0].get_type() == Variant::STRING && as[1].get_type() == Variant::NODE_PATH){ + if(slot_name == as[0] && node_path == as[1]){ + return; + } + } + } + } + + Array bound; + bound.resize(2); + bound[0] = slot_name; + bound[1] = node_path; + + bind_slot_nodes.append(bound); +} +void SpineSprite::unbind_slot_with_node_2d(const String &slot_name, Node2D *n){ + auto node_path = n->get_path_to(this); + + for(size_t i=0, size=bind_slot_nodes.size(); i= 2 && as[0].get_type() == Variant::STRING && as[1].get_type() == Variant::NODE_PATH){ + if(slot_name == as[0] && node_path == as[1]){ + bind_slot_nodes.remove(i); + return; + } + } + } + } +} + +Transform2D SpineSprite::bone_get_global_transform(const String &bone_name) { + if (!animation_state.is_valid() && !skeleton.is_valid()) { + return get_global_transform(); + } + auto bone = skeleton->find_bone(bone_name); + if (!bone.is_valid()) { + print_error(vformat("Bone: '%s' not found.", bone_name)); + return get_global_transform(); + } + return bone->get_godot_global_transform(); +} + +void SpineSprite::bone_set_global_transform(const String &bone_name, Transform2D transform) { + if (!animation_state.is_valid() && !skeleton.is_valid()) { + return; + } + auto bone = skeleton->find_bone(bone_name); + if (!bone.is_valid()) { + return; + } + bone->set_godot_global_transform(transform); +} + +SpineSprite::ProcessMode SpineSprite::get_process_mode() { + return process_mode; +} + +void SpineSprite::set_process_mode(SpineSprite::ProcessMode v) { + process_mode = v; + set_process_internal(process_mode == ProcessMode_Process); + set_physics_process_internal(process_mode == ProcessMode_Physics); +} + +void SpineSprite::_get_property_list(List *p_list) const { + p_list->push_back(PropertyInfo(Variant::NIL, "Current Animation Editor", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_CATEGORY)); + p_list->push_back(PropertyInfo(Variant::BOOL, "setup_pose_trigger", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + p_list->push_back(PropertyInfo(Variant::BOOL, "clear_tracks_trigger", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + p_list->push_back(PropertyInfo(Variant::BOOL, "set_empty_animations_trigger", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + p_list->push_back(PropertyInfo(Variant::REAL, "empty_animation_duration")); + p_list->push_back(PropertyInfo(Variant::INT, "track_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + + for (size_t i=0; ipush_back(PropertyInfo(Variant::NIL, vformat("ID %d", (unsigned int)i), PROPERTY_HINT_NONE, prefix, PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::INT, vformat("%strack_id", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + + Vector anim_list; + if (skeleton.is_valid() && skeleton->get_data().is_valid()) { + skeleton->get_data()->get_animation_names(anim_list); + } + if (anim_list.empty()) anim_list.push_back("No Animation"); + p_list->push_back(PropertyInfo(Variant::STRING, vformat("%sanimation", prefix), PROPERTY_HINT_ENUM, String(",").join(anim_list), PROPERTY_USAGE_EDITOR)); + + p_list->push_back(PropertyInfo(Variant::REAL, vformat("%sdelay", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + + p_list->push_back(PropertyInfo(Variant::BOOL, vformat("%sloop", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + + p_list->push_back(PropertyInfo(Variant::BOOL, vformat("%sempty", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + p_list->push_back(PropertyInfo(Variant::REAL, vformat("%sempty_animation_duration", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + + p_list->push_back(PropertyInfo(Variant::BOOL, vformat("%sclear", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + } +} + +bool SpineSprite::_get(const StringName &p_property, Variant &r_value) const { + if (p_property == "setup_pose_trigger" || p_property == "clear_tracks_trigger" || p_property == "set_empty_animations_trigger") { + r_value = false; + return true; + } + if (p_property == "empty_animation_duration") { + r_value = empty_animation_duration; + return true; + } + if (p_property == "track_count") { + r_value = get_current_animation_count(); + return true; + } + String p = p_property; + if (p.size() > 2 && p[0] == 'c' && p[1] == 'a' && p[2] == '/') { + Vector sp = p.split("/"); + if (sp.size() > 2) { + int64_t id = sp[1].to_int64(); + if (id >= 0 && id < current_animations.size()) { + auto &key = sp[2]; + if (current_animations[id].get_type() == Variant::DICTIONARY) { + Dictionary dic = current_animations.get(id); + if (dic.has(key)) { + r_value = dic[key]; + } else { + if (key == "track_id") r_value = 0; + else if (key == "animation") r_value = ""; + else if (key == "loop") r_value = true; + else if (key == "empty") r_value = false; + else if (key == "empty_animation_duration") r_value = 0.3; + else if (key == "clear") r_value = false; + else if (key == "delay") r_value = 0; + else return false; + } + return true; + } + } + } + } + return false; +} + +bool SpineSprite::_set(const StringName &p_property, const Variant &p_value) { + if (p_property == "setup_pose_trigger") { + if (p_value) { + if (skeleton.is_valid()) { + skeleton->set_bones_to_setup_pose(); + skeleton->set_slots_to_setup_pose(); + } + } + return true; + } + if (p_property == "clear_tracks_trigger") { + if (p_value) { + if (animation_state.is_valid() && skeleton.is_valid()) { + animation_state->clear_tracks(); + } + } + return true; + } + if (p_property == "set_empty_animations_trigger") { + if (p_value) { + if (animation_state.is_valid() && skeleton.is_valid()) { + animation_state->set_empty_animations(empty_animation_duration); + } + } + return true; + } + if (p_property == "empty_animation_duration") { + empty_animation_duration = p_value; + return true; + } + if (p_property == "track_count") { + set_current_animation_count(p_value); + return true; + } + String p = p_property; + if (p.size() > 2 && p[0] == 'c' && p[1] == 'a' && p[2] == '/') { + Vector sp = p.split("/"); + if (sp.size() > 2) { + int64_t id = sp[1].to_int64(); + if (id >= 0 && id < current_animations.size()) { + auto &key = sp[2]; + if (current_animations[id].get_type() != Variant::DICTIONARY) { + current_animations.set(id, Dictionary()); + } + + Dictionary dic = current_animations.get(id); + dic[key] = p_value; + + _validate_and_play_current_animations(); + return true; + } + } + } + return false; +} + +int64_t SpineSprite::get_current_animation_count() const { + return current_animations.size(); +} + +void SpineSprite::set_current_animation_count(int64_t v) { + if (v < 0) v = 0; + while (current_animations.size() < v) { + Dictionary d; + d["track_id"] = current_animations.size(); + d["animation"] = ""; + d["delay"] = 0; + d["loop"] = true; + d["empty"] = false; + d["empty_animation_duration"] = 0.3; + d["clear"] = false; + current_animations.push_back(d); + } + while (current_animations.size() > v) { + if (animation_state.is_valid() && skeleton.is_valid()) { + if (current_animations.back().get_type() == Variant::DICTIONARY) { + Dictionary back = current_animations.back(); + if (back.has("track_id")) { + int64_t track_id = back["track_id"]; + int track_cnt = 0; + for (size_t i=0; iclear_track(track_id); + } + } + } + current_animations.pop_back(); + } + property_list_changed_notify(); +} + +void SpineSprite::_validate_and_play_current_animations() { + if(animation_state.is_valid() && skeleton.is_valid()){ + int64_t track_cnt = 0; + HashMap has_track; + for(size_t i=0; iadd_empty_animation(track_id, empty_animation_duration, delay); + else + animation_state->set_empty_animation(track_id, empty_animation_duration); + has_track[track_id] = true; + } else if (clear) { + animation_state->clear_track(track_id); + } else if (skeleton->get_data()->find_animation(animation).is_valid()) { + if (has_track.has(track_id)) + animation_state->add_animation(animation, delay, loop, track_id); + else + animation_state->set_animation(animation, loop, track_id); + has_track[track_id] = true; + } + + } + } + + if (track_cnt == 0) animation_state->clear_tracks(); + } +} + + + diff --git a/spine-godot/spine_godot/SpineSprite.h b/spine-godot/spine_godot/SpineSprite.h new file mode 100644 index 000000000..48c9d9f29 --- /dev/null +++ b/spine-godot/spine_godot/SpineSprite.h @@ -0,0 +1,162 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef GODOT_SPINESPRITE_H +#define GODOT_SPINESPRITE_H + +#include + +#include + +#include "SpineAnimationStateDataResource.h" +#include "SpineSkeleton.h" +#include "SpineAnimationState.h" +#include "SpineSpriteMeshInstance2D.h" +#include "PackedSpineSkinResource.h" + +class SpineSprite : public Node2D, public spine::AnimationStateListenerObject { + GDCLASS(SpineSprite, Node2D); +protected: + static void _bind_methods(); + + void _notification(int p_what); + + void _get_property_list(List *p_list) const; + bool _get(const StringName &p_property, Variant &r_value) const; + bool _set(const StringName &p_property, const Variant &p_value); + + void _validate_and_play_current_animations(); +public: + enum ProcessMode { + ProcessMode_Process, + ProcessMode_Physics, + ProcessMode_Manual + }; +private: + + Ref animation_state_data_res; + + Ref skeleton; + Ref animation_state; + + Vector mesh_instances; + + Array current_animations; + int select_track_id; + float empty_animation_duration; + + Array bind_slot_nodes; + bool overlap; + Ref skin; + + ProcessMode process_mode; + + spine::SkeletonClipping *skeleton_clipper; + +public: + SpineSprite(); + ~SpineSprite(); + + void set_animation_state_data_res(const Ref &a); + Ref get_animation_state_data_res(); + + Ref get_skeleton(); + Ref get_animation_state(); + + void gen_mesh_from_skeleton(Ref s); + void remove_mesh_instances(); + void remove_redundant_mesh_instances(); + + void update_mesh_from_skeleton(Ref s); + + void update_bind_slot_nodes(); + void update_bind_slot_node_transform(Ref bone, Node2D *node2d); + void update_bind_slot_node_draw_order(const String &slot_name, Node2D *node2d); + Node *find_child_node_by_node(Node *node); + + virtual void callback(spine::AnimationState* state, spine::EventType type, spine::TrackEntry* entry, spine::Event* event); + + void _on_animation_data_created(); + void _on_animation_data_changed(); + + void _update_all(float delta); + + // External feature functions + Array get_current_animations(); + void set_current_animations(Array as); + + int get_select_track_id(); + void set_select_track_id(int v); + + bool get_clear_track(); + void set_clear_track(bool v); + + bool get_clear_tracks(); + void set_clear_tracks(bool v); + + float get_empty_animation_duration(); + void set_empty_animation_duration(float v); + + bool get_set_empty_animation(); + void set_set_empty_animation(bool v); + + bool get_set_empty_animations(); + void set_set_empty_animations(bool v); + + Array get_bind_slot_nodes(); + void set_bind_slot_nodes(Array v); + + void bind_slot_with_node_2d(const String &slot_name, Node2D *n); + void unbind_slot_with_node_2d(const String &slot_name, Node2D *n); + + // bone manipulations + Transform2D bone_get_global_transform(const String &bone_name); + void bone_set_global_transform(const String &bone_name, Transform2D transform); + + //allow z-manipulation + bool get_overlap(); + void set_overlap(bool v); + + void set_skin(Ref v); + Ref get_skin(); + void _on_skin_property_changed(); + void update_runtime_skin(); + + Ref gen_spine_skin_from_packed_resource(Ref res); + + // current animation count + int64_t get_current_animation_count() const; + void set_current_animation_count(int64_t v); + + ProcessMode get_process_mode(); + void set_process_mode(ProcessMode v); +}; + +VARIANT_ENUM_CAST(SpineSprite::ProcessMode); +#endif //GODOT_SPINESPRITE_H diff --git a/spine-godot/spine_godot/SpineSpriteAnimateDialog.cpp b/spine-godot/spine_godot/SpineSpriteAnimateDialog.cpp new file mode 100644 index 000000000..2d102a451 --- /dev/null +++ b/spine-godot/spine_godot/SpineSpriteAnimateDialog.cpp @@ -0,0 +1,350 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineSpriteAnimateDialog.h" + +#ifdef TOOLS_ENABLED + +#include "SpineSprite.h" + +void SpineSpriteAnimateDialog::_bind_methods() { + ClassDB::bind_method(D_METHOD("_on_animate_button_pressed"), &SpineSpriteAnimateDialog::_on_animate_button_pressed); + ClassDB::bind_method(D_METHOD("_on_scene_tree_selected"), &SpineSpriteAnimateDialog::_on_scene_tree_selected); + ClassDB::bind_method(D_METHOD("_on_scene_tree_hide"), &SpineSpriteAnimateDialog::_on_scene_tree_hide); + ClassDB::bind_method(D_METHOD("_on_animate_dialog_action"), &SpineSpriteAnimateDialog::_on_animate_dialog_action); +} + +SpineSpriteAnimateDialog::SpineSpriteAnimateDialog() { + animate_dialog = memnew(ConfirmationDialog); + add_child(animate_dialog); + animate_dialog->get_ok()->set_text("Generate"); + animate_dialog_override_button = animate_dialog->add_button("Override", false, "override"); + animate_dialog_override_button->set_visible(false); + animate_dialog->set_title("Animations Generator"); + animate_dialog->set_resizable(true); + animate_dialog->set_custom_minimum_size(Vector2(550, 400)); + animate_dialog->set_hide_on_ok(false); + animate_dialog->connect("custom_action", this, "_on_animate_dialog_action"); + Vector al; + al.push_back("confirmed"); + animate_dialog->connect("confirmed", this, "_on_animate_dialog_action", al); + + auto vb = memnew(VBoxContainer); + animate_dialog->add_child(vb); + + auto scroll = memnew(ScrollContainer); + scroll->set_h_size_flags(SIZE_EXPAND_FILL); + scroll->set_v_size_flags(SIZE_EXPAND_FILL); +// vb->add_margin_child("Animations", scroll); + vb->add_child(scroll); + + animate_dialog_tree = memnew(Tree); + animate_dialog_tree->set_h_size_flags(SIZE_EXPAND_FILL); + animate_dialog_tree->set_v_size_flags(SIZE_EXPAND_FILL); + scroll->add_child(animate_dialog_tree); + + animate_dialog_tree->set_columns(3); + animate_dialog_tree->set_column_titles_visible(true); + animate_dialog_tree->set_hide_folding(true); + animate_dialog_tree->set_hide_root(true); + + animate_dialog_tree->set_column_title(0, TTR("Animation")); + animate_dialog_tree->set_column_title(1, TTR("Loop")); + animate_dialog_tree->set_column_title(2, TTR("Track ID")); + + animate_dialog_tree->create_item(); + add_row("test1"); + add_row("test12"); + add_row("test13"); + + auto l = memnew(Label); + l->set_text("W.I.P"); + vb->add_child(l); + + scene_tree_dialog = memnew(SceneTreeDialog); + scene_tree_dialog->set_title("Choose a AnimationPlayer to override, or choose none to create a new one."); + Vector valid_types; + valid_types.push_back("AnimationPlayer"); + scene_tree_dialog->get_scene_tree()->set_valid_types(valid_types); + scene_tree_dialog->get_scene_tree()->set_show_enabled_subscene(true); + scene_tree_dialog->get_ok()->hide(); + add_child(scene_tree_dialog); + scene_tree_dialog->connect("selected", this, "_on_scene_tree_selected"); + scene_tree_dialog->connect("popup_hide", this, "_on_scene_tree_hide"); + + error_dialog = memnew(AcceptDialog); + add_child(error_dialog); +} + +SpineSpriteAnimateDialog::~SpineSpriteAnimateDialog() { + +} + +void SpineSpriteAnimateDialog::set_animate_button(ToolButton *b) { + animate_button = b; + animate_button->connect("pressed", this, "_on_animate_button_pressed"); +} + +void SpineSpriteAnimateDialog::add_row(const String &animation, bool loop, int64_t track_id) { + auto item = animate_dialog_tree->create_item(); + item->set_text(0, animation); + + item->set_cell_mode(1, TreeItem::CELL_MODE_CHECK); + item->set_checked(1, loop); + item->set_editable(1, true); + + item->set_cell_mode(2, TreeItem::CELL_MODE_RANGE); + item->set_range(2, track_id); + item->set_editable(2, true); +} + +void SpineSpriteAnimateDialog::clear_tree() { + animate_dialog_tree->clear(); + animate_dialog_tree->create_item(); +} + +void SpineSpriteAnimateDialog::error(const String &text, const String &title) { + error_dialog->set_text(text); + error_dialog->set_title(title); + error_dialog->popup_centered(); +} + +#define ERROR_MSG(x) do{error(x);err=true;return;}while(false) +void SpineSpriteAnimateDialog::load_data_from_sprite(SpineSprite *sprite, bool &err) { + if (sprite == nullptr) { + ERROR_MSG("The sprite is null."); + } + if (!sprite->get_animation_state().is_valid() || !sprite->get_skeleton().is_valid()) { + ERROR_MSG("The sprite is not loaded."); + } + clear_tree(); + + Vector animations; + sprite->get_skeleton()->get_data()->get_animation_names(animations); + + for (size_t i=0; iget_animation_state().is_valid() || !sprite->get_skeleton().is_valid()) { + ERROR_MSG("The sprite is not loaded."); + } + auto p = sprite->get_parent(); + if (p == nullptr) { + p = sprite; + } + + auto anim_player = memnew(AnimationPlayer); + anim_player->set_name("AnimationPlayer"); + p->add_child(anim_player); + anim_player->set_owner(sprite->get_owner()); + anim_player->set_root(anim_player->get_path_to(p)); + + gen_animations(sprite, anim_player, get_data_from_tree(), MIN_TRACK_LENGTH, err); +} + +Dictionary SpineSpriteAnimateDialog::get_data_from_tree() { + Dictionary res; + if (animate_dialog_tree->get_root() == nullptr) return res; + + auto item = animate_dialog_tree->get_root()->get_children(); + while (item) { + Dictionary row; + row["loop"] = item->is_checked(1); + row["track_id"] = item->get_range(2); + + res[item->get_text(0)] = row; + item = item->get_next(); + } + return res; +} + +void SpineSpriteAnimateDialog::gen_animations(SpineSprite *sprite, AnimationPlayer *anim_player, const Dictionary &config, float min_duration, bool &err) { + if (sprite == nullptr || anim_player == nullptr) { + ERROR_MSG("The sprite or animation player is null."); + } + if (!sprite->get_animation_state().is_valid() || !sprite->get_skeleton().is_valid()) { + ERROR_MSG("The sprite is not loaded."); + } + if (anim_player->get_node_or_null(anim_player->get_root()) == nullptr) { + ERROR_MSG("The root node of animation player is null."); + } + + auto path_to_sprite = anim_player->get_node(anim_player->get_root())->get_path_to(sprite); + + Array animations = sprite->get_skeleton()->get_data()->get_animations(); + for (size_t i=0; i) animations[i]; + + Dictionary ca; + if (config.has(spine_anim->get_anim_name())) { + ca = config[spine_anim->get_anim_name()]; + } + + if (!ca.has("loop")) ca["loop"] = true; + if (!ca.has("track_id")) ca["track_id"] = 0; + + Array key_frame_value; + key_frame_value.push_back(gen_current_animation_data(spine_anim->get_anim_name(), ca["track_id"], ca["loop"], false, false, 0.3, 0)); + + auto anim = Ref(memnew(Animation)); + auto track_index = anim->add_track(Animation::TYPE_VALUE); + anim->set_length(min_duration > spine_anim->get_duration() ? min_duration : spine_anim->get_duration()); + anim->track_set_path(track_index, NodePath(vformat("%s:current_animations", path_to_sprite))); + anim->track_insert_key(track_index, 0.0, key_frame_value); + anim->value_track_set_update_mode(track_index, Animation::UPDATE_DISCRETE); + + if (anim_player->has_animation(spine_anim->get_anim_name())) + anim_player->remove_animation(spine_anim->get_anim_name()); + anim_player->add_animation(spine_anim->get_anim_name(), anim); + } + + err = false; +} + +Dictionary SpineSpriteAnimateDialog::gen_current_animation_data(const String &animation, int64_t track_id, bool loop, bool clear, bool empty, bool empty_duration, float delay) { + Dictionary res; + res["animation"] = animation; + res["track_id"] = track_id; + res["loop"] = loop; + res["clear"] = clear; + res["empty"] = empty; + res["empty_animation_duration"] = empty_duration; + res["delay"] = delay; + return res; +} + + +void SpineSpriteAnimateDialog::load_data_from_anim_player(AnimationPlayer *anim_player, bool &err) { + if (anim_player == nullptr) { + ERROR_MSG("The animation player is null."); + } + auto root = anim_player->get_node_or_null(anim_player->get_root()); + if (root == nullptr) return; + + auto sprite = get_node_or_null(spine_sprite_path); + if (sprite == nullptr) return; + + auto item = animate_dialog_tree->get_root()->get_children(); + while (item) { + String animation = item->get_text(0); + + auto anim = anim_player->get_animation(animation); + if (anim.is_valid() && anim->get_track_count() > 0) { + if (anim->track_get_type(0) == Animation::TYPE_VALUE) { + auto track_path = anim->track_get_path(0); + if (root->get_node_or_null(track_path) == sprite) { + if (anim->track_get_key_count(0) > 0) { + Array key_frame_value = anim->track_get_key_value(0, 0); + if (!key_frame_value.empty()) { + Dictionary _ca = key_frame_value.front(); + if (_ca.has("loop")) item->set_checked(1, _ca["loop"]); + if (_ca.has("track_id")) item->set_range(2, _ca["track_id"]); + } + } + } + } + + } + + item = item->get_next(); + } + + err = false; +} + +//----- Signals ----- +void SpineSpriteAnimateDialog::_on_scene_tree_selected(NodePath path) { +// print_line(vformat("anime: %s", path)); + auto node = get_node_or_null(path); + if (node == nullptr) { + error("The node you chose is null."); + return; + } + if (!node->is_class("AnimationPlayer")) { + error("The node you chose is not AnimationPlayer."); + return; + } + anim_player_path = path; +} + +void SpineSpriteAnimateDialog::_on_animate_button_pressed() { + anim_player_path = String(""); + auto node = (Node*)the_plugin->get_editor_interface()->get_selection()->get_selected_nodes().back(); + spine_sprite_path = node->get_path(); + +// print_line(vformat("sp: %s", spine_sprite_path)); + + animate_dialog_override_button->set_visible(false); + scene_tree_dialog->popup_centered_ratio(); +} + +void SpineSpriteAnimateDialog::_on_scene_tree_hide() { + animate_dialog->popup_centered(); + + bool err = false; + load_data_from_sprite((SpineSprite*)get_node_or_null(spine_sprite_path), err); + + if (err) animate_dialog->hide(); + + err = false; + auto node = get_node_or_null(anim_player_path); + if (node != nullptr) { + load_data_from_anim_player((AnimationPlayer*)node, err); + animate_dialog_override_button->set_visible(!err); + } else { + animate_dialog_override_button->set_visible(false); + } + + +} + +void SpineSpriteAnimateDialog::_on_animate_dialog_action(const String &act) { + bool err = false; + if (act == "confirmed") { + gen_new_animation_player((SpineSprite*)get_node_or_null(spine_sprite_path), err); + } else if (act == "override") { + gen_animations((SpineSprite*)get_node_or_null(spine_sprite_path), (AnimationPlayer*)get_node_or_null(anim_player_path), get_data_from_tree(), MIN_TRACK_LENGTH, err); + } + if (!err) { + animate_dialog->hide(); + } +} + + +#endif \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineSpriteAnimateDialog.h b/spine-godot/spine_godot/SpineSpriteAnimateDialog.h new file mode 100644 index 000000000..b4446ec78 --- /dev/null +++ b/spine-godot/spine_godot/SpineSpriteAnimateDialog.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 GODOT_SPINESPRITEANIMATEDIALOG_H +#define GODOT_SPINESPRITEANIMATEDIALOG_H + +#ifdef TOOLS_ENABLED +#include "editor/editor_node.h" + +class SpineSprite; + +class SpineSpriteAnimateDialog : public Control { + GDCLASS(SpineSpriteAnimateDialog, Control); + +protected: + static void _bind_methods(); + + AcceptDialog *error_dialog; + + ToolButton *animate_button; + EditorPlugin *the_plugin; + + ConfirmationDialog *animate_dialog; + Button *animate_dialog_override_button; + Tree *animate_dialog_tree; + SceneTreeDialog *scene_tree_dialog; + + NodePath spine_sprite_path; + NodePath anim_player_path; + + void add_row(const String &animation, bool loop=true, int64_t track_id=0); + void clear_tree(); + + void error(const String &text, const String &title="Error"); + + void load_data_from_sprite(SpineSprite *sprite, bool &err); + void load_data_from_anim_player(AnimationPlayer *anim_player, bool &err); + + Dictionary get_data_from_tree(); + + void gen_new_animation_player(SpineSprite *sprite, bool &err); + void gen_animations(SpineSprite *sprite, AnimationPlayer *anim_player, const Dictionary &config, float min_duration, bool &err); + Dictionary gen_current_animation_data(const String &animation, int64_t track_id, bool loop, bool clear, bool empty, bool empty_duration, float delay); +public: + SpineSpriteAnimateDialog(); + ~SpineSpriteAnimateDialog(); + + void set_animate_button(ToolButton *b); + inline ToolButton *get_animate_button() {return animate_button;} + + inline void set_plugin(EditorPlugin *p) {the_plugin = p;} + + void _on_animate_button_pressed(); + void _on_scene_tree_selected(NodePath path); + void _on_scene_tree_hide(); + void _on_animate_dialog_action(const String &act); +}; +#endif + +#endif //GODOT_SPINESPRITEANIMATEDIALOG_H diff --git a/spine-godot/spine_godot/SpineSpriteMeshInstance2D.cpp b/spine-godot/spine_godot/SpineSpriteMeshInstance2D.cpp new file mode 100644 index 000000000..ca0fc5cb2 --- /dev/null +++ b/spine-godot/spine_godot/SpineSpriteMeshInstance2D.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. + *****************************************************************************/ + +#include "SpineSpriteMeshInstance2D.h" + +#include "SpineBone.h" + +void SpineSpriteMeshInstance2D::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_slot"), &SpineSpriteMeshInstance2D::get_slot); + ClassDB::bind_method(D_METHOD("apply_transform_2d", "node2d"), &SpineSpriteMeshInstance2D::apply_transform_2d); +} + +SpineSpriteMeshInstance2D::SpineSpriteMeshInstance2D() {} +SpineSpriteMeshInstance2D::~SpineSpriteMeshInstance2D() {} + +Ref SpineSpriteMeshInstance2D::get_slot() { + return slot; +} + +void SpineSpriteMeshInstance2D::apply_transform_2d(Variant o){ + slot->get_bone()->apply_world_transform_2d(o); +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineSpriteMeshInstance2D.h b/spine-godot/spine_godot/SpineSpriteMeshInstance2D.h new file mode 100644 index 000000000..8458d74b2 --- /dev/null +++ b/spine-godot/spine_godot/SpineSpriteMeshInstance2D.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 GODOT_SPINESPRITEMESHINSTANCE2D_H +#define GODOT_SPINESPRITEMESHINSTANCE2D_H + +#include + +#include "SpineSlot.h" + +class SpineSpriteMeshInstance2D : public MeshInstance2D { + GDCLASS(SpineSpriteMeshInstance2D, MeshInstance2D); + +protected: + static void _bind_methods(); + + Ref slot; +public: + SpineSpriteMeshInstance2D(); + ~SpineSpriteMeshInstance2D(); + + inline void set_slot(Ref s){ + slot = s; + } + Ref get_slot(); + + void apply_transform_2d(Variant o); +}; + +#endif //GODOT_SPINESPRITEMESHINSTANCE2D_H diff --git a/spine-godot/spine_godot/SpineTimeline.cpp b/spine-godot/spine_godot/SpineTimeline.cpp new file mode 100644 index 000000000..d4233f1d4 --- /dev/null +++ b/spine-godot/spine_godot/SpineTimeline.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. + *****************************************************************************/ + +#include "SpineTimeline.h" + +#include "SpineSkeleton.h" +#include "SpineEvent.h" + +// enable more than 5 arguments of a method bind function +#include "core/method_bind_ext.gen.inc" + +void SpineTimeline::_bind_methods() { + ClassDB::bind_method(D_METHOD("apply", "skeleton", "lastTime", "time", "pEvents", "alpha", "blend", "direction"), &SpineTimeline::apply); + ClassDB::bind_method(D_METHOD("get_frame_entries"), &SpineTimeline::get_frame_entries); + ClassDB::bind_method(D_METHOD("get_frame_count"), &SpineTimeline::get_frame_count); + ClassDB::bind_method(D_METHOD("get_frames"), &SpineTimeline::get_frames); + ClassDB::bind_method(D_METHOD("get_duration"), &SpineTimeline::get_duration); + ClassDB::bind_method(D_METHOD("getPropertyIds"), &SpineTimeline::getPropertyIds); +} + + +SpineTimeline::SpineTimeline():timeline(nullptr) { + +} + +SpineTimeline::~SpineTimeline() { + +} + +void SpineTimeline::apply(Ref skeleton, float lastTime, float time, Array pEvents, float alpha, + SpineConstant::MixBlend blend, SpineConstant::MixDirection direction) { + spine::Vector events; + events.setSize(pEvents.size(), nullptr); + for (size_t i=0; i)pEvents[i])->get_spine_object(); + } + + timeline->apply(*(skeleton->get_spine_object()), lastTime, time, &events, alpha, (spine::MixBlend) blend, (spine::MixDirection) direction); +} + +int64_t SpineTimeline::get_frame_entries() { + return timeline->getFrameEntries(); +} + +int64_t SpineTimeline::get_frame_count() { + return timeline->getFrameCount(); +} + +Array SpineTimeline::get_frames() { + auto &frames = timeline->getFrames(); + Array res; + res.resize(frames.size()); + + for (size_t i=0; igetDuration(); +} + +Array SpineTimeline::getPropertyIds() { + auto &ids = timeline->getPropertyIds(); + Array res; + res.resize(ids.size()); + + for (size_t i=0; i + void apply(Ref skeleton, float lastTime, float time, Array pEvents, float alpha, SpineConstant::MixBlend blend, SpineConstant::MixDirection direction); + + int64_t get_frame_entries(); + + int64_t get_frame_count(); + + // Vector + Array get_frames(); + + float get_duration(); + + // Vector + Array getPropertyIds(); +}; + + +#endif //GODOT_SPINETIMELINE_H diff --git a/spine-godot/spine_godot/SpineTrackEntry.cpp b/spine-godot/spine_godot/SpineTrackEntry.cpp new file mode 100644 index 000000000..2906e7a52 --- /dev/null +++ b/spine-godot/spine_godot/SpineTrackEntry.cpp @@ -0,0 +1,265 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineTrackEntry.h" + +void SpineTrackEntry::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_track_index"), &SpineTrackEntry::get_track_index); + + ClassDB::bind_method(D_METHOD("get_animation"), &SpineTrackEntry::get_animation); + + ClassDB::bind_method(D_METHOD("get_loop"), &SpineTrackEntry::get_loop); + ClassDB::bind_method(D_METHOD("set_loop", "v"), &SpineTrackEntry::set_loop); + + ClassDB::bind_method(D_METHOD("get_hold_previous"), &SpineTrackEntry::get_hold_previous); + ClassDB::bind_method(D_METHOD("set_hold_previous", "v"), &SpineTrackEntry::set_hold_previous); + + ClassDB::bind_method(D_METHOD("get_reverse"), &SpineTrackEntry::get_reverse); + ClassDB::bind_method(D_METHOD("set_reverse", "v"), &SpineTrackEntry::set_reverse); + + ClassDB::bind_method(D_METHOD("get_delay"), &SpineTrackEntry::get_delay); + ClassDB::bind_method(D_METHOD("set_delay", "v"), &SpineTrackEntry::set_delay); + + ClassDB::bind_method(D_METHOD("get_track_time"), &SpineTrackEntry::get_track_time); + ClassDB::bind_method(D_METHOD("set_track_time", "v"), &SpineTrackEntry::set_track_time); + + ClassDB::bind_method(D_METHOD("get_track_end"), &SpineTrackEntry::get_track_end); + ClassDB::bind_method(D_METHOD("set_track_end", "v"), &SpineTrackEntry::set_track_end); + + ClassDB::bind_method(D_METHOD("get_animation_start"), &SpineTrackEntry::get_animation_start); + ClassDB::bind_method(D_METHOD("set_animation_start", "v"), &SpineTrackEntry::set_animation_start); + + ClassDB::bind_method(D_METHOD("get_animation_last"), &SpineTrackEntry::get_animation_last); + ClassDB::bind_method(D_METHOD("set_animation_last", "v"), &SpineTrackEntry::set_animation_last); + + ClassDB::bind_method(D_METHOD("get_animation_time"), &SpineTrackEntry::get_animation_time); + + ClassDB::bind_method(D_METHOD("get_time_scale"), &SpineTrackEntry::get_time_scale); + ClassDB::bind_method(D_METHOD("set_time_scale", "v"), &SpineTrackEntry::set_time_scale); + + ClassDB::bind_method(D_METHOD("get_alpha"), &SpineTrackEntry::get_alpha); + ClassDB::bind_method(D_METHOD("set_alpha", "v"), &SpineTrackEntry::set_alpha); + + ClassDB::bind_method(D_METHOD("get_event_threshold"), &SpineTrackEntry::get_event_threshold); + ClassDB::bind_method(D_METHOD("set_event_threshold", "v"), &SpineTrackEntry::set_event_threshold); + + ClassDB::bind_method(D_METHOD("get_attachment_threshold"), &SpineTrackEntry::get_attachment_threshold); + ClassDB::bind_method(D_METHOD("set_attachment_threshold", "v"), &SpineTrackEntry::set_attachment_threshold); + + ClassDB::bind_method(D_METHOD("get_draw_order_threshold"), &SpineTrackEntry::get_draw_order_threshold); + ClassDB::bind_method(D_METHOD("set_draw_order_threshold", "v"), &SpineTrackEntry::set_draw_order_threshold); + + ClassDB::bind_method(D_METHOD("get_next"), &SpineTrackEntry::get_next); + + ClassDB::bind_method(D_METHOD("is_complete"), &SpineTrackEntry::is_complete); + + ClassDB::bind_method(D_METHOD("get_mix_time"), &SpineTrackEntry::get_mix_time); + ClassDB::bind_method(D_METHOD("set_mix_time", "v"), &SpineTrackEntry::set_mix_time); + + ClassDB::bind_method(D_METHOD("get_mix_duration"), &SpineTrackEntry::get_mix_duration); + ClassDB::bind_method(D_METHOD("set_mix_duration", "v"), &SpineTrackEntry::set_mix_duration); + + ClassDB::bind_method(D_METHOD("get_mix_blend"), &SpineTrackEntry::get_mix_blend); + ClassDB::bind_method(D_METHOD("set_mix_blend", "v"), &SpineTrackEntry::set_mix_blend); + + ClassDB::bind_method(D_METHOD("get_mixing_from"), &SpineTrackEntry::get_mixing_from); + ClassDB::bind_method(D_METHOD("get_mixing_to"), &SpineTrackEntry::get_mixing_to); + + ClassDB::bind_method(D_METHOD("reset_rotation_directions"), &SpineTrackEntry::reset_rotation_directions); + + BIND_ENUM_CONSTANT(MIXBLEND_SETUP); + BIND_ENUM_CONSTANT(MIXBLEND_FIRST); + BIND_ENUM_CONSTANT(MIXBLEND_REPLACE); + BIND_ENUM_CONSTANT(MIXBLEND_ADD); +} + +SpineTrackEntry::SpineTrackEntry():track_entry(NULL) {} +SpineTrackEntry::~SpineTrackEntry() {} + +int SpineTrackEntry::get_track_index(){ + return track_entry->getTrackIndex(); +} + +Ref SpineTrackEntry::get_animation(){ + Ref gd_anim(memnew(SpineAnimation)); + auto anim = track_entry->getAnimation(); + if(anim == NULL) return NULL; + gd_anim->set_spine_object(anim); + return gd_anim; +} + +bool SpineTrackEntry::get_loop(){ + return track_entry->getLoop(); +} +void SpineTrackEntry::set_loop(bool v){ + track_entry->setLoop(v); +} + +bool SpineTrackEntry::get_hold_previous(){ + return track_entry->getHoldPrevious(); +} +void SpineTrackEntry::set_hold_previous(bool v){ + track_entry->setHoldPrevious(v); +} + +float SpineTrackEntry::get_delay(){ + return track_entry->getDelay(); +} +void SpineTrackEntry::set_delay(float v){ + track_entry->setDelay(v); +} + +float SpineTrackEntry::get_track_time(){ + return track_entry->getTrackTime(); +} +void SpineTrackEntry::set_track_time(float v){ + track_entry->setTrackTime(v); +} + +float SpineTrackEntry::get_track_end(){ + return track_entry->getTrackEnd(); +} +void SpineTrackEntry::set_track_end(float v){ + track_entry->setTrackEnd(v); +} + +float SpineTrackEntry::get_animation_start(){ + return track_entry->getAnimationStart(); +} +void SpineTrackEntry::set_animation_start(float v){ + track_entry->setAnimationStart(v); +} + +float SpineTrackEntry::get_animation_last(){ + return track_entry->getAnimationLast(); +} +void SpineTrackEntry::set_animation_last(float v){ + track_entry->setAnimationLast(v); +} + +float SpineTrackEntry::get_animation_time(){ + return track_entry->getAnimationTime(); +} + +float SpineTrackEntry::get_time_scale(){ + return track_entry->getTimeScale(); +} +void SpineTrackEntry::set_time_scale(float v){ + track_entry->setTimeScale(v); +} + +float SpineTrackEntry::get_alpha(){ + return track_entry->getAlpha(); +} +void SpineTrackEntry::set_alpha(float v){ + track_entry->setAlpha(v); +} + +float SpineTrackEntry::get_event_threshold(){ + return track_entry->getEventThreshold(); +} +void SpineTrackEntry::set_event_threshold(float v){ + track_entry->setEventThreshold(v); +} + +float SpineTrackEntry::get_attachment_threshold(){ + return track_entry->getAttachmentThreshold(); +} +void SpineTrackEntry::set_attachment_threshold(float v){ + track_entry->setAttachmentThreshold(v); +} + +float SpineTrackEntry::get_draw_order_threshold(){ + return track_entry->getDrawOrderThreshold(); +} +void SpineTrackEntry::set_draw_order_threshold(float v){ + track_entry->setDrawOrderThreshold(v); +} + +Ref SpineTrackEntry::get_next(){ + Ref gd_entry(memnew(SpineTrackEntry)); + auto entry = track_entry->getNext(); + if(entry == NULL) return NULL; + gd_entry->set_spine_object(entry); + return gd_entry; +} + +bool SpineTrackEntry::is_complete(){ + return track_entry->isComplete(); +} + +float SpineTrackEntry::get_mix_time(){ + return track_entry->getMixTime(); +} +void SpineTrackEntry::set_mix_time(float v){ + track_entry->setMixTime(v); +} + +float SpineTrackEntry::get_mix_duration(){ + return track_entry->getMixDuration(); +} +void SpineTrackEntry::set_mix_duration(float v){ + track_entry->setMixDuration(v); +} + +SpineTrackEntry::MixBlend SpineTrackEntry::get_mix_blend(){ + int mb = track_entry->getMixBlend(); + return (MixBlend) mb; +} +void SpineTrackEntry::set_mix_blend(SpineTrackEntry::MixBlend v){ + int mb = (int) v; + track_entry->setMixBlend((spine::MixBlend)mb); +} + +Ref SpineTrackEntry::get_mixing_from(){ + Ref gd_entry(memnew(SpineTrackEntry)); + auto entry = track_entry->getMixingFrom(); + if(entry == NULL) return NULL; + gd_entry->set_spine_object(entry); + return gd_entry; +} +Ref SpineTrackEntry::get_mixing_to(){ + Ref gd_entry(memnew(SpineTrackEntry)); + auto entry = track_entry->getMixingTo(); + if(entry == NULL) return NULL; + gd_entry->set_spine_object(entry); + return gd_entry; +} + +void SpineTrackEntry::reset_rotation_directions(){ + track_entry->resetRotationDirections(); +} + +bool SpineTrackEntry::get_reverse() { + return track_entry->getReverse(); +} + +void SpineTrackEntry::set_reverse(bool v) { + track_entry->setReverse(v); +} diff --git a/spine-godot/spine_godot/SpineTrackEntry.h b/spine-godot/spine_godot/SpineTrackEntry.h new file mode 100644 index 000000000..aad56ec4a --- /dev/null +++ b/spine-godot/spine_godot/SpineTrackEntry.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 GODOT_SPINETRACKENTRY_H +#define GODOT_SPINETRACKENTRY_H + +#include "core/variant_parser.h" + +#include + +#include "SpineAnimation.h" + +class SpineTrackEntry : public Reference{ + GDCLASS(SpineTrackEntry, Reference); + +protected: + static void _bind_methods(); + +private: + spine::TrackEntry *track_entry; + +public: + SpineTrackEntry(); + ~SpineTrackEntry(); + + inline void set_spine_object(spine::TrackEntry *t){ + track_entry = t; + } + inline spine::TrackEntry *get_spine_object(){ + return track_entry; + } + + enum MixBlend { + MIXBLEND_SETUP = 0, + MIXBLEND_FIRST, + MIXBLEND_REPLACE, + MIXBLEND_ADD + }; + + int get_track_index(); + + Ref get_animation(); + + bool get_loop(); + void set_loop(bool v); + + bool get_hold_previous(); + void set_hold_previous(bool v); + + bool get_reverse(); + void set_reverse(bool v); + + float get_delay(); + void set_delay(float v); + + float get_track_time(); + void set_track_time(float v); + + float get_track_end(); + void set_track_end(float v); + + float get_animation_start(); + void set_animation_start(float v); + + float get_animation_last(); + void set_animation_last(float v); + + float get_animation_time(); + + float get_time_scale(); + void set_time_scale(float v); + + float get_alpha(); + void set_alpha(float v); + + float get_event_threshold(); + void set_event_threshold(float v); + + float get_attachment_threshold(); + void set_attachment_threshold(float v); + + float get_draw_order_threshold(); + void set_draw_order_threshold(float v); + + Ref get_next(); + + bool is_complete(); + + float get_mix_time(); + void set_mix_time(float v); + + float get_mix_duration(); + void set_mix_duration(float v); + + MixBlend get_mix_blend(); + void set_mix_blend(MixBlend v); + + Ref get_mixing_from(); + Ref get_mixing_to(); + + void reset_rotation_directions(); +}; + +VARIANT_ENUM_CAST(SpineTrackEntry::MixBlend); +#endif //GODOT_SPINETRACKENTRY_H diff --git a/spine-godot/spine_godot/SpineTransformConstraint.cpp b/spine-godot/spine_godot/SpineTransformConstraint.cpp new file mode 100644 index 000000000..15450361e --- /dev/null +++ b/spine-godot/spine_godot/SpineTransformConstraint.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. + *****************************************************************************/ + +#include "SpineTransformConstraint.h" + +void SpineTransformConstraint::_bind_methods() { + ClassDB::bind_method(D_METHOD("update"), &SpineTransformConstraint::update); + ClassDB::bind_method(D_METHOD("get_data"), &SpineTransformConstraint::get_data); + ClassDB::bind_method(D_METHOD("get_bones"), &SpineTransformConstraint::get_bones); + ClassDB::bind_method(D_METHOD("get_target"), &SpineTransformConstraint::get_target); + ClassDB::bind_method(D_METHOD("set_target", "v"), &SpineTransformConstraint::set_target); + ClassDB::bind_method(D_METHOD("get_mix_rotate"), &SpineTransformConstraint::get_mix_rotate); + ClassDB::bind_method(D_METHOD("set_mix_rotate", "v"), &SpineTransformConstraint::set_mix_rotate); + ClassDB::bind_method(D_METHOD("get_mix_x"), &SpineTransformConstraint::get_mix_x); + ClassDB::bind_method(D_METHOD("set_mix_x", "v"), &SpineTransformConstraint::set_mix_x); + ClassDB::bind_method(D_METHOD("get_mix_y"), &SpineTransformConstraint::get_mix_y); + ClassDB::bind_method(D_METHOD("set_mix_y", "v"), &SpineTransformConstraint::set_mix_y); + ClassDB::bind_method(D_METHOD("get_mix_scale_x"), &SpineTransformConstraint::get_mix_scale_x); + ClassDB::bind_method(D_METHOD("set_mix_scale_x", "v"), &SpineTransformConstraint::set_mix_scale_x); + ClassDB::bind_method(D_METHOD("get_mix_scale_y"), &SpineTransformConstraint::get_mix_scale_y); + ClassDB::bind_method(D_METHOD("set_mix_scale_y", "v"), &SpineTransformConstraint::set_mix_scale_y); + ClassDB::bind_method(D_METHOD("get_mix_shear_y"), &SpineTransformConstraint::get_mix_shear_y); + ClassDB::bind_method(D_METHOD("set_mix_shear_y", "v"), &SpineTransformConstraint::set_mix_shear_y); + ClassDB::bind_method(D_METHOD("is_active"), &SpineTransformConstraint::is_active); + ClassDB::bind_method(D_METHOD("set_active", "v"), &SpineTransformConstraint::set_active); +} + +SpineTransformConstraint::SpineTransformConstraint():transform_constraint(NULL) {} +SpineTransformConstraint::~SpineTransformConstraint() {} + +void SpineTransformConstraint::update(){ + transform_constraint->update(); +} + +int SpineTransformConstraint::get_order(){ + return transform_constraint->getOrder(); +} + +Ref SpineTransformConstraint::get_data(){ + auto &d = transform_constraint->getData(); + Ref gd_d(memnew(SpineTransformConstraintData)); + gd_d->set_spine_object(&d); + return gd_d; +} + +Array SpineTransformConstraint::get_bones(){ + auto &bs = transform_constraint->getBones(); + Array gd_bs; + gd_bs.resize(bs.size()); + for(size_t i=0; i(NULL); + Ref gd_b(memnew(SpineBone)); + gd_b->set_spine_object(b); + gd_bs[i] = gd_b; + } + return gd_bs; +} + +Ref SpineTransformConstraint::get_target(){ + auto b = transform_constraint->getTarget(); + if(b == NULL) return NULL; + Ref gd_b(memnew(SpineBone)); + gd_b->set_spine_object(b); + return gd_b; +} +void SpineTransformConstraint::set_target(Ref v){ + if(v.is_valid()){ + transform_constraint->setTarget(v->get_spine_object()); + } else{ + transform_constraint->setTarget(NULL); + } +} + +float SpineTransformConstraint::get_mix_rotate(){ + return transform_constraint->getMixRotate(); +} +void SpineTransformConstraint::set_mix_rotate(float v){ + transform_constraint->setMixRotate(v); +} + +float SpineTransformConstraint::get_mix_x(){ + return transform_constraint->getMixX(); +} +void SpineTransformConstraint::set_mix_x(float v){ + transform_constraint->setMixX(v); +} + +float SpineTransformConstraint::get_mix_y(){ + return transform_constraint->getMixY(); +} +void SpineTransformConstraint::set_mix_y(float v){ + transform_constraint->setMixY(v); +} + +float SpineTransformConstraint::get_mix_scale_x(){ + return transform_constraint->getMixScaleX(); +} +void SpineTransformConstraint::set_mix_scale_x(float v){ + transform_constraint->setMixScaleX(v); +} + +float SpineTransformConstraint::get_mix_scale_y(){ + return transform_constraint->getMixScaleY(); +} +void SpineTransformConstraint::set_mix_scale_y(float v){ + transform_constraint->setMixScaleY(v); +} + +float SpineTransformConstraint::get_mix_shear_y(){ + return transform_constraint->getMixShearY(); +} +void SpineTransformConstraint::set_mix_shear_y(float v){ + transform_constraint->setMixShearY(v); +} + +bool SpineTransformConstraint::is_active(){ + return transform_constraint->isActive(); +} +void SpineTransformConstraint::set_active(bool v){ + transform_constraint->setActive(v); +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineTransformConstraint.h b/spine-godot/spine_godot/SpineTransformConstraint.h new file mode 100644 index 000000000..a2b3a2be3 --- /dev/null +++ b/spine-godot/spine_godot/SpineTransformConstraint.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 GODOT_SPINETRANSFORMCONSTRAINT_H +#define GODOT_SPINETRANSFORMCONSTRAINT_H + +#include "core/variant_parser.h" + +#include + +#include "SpineTransformConstraintData.h" +#include "SpineBone.h" + +class SpineTransformConstraint : public Reference{ + GDCLASS(SpineTransformConstraint, Reference); + +protected: + static void _bind_methods(); + +private: + spine::TransformConstraint *transform_constraint; + +public: + SpineTransformConstraint(); + ~SpineTransformConstraint(); + + inline void set_spine_object(spine::TransformConstraint *tc){ + transform_constraint = tc; + } + inline spine::TransformConstraint *get_spine_object(){ + return transform_constraint; + } + + void update(); + + int get_order(); + + Ref get_data(); + + Array get_bones(); + + Ref get_target(); + void set_target(Ref v); + + float get_mix_rotate(); + void set_mix_rotate(float v); + + float get_mix_x(); + void set_mix_x(float v); + + float get_mix_y(); + void set_mix_y(float v); + + float get_mix_scale_x(); + void set_mix_scale_x(float v); + + float get_mix_scale_y(); + void set_mix_scale_y(float v); + + float get_mix_shear_y(); + void set_mix_shear_y(float v); + + bool is_active(); + void set_active(bool v); +}; + +#endif //GODOT_SPINETRANSFORMCONSTRAINT_H diff --git a/spine-godot/spine_godot/SpineTransformConstraintData.cpp b/spine-godot/spine_godot/SpineTransformConstraintData.cpp new file mode 100644 index 000000000..af62fea32 --- /dev/null +++ b/spine-godot/spine_godot/SpineTransformConstraintData.cpp @@ -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. + *****************************************************************************/ + +#include "SpineTransformConstraintData.h" + +void SpineTransformConstraintData::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_all_bone_data"), &SpineTransformConstraintData::get_bones); + ClassDB::bind_method(D_METHOD("get_target"), &SpineTransformConstraintData::get_target); + ClassDB::bind_method(D_METHOD("get_mix_rotate"), &SpineTransformConstraintData::get_mix_rotate); + ClassDB::bind_method(D_METHOD("get_mix_x"), &SpineTransformConstraintData::get_mix_x); + ClassDB::bind_method(D_METHOD("get_mix_y"), &SpineTransformConstraintData::get_mix_y); + ClassDB::bind_method(D_METHOD("get_mix_scale_x"), &SpineTransformConstraintData::get_mix_scale_x); + ClassDB::bind_method(D_METHOD("get_mix_scale_y"), &SpineTransformConstraintData::get_mix_scale_y); + ClassDB::bind_method(D_METHOD("get_mix_shear_y"), &SpineTransformConstraintData::get_mix_shear_y); + ClassDB::bind_method(D_METHOD("get_offset_rotation"), &SpineTransformConstraintData::get_offset_rotation); + ClassDB::bind_method(D_METHOD("get_offset_x"), &SpineTransformConstraintData::get_offset_x); + ClassDB::bind_method(D_METHOD("get_offset_y"), &SpineTransformConstraintData::get_offset_y); + ClassDB::bind_method(D_METHOD("get_offset_scale_x"), &SpineTransformConstraintData::get_offset_scale_x); + ClassDB::bind_method(D_METHOD("get_offset_scale_y"), &SpineTransformConstraintData::get_offset_scale_y); + ClassDB::bind_method(D_METHOD("get_offset_shear_y"), &SpineTransformConstraintData::get_offset_shear_y); + ClassDB::bind_method(D_METHOD("is_relative"), &SpineTransformConstraintData::is_relative); + ClassDB::bind_method(D_METHOD("is_local"), &SpineTransformConstraintData::is_local); +} + +SpineTransformConstraintData::SpineTransformConstraintData() {} +SpineTransformConstraintData::~SpineTransformConstraintData() {} + +Array SpineTransformConstraintData::get_bones(){ + auto bs = get_spine_data()->getBones(); + Array gd_bs; + gd_bs.resize(bs.size()); + for(size_t i=0; i < bs.size(); ++i){ + if(bs[i] == NULL) gd_bs[i] = Ref(NULL); + else { + Ref gd_b(memnew(SpineBoneData)); + gd_b->set_spine_object(bs[i]); + gd_bs[i] = gd_b; + } + } + return gd_bs; +} +Ref SpineTransformConstraintData::get_target(){ + auto b = get_spine_data()->getTarget(); + if(b == NULL) return NULL; + Ref gd_b(memnew(SpineBoneData)); + gd_b->set_spine_object(b); + return gd_b; +} +float SpineTransformConstraintData::get_mix_rotate(){ + return get_spine_data()->getMixRotate(); +} +float SpineTransformConstraintData::get_mix_x(){ + return get_spine_data()->getMixX(); +} +float SpineTransformConstraintData::get_mix_y(){ + return get_spine_data()->getMixY(); +} +float SpineTransformConstraintData::get_mix_scale_x(){ + return get_spine_data()->getMixScaleX(); +} +float SpineTransformConstraintData::get_mix_scale_y(){ + return get_spine_data()->getMixScaleY(); +} +float SpineTransformConstraintData::get_mix_shear_y(){ + return get_spine_data()->getMixShearY(); +} + +float SpineTransformConstraintData::get_offset_rotation(){ + return get_spine_data()->getOffsetRotation(); +} +float SpineTransformConstraintData::get_offset_x(){ + return get_spine_data()->getOffsetX(); +} +float SpineTransformConstraintData::get_offset_y(){ + return get_spine_data()->getOffsetY(); +} +float SpineTransformConstraintData::get_offset_scale_x(){ + return get_spine_data()->getOffsetScaleX(); +} +float SpineTransformConstraintData::get_offset_scale_y(){ + return get_spine_data()->getOffsetScaleY(); +} +float SpineTransformConstraintData::get_offset_shear_y(){ + return get_spine_data()->getOffsetShearY(); +} + +bool SpineTransformConstraintData::is_relative(){ + return get_spine_data()->isRelative(); +} +bool SpineTransformConstraintData::is_local(){ + return get_spine_data()->isLocal(); +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineTransformConstraintData.h b/spine-godot/spine_godot/SpineTransformConstraintData.h new file mode 100644 index 000000000..5408d0e5b --- /dev/null +++ b/spine-godot/spine_godot/SpineTransformConstraintData.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 GODOT_SPINETRANSFORMCONSTRAINTDATA_H +#define GODOT_SPINETRANSFORMCONSTRAINTDATA_H + +#include "core/variant_parser.h" + +#include + +#include "SpineConstraintData.h" +#include "SpineBoneData.h" + +class SpineTransformConstraintData : public SpineConstraintData { + GDCLASS(SpineTransformConstraintData, SpineConstraintData); + +protected: + static void _bind_methods(); + +public: + SpineTransformConstraintData(); + ~SpineTransformConstraintData(); + + virtual inline spine::TransformConstraintData *get_spine_data(){ + return (spine::TransformConstraintData*) SpineConstraintData::get_spine_object(); + } + + Array get_bones(); + Ref get_target(); + float get_mix_rotate(); + float get_mix_x(); + float get_mix_y(); + float get_mix_scale_x(); + float get_mix_scale_y(); + float get_mix_shear_y(); + + float get_offset_rotation(); + float get_offset_x(); + float get_offset_y(); + float get_offset_scale_x(); + float get_offset_scale_y(); + float get_offset_shear_y(); + + bool is_relative(); + bool is_local(); +}; + +#endif //GODOT_SPINETRANSFORMCONSTRAINTDATA_H diff --git a/spine-godot/spine_godot/config.py b/spine-godot/spine_godot/config.py new file mode 100644 index 000000000..827e2c435 --- /dev/null +++ b/spine-godot/spine_godot/config.py @@ -0,0 +1,5 @@ +def can_build(env, platform): + return True + +def configure(env): + pass \ No newline at end of file diff --git a/spine-godot/spine_godot/register_types.cpp b/spine-godot/spine_godot/register_types.cpp new file mode 100644 index 000000000..d5aa1746e --- /dev/null +++ b/spine-godot/spine_godot/register_types.cpp @@ -0,0 +1,151 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "register_types.h" + +#include "core/class_db.h" + +#include "spine_runtime.h" +#include "SpineAtlasResource.h" +#include "ResourceFormatLoaderSpineAtlas.h" +#include "ResourceFormatSaverSpineAtlas.h" +#include "SpineSkeletonDataResource.h" +#include "ResourceFormatLoaderSpineSkeletonJsonData.h" +#include "ResourceFormatSaverSpineSkeletonJsonData.h" +#include "SpineSprite.h" +#include "SpineAnimationStateDataResource.h" +#include "SpineSkeleton.h" +#include "SpineAnimationState.h" +#include "SpineEventData.h" +#include "SpineEvent.h" +#include "SpineTrackEntry.h" +#include "SpineBoneData.h" +#include "SpineSlotData.h" +#include "SpineAttachment.h" +#include "SpineSkinAttachmentMapEntries.h" +#include "SpineConstraintData.h" +#include "SpineSkin.h" +#include "SpineIkConstraintData.h" +#include "SpineTransformConstraintData.h" +#include "SpinePathConstraintData.h" +#include "SpineSpriteMeshInstance2D.h" +#include "PackedSpineSkinResource.h" +#include "SpineTimeline.h" +#include "SpineConstant.h" +#include "SpineCollisionShapeProxy.h" +#include "SpineSpriteAnimateDialog.h" + + +static Ref atlas_loader; +static Ref atlas_saver; +static Ref json_skeleton_loader; +static Ref json_skeleton_saver; + +// editor plugin +#ifdef TOOLS_ENABLED +#include "editor/editor_export.h" +#include "editor/editor_node.h" + +#include "SpineRuntimeEditorPlugin.h" + +static void editor_init_callback() { + EditorNode::get_singleton()->add_editor_plugin(memnew(SpineRuntimeEditorPlugin(EditorNode::get_singleton()))); +} + + +#endif + +void register_spine_godot_types(){ +#ifdef TOOLS_ENABLED + ClassDB::register_class(); + + EditorNode::add_init_callback(editor_init_callback); + +#endif + + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + + atlas_loader.instance(); + ResourceLoader::add_resource_format_loader(atlas_loader); + + atlas_saver.instance(); + ResourceSaver::add_resource_format_saver(atlas_saver); + + json_skeleton_loader.instance(); + ResourceLoader::add_resource_format_loader(json_skeleton_loader); + + json_skeleton_saver.instance(); + ResourceSaver::add_resource_format_saver(json_skeleton_saver); + +} + +void unregister_spine_godot_types(){ + ResourceLoader::remove_resource_format_loader(atlas_loader); + atlas_loader.unref(); + + ResourceSaver::remove_resource_format_saver(atlas_saver); + atlas_saver.unref(); + + ResourceLoader::remove_resource_format_loader(json_skeleton_loader); + json_skeleton_loader.unref(); + + ResourceSaver::remove_resource_format_saver(json_skeleton_saver); + json_skeleton_saver.unref(); +} \ No newline at end of file diff --git a/spine-godot/spine_godot/register_types.h b/spine-godot/spine_godot/register_types.h new file mode 100644 index 000000000..694761811 --- /dev/null +++ b/spine-godot/spine_godot/register_types.h @@ -0,0 +1,32 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +void register_spine_godot_types(); +void unregister_spine_godot_types(); + From 0b0800143a0e6391b45de746b7978cc67e6ba027 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Tue, 28 Sep 2021 22:36:16 +0200 Subject: [PATCH 02/18] [godot] Test scene, minor clean-up. --- .gitignore | 2 + spine-godot/example/project.godot | 1 + spine-godot/example/spineboy-pro.spjson | 8699 +++++++++++++++++ spine-godot/example/spineboy.atlas | 101 + spine-godot/example/spineboy.atlas.import | 14 + spine-godot/example/spineboy.gd | 17 + spine-godot/example/spineboy.png | Bin 0 -> 249068 bytes spine-godot/example/spineboy.png.import | 34 + spine-godot/example/spineboy.tres | 10 + spine-godot/example/spineboyanimdata.tres | 7 + spine-godot/example/test.tscn | 13 + .../spine_godot/RaiixSpineExtension.cpp | 80 - spine-godot/spine_godot/register_types.cpp | 4 +- 13 files changed, 8899 insertions(+), 83 deletions(-) create mode 100644 spine-godot/example/spineboy-pro.spjson create mode 100644 spine-godot/example/spineboy.atlas create mode 100644 spine-godot/example/spineboy.atlas.import create mode 100644 spine-godot/example/spineboy.gd create mode 100644 spine-godot/example/spineboy.png create mode 100644 spine-godot/example/spineboy.png.import create mode 100644 spine-godot/example/spineboy.tres create mode 100644 spine-godot/example/spineboyanimdata.tres create mode 100644 spine-godot/example/test.tscn delete mode 100644 spine-godot/spine_godot/RaiixSpineExtension.cpp diff --git a/.gitignore b/.gitignore index 444577872..ec39cf43b 100644 --- a/.gitignore +++ b/.gitignore @@ -155,3 +155,5 @@ spine-ts/spine-threejs/dist spine-godot/godot spine-godot/spine_godot/spine-cpp spine-godot/spine_godot/__pycache__ +spine-godot/example/.import +spine-godot/spine_godot/*.o diff --git a/spine-godot/example/project.godot b/spine-godot/example/project.godot index 0ce873e45..1f28721fa 100644 --- a/spine-godot/example/project.godot +++ b/spine-godot/example/project.godot @@ -11,6 +11,7 @@ config_version=4 [application] config/name="spine-godot-examples" +run/main_scene="res://test.tscn" config/icon="res://icon.png" [physics] diff --git a/spine-godot/example/spineboy-pro.spjson b/spine-godot/example/spineboy-pro.spjson new file mode 100644 index 000000000..4d8c7c2cf --- /dev/null +++ b/spine-godot/example/spineboy-pro.spjson @@ -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/spine-godot/example/spineboy.atlas b/spine-godot/example/spineboy.atlas new file mode 100644 index 000000000..b07ccc3bf --- /dev/null +++ b/spine-godot/example/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/spine-godot/example/spineboy.atlas.import b/spine-godot/example/spineboy.atlas.import new file mode 100644 index 000000000..f8d1dfe86 --- /dev/null +++ b/spine-godot/example/spineboy.atlas.import @@ -0,0 +1,14 @@ +[remap] + +importer="spine.atlas" +type="SpineAtlasResource" +path="res://.import/spineboy.atlas-ce2b95e2abaaca5faa7726fe317501ea.spatlas" + +[deps] + +source_file="res://spineboy.atlas" +dest_files=[ "res://.import/spineboy.atlas-ce2b95e2abaaca5faa7726fe317501ea.spatlas" ] + +[params] + +normal_texture_prefix="" diff --git a/spine-godot/example/spineboy.gd b/spine-godot/example/spineboy.gd new file mode 100644 index 000000000..b2047dc82 --- /dev/null +++ b/spine-godot/example/spineboy.gd @@ -0,0 +1,17 @@ +extends SpineSprite + + +# Declare member variables here. Examples: +# var a = 2 +# var b = "text" + + +# Called when the node enters the scene tree for the first time. +func _ready(): + self.get_animation_state().set_animation("walk", true, 0) + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +#func _process(delta): +# pass diff --git a/spine-godot/example/spineboy.png b/spine-godot/example/spineboy.png new file mode 100644 index 0000000000000000000000000000000000000000..3f7eb06443b791729ddb33b9534b08644a684761 GIT binary patch literal 249068 zcmZ^}V{~Rsv@IOlw$X9YF*-IowmM12HlNtGZQHilv27bq^5s3>x%c1wwQG;D$Eey> zwdPuD&KdSwUIGyg4-Nzb1W`&-R0#wG;(G`R0t5B^V4#Gc00EzDkP;PAaa+5{a?K<# z0gi0XBwltbYcsZWJc#2-!N8)x$iZ}pqF{&#g-fEMK+M4i@Pz*GCkf9bkuIID5JZzE zfjvzTe>LRgwn2#Yz8 zFxOcB`=98Kkz8EV#lZV&TY?c<&;k=fODCk$UF} zhB#UFrY359t#oBM>x`MQ{tl%&3H&_OqEjGxKU)r{~iM-0OYeBuBZI)!G zl7&uo^w7N76q_6J<#lPIMs#JtY8Ouw(IyP>(V2OD365&jUcd|mzTIB|Oy~E>4khe0 zD8e4D!{5_qgZ!Uuc(E0Pp2iT~*m;Jo2#2E!6^CbWVx2Is8@<6Ci7QlwP1kOoUujHp z;^BsGMM%A+B+bxvTLI6O9FOSlHK5shM#na3)Toz`m)oSf=$yqnD zu^CY>NREJNFcozwEHw5Yw;m=Z={bJRqXMQDj~Xitj>154-o3ZdtlXYg0-zN@{?FN5 z_)3!w>N{_yswmE7^!qy$lG_vDO9cl?)5OhBWq^_jN;g|=_AXW7TS@S=fcHQs>Gy(d z%e}ZZ9cDU>%%IunT$^CO``ADTOVgABpDDRE7J*6ef_PA1W;SMjcJnbOzl>3v=+qo{ z2LqVV&Eqe_B4KKQ^!jMRAMF5=o8nZS#aFPkncq8-2DM}@j!EjH!ZC?1jf%vvE?o+( z>+68GHpdt2Kn>Ye!f>@&j);f=SE8 z^@%jfOXZ-D&qJJ4?O_Yd^z{-k1o%qw(8uDr+i?^w-`CUoq;6;A6rvnqzl@wYY!Cl_ z2El9t_SAa1-9=XGr%dy{&d-CV^%P*pnmn;zt7o91%cN+5xXOtl8^rn`$5zAADlt{F ztbzfMAoWv#9>jRvTqDj06vB5&el7ilFU&&z3l{WpHKzMabj8_Lj2g`MM0EDNbvYa6 z`wmfq{BNjyRh%#drV@o6q#)sOwGYf+ONKcS5RCM>5X2%W&F>-#A{i+L2C482l`q2A zRsPFR8b`+%d!-)~I}g0DteygqZFaq;-%M5wL#;eIhnk6ciu|l5B*s zkT)kabR9LrakOSh3{w4}KoOXP}%C+eHY5Ahp@&1*5tF1j@Du(O?WRZPHz&lcnxaX?8b28$Q_|2O(y^aZ<7 z_P~1txC{<%z**$bQMjT5_E&J3Kro?pxR8>qP4?zC4M7}6R#ik|C5H}6DzGGJvU<3q z?>A=*?Q<+QIdyA5O;#gmgo%}eePKm?;SA#HJB$6u4y$dzVrV1Gq^*;F^Z$~O!R0O`en%o6ob3bRE|r9L z=6hMBc#k93bf=vX&y2*OEilJQem-2Xa#t23Ti?pNyL1KKLv1-sIOc%g;%b*2b^!sq zA^~{$?D)mWs26WAVa#e>P?cGD4j(?^*IF@b&Cyp0=kM-S6^mB^4kTEKt z8clYrTavuOMtkgFRVf9PnrirR871uIeMx4Y++!c)AwuC)y9PG9dmJcQ6VB%y^&Ecz z2vS;G0!CY~m-)v_&Ql&jhoH=MmV;`w7EW=U85m-~i9M9Vp^^3VKn0EZ{3_cC<*&T8qu-somSK%Y6DeoQr zB9W-dt`7^MiJD7*gM^^u_~wzTVzOonP6Wz9XKAGq24X#~owxa&_x{bC%JYGrFuKRX zZ?}W@9qL{goJ@W>F(_ZR<`h*d*^REm5%Aa(K*tbD8OHpSEG9_;TVG{)AY&TGT;3YC zB}xk>XH9mML)YU5>-r67Y^f-&$kJzqjNK|;frPZF?O;k7!Xq2u&RGZ!{fVONn zyaUp5_wIzpns?#E1QW_Pt6fl)%GR8#O?~fiAwf7mjm5D`cSxOZ#Lh;}I#YQIT z<^vP#E;iq`CpgXo4oBg8Okt{@B*@6bIUfI6US9aOF`1?yFqMJN(HWSS0y5D#vj0E% zw7VFGF)&qCN$GUmc9N7Uda!!*mIH6;QGE8Rub&-?$7-fD;- zO|r2jUI|ILuz(ldlhfQ@`-ME5AP8e@#u4?)D;MDeKGF%bzcQ#PgzWD6$9&T7!5&OA zwKh1sBoiJwh(_A{WEa#>t5m@fSa4o)G>1>ifVn6!UEP)dgC&1TdaX~IkPCtIt;M9= z^H@p$g{TehU6L;kBd8L6H^eYwI0Av~1A)h}m@eZ9u4 zZC$KPySZ+0$Ykk^SO>P@BgX2E#|HAyMag;uMi>1%C)S4`$d*0?Xr znko)@%jijzQ$n?*^kQx;W;?mX$ zqlbmN3^d;7ve224wc@|s?~@Bp;ns*H;0v8J!vP`HdEP?Xj-4ofgq&3uZHe6v;&!k3 zZv**PkI8{so`sw?fudlmOTjb{#V8W+r2HV=&jO!Tli_(lh11oBuc0`-EOGu)4h0itn0gZIS8cn^rYqrUonCB&0~KsY!sb^DJBXAK zjDnX=^@HIQa&)V`I;TD4VEZ=(zkb_AN@IPUb9f4s8gmG3f>B0lN%PR>%h&_3T!xPQOY)3wu z(WPySYs?3D;}Ew^KTh(eC!UEI1trwhWpgnR`73B*cu+ z^*LAE9<`NsVk~VcR>FV+@BFy5Jx`iDA(xJQ*y$6&X72XAKA{YJsYv{pOdOWWq!Zd@ z0$-m8nkJcBve4P!K#BeNzKsAAlE&}BrmS8~@8-VV91@69KseGStO@$5o||yZ>mzyV zTQS3iv|*dr6@&`DU&(vuw#8JlGuE=T#sy4L&vw|^`g*+M|F15;!4&gLbZ}5qgzYMS zpI@03l##)Ylk^E;VKy3qUPpylpN{pEAPE|D=|#~R1{WO9N5Hc53G8DX@J=x-N1fdTAII2x!{61Jd=rK>xH zu|Pxz8tl~$B1sVjuLgP$M>RZ?CFLMYEx*wl=}6vBEW^e3uRpzm37Q@DtkL^7FO@Mc z@3KDjE2x7BS@cGMrAvrLTlo`A#QX=-yy~v^>(jhToU^i{P9sCuFX#js?a88!{)4eX zg-Wo6k!92dMv*vvKN!Stpvcm8T-7R4YpvE7(Y7`hWOSWg4;N3J-pB(-w_hC~`e$ds z_#-t!1?@j?1ce?bN0w7-vAbUj8?(&Yt9zJ&<=0+vPE@iqN*l(0fLA|R(b73BWeh11 z(G=4G#F}-fRZ>s)@B^qrmxv8EP|6c*{#}Ii>xg>_PMNm z270;+OFf3t+bM|wNC(@OpgTy=wBQyPugDeM?NAy;!o;IvmwC>|pF~R?uB)Np;rfZ# zSbs+L&Fb%U8=!fNUTSwPS^vs|5j_{}U5>I;po%J+YuE z-Jzohzs%v^Spt3=raO5Of&Xo(RVYm+*0mFQmEhcR+Xa5-sjY&A;$K<*bcr&DredNn zw|=pE=+MVDJK!~*|7H0B07QXbeYZE1As&=44E;nub7ZthB`sETEg?Z38aN!Z#EMyZ zFgYQcE_s&pW$nvUIW!ovQ-T2rz1DjAFs-GIF12V7LCaUA^YkeNoq$Chu`=U7v2Z>H z(DEd%o#vBM=^rPF9CS*xqCp^ubZDsRBWxIo^-0gY)ZwirGo&qnxtG#Z7k?gNe!d9rM2HIGtJmujB8&E3{o&L<(tOD% zv&?W;gFj47`$3)p3@FZf_jb#M@h=mr(7~E8nm597{RwqwXo+Hjc_u z-A$4x80!?K9i8Y9BLWJSUj%KnQhV2C$E>BHr4ohW-dF}x*IYh@* z`z$@5EdNt2Qcoom2CB9Ib#F#sX2)uZO02RWyV6lYjc zmlOJ3_6vn{uq9m^Zwt%^d{X(W>c91Q&CNy`*mYvY0Lm;e7a=By*Kip|Lj z6EQH84bqDpmXlA~{j_ch%)zFXYT5Beu)a%~W(IoRAoG{Fa-H17v~75k=NULqVHmbN z)UbnvwIvMIh`V-1n1r}}JVKYYJqaDg*VkVDUfA$|7Yy~VpZ&d`j1iX7VPM3x{XJTT zFlMT|V5I8(y&O$|4qi3S_U%^TdTFD(8T!jY|retq$C8! zAN|d|hxkM06K}?cP0P_MQ82Tfxq5u`BnWFs(7t7>gOic2eppC~+y6vmmsu-^>rvR* zLk&>KPy+?-M=wyxQ*|`czHZamp+Rb#kLUTbc-RG2w?17;4)mKiH*I&AB2lV;P-!TJ z;vyN3)3!e;UI&xlg6&C2!isB*i`g=W@yw79Erc>O49?mX^B2IxGRT~|#=VtVSkgEX zDn9D9R^G3A7m>9sWxIhK41U6=NJRa<J^}Az<3X7_E+UpLNhZu;h|4;yVQr^q09(9g; zTelvM#l9x{$Xht4M+}J}(AV|W8f31s;&oJZe8wn83J%OQWcD0@8i@h8IG7&qqSJ{w zof&jF4EnfRZ)|nqB6`a6WM%KmH4%L---sQ6NS>!hQ~k{5pR)r!9Aaz{ZS(x} zitOZTtgnw0&Poa4Hvsu$F>?EOJ?7pGM2}U9Mi=fBrM~^EkFMi>#*Mw{IO+fff9yTU zZ*pE|g-#=clUD!xgvShuOaR&Y(E`cFeD~C~_c7DC!49u~}YfgdJvcZ{k zEo4R@hJ-Xhz~`}1vR52x=o2*NzX5dA?s+kgvN}e_Di@zPjAH<&dvQIZD^`~a-rkiNyGT8rOt?%0*^f$h6^z#z#xveO3q^^;M1vQ}pn>EpvJ0Zp zVfz{{z|ZKFFWJnVF!NNLVB`VjSvEvDv((}ma%x}mRI~JC`yMPXxlk)I4mLRh<4VJm z_AOWJV)N9XPVNb^$@IR7ycjDtv7bM!-6O&GJQ@o5genCwwZLx(+F3T zLW??Jf-6al^^#R4cdA6;R@q^a(JPp%>l)732dHM^eR*BjgaZWCyI;Q-G_|$1A5~#mN%bbem$(LwuD3z z+eZTc(gXs)@;9LQN~@6oJ!hoUmdbe_Itah%O0%vlFNYG(>JWPIZb^P2)YOgR;@#ng z$D_rEABdJJ=5Q!#Y6wxd{Y@VPEv?(f?Fjc-X#vPEENQl4!2U99LUiWcrFQh1nzWla zI;qputIBcI6i+aeJf9y%n!OSg8U#}t#jfk^BVD(ijC7bQSYO@trvyP=WZB zZAOlPkbjOBoYx@=0=~fZGaD?O1TSju{#~WMS5~+;a>N%6l#O8@HC7I)HOtMJ8daNv zh-a5}F2$~kN;mEGm=?M27hkxEjivv_!HB~U9g4TCGJn4$Z z(t{5O?KWF@u*b;rf!Txtx_cyqHPKEu0#`7sN#Qg81~Xk0Up8R2t<%3;qe?r5 zrH!yhR!%(;bO8tI+b`lZOU6I} z1a?rO1%R~KjPQ8dTt}$@+PMDzxY-wix<32N!u|15x;U6TMKzr$^Ox2m;Iq5Ixf&Qc z^&k1nP!=yPGCW997zi-g434PV{Sk24e{7db`s8SMWmf_xbINbT#oRNK6vaU&WtjCb zisSg&Y{@OSqsdsto&+OtqrNdu9X=6VUfg6Tg4!+7>x^B2bT%DPV~2-)&le2^B7VL1 z7G$TNX4U7*$;l6*&EFiDU6$@ISN zN=i5XbWy+>*cZt=*E?Ij4ov)R)c-IZP-B_(@ zD9q!%xA@s$!1=uaC++fNbMl6Ur0K;4=DePusl~{2S!5^(d(Y6!k(a7qYf6=08lruyRSS0AD!jlaf%4-ot7_ zJ8M$xxcO$s!{}w*WLb2hXfv?t_kR4EM1sa`$?BKBQ$n)I`vw6+LrZe;Sp_}j(J0$a zzinoRRn^hBy8#n{Py5P*0<0r*pOi~w6twu~3|ezDYtw-Pqt}Ok)dz$iohw8e{1j0J4A|i8a2yz3n&Vkz!r4%`4*Kq#7!si@EzpAfh zvqRTui8s=r9C_0Rd$P3~MO{qRj?`4}(Oh>^!I8Guf3P`LMA(#yJOWPnx1E}!~ zeHtN;nDQ`P?WQXpS!wPvXVkKC4iC8mU21f2i8Drbo%n*wSA~kRSZCxW4V$j=(xHy) zDvSKaKyY}DOgkrREouO74pRXF{n{K}+EVIl7k|8ce2OV8nBK1!bSrw@jK<9<{*FDK zYX6_&Sfp!E(~?)MWZd4}9<$xXVKqVF&OsSnOAhfsHgwl6)ilRD`4b$9q$o4rd~HfU z;T^Dgx(!r>MD7gy2b84XKoa^;IYs?cWtw#+v;;yKJHi)QNtV>ASE?u|6aaXl^fpsW znwki_MoB+j{h)`zpD+5jBgbN}h%Z=KBj5(u>Mq#4J&^mZpBtQBsc~ieeYe;HaM|~A zSs-62uR&b_hy!4QIX@UVXNhT=Kh#6uxLZrynO1bxle zq>c8~{PReP&1omPw+wfeqavXNEiKXWeuoN@_~vD#c_&r?mgdj6IKo6b>OW5@l+)@p zo2{2GkKQgawKi!?tQFeg&rK4ptik?zVR=+qRLv-7gJ|pIK~IgZZD*p#$40%jIF1cm z#TSP4C0vQ#4P$Tl@59=3?@Eg!Z|YI(#*cgo8P+&lz3zDbt=1B2PsjuT3%@Y98LhS< zkd$R>9(D1tp4uaL|0Pc8b>X_O$@lV1oz_~EMqH^qVnH)^ekQmaCu}g45fV8P_xNZv zrJ>YvdG^4mXD_yby61N>6I@K{8?#h>*km%{23$zOc%Y|RYKi~tj@rI`F?-@7^~rmp zJxr%^WoPeje4ca{<8YfHa6$Fz8Ug~LYuq6SD-Es!BVYHXs|GR}4l1IX4XUZ`ZG^l$ zaYYNUsssLN(P}$$nTcg_Qi%zw=y77&^%15t^-*y6a^|XE)siw5`;~1JSFk3or zOt(aR4&ucr3fFS!ZaDle6$LJ^wjf&ExBpT~fOeMK$oMJ-`xh6OiZ5 zP}Sh&cay^mevE~g6hrvSqw!R3;5$GJt_?{wGi51xvQXFzf2%1)S@U|mzi*c`H#aW? zVBkX4Y&c^Nxw}i!)TqGs)%?r{21j*PUT0E?E<`)a5fVr@;%LY7RIIbw$Ss9qa%s1a zFu>2#NK%lb4Q{muHI!ry?|;2vOOBauzakw2zTS_)s9o;)rs)_?{hX`p^PrrUIVlojt(Iu$=CXJAH-M*O?qn1fxG!#LF*UrbI+xqSiFLx@~J{ z{eDUf{W$=o7PSss;T+0$esw|**GSvZBu%drJ&R^*CNPaA3*2^_*c9x7q9RxbQL;Fs zyX-OOSa)_g;>%ksCpmH)7?%%zkq>qgAa-L*i!r_T_#J%4E43t5W)IOCIMoL)qa5K zm#m@QaISvG-(NM=x?|w1ru9zufAN&ZvGDc8Ii151)#Lp$rN6HWHW@Sb74f;vwF2_ucYl4rM?`dv z>kV?so=@As<$lL%bEG_kuh*i>d+R8`aM}`#{$P{XHoJJEF#MLY|nUD^{JQ?loKKuvWrF%{J-kk0plWr0x zJv&yV((0!GL~=zZ;l$z$>*DbxBkA0?^ho5j7E6l09|plsdUO6JzZd&k;7mBz63=kq zAo+B`(oewE{_4FD3W132rtJBLyE#X*O)hDfWt784aTOo%#E8%JUmQ^2O!*O*;*l(1 zmoDqA(PL+SSs0!!kQjU){o5$93TC;*H_vK1zrf~x(Ru%qwh^UA9sE%plR7HHO%(KcnXD-b8xIN(Qp-2!yG@|# zW3EeP9MI~*qsL#}ing*GkSbc`#4)%!sv0$s0d0M4UjISI*j=y8v4wy=UpA!Li=4i;;sZ-2{0e4tvm$$tW*J= z#VO@^U3iZHRc*dvop5+ZokL*9E!Yc$M!Uxp9Ki?`T3Eb%iMfSUZfh$H3gK-BE-8u8 zsja!W=mOh^PZGo|bFDSB?hM5mJ3_*g_7Xbmu}LT4yp)y}zT)kha|a2X7E;>`aKjr2 zs{R5_n+>oP^|e|8NF*WiDh-)H>yTpQWiniZXKfYKNg@!Y3$s#_NM6`%bLbvFBP)QL zeE*bdfBUaYYY4KWy%HM>e(E7`RhI`HwEFE!5is zTL8WUB)+uk&ztv?bdtEpf>XRjc6M2QpP$RJKyKF!7bdy)tiisPFP?qRENM~%a1N`T zq{E4-qMMm&dC$2d^(Sm$9cY6S9$R|tVfTgNxg%N=x7n55&=2PHnUj-}4ze#LX=cQm z_g>S#S2c!$94vcR!WV?cxNRqwpB<#z?Q{wfOKWMKJ3C?N(NI>CgwrS98Bd9tGamIrY0@ z3UtItWyhEl;qqJY<^6uinQa>49hnes9|cGs!j!2OeP*j$hM4|4zdw6^wCG8cfr!;5 z_&T}m@(63RrjzZa$>bcp&hIlcUO`c!HBS1xC33i0$lIEMRWabl+J&m)UOX05TH z>Nd77zOS@x@zafJ@GYeG%zBxMunR}KrSL@J6^!U;45qTS_5?EEMT7|OVSnL#ZkNn7 z6T7Jr{x6eT_Mh|TbuW0^*=5UsaOg;3qS0dRU6L>t-Y;v>O3ptEXoa)9Nt*X!zU*Pm zl?4RzH-=35^5tcyj{RDcc+2zh>|F9a>^)_4g$Ke!+6AaE{=FD!)3!22>6(&;bSvNMbPs>oC=@%l?rygGrF=wT+-O5~Do_u(n}vtr2ZY``+*&K8x2YSn)%FCEhIc3o_}Dk3kG5IF*Ixg34FV{0n)O=s*LZXg@lJ$9}8 zD9YA%?Q$HS#vGZY;CiNFZO-T8Dq$p7(sp&2!s0~OV>lZ>>gGh`z5*(VsOnp92?{Y# zC>JtB%=DiyKdD{sFSm||J6{s6cUXi_c_o#z8*mzjE!MzLn;99>`{e6?dEerc9Se_r zMIDTES!rv|ef34I+HqQiw5M*}E!;H&=Za|Y^;zzX+1jtTrVB8wJ5PTkqXsqj?Jd## z=Bu)ubq!}-r|Zp<;Yl*1iZ^T5HgyfxUD=z6sU0|h{v$z2$cc|GZVEcrq(AuW3AcSa zf5}?epzOm?rPI4L~ReIA_VI{Xi{Oo*7G8QR(YnF+YtQ8ps}nL9!rI} zE55a*F=o>J$b=02C3@1RQI*D$DCwPGGg?YN1HNjkP(XhPL|$vM*$E zmX_h_DIpe{uu02IdE#r`Pk%q=ua^;l*01(+gFgSrq;Jl9p7rmJ)p~G)GhN8>F)Q;v z9*@dGqrMO1bw`gyZ|rRy_j#Pha+~@`y10>+K^yo10(zS>{!)f5S%Q?=cUITL`6S72 z!fbPA9V^M+yJ(muBY?a7Sv`Sz7ul)765ZHPP+8I3XgTjp@y!wO8R)~^MQF5J5k)5^ zCaNfD{N})Gy{<6E{Uj2Z04SVr!moZD80J6wE)4xfC^K}Ota0cVWFX|Q(UW=E0k16# zUi>G#$zg2B(B|xCBz;fzoXhs%3O?#Abf|_TcbH@ ze+7p0=Ji9=2vS9DiP`A}2MGs2Awl5caBH71lW8}YN1elJb+Q6TPI}ZKLLj#l3gNR|Ct(a$}VEH(FhoCBFycjrdZifc!Y8 z^~*c04|Rbye{@Zs=#QxwG|4aVr)AjBis&~IHc!em~C3K5v zEUMtXfW*UdKl0Otg=URLZ?9&tKlnZVrn*lTY7iWN1G+u)KhOZ;ZQJ9mNi9)Fpizhq zb$Kb*DR3`^1-QeL)8;^hKSW1_(CqrdxUBDu)uQhTE2G{ND?8Y>cV?M}`J?c1SArQ0 zwtBNw(LzqH#l^XN0xe9$uRziMi&ed9ud>c4?RA0fWhfE-r#JhK>13@Rp>c!q9`Q{> zeO}o0hcT_lcR7;r_263Wp?1@7-!nD9sXNtl3<$9$V2d8IS-3^YQN&s^2p+o)>gCLnP0@- zgUQLsmaeQ+g=W{yG=#jTam6BZ*R zm59Y@27&lIPyouQF}>ufl#cXj-3wMec|O8=-H#tXOlEsg|1oCCk#DfAfh5hCxuUq)0p?stK}nAVPBkKPdXI)Ay|hFzs~T^i*&+>q);xm`q@^m`+1S;&7xppQ|@mEW!!rk<6JH zL!4T@v1xRi6){Us{#EC*IZTrScP3EdN7`X(27@^uWdhsV5WsSu&|l zc6^*Tk^anB>!ToM>#Xq63x$cSb6oG=E(Y?o`O=VzVt=N=rKzAOcN88NnO=& z62Q&pa6Xgk{LX-$9(=^=u=&sdIpGpYtxN(jXBR5d%?U{gF(0?_88N|pClWXwaf2y- z{P;OkV{LqO7MR!iGkUgMfw*JQ{(eyy*x7kHv6Ui9YhDrD?uk zMIt9Jz&u9$bzh1)PvG+<;#StmMcw#`dL0uwWB>|rub-T14q&FA{o;lMQYV>eXHPmG zN62`%PSe_Vw!|?^^!$s+d(ZvqeG#)V`yNhV%llUXb!48pCQF=Is$j2zbBxk-jspT~ z4v;m%lz)P5L0~7}(q;e-vg61xy;X18ovw$qy5dbo4aCmZ&w^0ptb9Ihlk@yjKNrH^ zYOmXe(e-1N=wG#K3duv8gSyI5Wz4Wkd_XP=PSs$j)u&%=1zO)#r!^kI$d%KE6aEGd zuc){|Bkn9<#aA~@YjNA*7l?zHFNb=LjlC+gUBVY3ABe+y9r!(#?N;XikFf-)ph#(* zt*RqDAnn)tkoE1$d&enHop?#t>G4uUCoiq=L1zQ5DwbF`5J@hF-sI>G?W$qhWS@l` z*LnAFu-ldA8JoV}!D>y)(H{Wt>FmpGE@EPEM%2+#l$@QddHiehU$5^eYZ=3N?6h~; zB-QXBgN`>8l+;Lx=5>tSBWSf5Ze<(7pxtWy>6Kkpbyx%n-da)_sZB>4tAr;Uy6rV| z^*-8d(q*pG;8)nl^GKB_=~TAA;F@TZ)WVO17j2T@^+t0BM*0wSUZ<@UJ2f@xMsU8M zfZK50ZD=5gef%5!Cd30aufl>4_Ze_n+^_j)7-I1YEeF?N@CIC?`wu80Vn*57YK{=N z1feO;QAlqs)45#D{BrgtZTvGa&0Av5BngDUZfmv16Hi;7KAeaG@3qQ z7?fyH7)TL_08*<7vMlLCdVC6{wZa9d!baG)0F|dw!;jVh?xRv$%uKrr&5;;<-qV<* zUlz%)K)<2%;>{AtgcOn90r?YN!+w#J&&Qf&gkMKEQ!YHuPV7LRt@NiK#fI_QJ)Cj% zXh;0-^pDOJnq788A^Pr`imSbT0)%dN2l<6rRM+z~of@3`UCAo&sJhgJr!Z53E&H9_ zZ&REpjn*9=uE&QCUo##c7^PxwW=UnAB0Gpl2Nq3QFY0ALf8XwmJKg7Rb*5&MI)h^%uKMW+JIC#c+ZlsuczdX zj%0xpCyx6iYwO&`ape>$)%-5Q>r=RaQvE%$gQNq&ZpU$Z)-Y}2bW-J zrSI>Uy^8jGb`A_IY!xmc!0<$YsWWEL;oo(q5lR+9_!gB=DHhUZV}W{0K2LVo1lskD~J z<09N-2mrInS~dnMU32!@9lON_uLFjuv=9TPlBdSm@l&}yiJYsf3kUKhyUZ;^f~jn} z&%op}ex_O4eh|v{ZZCEr?H&JPglWAhm$9Y!L+qmYyvfa!A8uv}>$Y^*t<@ECqyjvd zPUpdA#IS2RbXnYLu)N|^HxtY|2MQ)ZlW#9V3vb>Ef;4kAGi-K9s#+)-18E=_6^AGh zBx?yHcHbkvA@I^c=Rz1l@;KDxl5vmNH7x9OGY$~M`T5gSo^0>lc|M~#$D5wu=&fbD zc&gs!VmP49$#FY>rw|^{$MR03aBaG6+E_-u?U5Bk%yy@zNf#G}j>~5tz-F*LXO!x; zRMa`HTSX$2%Hy*qyaCq=u|pQhoDuOyxs)Li%aRnU&SN zl-pb4nMLXc4msNN{=l2Z)#r0hTcZN;5j&e*>%N_sGy9lRdf~pE1N|_pyF1_VhF56y zxw6%|&t8Syg0t>+Pf6TN#FE#z3Cjo`(5zu0OZEZDM=l>;#}I_~NGK`qha8K5k(bXw zGJ_;Ljk5YkZJvl?#2hkD8pSudyK_Y!hMOj?8@*C+Ddm&vjJdPs$WY+;+DN^jf$#f6#LMmjH(zYwPv2&X5hm{w zrVyr&8uyBMxQ`Hf!E+~usr65 zE$<-o>dtUieQ$BBC6x%xXMQKw^X4}hQ)_Kbd#lEWm)PC&ywxxhVs=~iHps2>qt~_u zcj%l^pNq@c3qgr&?Cf^;a_T4u zL8wYQ_ph@~;1l+*53*XNuD?=3(%#o7265rIHfq}1NSdR;2BDSI zy{6P(y*pt{4KJ5}W9y>1mmRqN&OX&BUeiVs0rkB}{Uzjc`R%D_-?tZ%4cJ}J^5AdX zNx6HlTEK1(#vOyf*d-FHY??1rO7p=*3~?O~+6nZ}d@RUuyk8X9o4@s z>PCzF>-}d+CQvRqojJJaQJd>9zDy%|2tQ_Hs#eGw)f_(F90`{LN7tA0Fr?D;G8WpKEtheiS#BVsvWGNFjh+rTlF&V-ra!g5{n@#~b>qQimXE%9@3&R^HZ!;~D(l4&FEK@o~F|{;PS) z2u|yxB$ElfMr+R_o9RV*8hU|;#019Mq|Q6iT}aDPOxSUc6)uLT(I>Fvk4MxdP<9b=p+j)WTz-5|Rnam*)xOo8X3|d6Q%qqm7kd=T^=n&l?Ee z>bOKD{y8k$S976CQBCcl@MHVtiX@mqryq=^6xn9`!;tVV#WN#<6T&=5_LjVcQM^bk z>MA#XE$LusY?%VEIgFwHF|m`q2K_o~S!5Bq9zesJKqXHxg)JQYXNxL1 znQpOFq1*p*gr$|^165^9+_*<(tc(t6n(3z%di2M)_;f^q9Fi+qbQw|-nua}zi>jkG zjt~~KNM)O*{x7HY5tccVvB^?3v@7+bD8*hGpk0tN9TE_OOcrIZE`0lhuTOU!vzwo&(2lZvUdPev~?mpcHnhuaJ z%LQXa7A)Rbi2?8g4{G--gOwf0@1J#7d&sXc6)2=?b-le$O`l72sl2A$tF3_SEUI)Q zE2+$jLx0;*r~Ha9chXNg=bGX!n)jE+SS^H+Ll&z&D)U?{?WD%jxz5mC>Ti}G58~b= zLG*+m4J60@ddH&RbS@t`UK>rv7iE?aZn7|94dwG9^aw9!V;Bt=c9;mxKIE-B z$Io0-3kVQb8R=}lqV~L>!6zhW)UdO2UOcUQW&RYyw)4ZtH3uWdAo-oCP}&L8z%1@{ z8653x6!)7-#^xzQHsRc+JH*qbJ={wqq;dZ1J|AJ@8b{5#R07?9-L@Ob=$s=qUc;WW zB+C_(Jo=r;mhTQ9X%nDdYh_1(gvXMqzU`CaMl1LGdQfxGuvA72otqRS*rK3)BA!Xd z8biI*chde_YaW4V>r_T?CF|Y%hM*l1=ZjLh=b(36=(1*k-bH9Rbr|2gH*FPInDz)` zS15SWZS>In7I-Z+Y*;$hEs*qCo^Zfgw47&tR@}go=~OzVvM;{toa@08JFk57kKLn_ zpCdMlq)->~gN_8pOT=9_{do#GK5wK+bvV{#m)yj_U_S^(@7ve%^@s>K_C@HAT zN2WD4_z6>`9gWHLe<@E>MUwbbZv|G58L8$O{rzBtiENE*sMaZxBKre=LgLSO@hp*I z^*&&5vP9nUN~k)^fehm^fg+pbe0?bu(!84WVlfbakm z|M-3)tBua!2usT}HRS}ur`0}L<4`+f($@OIK>ejB&6BuVl(_5GKf~-d>N-FA@A9{4vgCYvhs?Fi z{FV;)ylC+n`p^tE+)&cf^LcM~KHsaBs!=tW`0UR;y~w$>u;U3V-ef`{tu8vnhq-tN z+{ktcgN!JvtS(m9^O>429=6F+FgK3@U#ii(y?=XqL;oB|A!0+g4-%mwTHijtCnu!r zyi`$C595y(;X>P;-KR1tTEGcEc=zJJyMsU7v_-MDuCiL!nYp8sS!wM?qC4EVhiu+% z+;~sS@~dhrcO){I91U2peIT{k)Dkd14G&5vbh@%Ow{%C4_+l*-_~gTWBkFegaRHbW zLMCv0T%=x}1`5*GREWX9Y2Myt96Xo(y+9oyaVE6FUwEkdGsd?Cc-6f4_e4=2%^-vw znwp~+LezKGQmo8w&v*ZKYG=i==I?7I^29o)Es$?|@$yr@@@@);7Rsl9t}jVTT)9Ta z9aw#5xMnk0l^94#4(_)H9}yANYP4_$(;SWh6wNrR;#HBnW(Gf#{5t`rH8$Wx5cvNA z;Xoe0Bk>6xVHh*gDXV^03wTAEvdO&Km32Mq!W(cA|A4EM*(P9#BK5<7@#=J*c8LWM zO6G#rnVfPCO6trcOVy9rWhbOyT%m zJ^0xV&*bWhzt7fWijsj7`PDstA>cFVQCh?W-#Up)&;BNQaUr6q8JS3K9{~-WMa$Q8 z^&B!eR)jOH+YM6p6=e-4fj|HwlMAWyOR#N{SgqYX_NYF64tJoZ&@{AA0Dn=8U}*tn zei$R*XY01@B0_md!FJ2M5Ui`Kr?jMye7_G|7Taa>7PGo;Q>Nca$+p&3N+MxW1$kV1 z<99mtJL0>S(X{kkBC4y%RGLZq?~9d6gYNH)!eN>rt6qlgp`3MtOT;Gn}4420LTge*)SMWc?5{Ast}}7 zi3OIOK0cc_B$ZBYU#qx`{~cPr20}$BInqHolB%k{1cTv|;_b%aMKiUU+2Rz9KIWz;Ya3U%8UU=g(icuDSUXRpNAa@aaN}IHr-| z7YO`9XCpR`{4j^=}j4sjjg@g((I8hPfy`H#B6OX`K4n?r4j@JA=)>t z;j}02Lc2 zMV+o^g@DXjDjF%ExwV1ko0@p3rG-Po;fz%%JI)J1N=hy&D&nDS+gOuMUkd#8OI{Yx z3`8RNBen)vFX|Z}ib*;~Lo0oHO6@JfG)zJ|CH3R#f&V|0kcJ2S}%pC!Iv%t6w8HW-MKvhthPE z(9ugvN#t~fll?dbSMJ`o@#qO-W==NDoZLztgvm+4DIa7P=ziGWEf3gpH}O1|@#Cg( z;J|J+ZC=H+sq+bkW6Ym-V({R>JvY`L-2IVAq~xoK#QcZn&CX8UcVOqQnwt+?1Kj%$ z0|10R!&P2xlgrgn^w^d9!txDtcG1pd!3Z7_t?20dGwFJ$eftqRb`mQojc|AXVBE-> zG2gAN8Fxt}TzcjJGGXt`U^DIS%$a%g;_|YpTsdHIlHQjE>h_xy3dwnwUxM2Q37hA6 zc%Fx4S=82zp>Es+vQC!z-Fw)$b}h{fO&Gd~VVVPKK?AtbLr9O3l5&n)bQ(ZOQ_I0m zZ{GCgr}x$GUXx07-Bnsz`kVIl_V(dr`hS&Oa?Z8a-Lc?9OJlFU_#}%x zKqSHoPd?1$H{ZPU=CjX!8o1*~Pt@=KH;c5q>-@mB%g@@k`ax^5C~KGp1cd({%jW@b z2XcBfAzogYN}bx_x|jl*MVP-*%T;P?FEm2&cPbb~no%T4qVXKnn0^&q!p+d-rU_`~ z!-KudqB35mNEN^;sszZhkT?3*6a}{X+TIWORS{ueWf5DySJWQRRs<{*KYDWuxJB>n zT_*f41pmOalh(2E`2&8{#z2E1xA!_({{71T%#ROJnJnA)9^l%Wf6j9&-r|)v*05;q zbguu*$2k6^<8u3q5FBW3MXJ6@mxK`LN`HNjXB^RWqh>G%X0usNI{A3+yKm>9X$vKM zP-q&uZ4xMn5U41@E{$LWY%mP6Zg&D(dPP5lVeqB@xt06w`7ty!_dwB?t$3>kKv6yM zc*;v-v~|RLye^eu_s%`ctQ%R_q)Z_&gTb5xNcN06? z+CF>R8*lvNwm05bumBIS@rcSPWOd!ZAm+xm@vTBTJl4oIr@GL^GpzzQl~m z2p{^zA3ye)?_J;d>T{2Oet4T7wtofF{t4fCYg2~m8!9H{e$oEdma?J7Ov^C*dm*$(jz_4^4yOiXp&t_i+WVp z{YlM&HF+|BtFPxQ)50mbFUpgM88g_tXAeGEQ=bcKl`_7vbMMAp(tjYODq!NpneJ{q z-frH8JksoWF10mdsH>aAnsu+|TLe^f^=RhLJz>(+Df8~1I;CxWYkT9}BWuT1jvG7m zccy7Cvu*nyBA;goeXi)E4z2(AUr=X7S?L{MiXEi)-ldetJ)}f=3TML>yg+cE63&38 z8Q(1}t=t+6g)a#NgWKoLU68u}o@JAkE!!D*H?FxPQgUipX~i|ur_U48a|>78({Jj& zE;pOyoTV4{n@#F*{ZipLPVPR9AJ5qrUc`kTx{N8ary+%l<7E0|@a+=}a2-6)rM$F? zQ%*jY%a&d>=kz5P{Kzl@O#v%#&x|Q^j~QO7|K+W;ZtmRszqxGLACABBFu8wm2(mkuS*FDr@imwSIg!-nU${Jb-H^r@Ga zcKrF&&OMVafBk0e`~KI_B4G#x`wCY#ikV9e4)PSnn}!w6Z`PWo4Rmdc8#`u5i5{Ve z<2BpFibb%?qgZ7TjBo&986Xs<-u+QssZ=3~jH8Hzg3#7+2yilMQuh?p{o`BPJNw*c zn)V;;j!b<3VQ>9`p09P^x3+$Q|Kdku9~>1F1@NNRqZkw@@!9&X@cBLLLCj~-s|sK_ zaDor0_0>91ed}0QUg@1$+_s%McTNx{lCu13>b9V>xGD^>x<2{yJeh#PRRD zh@U_DBJqpn@!+5So6y5g^MTzFVpf!IyURH7f-A^68EiYq^4I>tXGf39mDU;tS#+YU z2bjI=_l&M7nLE7I58E&R(7*k;E7`flb+hQY-Xl|(*Z0f?mAO+h4U4jpN_J#2{It0l ztB;_yCN|+i5prriw_xL>zM4}~TqZa3Mb25(dpw|NJp*SGpoKdB4WM4a+LZ;K$ zAG(}h-FhomRFspEvb$6?ox(Wb1m1Y<)lR?UvQKODGN)W>k6_=yorO$rzCTT7&)bG^rW&#IL7Ev6PY#h z=u<+$k|zzr`qsP24zECHXd^9Q3~Im&A<)sN3|Lf}5Y)Q;2Bid2X?Xra`fU;Mj7w8P zQ-9g&QNdv7^^+E#^`)~;Uuw*peiV+Ao%q-je|+hxt1o-~qaQi-?-M6Ze{j--X z)C%ef}JxB|}$olv3h2S?pkt1&fYl z=|?`w;?qvX44Y&!scw16J|Gv>&8mnHima1GDaqI|leqZ8PZ;OC|MCxKT<7o6aBPKX znxF8Upke#hvWw5S=9-;1y!z_W(Z?PqUVP>;Ub*SVgsUsDVi8)lZRey*Kf<*SJxEGP zOv~oQ$L{CV#~wrz-I~=(O2TEOl+=vyTUm0}+1i9_!=m?}!;WWOz>Y*%@yasJ`O1Gr zY9>#<`$#I?{7jZ!R0dz+OM_+nzW>G|GCQv*iyilaC&UUWc$0DrKY_1n8e8J^ILcerk?z8T`9MNPku+Fppuqnf3?2^W20cF5 zBOTFAtX6F8oe8qhD0W92=}9hr-$`s*_5hpLK1;;1S@y;nPC4%iPQCQg{OP%uQN_GJ z8qW>kWGCBpu&|a61lCF^88Ko6{bZjHv9(|QYPDtoj?(5zfVmjFsj zB8B4*G`E6J2AfG|m^pPqci(@JEk5mpLg3$@!bbr}DJ%7>Epn0croHuad9ojM1r83p z?W259{g{Xo92HXx&ji=cR&Dg_o4sRV?I zqyPt6Pg)%(-Jx}}{vq9gC=0riIQi;8*K?RRXCbz2o%+8i)-lku5GJ=cFSF>fPcvs% zig7RR<}XkD9?Q_kNXZrd{zYzn_yx?*pU<6h+xX4QPL_P~i&U16!p%AyY&pP^`i+bW zM{;~0fH`+A(sA$%3*9tF4{!Iw_OD{bKjAymO3B+>I~u-UQ#HolsB&v{Z#3I=U6fK( zl#Qe_-pUV}n)qm08L>XlU{eUL9WjC{_wGH(hDn*jFx~zWZL~0Sv&K*0RBL?Y4nPT%kcSgJ|Y z7}n7+HIs}Sm}^M@Bg`oGX4Z4ynTz|Wi^2bM@MLul*SSuMdbLO2N|LIRJ8oy|f=t?Gu#A57! zZ6)EF3Oe@HQ#)Z2pL=>4W#h)tmCdaukKg?x4(!>HW4Nb#;VZ4J#S8{=yd=eIzZKw> z7oOtMZ+x8_PB@wBxw8mFBfR+RU%2AdTTj0E{qMh8y6z8-5Fj`FlH3}j6fnV zl`I5m!SW*y7Akmcq zAILBagG@SeC=o0`TRRW`?7ukwKfZccVwW+~C*^nr1YlV_`_ghgvh^BLNgeujUc~hM`kdUd80eljp5l_x3rQ)#ha<;Hi&-b}T5r z)kd`+5=M8pS+7+D{BQLGjy$c9BRf-OkVnJXG+v5^b za~K=x=s^Ufq#`NRw$xcDA#|O}%4#YrtI>ppVVFV)G1~K-(V0woNmnvXOG_ikR2Lnct=UW_ z)sS^EJJQM2o~~44i{oUrd7gK`&$876S~wj2;jEd*;5eB98F>I4$6?{|$Gz>~zqdo2 z&148iqAYpe*(6g*)~8u*^GrKf-X^S`?MyWfqa(`l0FTn~RLmEr?eT*aPaHZpO} zY{nmbG>K#qPf9x5nt1e%ALFDmh2URFiD}!E)YRmFp*}N+D%T3|m;3qLy}#r8mtM@` zFMpO;c_kUcW8Cby3wFG@a>y}pQ6?{3R07=S&$Cof_Fwg4)Nd;yz3VT-*q7av_S|EB zyX*N+p%jLuV`&Da&GE*bOa*zx~5}l1{wlKd6ZjW*_KT#2cA6AAFU5ZT=g-x z2O|6G_r3qL0RQmUEY*f(-x>^GL?D@F(d_B`eeI!G@3y`Bx%5;2NkwUl%Bpfmra92m zOldTNa$Im-B922e9O?%CbA+^8279gn!#c(=yA%3i002POb%ME;gF#h#>H&MPSr#Qw z8pSFJV}xvksdul(N>Nf#)(rrpQaK<4i0K;ft|SBl(3R{xU^w@EC-cayH*vvdzeayW z3xD|G4U}oZpHT|W^#}(8#KIxS_Cb~7sn-S=cX?p0qSsiIMcfpsk3hPw?m*>B3JwOy z%U2G~1y1&Z_9h)&g8Niy~0C@2bG%r2Cb3g8YB^ zG>=d^6DLlbyl&lkain{zTEE^xG(L#OIfve6QHfGhfRD5B`PbF@7e66pp0wdzoaVYj zYEP6MzFXntAfqVE|y*h5>+ntjY7-U$=KQf1$Fh7U{G8 zABtdWh1bhUN6^~d!0+1H_;OVh0U=nOPV7o7cp&;7EUe)7aWshNVerLW!bge8Fq0R#My1LDk4QQZgsK zDiLVeH1>rTarr0;e8}@Me|@KJczu~+mvm)AhQB|Xnt_twDX-VgCeVb&Ao zN%L@&+bw3RM7}z)P@XL& zV3<%SN-z+@Fbqt?L`uoump_MX2PrM7pscKtShSQtAV^6`IVC0Kj2bl#4INF_EM3#< zB(lzRT|CDjnNA=*iR-xp0-@xZHLq{;q>Q?*Q`qo(Y`(qP0Gw=w6PKJxCiU)cXJ)fm z4Bg=9<4$D$F~_oX<3={GUXSM~tbCxCSC4F8upQQ7wKHbi`H7$X?1STvJyvveb@f==rROnn-aP6S zF2r*j;$2+?LSZ()`8v=1@wXU;iRPCTD=7&?qeQDJeSP(T{m^(v8*!(LlP|uMO;5f+ z)h9p3@2|biZFqCtw~r()EMm2f`2j$l<-gMp^u4?$y&n|kd+1aCF_9rkTdK5|`3!K6 zuItqb?2K~5Y3T$zykrJ+=^SN~t~Xw)5GGJK%qZIoUsBT89My zgzIwm&0k~2*&purm}l?#31%wy6Fl+C3Z{)4-9s+VkHEUC3EZwhS28Kxn4}54(4yBB zj}r*wC}gCcl`O=^p2r)@-@p$*5AO^{g0lmqVXV>!W+aGanz;;d5ojF?1qlTMBvWb9 znJlEzIbTgmE`9$J(wzwcx|Rnvy4Ukemh;XyksZ(ek*ojfCp`YbYk2-WId;wr?)vUm zm^OJlWc}*ANSJSZ_f|fC)kpdc{&U{z+AZt;69d;H$IZv1FOMO{n?fif&cg=4<@n?%!eUu7Wgq~t$W zr>U`?U3)fDJ7PS#ZjwmEaosFZdgz9UZ3WSUMro{y&h|DoZd%2(sSA+O<>-Y=c=N57 zalKl~N=G22*Cz-N41}3FWq!%F?du+j$2&jhd6~!GiJRWmR+g~B2O1(7Q4IVG9I+H>vi6#VdW*^Jk*~j5}4v9o32M+FK`;LvIQn}zM z7zz;zMG1$Z#G)nGc92joOfVG2vI7LeVRWHGPS-cIar5e#A2{oBTsI4a^X~1kE5G7T zQ8}WjpUmnzYk5Fo>daY8ojH@O>o&4^%{rve(DNmVzH_YUI`NJ+VkKn-zf34mXhX?l z)0l?IqN7jYn4?abyKB$3U$0*M`v24)-1B28!}$7G?hnL9wrgmFELU9U-rY3%uM{pZUOZ z%k5X3eAos7YRr9KquTiVEhzPcfx`&Jv`ORm!;iknW!K!;8yMl4U;mIfQzwG!LMX&< zA9{j6{ObGQgY@|>Cy@sMP+P>DbJ_-Znzfc;Psp*l=hSyxSEqj8J|fX5i;g>*RV&vJ z2-s+vV9L~KG&COY{Far&npG01vPxr^(GZ$xAT)7E%R|gEnK5xJE7xx!(UoHJ&b>^n zs|Bf;K5Ytrd-f&HIrRjTQ)Qf-T zq+=FPVcXqOgFWpLG40gNeK?I21^*!*l%Ld#>AzT7QtS0T*$WIX{Pm+)l5#NMp$4n~ zPV^c6kJK#xI^GYg^Ur5M9s+)J(D~Y5P*2FAXWu zRySyD4E_q#{2^VbRQIcm&wofvKjpr6BM&iu{;5vws0r5SU;YixvU1w23N$q0p2XIp z+!&dUv!b4-UcHWGCK#h8lG?w8M+1T}ktl9nwM^4;{1>{8&@@aO)Dm*gIKhJP%y&1ZEd_cWeQG?VJ=tir4&h} zm>UQ%-m*C8I41$`DF8sz^dDB0jheg7O|ox(B{ffVB6WqbbPOdJqgVM0b}k5a5oic9 zQn0zBg2r@+v5`*dX<=RBUktQbu+Qcg#_ znQhzGGI`Q$JkRB*1t+p@{ToQ>QB^S#*X!F|wJeK?6K2>ucW(TBYg^;_!1HhSzNbd- zt7%E=m9`6pnjhH<7&QJaFmmi#P?6D$|NE}uM z(hdfx-?fb=@416?GKn1ubxW;jg3^&AF>Gtl!GGa%10kMxwT>704?sqEgk zowl}isz%i?ZhRdPsdB+TfNj#!(aFe?D5SHwc0bh%1VBADgfpBG3`8`~bLdR8QW~p5 zN{MNjq*EzYtysyKXP?Q_Pd!g46y*AET+7$L{*|~-V0U-`tt=8VV<9x#Li8eNE)KCz zJ$3;r*Kfh~Jl1a6&eSnE**?Q{IsJrVNW>F_Z42cogrywo_F+n>|UP{ zjg)^<*G)7}ar1L`^5fuJq#`D!(2*jakM3rh&z1G(7AFrub0*BDwvqhsK!%H~xok^B zXiSG`%>-$Tn{>`Qm9On<$ZXxV^-|wS?QKC()HImS{1;>ZrOcHU=2`nRL37JN4jkM| zBot%+!R^>qkh+mmC@-xh7O9}Tw3ZPSqZu=DDkUXV9B9~1DixmdT`Gn1|e5d@H_|9bSS5Mx4SJD?m!-vd#JX-|cq@JgL!{wdqPhaN%rz|LmWi zC@%jmz8ZnZ_8z24DLm=nc`j0Vg>kNFIznhDrEpz`WU7l~vWrYMlOxwt0$npPjR1yj zp=%cDbe6W(HVz)FXXB>zJh$v|=FB{XY&KJJopuDaQ-7=4OOeVYH9PDW1!vFjdno=J+f{(}p0G3|?Q0;Fm%{~Z__5*_64E6a8 zqUQ(x*O z&|EhkX?3q*g{4e9JcLtRWLW_c$#%+OBf6z{HI15)Bhhq=RV&_P!BKOF$K$;G((9~U zw?P~1*b9_ILVD0fGc-R~>~qoPf+fcnzWasOSAp3b$_I3va3}~uLl{GJF9SBqH|^k8 zzj=T!eeUCE{RRI*d`HYYb^QPVxb){=mtP5%0XF&-kqO^7lD!_P*T4DaE&lP|5aw|4 zX9V8?AAPL9?&P!o19JdKne3q~<&!#l%CDbO6j=W$QUJ&=dxmKe3`7V9LjYAnpGfBa zyp36?q4D*1dTwWszj^l62QzisTJdzVhd-BZpUr~+8PA}@GiY{oG9o}i3UmdQ5Ck=i zolb@ucWvX8C!gk=Z{N<(Z+e(*PbAp6OlS7P4Oja6#IOz9FaU5EdohvhSf6zUm!VNg z5sj1*4n?`Qy}eIuo2*h?P*OsPrq6f}-RGcb+PB3b6{J#eblqUaq&bvLoy-r76+CKg zBV~hTn%%N!`AodeIPWP9r3CxD6c=0b*w`6iLt7Q=+efgWt&+`=8Qd=n@0G{@`h_fC zThm|6)fbDg>UEFt`~Ia=?AgB+P1A5(hcP3kq3b5Q_HAI_fvxPR-^9KHTXNDd(j}Ws zGOA`0jjj7|oHSJxquIQ94Vg^J_n92VkDE#?R>s=(f2XCjfriF?bab|oPA79@HGak~ z9F8$(_M%`-^{77rA3D+-pDry6q^`GlL+W*f00E&SC)3%s*^6{K-`l*yhqwLhTPY2srazWVYL7r$?9d3p8Yz$wF-*mulgRTCyW z_|>PM{?kXl|NTf;Jbu`0y=mLDw>0wWo4&%%b#D;}h6+_M2q>wkrnIK!ZJ(H7n5=sJ z1y25tD;Yay&NqO0N4PiYe%7$EC>ZD{%Kpn<^Rrk^FQ0{Ui$H~U-Bd2m+~;F>$PVTP zdN&Sj@shcqzj*!BG+uaf1MTgdoN(-dp8fwl%CS@{qIty-zU?$AJz|jxWRaqd>o`a$ zv22Tuc!GU<_Y(*NxcA;aQCVIV^X2RgKW{<-TQjtNl@9U%z{EMz3;WJ9udRa8l0(ol zp@{(r3VST)mI;wCSAX*d?AWoJZ+-c*80k!Zo8a?wMQ%9EC+6F55;qxN3cZ%-#w7d*Vc{u}irq8Wa5ELu5UA(6^q=8XA7qET$iX3orG=$Kx^kAiPVC%MZtlhAjH&?&R$~RwN_1f2Povdk^*6;ib`-Gv~ z^s|;MooZWwYh6!rFxkY`#D3n0b+WcHi)Y&iVS~y6EGa3;`0W%KPbcM?I8w(`0#^yr zu1?&sXiSD_PKI#o7_Uzr%|ow0d9_dY)2~PQj~Zl-lcjpZNa;A)9x{&k;8+y}&G~8o z!?Z9AV@Lpi@XG{sT}St;bHotlZ@*rS>k+Le_};OOC{|83dDC;gxQv;VsrH(oSy;X=B6 zhW~*q5Q?z+rRVtL5C01#CAwkwiY5{}6sEkc4l5WO5*LLT3L-Q?S5q@x4NZ92EC`Wf zZq{|4c=$g4<2S$2>`3IEA!g$8Ox~tX##P~G5u5zr!8r`MpY)G${NTYIWbg2iMy*2m z4^Z654I)=-o_qLzQ*_KQ7|`DjKl6+|C^@(crs}n}Dg~y=%j>uB#8c1n)BpZ5dNzBg zkYb)wPl&IGnU@TjwA3(6GZ=^*vR3E7-`w!hb)EM1PBcxUv%Qm&(sF>wgK`E<-5bn0 zUKI{<;pry=uyxm7R=l!eV9=o0bPdW%p`r|In^l{)^Xcnv=DKfupD$l~C6}FZI(ok? zJL*+RA|DV77dnRl0HhDTC49i{EkF3*2JG`I1A0pZD!)RY7(ht+k0m}3kQ!tQKtA}- z`abryx5-IU@0b6JBLNbH5V^fj74MWjx0b^9<#MI%x~>zjZG>h}QC^N=Xt5!EStc;x zI_p{%`yCe<4CMOg`yGtx@^?PkaBsRhy<(5y*Ao`zPa#Q?0|D~Ef6CJ_q|I;ITKV_A z^}N_r!^g$@_)OqfrW+NwLXuJrrqK9V`V|%$bt`_zYpLN?blCn??7hHNd4ES|^9|Ki zql1G9LUL6AWi;3!mZuy}2wOb>01tto8O#kwqT3URQG+GGc^9q9vVva@g<`a|9b`mR z4T(gYP&k6730&7D8j7%R{)wdBG{4@t3HG(Hz^&jIa~!2w5KnqYnRo9f_-}c}*4BX6 z;cnjhi}S2G%abD0b_375eXoD+W~GuV<6UhFBjHj%^OlqMQ9|Te6n(!&%3K+?Z3QWf zRgp?}(bnFCrWv4QVF49F(AIvCSfmUgG+Z}>tLL2itdqtx1L&H?j$NA=KX$6mIgo2J z2uEU+mR9u0W-C84EtQ9o3aKQX>xg7BarA~wD~|(q4CbaUUAk0{cknwQ1sxr&R922; zU;Q>3I~r(=w6LPAj5%H@r>9F8l?6|@{y9L>(?~iNts;n_dpSXGsgrUHGSVQEkz^K3 zQV&1<;E!&0KKkn`xqX0yiPtLs0R($O2s-2K-nhESGN;VYQ!2O*Eia^!1cSi=wWRyG zCNk+X@pvcMYzi-xMhgbg!tnxSrDa6Q%CQ1Lr1WrIhoKY~D5X%I#~J6GkLP;4^yE`y zl3Ap$Su6@jmB_c#=K99zNjhD8&C+%7fbrv|FloY!Q#Ws2vwY>7uRYM(+Hl=4N5GIQ zI{v7IcU|tLXDGf}C=i>RYY{sXdrEe75sAf6vRhHfaUI5v8INB9^Xy^w5KYAUE&VS(E|cY( zU;jK0J^dmG`1lvU#kyzykdyyA3=pvYKqKF|;fG|hS!%1wIqUeN`S$hKP-$4;IsFm- z0sM~kz^BBFg{eVI2U$eK8TZTQ^BZD?PvY5|>@VX7`2qjA?$7l(J_+F3UXq{vsQ{=V zC6KINaj+hk2$UV+h-?Cm0$v#8@p|tiC!ID63Gy)aF>UYkx8#;4OypU{LCv{WC^UEK6lLZs%`r&!du2HLA{H0iMQqwy)v%4B( z;_3&Tbq`-`%^|IvA`l?wTewmn&~QByN0VIJxS94$kgEfyFjkb1MfP}KP?-EN`xXkd z`_jm)s~%}xH@toh+b{qy1lyHLC!bEIljqrXXmGxgfKV{Ps*KB=h>cXLXyp|sr86y9 zB5r8fU;Z8d06rIsl$B(i4Ch|_VLoxy)qMBHFOx~6Kp1`rmWJcG*t*5M>BnHqGdbAW zz|VJVpr+no9@R{+s)=Bs$y~3jlzx_8CE5dV(-ssv_V*dLEM|&S3JS znM>EKU2*>EwJUxSkGI`4tQv4Qms0=Wg7eP1d+y~IMPGRGLCQvsBvw0cb*Npv?cbu?PTg4l}Qd zgAm?L4uE`V|MQ%zL6f$N7ql{Bq76il-6BP;Dx*v7VwZ{&SGQ9u%XmO4mdfEWfPQ}b zu_v~vP0w9~6psvI;VrDQPBzPlixv>H%$#(c=+3hC9$YAKv8Y=-lx*SApxlNkB@wiU;OSN_8w^D>aTx~AOF{N zkR14uMpajF>$k7%=5p~QNC|F#+o+Ie@*<`#c}xf)53>gr%W-;s0N&|8R8a|iyZ?96 z|2yEzdo}~5e$_x(kp$jLMf2V}%zVyQAEf-x{4G!mM2n8e`fJKyZ3^(0Asip-UB!_j z4i-qI(3I?@1dwa{5SqX=O@hHdPNLW}(KJIMhe8nST78BU(J*J6^1#88k7#Sk;taGGO(Bc1{vj{P}suYvFrw3b9V2&)LwAv<*k3%JG^=h+b{qyR3}EM z+gsWi&Ko^)0#XjbPg3AYk1bLW$HFc0#XK}T1TiDP)@(BLPrkHL)381tiIwyI3qQ=c z7kv<24>4i#G}f(H;j`!~gjP^v#giUnp{A^w@yCzDkuE!%8`!XI57xm>${mwRGe%9Q zjI?lhwQZYzo;CZmxbRkeA^u?NXAgf)iKA;KowMP<_U-%J?ImMIPU!*K3v$e;u9GDg zj9{8J?Hx@y?sY#J&a>!uXI=%VbQiIx?K>Vi!9avWS9^|NMM=ubYT3NyE#}NVHrIQu z>qyT9^YHti5E}8WPJjc0x#>%nF4faXZ{(|@aY?um!zhq}6EOs*SOG3%&B#7fIar;-C^d^4F0 zS;t}0ZY1R~KPOHXR1&YoA6v-`!@C>dLq<9moFaN>#G ztM0x3j}N`I>QO)2*5kyU%JuOt9AX=Q=C=Tp_*1{#&n6bw|NF@R7J~rpyWjh-xRD$6 za>{j^R=tcWt&O-I!PZQ4k);a=dy+;*(GoZ?2Ynu-DwwL?jj?8i}C!B+3Chq$WE`O2L`tKtpO!|$-Uvv|7U&fkA(jo?=aOr z#r^*+e)it@U$!c znMMkoAchK<*&Xt`?fk$qU0a5v)4F{Brj}|w(7afSmMm-DOYMlU zJ<0$S5Du4+N~e&XM>rJA_4(@tN=g50RiO+Ur3wu80ETXM)2sMV(%KLbR##4T53fZU0RlMqmzsg#WM|*;nAVW5LyP!F$lX+ z+T1i@w;Wrw(Wc$V4NCD%#BeJ>U%#VNdtdz|iR^fkTKqPb=i*YOtHg{YzZ&XCXqr~q zSF4s(l2kI+x*iIakc=ltbarBzCgDf~*LB5&2@@u4-@c>T&q()go_dWT@VMCN3{U+2 zR{r$x6a3q?-{z95zsb$}5AuIM_wUfw4oAufqtspC-6&?BvFC_Uv7U0A3IBP1qigcl zgE%nWCkSjP;`iwEfq)f07?4*2$Q*{xLlpsknIiC^$*(fl;s4#cbSi&t{oSyX{~4L0 z_M?HuN_oEZs(YN|0(~WO)c{iJc%F;EM0y_5A6uqnVOch@SeR@!fn{5olNv%7KtDYs z4Lf#GtrS_=y%Z*;$CS%oEZt`D9;28RxnW~Xf9MduAR%0@nD&gMj80{3KA@{GH6b3p0mzLnXxb$G=b zwtq#_-XrIc%4RcvOmuZH5M{byn3R;3VVYL1HylAq=%mO!k{G1X$)XdN3QLH8W;V~z zH0?9fW*tvuMKz=9syXef3wZUVXK*uFzZAMa#nKG~_?oP$pcO2TQsO!pr0Y>yIfA)I zFXrP{{U;?g)tln3`_hq|T%(t6xT<6#UGbJeK$OquYnn!9qK)R3dJv%NCMB^-vQ8S; z%i_4%LqPp-sKh6kQ|N|?>$&K9x0IKZ9_6LgY~8j7P1muk0FIL_H0E7?a5=|x?7-0s zq|i`8po+w5T{k;uJ!7HN*FDdrqq809d346xbFxIjS45Jk5C}>sahxoHV3--x7cgbo zJi01_tcfMqJPOv7b@60yFZa5u_(l8$mOJ}yyMzZ)gUy_|%4;1e1wc0^LhhV3P3tDz z(+zapK+|-jl4P@KlBqbEbV@6YmXBAen@1rpDk%%0h#--OqiII2^jaw#Cqr*%p)WH{ zi{Ib%^Yok>zVV%kvC}=39sK5;Nn>P_1g4&Te(Oi?`{RQb|LNhIHka79{oyx1P2PU% z_i1iwBpi+uGFeJVDyv2mg8zaO<4F)Oeg14tJnJ+fu_$iV=_WT+impVwJ4@!jE_(<6 z{{4_X65=`zfnbPJPCDnPDU)WsI(z2A+a^pns^tIUeIZseWy*b5{ptP(YtKHRky?5}~uWluqN@7}efh0{gOe*R|VFm+ewoUtv zJ?wn;Wp+IK68m3WQK%5;XF}jQS)62&im8+6*u7UZZ{7Ca*+g5B1$dJ)$sr7IAFezZ4!>(>|ijv3~L+HI8a92X9^To_1w;jp5rIhKuvj3XU2!~1t z*ijP6c2e0cLZJ{&HcM+u3okzZB9kUg(ShR*KkD5T9Hz|v5GN;{=Cbq7WcM3?<+NiL z@WubRm5Z;q2G=rkrG!J<_-+9?PRu;@6K^y4?;VJD`MyIZ(B|{L?C^u?E}tZ@(SPjm z|9#be-t1TZ92WfRHShCMpeg@5TYNy_U;z3+1;20Mr9OCQdP_KO_0PX|8$v&~QLoa3 z)*DnQ^2H>c>*Bf&j+-Hq&5}uH$Y!&-*Rn3PBTET~qr_sRL-Sq?tH<)wW1qt~#xrL8w;G*fMOYVx}=wN#StGr0S8Axa1=r zqq?@5)|M9T_{mL-tQl7*E$J?EQFz>Or6OiM>2i-T)y+)U)Z*F>-t{~X`^wR-8nKu>rn1`b!gz<-qB1to$A3Z z?MV;mxwxJOBIoqkc92jgLRm>Um62*9k(k}m)(}=`7`l$`XZ7><-}PLUz4#Zx!3d^l za_pkh$YwJ**({o_4OosZgkZ~tHL~i%|8}bxtv22csX-=<4F)HC>I=KBxb_Qsns@Ii zx&8J#LihgW=h2f-`+#=b;*-f{GlvBK#pby#b|AoUr=85fefwFray6doVi+bZtxZ%` z*7$^yJ(v#;x%Z;r4ER8R>o9rJEUK$Ve`?$I4d=yXAM^RQ)-HeG|EHKox2y|KxZ;XC zKK7#@mEZsCpRnlTveI=zvtYg_TD?)ouoTENjf1A5+EQ;*cTC02ndLyqO!~k z?xN0bG`KS|ItnU+f+H$IP*7O}M35bl5Xc4z*_Yne+UsuT_eb5TuI_Y_P6#B7eLkQ2 z>F(-U&OLSRx#xM__kEt%*#7KGNJD4B!uK#?;c=||-z9ml;10V^kV`puSwkQYq@t>l^2$m)*Cm-u^6b;g@NMk&sA(W(oY|t*KKVRw z!anuPwizD|@z8I6%#%;Oz?EP99#c-bhuLw zc=@9=13>!Mqx3U-JRkhG_}PUi-}ck;BleyT-V;8MAE}#1LI1<@LAzT*0;m!@K?S_x zzwab}-Pz)29~8=0JAs${{-sAkLI@$p=XH;~K?_>`6Fn3X*K<*hzrS!j9L)xy=LWUGP*V@Y`CmqGt&wMW*`N(H@_OHLeD7Ao8 z+6BN(Z^NZ+Wt8=)|IICX?%Lo9;$eFYag`+^4A#1Bj1%RY9+<{7t(E{9&p4a;TKZ8o zc|EP=TIkxen|mNVx;&1yQ3BwAwYAAq|I@Z@oo?s@>C#dP3?tx2n1Yipw;W4SH9E#=7*Y^X5x8XUSVAbq}15Bc{NSr z52L!ahEy_1Pj@#`LV2u~aHx#Fcn8^R8qaglG@V#^9flr2*G#_#+a!}qQB_etG>Sni zT)~#D>!_)&qp!aQPY5ck1g^~A)ykYWXZNfs#7xM_Ah$N1g6mqT5#9AQ_k$=%rIH|g z;Wy9oBa8*@g1m87LBGH>3__tWrfC8aPZy*$MJy7bqP&7}b>o>ZZW2~5^U{7qBRXx{ z8Ys8(Ywe__7>`*(IySk#57ET!62p?VDpxB95MSi48vse*4NqDvV}3VW65Q6Xu6JL@4hb6Gz0wd z?mIU9=h9_e$>iXa|NU)-BKUfiH;$Mv@tALZ``ZcEwvxBpd~^64|L?lkykk$+&p!A4 zzKg)_Q^OtGrnaG;Q_pK)-KsTo?rf*EbsICLA5pxPilq)h4AMdshw>s`{|veySfQgRuZYJp?_NobI&@Lrb$!SI`Mgw>kZw-;yN~()VcVw zPqFdUSNV?x$K2k&YR%_HnhEq42>{Ip0TF-Goh=~%_Wa@jF|y)?N{0YeOn{gmh70;yyI-Ovg9Islbb zRe+?auIa>W?IQ}R|74#D0Dq0uGFeW4&wSo|`j6cIm&bYkRbS%MA6dkgKmGB+x&T77 zfVvr+hnR8t8nKUA2P3@idL?T7=@Lu60ufLk_Fnf%f_O=kKj&Zj$_L)bA?g2nD*q`Z z{?h(?n*RIr`)f-^{uqc3sZ1;>y|#k=#k#9sa&~Y-=nNzR9gQqDYuq+| znR|)XoEB2bS|bs^Do6dI&rOdC29LH;0^mS5+s@t5*WY>Cn3{1yDdnd<>q9Jb22{;m z6fq;r`)iu`_nKO&RTk6BB811!d;0l7SBG|xP9+vJ!)FU5PyhXQG)|bojxB4bt*Sw2 zgIQ4N`NdzNR02Q@@@p^LQ-qWR3=_>T$y$AQ9&7ibZJuNyN7O&a;d*7tVr z>1iVzjxu&!BaY(`3WuqdlAf+Ez(dyz##A*j0GWgzt@emUDzNMf=}dxfFh<_8$QyKD zjz%hJY28G9eIt%zqw59@^>ujbw-qb&tP(ARke8)8*N^ME@x7hcqD70$Tt`&Bj zM>dmkL}jgBAafkoLHVl3g;akjC7P~d>L#I31k*Ipbpu_~i_z?S%D+V>lg4%&T-V02 z9c;%g5FOg)t*={?C(aDGu1hYLC7aD4r6gxr=(>U9*ffowhU?n&_Vf@8OTPrb-W`~s zqpgM0zx3574ixw=wC7qnHcqb4-V>>;w$M#+-RC}^`TXZUpT7OppN0SP`m3YIELdoq z_kl}Lp0`^fKzSYtMf2Rl`Rk4iboaL7x$Z8dhy}1O2KKAI7J?ci7$|&kB-^p6uNy~A zb=`S8TerM<+9~IK^~96s-?Dh|;@xh(=FOWIUcP*}1qWAnWN52_*x}P=eeuj|uAG1P z`0*#qudR($u2@0ORab4g`>MQWNFX}WLFscFQmFs{b|BL~3h52vVKhEV%d*&iTM4 z{MUysr{SczxTV5iLSSXm%$olm<{fz~cYouCmM3og$*0_$`_Maq_eyL41OAcrfrPye zQNSYAq4e$Z=#^0x-crS?KP>cua5mfq%NgI+iDE>;8`^4OZ z2MR2#&SsLCNT@92?I~MJN;2s*v9dA}@i?hu5)@dTJ2FA!cJ8B&&-fVw``#QE6PHWg zcLo={_f(#Fb}4r+d5BBicShWk`uB9levla_t$w=*u^}291t)+)_KxtcVa*5ph2O1` z2z%i*h3h=&zkXjVJxg6cQa*X0`=6nFQt=fZ+}kCj;^RKi*aSS~ixnpQpN0PItsj+A z$fi=8W>qA>OS-2@%1jH7iTs|(wk$H~4B2c3*LCfE`T~^GG~C0DlN#CLx@bb+D8=@4 ziZ30$kU%Ju&uj!P7(avOpI=JzrVh%FZYEe;2};$!o!9htCXK!Rvs+i3IZHH6c-h&e zwRmwhdfjYtyXjS#cHkc14q&B+QlrR!w2cw~Z(n;Vp6JWe*EWWgP=hv|4ASw=H&+R= zXrxq-HUbF1lpX;od0lNFNQcZGobx!lyt1aOELu%h$4<(_Q7X!+2g;jD{L3{!a}`2( z`SXB9j*Sok-Oy1$TgNu$ z9(iIBaCx3bAP}H_>{xnxddOw7cz8qZbps%)yle~|UE3I2HwDjghXs_nG)X1^|gRg7~f zKLNoG^YPfiQ_t1kd%-0*jx}s)fDn=g@4uJx-hVN3k6wV4u~@Zi#ekMViLOWy z?iX|eifn-YSc!0;>u;Qz8mC42`?`Ph!gH%GTeRp?pIox!wpE2|$yX|F1FE-eYx%Tk z2D6rx{l>w@Dy0^bx7F2!*2kLv^NUaaoz%*;*tr}jDVcD?4YgEP&lpoT`BFO*`qJvV z|ICDi3n-t~$m>u3gNX}{A(P7$=b&Ml^mTW!^zpy2an)-Gp)do1U4Xx)>(or0!i)d? zQ-T%c`Ehn#gp?%PI(W~eALgUq`3}GP_O}Q%H{q3l|Gdbk#zh~#iXAK0@a6X$|J(LA z*8S^91waqb*lGT~G3fuEECCVwTFcx5`y z7=al!@#^Yno888^b_2r#EQg#WF`W#Kj1mwtCd@W=M0 zGV#Aws`?M?6@xntJ9q3TW(`WI(VvKq==u?-oZ_f8PhO2+#aoQ#5CqOR>6i_aSA6=E zi?4g^si&TLCyCM0TKqy}UzP~&CH?DJ_kR{NJ{Y3*pBzs7Zw~~98YTmwu%`6+zi$Sf z^WV2XHr(UiM=am+&-43}@?Y0q>OiuG^B!-SA-xcIQ6;6FgK5cpcC8c=DFvFQV`w_z zP=s(KN+=YjySp2IT=u0+81~UdG-FMA3!?L|%YxAoJK4CR0Vg zUrb3>0~r7cg{B!8hCy|06JYunGcC>6kAka0* z%0MGaYmef>NwA<^ph>XYym(zg3)5kgf#>a&%h7~)q33y|Q%O?kIF%J+ina8mR&WKN zfu{(C!o^IJylqmj2%bTq>pHp?WM}&Z{Cd27j)_>7wOx!@5xG!`Axj7_ijPUD`TrBU z)M6{;QB&0*x9xb-9jq9w2n8byXGa+COVBuO_l`tT)7Y|gqoec#FJfj&xbOb^T~iEn zOaQKew1@oIRaa-%zq!7B`t+v0fBWPj@42U+AY39ASQwYy-frG|!Nu6NO?7oGV;jeF z#{1t(&6rwj%c3BMs7eX7;lO{%->T#>*RhGl%BiaxcdVVuzIxGxAOGGJS9~E-QBiYZ zI2_$RwxOxxxMNS>dBSmLf5kM-FN8v&#)G_$hJh)CKR(dj-kIy$@ywP@9oV4|qM`y3 zjWYhVm9cRr%zM3T!j!LR!9cLQ@kp}0-E4j0SswoN&xiyEY{xWR=h?s9$K5wAX49IL z=!TA_8$-aqB3e~R{j3?h{G;0mRaF$NrqccWghNrT`q^!Kli=UK z-bx98LJ2^j93brj`=LjogzQU|T=%6>ceM`!pl-=$CH!@)!;dHzECLJSgKzpj+e;qn z@}vK~B^gM2D?yqT2!w`YUJeADfV}OrzvnSb1Jeu;Gy_DVF=}h;s2kHjO-(i3Jw3|L zl-QTSpFHg2T|IpDnk!h_7e^O@nUPvL+gfpLn^Zi(woRMpu(OPBtVau)IQ_{&r=Nbi z=Zgz>0iOas3|!@x!7LjE|D$b`0C;Cx!1LUoQr-}-qDsQ%#R?{$VwE^P3E(1eka$Qs ztu#5PJ{X(tP$+zAAP^vvNfQi5@&I4tS6)#<#wrw!R5%h`A$)4L09I8#MXN-;Rg)Tq zZcv`8r#k~Lv{>gGHLn~Jv22=Ek;?DQfQhalTP7!9-il+8wR?r zGoyJHvu7Vc^X$W!cl0romsir&*-2G(4Utee{qatQvn>J$nPHNNIIip9I4&X2;?C+b zxV`2a8Y;qEG6~Kc2Mtv<+%w^10uq!`drU?9)TcgWfVkXoY~qQ25{Vun;j*F-&LCfS zK#Dx;t?LFtX!-hjGf={s7in^;tE*W5#u^|L-=7JQ&8622mkse2HaLUa0ZN-;=+bo^ zM+iCW>vnleY6Nr_+a7*@W*7##5m46KuzkxpgtjF!Ep8^GO1_<9cD}1n84r2gXFr#D zbJNB)NhbN(Yp+n7HmoNci59=B%F1dSzobGb<&$l2^hw9F;M9{40zB764HerQ3jRxZ z#-W6O%D-n>S*0|M!1cLI|IYWHcli@1pKuQ6oON;KlqoZ`NHoff=|{wr65l)+i>C?A z3ueyz>^HBx@^4jeRLSNqc*oAw$!A0(A%FjY*tg(SiB0;*hmxf7G z`Q(p&%2%Iwk|_&M;#-T(r#IVA^`wdU%m5*ZK+xGjhFKyv&7DBGS{#stKG6(?;W(3!9Xx+A* z-tKOy%^){ze~r`5Jq@=%fffmY5*|`5VYH35(e_V402oSP48JGawFICL$#Z=IAWs71 zk36;K8VBJVjtPg$%RMh&!k}yVuy==o61fuKNU(*%lLL{;g7BXzu>>$pgFrAyC=#H( zy`y*Cx^?>_hSg@-xwWo0fas*A)6%wyrtydEQaf#!CV_y7X`1;I|B5Oc$HsA8q$UXl z^DY82X3fGh19WwE5Q~)~gd~?s@AmE(FhkgWO1DA~@^U;IY3AP=ui?7JtNFob%aTmS2?Rp8o>R=8C;~knASxgb45Ax(-`l~Url267 zPadxwQ$=fAt5;rLo7#`@7TIiSm2KMxY=WiIak{!%*s^UMTehwnlxg949^=MMVav94 z3`YVCvteNU>u>DNz85QJQ9GuN1K9n6_fDf7{@(Lfcl7k^u@uQspp1a{?)Sf+_}deY zcRcs>!`bgF{vwuTVfgcMxMo{6l~q-o@&5A|KY1dyl>?P`3{k3NKI{$r7p_%b>q3({ zrV%K2Tt{;~hyHjkp6lW|Hiu1}4X6u!CFi%j{kVQ=?ZRW`U-kVT|9I(hFTcFzxx4QA z!GBzE!Ga@Ty8o0D=3a2Ynk)bD=sC}AYeOrXtq^!ywh-8~i7)^9H}tf;iSj&Zrq5yd zt-mGJ)=BNcdHnX9U*k`A+)Q6bJGyD^0{jJnSZy^GW5*(N9X%AJd)=E%UvwUyxbs(h zd)W#;bI%fHopC0w{PiKedCuvKJ#HQqjpOiqqS4A_Ip(bM>3n8I*DW9X;Kgn0)?M-r zNB!BAZN~HofYJz}w-5FIZzCXv^~6Mkh=^lq9!d&q4WtH!W}{O<-$WC)I!LynnU$9W z$OZ#s!wO-5)C86$$!Hn$s<`oO+MGldX}Ozb+~H~V)?AONfKL zl7B<851f+sE7%Yg()kNN3y;N1gaYIKk?@aF3&K4L0P31~j-d};r-Q)&;Yh^qpG4F0 z8K8z?VCV*hVPY6&em|re2n3Z?F?xG@`}SoWR-2y;qBwH*JI^jwJbV|oZ{3bAA*Pwc zi~yCo$ye4t&w>x0#GG*rq&IA*Z0-!Ot;hUwo6$DfM%zCD0T4uaBLnSfV5cUAB%2p% zeqBlAAe_TF}4u7hq2k84B;kKq+SNXbz=IsbRhPvZrzx?$v1`8CNPL3lr%SqRWHoiTNl?A*~BudOxr$N5Ehp0_%iJ20j(%C}sstsTdt z2{Wm$Z({8m%Zd?jfN(Hk#QS^FnznZhOd$jhKKNH=OdY;-&#^6{v5Nh>n1k5iAX$A6 zvI4@Y<@%T3TAS7JckBO{b}GY7{v4 z?Otg9qpGUW3s<&3c*??CuU)om{*=ovr}zBx$=r7zvyVCEs6Z@s(-+s`IF z`|2}ni{@yNvEty`z(v)yJoD=FoPOB_CEA<-YzYCmr}bw}zzj|r`d~VproX=zO=@|aBdMY3zWb0b zd|U{zIgU*xlO`O|>FVh0^~YjlElv&Wq3l))CRCNvv+^j@_z=T_Rut)XjCVg%d~IUupzgfD>0iZjFMXruwo5L(WXGCS7w<>9>48O7`E-5F_vtqL&7?aL3$Q(bkOK#ZmAC;! zFOy}AcF~3_9h3yAIe5C%mF{So%*lYeK~8&RgPil1vj@04xIe43Fpy^y;VZ*pwM04OnijVXeNXxOe&IBLNbLuJx|tT-MdQv)@yB z@nFZbvFt3#bU(fQZ3y^7L&K!GEiD^fc}w@3Sr=QRVjn^5!HP|gLC7zNS*M&Xrk$HR z)W)lX1SoX|NS7R`5}=;;0r$`>fDsdaLr4dEh#NsE;2(OVcB4U%9U@FPY(I2eUsPQ+ zZkIh*tgM{snlT8GFMX6!Lz6mE1>>Ed4#@XH$6QaXhTAw!cR3XB&jP;4X#c01p|tLa3ZhptCUAFnRqKHvP-j8 z+7k#enFOIggv#pL-KJ8P_BY@QgLx%=%@YCnI`T1fb<{VE#dBSv;c^nmzTs=nh0Kcu zW>RFO&J|rxa9nmB*K|C>FSq@e5A{C7VRj4W#g}1AgFW4RuQ>CH2!fN+=_JWiKe0$9 zuIsR;)5(u%;dgBi_%8tMf^&eT36xUZZ(+Q5W^y@U5$CWrD|#BMlt<$3!IVgf;O(NzD;2Y&U-=ovwI$#;%F z=8C?Z8>MLuuA`I^mabUgm|oEcUJWGy)G&{GKvoHH<4rfke|OLCI&b;GH=JMJ@e@L! z@E+@9ZOdZX%x2E~zg2Rg3p|B#+?uT`qw)@`?H_jG0!yLTk_R-2|M|#NA>Z93&Sb|US}uApL8;>tz60< z?)({^ZIesHNl&a{c{VWcT%gu-=~%UnhyL_C{$t6#^tP=-d5Y?(vv~E6B_vxrIp$xl zq+{7CDjFK77+X)UY**l4+FZ*fSQevlVj~qz<1xZvoNS)|v2t0;#?&!=>XAJ7>973Z z@gMzYij~RSdoZKwLpd>D0MPI=0KAg=-{I!yJKCCAB3jubEG!wrl`cwZC|w##*HLBw zr7O);IT>-fWzEiQV$!P}qVaJdU2L=>!)Kw1EN1aSIe8cWelXi&5S1Xu(`vf7fpYq0 znzTe}*cO__)?hswN=SfzzLw1N|G~0T%^lr4{-ZzM`A{a4T$RbDpA>L&dF9w6J9~Cs zw0ZOD_5%W-=g+sr%u~LI#!QsD8N|!Lauk0-dDme&4PxfW|NSl)w&CpgG9@KGc8M~7 zfdsHiuKj%#^eiPE>=IC)*@NaldN*YW_Ff3cvS_&SUv+J80_~W(IwH|XexEEw-bqT+ zkXk+)U|@fl-&>|rNxFNwF$|5)&dw2Ma;P^S4gfzK*@O~#u;0=F?VZrs4MQ?d5n`|J zC6O~0nRA$}HLxt*Mt8Jk`neZf_nS#$#@`G~8-;hHZM3}`2>`L{Iyxk_Ut9)-8jd8$ zKeJ)nET+ylIiTr*PYNL(dk5-rj|c^$rsLR*sc+TDKs5 zuT`Z6i;*cml3ox%EX4l{U`CS?l*p%OWpfB2_q!G~7>t~yJSC+j>5F&LP(P881gC|R zXu5`{@_@gP0Z@8aR*q@YrxOSSh()VNq8hlxLI_EJfA5eI1yNG}4+;;*r+c1G`+czPlUVN-+{FDfA%6@*ufu{2EMK^rm3s1fD%rh^1 z|N84cdh!Dglx1$dnGalY$>pU_T-mqdZ)+@XkjSM%F~w7Cd2Iz!$YSD#iCHTT?~&zdnbly}FN&NQM2DY2k>@X_-iL(I6r*^lb)BWG+>TNl%vuDSg z?%tiJwsmg3Zu909ue~i7$MjR)5VKCbPBbq(Ry3b7U(7n?d@<{^o5hqf`VaN78YT-M zS7OtbDJc&ql=@_c*zWBU_%C^`S5khEDT(Hf1o)RewzmwV`DL-{^3v$PVVHhYLk>6{ zX&O@M$bv;~iA}ESI%IPhQmHuQ6)|3aecj3t53n8j01!KHlUv=pS8`kiD|*}{H;Siu z{qzN#`0?+VpLWxA-@M?Qf|~zm8*QWQT}J?@A>r5(5kOJ$kk|$I58iMh1hsY3n7`l> zDk{ew4dU0sdea@ac48z_j?^@2$2QR0+fKZ{hyK1EF8i0yV1x|+RK!3ZOG$u&K-nO~ zTB1rXz;#`0+eKVj35)?(=K@{edz_u)`oQn|hE$QGZr5+LoaOy?FcpXlD5m6r=IhjlTWy!ck4PWXks~8v`NPvzo|c+E?5K)KYY8A07ZFB z56F0k8*lo4{FYz-V%rzLa82@|2ktF81?;X_xg1TCCUM>+7g1GLP1YwmhKu?SEft_h z6hJr}rLVuM=x6M>4wEKLM@o6#J`P*i0vY`JFTU}O^~?YK=X<|YUVd`@HP;aT_{Xu= ztwY7*%s%U^xuxrNI+574wQuvLR&9XWR8phjmE|NhZW}~!X_~=Cy^l9URq?T0Cd-MN zHlvv)8&|)=aTi^L)w2;T5CqS~NeF72k04lC&hlIT7qe{N_jt;4shcpFxksGHl282W z{g3|e2a~K!=AJ_+>Obsd;gbOFP#|!yI<%M@#K}MpF=5jxU82%fuC5!x(1J1;(4A;R zOO6>M+h*vx7m%7}q_nbBRts5KEn>R_U7>rz1F4}49YX|2i(YyK%mcoD$PE4(5IR9= zlhtE*Q4^~sgdM4+{h}~w19E174RZ0@dp{p-|A*R;)O@c*-=j3cXXsD0ACdo|BtYSF zof2{(J;Z5XcfdbgqCv3REQDCBa)BoGUG{4QjiZ8VkS4W!`J<-g)BpV}fWqFvwrxUT zlkTog)~;Q-dPM8{nkVal-yOL9zxuJ5e@fTho@U}jUYrx;v`>GFBWh)>;1s%o?5bqiwXk+X#T6TmGWlUn%JGgT=c!iYdKH5e!DCs2qzBZ+lwM+;BKX zU%ZpCQR0@w8@FR$`N_DWLxOQ5MLk^w`AUIhwKjPBW%Lm+5|_ZvJ0 zW9!4g80mDJNT_U&5xr7S>A4<;q2qZ@9_%ZHr@TB7;QCnsZvJ=EG^uYGOC(gb+bjUn z2+-HpgJC7Oz4lDHMQq@f>nYX;#_~ewFk~LY?;)36oRUby$yymg!N>sU7qC0p+HFGtnA)4D(u|SMom>2mNl5HF-?<>jt-^CecNbz9^$Nj|NJYfHf)F% z5OY=`FTeVl{^uTfFt+Xo-}(Fx-*@%}um1V&+Nkg%iEK`kU}}Z|TP4-`gP)@Y_#&}( z+472SEr0FXe}CnrHDCYozxi4Zau5CV0Ko~ToyN)MoPol_b=<+=pWTE1!ZlexW;~8< z7yloNmQz(#cjCT`*<=uQS>0vF{pGnPMR+CTs3_fOLBgM}6vF*!1{6cCXJO1bQ%t7BB}~C4@wpCM{3A(D&o_ zec;lquf2MqZ*O%dw^AK|QowMK2!MeI_j=ZgGJ1uBk|LsM5!2MAW(0KUg+n4&Q6ZBJ z5zVSMG#T9*n7+|AW46>aEuh;0X?UigX}WIYbpvz^VGT#r~x9_aJ`ie^EFxf4Gjr(Z?LYGtWK;uz6%B z$%B6C{TY*^%OFlWv8mf`OBa9*)`V$X4lpI zz|Tq;z4k`iXnR)?0J~%W3^oJY+a;ZkJX?9zQ`ZVx_{`h5ffI%in4QfenL2GQ>(*{0 z6p1i><_Ro&=_v$?t()I00i*-q!t)jNJko9 zG|^`0CYolTP(=mv;l6|ZzFw?c&cA6W%s>#wu~B|sJ=e?k%NGUAEA6}3j!kuS4bgA~ zsdPWXM!$u?)PuwmadH@Zy6F@AXw3WgOZj~MtL_7Qt>IFFo>l1IZs)3$a!y}g57}&r zXry95N5Rhm8JgXo{3z}8!;bV*q)Rv^#h|n}1@!jDab54NmXECO>+i}O7##pbG*Zs` z4J(O7E0{Q82Ch52fM4VIY1*dEYn9wf!bmt2Vd>IWsIDARwk{;`crRvP->;kIg-5sE z_TS$xtt(KrfOSPapNs-0MHkY;jUM;D?y-??-I~3 zrYg|ex})}n7hn8!<6ZGdYJOBNsaRX6a28JNXlgS-jg9reWLQEOU7E2>gC}&rS1<@!w zceWNsec8&TeDI4`;aCoCE<@7^=g_fs6RUrBA4VvccLW%6O&OsOiJk4N`ppvFxc_1L zx9z};gh}jd;kj@9@ct)mxn+u#N&fy2kNOY2H|m41=t1s#GtC0#F`n_56#)@cov z=@^DiD4;p9F|;oT2x^0dSElPSDs(Lr(sNaHqHSterenHhg$>;^EmLX|sktZ_CoY=( z@`6L@3)lfj%DoJMjE)zQD8nRIrehg8Ni79p)*-jK-xJtBG>HJ^kKtw}2LD+|fRe*I zP+))W!#t=IAT`8YqyYA<5`rKzBs*cZ{c}BckW))M*-IkXi)Cj?Cz9;kzAazIZAE5 zj}Th54cB+vvg`=AWgO1B;tHn3VrO1hSJ!h?Ft{!#~ECP3FC!KY6 zylchE8R;zMzx?EvFI@258*lsa7q7`Y^Y=&db8#=twk?i4`e@#J@dwG-8FIN?3GujV zccsQGGk{exHTB7O>?SP?g187gL@-2Z)8+!1 z#`={@Ir@F?!%J>OGlO`xg_KdMr_MqTn!Iw`T_vRe3Qf~^<+fk5{?8AS?d_*-)(p&O zgf;j4Y1{KR{p`|2YsZB^&$|U5_=j0ib~K{7_cnH^__?iY620^a*Hh9BD(M)Wu1R4a z3Fw9%GRNpO;c4c$aKx>Nn%Ua0X4QmrFE+zld1aMMj5UN4M$^oY>FIXR)m=OpCM?#H zlK5o?17P*wwOOF*$$EX5b~lrHJnSADBc&5>@=!S&R{=bA$btWSTMS|m$b~$mErKDX z3WpX6Q1BQY4~$HJP!TWu({&vpp%~Ff1p??#cA-4Q z<_#P2B(T(coGu1M{{b{jGGW4aR=o1sGQSUd0{>q`@DYSxMj$0fEwAibIQ;*Om<$ly zG9uvOd9kvWH{dEzKJj4+jUT3;qwCVkdHSng<@d8^b60)6{`|CQ)1I9=^4on~FKgD1K+a$n0z?%e(|ZMg&u<7QJo zZZ@k|{FUCG9lXt{K$A@)s0V@}8pchdvtui>=A1$-CaJDz;x~8vn1=ese2u>v*pPc( zX$F8-;sT(Gb}qV}XEz-uPYxuL8LDfm$IP2IuWCR0n(2#o{g0M)=5T&!TH7{6$!UL+D1PVAcxrz(=mXh)`c2@%6<<#VCHly2iE?@Ijq6{JYI=Eq9 z=eflUkwSJu;foOiA^^TGZie!*%CS?K`j$Lqlj-Qb6vqOsr@RS5umaPp@y&X zA2B^xc;BY6W9`=EFCH!>SPsUqANp9^*PnjrraSJst>c$J{~yBP$X@&H*fyb1m=AsI zV>C^hNP9=C@7OT}{CjHPu|W<2`3!)vSOst1@ERCf>Qu5Mb!8N5OrA)ho*N^xvBL{DqSpwSALLDoB++-+BKlRJ^GTa)>A zsuAJ_uqRbiywK2mNm;j2+EtL^2P%Xk?Be@@7j;C;i1P7QeuQ7Ja^;G z`Hdbh@zfJQ2wwU5Z*Sl9_&=uNy6>i_f9ZWu_!$6l2oZ3Qvj8AONL0m4;i-T`mzu5# z4PDbbO&Xnvv8&AUt1Bjb*gK)Iu76HM_bSG#)_KSPmL5SEM$pg**j~`om8VN|O-I+t z=oJmbL_W*l&}ccPdfS;~cTvk9`Q#n_RHVBZ`P+!8{-^UDCdVO&QPBd`hGDRN{TrC3ncp21NdSsgfK#S4v32WavT0}S9#3T5lP4g=_lf{t zf$uArzZXbtfDG^*tVYxf!ZWR|^xrnb{btU!-FJP~K9mlh< zahPW6+&6K8K1WXeteAY*@{gW->H1ksQ?~1{1b83+#Ev4PZIl2wv~a!5p}?Y(OWWVTafcT?%~V<-n9HR{LC;JAfX5DdoN?tUK@42IElomi}j`Ny8Y zIp;6rybpeYt3L96#*UeY>$*jexnk701oRg~T7;lzv*#&4s_u*HIgU*to?_y}Nx^mN z*44j-{+d=c<3z*d)K-lr7>v*t?_k@G^=#epCapVnl87fLFE3|IeLcFaBc()YTCx5= z5B`1O!h#*3pDEzFE{@|6jzkCsqNFnMVQaAifiPX&ZD^W?gXEa>25#PdJ9qB5g)4jh z#)tZ!rHUMWJ?^d(ST`Hv@i>lSW168sk#5&@cU!NlR6gq>PZRjxK`FW9-^)DZ(c9Zg zU4313W}F^OYrvDflEUDJ8|u_qbVP(A3%o8CM}>*+{F z_UH2#eSPr@ci(kajZ(YT^zQ}OD;T5+z;K!XL*GX!prfrm7w^hjM>xo`DYLvEtlRKE zuWowtjc@$F&k_iZjQG!Hvn)8_WETC)74*d0NT-s%J>-BBKq>gAC_b8>TU}l4B$J8t zd%6aPd$7ZCURd6}=7ERxsf2NcVHyL-rLSUVv-xO_r_g6Mu`-!M^Hcjh0kdqEo6Xrq5u3WRyK>9%QE5Q^Jrc1 zIxFwIn{aIn%5~ZHkLL;1RDn<&{^3P*ta_vKh5xzj+(b+3r}pIBaftKGntyMUC9LH^ z2med_p9vBos|;ZTJgFN>5)hg&b&(6itf1~x=bp^J`Txw)1o5Z132GB{f+eKq8MY(HZ@Dk_!+Cpkj?ZK8q zZt^SwSqXA1twt?reJ=kyL1VKKp-x{5+Ea%(32+EvX0iL@U9_kS)*dJo6dm^1*Rlk| z2>&)`Wz=w`mP#oq%4+C~=Y?uJJKB&kpW!I|Oh+N|0)S_nbrSd8cR$tD^^fiL8(I5w z1D<@8(t1WQRE29O5umYGt0}>wV(NQ3Mlzm3p^u3QlO8Y4L)IFe%)Nm%A?8NCe?X zIdAg@ZjNCDNF@5mWD;c37SH^B8Q=VmYYFHYx?vO}{so~w&##@wS7Mh^;wgpe=A*lw z=M^;p9NWgWZF0E`eSHazJYp`%Wb&}L(BFjRSt&#wVeeWyf~nef_w$OCS&`0)OQL6>*gOPrLj2UhgDy8V}OE7Kf zbkW_t<*oXoJV{f`YM^)xOr3JLcyq&RYER^YrfDqs{U4Y+dzzop zo`3C(!;jQ9z5IN`{`9GF>iERBzP>mZmP(Bj_^V+S1ht!MSCxEKoctbM0J1<$zx=^Zf4AkyXD8yikGxCohoS`Z7lZ(1 z@piN8X8xV*np#xY{MH18?is=}mDF@yN-3qMOX=t)Tf@^ z!oxpVz%*-YZW-DUYHrHF>haXp8vTQ;E^M*jX+ECG->j?3i9 zO)OuwYW2h^r$4oaRq}qs&>NE&5K1qxwUR9nG4Tg z-O&wvZu$)D#~&y8(kuM==`auXS$xfVfv<#D^2wGRbXyuW7UwdZH~w%h&Hs7H;>0;OyC^DW$i>LFFSH}HbJ$HH&*hy$$M0Gh5Lq$FSlvFzd1=uJI9HkZNhY@QC!9F#1+#i(VcS&0y0*a);` zJJT&IM>dxt6pReI;W5O;VAr`b;AyUgp_vMq8U67%&CQ47y6#)m0q|@)cW+N`NAH2q z0vOs-=>+W^JJ{K>nYNA{dA$Q6^8hhihGkpWc6N^h!p8L*h{eJvZ@_|b;*@Euc;Mc{ z_oq+EI1z8si)HVePoWN4=$olB?*7& z(MSJKK700)U%2k${`idSd&p(8%sFBnmwxo)oc+P`IqLXhn73d7(`L`0roNV~+cz|H z_ivwm+2!Y&$1GStFc|v5y4P2Kd)PPo#jn2mnLq#exYHMZt?b|Kx%;S7YwA9*3p)qv zo@;+~$-{CAks*O}SHU7zv9qJQIG~yk>=AjZ($U-22uz_Ur%Pt8lB!(m`34skIg^~~; zkYHNq9gHjPz2GX#>TM)V{mQ-f_s5K+kt~BTw#5?P=b1;cEX{o7e)qoTyyrdd>qxdG zG3EQ$pnk;~G_Bjzw&dR5pPy*$xH2to{l7Xgv;8DvuE{lq+4Mj_y%5GgX8HV|9trEg~-_HA2Ju~|muJ})nXg$oyB_pYk%KlA1ThX>)#|TqUu)jrhoofycgvQ_w!W$qh!>$6Q_Oe7F>4uf8wmR9B3O>;dnyf ze*6(Wm@lw|HRAPA4o<%Q4xDw>Z5Vsq_wZ-mCJ;rCfP>Stqj7(8C$eg4Fz(4;G1}TDNg{$b>TWTH15T?ag~$5%noZi$;Ap% z^@9Y#H4d(6$j-_|VZmU8vWvi}hWgqnSauTIw{Jkzt{rHsZ$L-59hQ~s_AE%r>ji{x z(`I^rY4{M2NA|k6N=ay%j+WLY5D+x*EZk9e89wrk#ox1z#eWxG4pRv*+J8Sk+e!|0 zTo;aOV;>@ceez7M>q1D8?ii4ndhP+gN-0=Y0)qyXp}2U^^n)-}UaqOz8DmV72YU|s zya5yzl%cq&0s&tTTehx7M@LH++k=tA$7A!StL460BO=}Q?~T{rL1{^T_s_h(0IELv zc&sP*#lf8`L9YDm??0aV!V9@V^?>xxaQE*E>ND@kKFa|z{$J&0WxK7L)>kUXy`J|- z6yAS-X70PC#~uI9k8iq0Ws+E*H-r!=Q%#KM?x%oI#Ib~^69|Nh*MK70?+ zXaZ0C`SC|ru2}ZteZ9|`s39McWASpJ693zni*<3az0a=<@`OS!sqc(ZoCX5&p!j6+#EQ`B&6d4 zltS1}cVI>sgA$@&?FFX{AAIx{uKvv(NXDWNwuND*UW&%mo3QdvPh!hUZ~UWS^@ef) zuYL{oL)qum)h5izm~R6NHip9ux>R@s<+`GTO0E%ToI%r>F#XKR))>{P&UD-K3T=9} zG3?CvWNvcJ3p-C!GMhpLG^u<1Xk`GWFU<@8Dj(pRF;WvS@9JJ-- zqb?Lct1lN-IsmrwE2RQZBnvfdC0H5%svJ+3iQ=UInU_{gyoQym>-$+iKjw=6@?%R! zwB`Gj9Y=p8fKn2s;RQg@)KCvfS*o2jNtFQjd;$FSzWbhAzj^ume(%c0_XY#xmK3OG z0ObHT0ImT{2RH|q1~8sh0Azsv&%H}zF-D!ZUo|~mrcFO*#ub>bsu80eegpoG*P{S{ zwtENSn|GpB&&C^rI&s$N*THpccsv@$Po9ABmt2iy?oJQ@V|gClZUbJ}IT{}~jYh7S ziy8U3Cj%IKWEveAM+krcTKO|pt9``!WIsrOjISh}VW$L#FndE8yZz%dg>!*Sd+QR2W$ z;OF$fYP!cBGp70WTW$&XsFGcmw?8F7e{TP(5Ag3(4$yCR00p4LV`N8bs`_2u;z^j_ z`O8!DDrU`o`<5SGw-=H4dBe~Ry!X~Cs2o2D$)t_RM~}rx$4|s9|Mj1E;;CmIt*)-R z;j{k!qxv=9f2(1`TmR_j*!bk0<#$D_FirO>POS-sapCBzuDUR%xD;ED3gO*k4rnh* z69^E6$<1xZt0;#zHw1rP2zD}wS4tbP?wi99yyF@K&N~Zjh53-Nc&~>;SQfaUcdxTK zLk45pn;$?A?rm{FC`I+B8!_sH<6$BUs%dCgv*1A~)X$pMZo0rpB)F@@Yz#tXl;jc`8&8P?5`y8or%*hHq#2 zm7C~Jto%xrQ+yH59>7fietNLpFdmOQ*4$QmQz9AdxARr11WyD;IH=_n{F#)M<0qoQIA zN(zS}E06~%1;QPTsB7GX>ODKKYv*?C+PMQ&J9k0>(6|oUvHJA^Fg-rBwl=}=cvG@$ zB>^SDl|Y>6kd%Qjwih~?Jb7cl6>h#|C8293q*PyMiV2ZYR5*?U(M<%Pmr^55yP&qV z5oM)=PY2*X2=nF1+Pa{t+npG4=Pw@>bx%r@WhkzOOHGL{ab&012k>_?uB8Pc;O#^#kAvQ zLMq_IV~@g!Aw{_K(u2oSu7Ld=X3w01;Lzhou$e6$$(6Du+F z-!4a1C=Z=gH6V_&_nJs4?7oD6ZDZ8Ar=og({|3yuY2u}4AH!YmzJslAJpFvzjtxI- z-?jM{LWozsru!nvaR1LV1RT(@3HiiV+DwEis4flaGRdiMHOiz;i1eD$4$(2$TJina zl_i(b5e3=FGWuUbsCXmlf^aT~PN`yMp3^walvb|h+CizLS11^Or7>vCg-b*5lTFCa z@B%n|VLGN=W z)Z}%VCU4bs{q#&Sav;V$fJU&A6b#Rz=m@gBNSsgW*lx^{W zuiTU_r}#ft25v z(=^bo#;1p7WKlxRZW*}(gcSW8e-9y$QYEln#0DX0QXpNnKnOqy1tB!0q)NAbb6pqV za0gDBeF}yTAMyQtoc{idhIk@U^VxOsDNx86LuW@jwrp5~STurIqyvM?%Q5wY6EWlD z(=lcGEQ}g85&5A~Xv{#;j-$P!8O^PA=!~?%c9Y;tgX`{{MCO#Ev9S)iVM0lPB;mNS zV-dz!HTZGMo0w$n2G>2AeYpVu9#1@1O6jqzI84*qFS+npvrI_|DO@Ne;Y!(E!qDqi z)1<rSFDm;IT*kiptSLx(yOfm~|>y``oh! zRB|FE$d&g#F#m;@UJOw{(Y>?wYJYmID*#dmFxS;6fmEOIyXTyLVdwUbJ~%qlylpQM zAP)0;&ph*faLnk1cisLYn5O45&%-o5`0L{jVaDv!5ex=#?y1w!(bkCR)2COx_~J{` zEz5f30PkZ9fFGAlo%GY$-~G-%kG<&P6Ut{zL&NeF;EJMU#&9f&X=oA-o|lFA9XlHD z#R8~xC0bUl#gLO`VD!c3K=*m!#1r7Uj%0hs-s>nKh_|%Cm!G?rGDaz&_?YqgCO&in zZ@%>+ZhY$Li@(PEA=#UYf|(8o$v|dC@5G&?7+cA1CrLG>5$G1vBw>;;jS8+)p-d{3 zSBLcBm=O42zec7P5bUzS8yp?B(i~}uR+1kscEd;OLixE8S-K)#t{lSv)hH~+5n%x| zl45K<%<}rwXH)_t2#o|Fc{bXzyy&cCkSrTbWo;P!qF^*<5L!ax^bOf#u_n6^D-8f_ zV6wnH^8Y;mZ2?#S2_p}YtYUN&Pf%-b97nc&(+h352ddZuH%l3g;Q~CCKHh=KUNhJs z3M&r?WN#6>5RxT2_Zv~Jy3C>BC`NCa&ij%m&JX|N}AlC?9_*1CytHH9pz!0 zJj|-stfa}?BLVJy?!uiHZf~4e z+pz8KNGx0{l?z?h!FkI3PY8ifZY~Oo3mV`1;Kf^)ubh7zfX2^W9cd+)mdf%ImXi1* zqxBz8cTFX{$5Td1z!iY#dUcTiz4oP-$f()-OM(<-5tFHOsjmix=d9IOINHVT|93pz zm||g>sK$t;)o=|BN-BigJF#;42CRPeDNIKx=8^GcLpWV?FS&F3)`{L9!}uA^UgnZLdAsaeo2)5z-EbL zY`5r25qExf08sNGYI?VC5CYWt_Kk}(V_E5q~|C*t^7r(*Jy6ESqy zSY!qAz^MkyvcQ=J%SrTquVrdBI#OY3Vh1jatibIpui|)XD@NN5AlxwfwgM!CW((m$ zxDNJ}(f+LYr2q)m?VepS-I6i$QYw{ddD!0GffJ6Og%Kl0|KOl((5`)NZG9CvK!eJp z0{-8UW$&K+$tUl;KX3V)4gLMn!i5XN^OwE#;o@cQok$hA98kNJk{DD{VbnG3PV6%{ zWDIlv@lRBaDu-p+P)ebE=m;!)^6?4OdtfGSKls4-aDI%$a}Rym|9P0IR;#gwWY}-}}R#COcf= z?Z+QM{>UNlhrDnTF(9`9H8~MH&Zl8z+{BXD7A!d{gbg=cjKSk8K{$n*w7Mmi!m?3N zIT}0Oo(J9U>$Rc?$A)tI=R}l{`-uBeoietsT!Y2)=6#)OZZo?8WU2tPfj_jLqaHb= zTt*0S29MZY*ns;~v(xcPq(%O+R+8-rsyo7jAWV0xoLmtu z&y_8sJW2)_;9-gw3RI)uOhD1yuqiMZ162mliG0-oBAb!hbiDcJWe^ zDdT8u@uUl!`yS3khY>`(>FZ^xcX&sa{NE2yKRUT#8k*!>A4AukX2LBGk@)c-LFAA~ zC1KQ~DMR!7qs#>8$N>bcEy!w&A*%tNh_{)zMLOI(MN|w3eA>`{+JI$1M^0Wz_H?Ac ze=KS6d^4#PXbDe_-Qme5k&&gzTHkQGJ5Z$WHl(95k?^pgl^*hcLtGepc7CL8Dym|Qhz4u|! z?RVgknjCa62Wy8g6yy{^N{P-`2Zlx(aq4?d;2Vt_@Zj(MhAY1FpHCRv`0){Vcw`(Q z00wI8QvuKiBKIi)Abs8cYLlF0;Ou^7gUtMmuTiVoNeP)f1Nvg5s6S~A_yNgqPS zab0-4en=reC;?>*lu$Ufjc{uV>h|nLXSfx9p9kY6Ov0(>T!3>fz5?f7d?oyWAZ$C? zj}f4Pu9;{Lw}KIh2+@0HrverkL*dn!)>oRv7!3(mz!45O+y9t_Qi@ot146j4>}0pu zU+R8jlmURGx;H2V$Fb4T5yg4uT`;SnVwQOj=FBI}&9w^-U`mF;_|#99z5BmkTw|i8#{VReEr6yy^Ir6^N@oO0@oGTQ(cXc;=D8nqzG5<4*2zc8q@E` zXm5wV?CkUAwTIhym+YVJhXSCF5unP;$zior?Rb3swioZd>&`4@Tm6}ZC;-UTxX)^7 z_}mK|iNbs9haWsU|C9N3ixzwcu4%oliI5Tx-1iIIbI(2a#zm)L*N)AYdE$)b+iv^s zOFBC{uK>{gWhcY53ogBp1pOF$+G&XHse?#b7;^FnXy3RF2G_7=+EMs8yb7x>D24vh zZyC}^N#hh;hl#OCpi=&baI6AqAU2=OBDy&C?b1!??_w=2$`72I6s(9y3 zQY&c-@o>J!li)h)Y2^Td>5%~G04V&FIa28fc=auG`j*xFls^mNPl9-$h=)mLa4621 zA~cx~5+1-~J_fJFN8>LMB+x;KS_!Bs2^u}oEek{tpE(f6bSa*v;iQLjfq&B*=K&Tm z3b7}UMQZYLRNJtVomZ|LskV?35;0A0oJ&Vz=m@gr0aobj2eJ6$!DVHC`DDow--CDE zg+)L9HJ-ceVGu%~ac%&pIE0^X0eGdoz2$c;Els~jBx3j2!hR9JGT;mB=Y&SPGyA$H z^)kF^*JpurmZ~eTOlADLRFz8g-pw;>UZq(515lHC3!`}5c>+Ej>kkE7kix$0x+e!x^ zp_wSOJ8_$-mWI>6#Idi5 z#XB6@pB%iOpSg|$!|=crZl8snbQ>-zB@vBuqJGbARBhXgnw?t_Zmh%bVPlcBV%;SU znFN5Ldr(!i6@g$7>$O4n$TJ#k#EXZrPQq4}3$NG5`w{?3sT?6Cl$7|adiu<)J|P6H zZ4Ka>0T2b-wo*0nX{oyud*e{4QmT^H)-WhVaaNXlFq~plA{qNtW78gdp_YJzJhf!W zo9hqc12=Ab-nNAKLjc=M!_3ahEo`f*-jco-1f7vEHf>&kaCD$frY>MpSufbKWGcRV}kz300jWU$BebAmaizE_N{-bPM&bm zAI?7e9Dlg3meM{-fFyv^PdiO+T)Hwu>F29rEaCCo@!^8U{_xPR6Yb%)wDF{d`nnpt z@a*Gw{vS^xH`{}&uDZ%S`P4K1R9_z-4dBItw0`6aoi=4gAioF<6hls%iBDg78%)zM z^z;+awr(|~VIqF%sYu!`s3X#yK_qfV4aM${7en)TyPsKMr7BB|Kmcyif>MBMSR9GC)lwsVyDGm0(KQ8g*?mWVHaU2n}Qt@((+pssvOcpz1K# zY4D7)wy_iUEcd=Tk$PLNDl70#%o*ACO*TC^gz`wfO}t5m7%GfnwQ+#V88;#Yh ze6tFrZ8i1Y;PyX)$hS-pI1cif7=+I5Lh90AGd3jC5!F`-1`*QYk;DVRlW=X` z)%eI93GP@326A)&y-+?Q%BPfqD;&`MZ5>GnqS1Dkh6j`|xQ+wYbs*EnEtTvs0Zc0) zlu}@fVcWJ{C@n2Rdwau_gEVhGYG|rn+@D+TK1PS_il2X(4_vwOwYVheY$+uxDIOY# zM8ffCv;&k9L?Z1NJ7zK(n`&TLaV%N9909+HyigEIDV%Zc#pHvB?w@*~pPiMPB_8|h z)0P)**X34So&cE@GX0SNUFLxKp^&|M_40Dzf|O03VPE>(3-`@D_xz5x|M{|4r|2m! zP{5QKGm`b|Hx?1Pf6u*d@NjwIoxgnczF*xY1Hmk;SiTrC*@9o)bqDUa{lAkFCQSIl zGtWFzk&H)gtf|@9cCZ$Y<8Qcjn7^pVG;{-t-+2XG(@->dJnELOfj2i7fxIj@u^6aS zaHNSuOHUUE;R=*aI|en2mxH8Dkz6ZP4j_d<+3{1b{ml>1xPB8tBZl@O_qb`GaqR}I z{o6}u-c}DDDnW4Q7zBrphNrLydN7z$0+60($L{D*U*r9-FX1H8^8YR~z{A`UFC}SC zN%5PhK#~e6sE{U=mZGjCjJbqy+cqE-N++~U$#WVjYNMg8JDkGx35Q0go#525sO!Ro z5a3E`K3GAoN){+esRpVO#kfb~l)zyYG-4u3+7Redqkj10)qX$$Ie>C#j@s(`v9tSx zam=3xaNQl^#PxWiy<&;~{JT2fx0_hVj(&#E$DzGHsSyQ;kpt?H5iOV3`Nv^X>1eWP zik~>y`qaWK|pfxN(3<00o6aBC!X|STGx*_ENMDeFMjCKitPL z2OtrwBs^(SH^7;6IrB1I%hi+KLe)@SK*Gm{Wams>iHa-|E2oC^xHO{MhQ^Ds81==x zbmLb{0WfFI98L&%?iY96b?b{Sy`*{GdJCNwTmZN(c-nMULL#7fk@f}{s4IgjC+|8^@l*WtPj z9NWRCZ~qy;s2GAI0HSFiem_W77KGyhh6XDc%{l@RkBlP(z<{ugWFK2@??!)J_RO3R zXq3XB6lU7oqq%V#T3dE?gU~}5z?D$SKnOu+XB#F?orxFUT8`^(yaiWWeG?w|^ISAF z*ML#hooQA|fzlqyKVuY>lJ4Hzw95}5oqHlg0bL~lj6ev9NGy(^KM(nZp~)jhj?6p2 zV^2D^waj%LHxneMN)4R;80~cXJiAxxysq;C&`VO^-NsNUL^|7X{EV}4(ya3_dh7(W zb=0Aur3z9CXqth#+T9?O!F2_=lK^w#ppFFvg-|FT@OXM5WhpVJ>oZ6iM0a&hNGTCA zJr;VxdYN&oQc5_E4I!Mg$)f0ECa6F_AfeFE(2QY2M<5dEJXp-Ij7B@}YHF_CPZfar z`^uH?f9dvtOP9X4O+kHEN}*MbnaZ|oTVqS9P*gY=$z%efMjQ=IGvM|5F!#BaaPo{v zNF;5Pl$K-R(|;cC2_9J6x6XEWrd<2I4{Ph{HPzFNvAY~V_MT?w&m@o&xShMUmw~2B zHCUE@`_dIp-t)}!tAFyNABDK;@v|5{YP4;4hO;T%KY$=y(35Za!FG|Kzv{kU-iD6m zYW4BL1@5F{j+yiL(cUliR@9s(Y&Jy(e^OPPC5bY zo7RDw9&pn{GuC4`2K@a*;%AlkLK*3E|Jsliu2NfqBkL>cnaH1*u2C8wy8=J7{ zg}30qi{j}gz*|%dLMf!{KspYTl>M&B_SahhfWGrBy#n*YyI1yr%ei=-zK@|4h|v%n z>Q#bDB`KAX!x2mhP^E~rmElv7SQK$tQN%ApY#iUtuTb-j!L5AVpy0Ya+Q9F?=9c*5}H$+tMRYt+gQ zmTo@kws$_g=$88Eptjw7d`luSI9UeB$^lXUbk+X{MJMwr!F|luN2^t{E9Hg@^GU}r zIj_-$m4w&pX8B0c<7XWjQz<#(@ByCWk6?xNDt_WW7DtyzXZqFj^^4?rso>z zt_oibAAmV?=FmBF=DhgmBad8i`yF?1_wBb4yX`iRtgO9S*%+zVC3gT0vlzhK;-aDz z-}uHiCID#t>}5&51Ch?~E73y)2pe#1z;yu20&FM!@2;`{^ppsQ3=aSySD=Z1AvL3r zGPJ$Ig9*o-g&}XQgo-4=h(cUSoZ}sh&@&(4r#D{)SGdr115&uK5^)IOz_yYA2wX?v z!{_hE+`KI4i~*E_a1K6kBDCX=hl)fXbseqY@Yk8_J~EDsuO0zF_WAR@jl-2vXtbl) z7Hh?V@NT@^uo;h3ufT)5K0%WmM|RF2P{JUE(-jaOss}oY5CYq>P*Oe|C1pdfbnyZ> zt^>%oOjQ zJ#{A?FbaiyKVe0CK&VpSng+%g>|_$cb-Vc(l6GRZZL1erQyE$75j3 zh%&^YQ4AeC)a0%_U{kbj{bJ7YpZ@2Miz&-6`O8oPAVUq%Pn*CLSrF+cKqAt8;}das zZg}e1kGA@AU%2F=i$jTUD;Rctp&16Ei5P}$-i<$9e-qBMO?15S9!6Yn8tOk;0>UVaP#&t6 ztO7GqQ&74BgQiZx*4N)l$^O#{fUdy}1KzwGAYG!%-U zZdJNI{%W)#QKi~+J7PL6jky9z+a-2_c%l@N5&~i~-EHKhJ8IeBbqSu`2~I&3qb{e6 zLs1Du<1k1ke53?9Wb6QCRXf8qlqr|^WF${JF_>E%wB`34{~9}*zja&qsD`!b*oJCz zbaWT;oiHHhq-gTP6tJsqb;L-3BmojvgvNEs2$kj*ZR#pepDgyYPNaLHy1J$ugYp{3 z`)FLtmTjh2HBd)^L@IEYJ1z7cSKu4jN8^JZ{)yE6(FGqPU~P%=)@8sv_b@+l1OR+7 zFRhP9nAhZtGn?xksd>2c`bm7aN#qEnc>v}C=Q20I5`JzbbW>wYm>NseP%?7zS4ROb zXU?3*o_gYmbH982^~8GS8Cd`L2S`p%3j6|Ky|yHZbhnYi8D?JrVC{9+UVG{0EnCP% zGtV3kV8Unqm6yE(;nYFcfN;_+{zOl`zip?o|E`^O`cHcT^z7(ey`@usV>?%p*|WdU zTnpwE_)oszMij2y1>dGU-Q5O+qKFEK6OAFbdV`BOm!F1zzW#S`uEF$px;r35;xWAU zx4ZFzkD|=bAsGYV954(JT~EDVG6~1;M>HHx;>b8MzQ%+9UpdfJ9=10{Afd26(tw23 zj)1a}3xPsL5TG1!TOp=;C9||fZx=|Tr3_4?JH3ETcTQE%z9NU5ISlv$gy#RK%8ChCJpQZ*9 zu^5Jo7>zxkk54q)jwRlw$|s^GD3B#(j9{V5T&5HtS@AbNno$~YYQL~$B!osHPw1v`BB|b zRMLii!L7INs$IA0!D%PXzVZjxT@&(ny$I&!#?%*h?xh4OrcUp;?zrjA6HT1fvb$<) z8Vnw?VR{Q{x2|8An04KCo{!&q1t$s0qb$HlNSPQs4&J_hByOYxMEyip*GAkq>+JVxLvDTYV`|E_19={kh% z!0zlovb|j;TUv+{kGBcijuJ`}Mpl+^B9S%!B70-HNd?@V>3BGd#!_HtE}o}hglPy3 z)I|~XfioL6r_$1-lp2V^b;s2tHK;>8jzgT}w#3jyemDgMqH#>K5vm7>sG|it2~nCU zUDJSNCPCvSb9k8KHY>uYBpLw&(}c#PlFamIlqC|>g@;tbPc~s5nS)s*1+W!493ZKHb)WDqVfRKg54`-b_;&`E&%Y7nfe8-0x1cHR!7Y@J7UXm*-&YaT$^ z`U3o*(}zVbUd1Et7)X|a(G{^+Y#>}dN#!h%j_sVNY*5=tGOyReEr;ub8@lAC4qpxs zcc3&KBdskruFE?1W-pRjl9|k9pv8pIUCFNo0l+z*@!z-J`fpcVeKkow{WRQ#3qkyT zK-Ym}5)uS%cQi|2O9ud)!*qB>0RA#~@Zd9kd+)vEtdmd2Yj-`4h0nbW04D)hzR#Of za!g!(y5Ogf@+nY~a{4DMCHr^XwCSJhUGq=Sra{m z6YyW9mH649;kd1&9QmAQ;KW0|FZclg4Mv@?BEb1TM;n}lG{e_}9L8alw^-@M2P~7E zkP^XQ7A8$S0fym$olGJVB=)p3%=HbIYx^Tc$VjRF?xyGob4_HgDdJi!Zqhgvj#_;`~`!*HHD3&zh$Ss_|e? z+GWc=XeCg;R!YI^3-F5aG0vLxiv{OB34X)S@$;Ym4;W(@I=C2@U3@m){Po>4JpKb~ z2bhdQyYSb)d27|?E&j|WyN5`EA_|gbn6RmyN)u&CkXfgmlH9Xydv0HIKidY&A3e#v zef7FW7g*}WCzq`HV8#!B@QJX$7||(RkSquJO$`nH9ox4rJJgHEqTl?6>|VLj*|KRB ztd1D|eeiJ9{OVpvDPSj)@XY-Ou3x%BYf%5>kMI0HjDY4K5+g!-nY% z_{-INS^qtuOH6kY`KdNfZ=RnejDmAYk^5k$3G?%8^_;G*<2b|~$ zol43j7^9qUF*?^KKN}5Xb49*87U97|*Dlo0{2LUd4s>NJkeEBLfb}f=z?zBI!}V$p zPuP*y6N$tg3;>xj2S8l}goQLpJe(TA0F!Vvk5_3lK#W8%zXgLr!0bvu^B`vC*J_&b zdUUR7oHA2mtliIOk+q%78DJlPii(QtQKLq^dHc_P#+{d6hP!GNh}R1+2Bf>o5Ge3; zVniwhFEhGh$U`=3m7;#XeM`2=KYyMr72C zry<=x!nFa%N@x2;$^=l!KCwFXWdL{vIp&Nv4&XFauGs#G7`D0wLS!}-AZfOiKqvx7 zQFJ)K6ye8HBoFs*+lcXh`xX9U^=o*uY!I>;Pfc=4Q}=~)z%*0AM_nCY+vxCkkZfU*JVPgBr*HL*3sCCDAG=wo3yGWHw%x1$a#jLNknBe{+a;1w#mdtn54} z0D~*WV^C=cblrpy0=AXFt{q#!IPZ49@A3?wl%{L^Nd{n5J(>RQjK2U$dm9Khv*42ymuP-ji7U_0` zU3a(#Lw6BLq_+n^#?MHao_1UZwv|!=P)5O7>ON6Iz?cS2(?AJ<5CUzj9XR9EGokDJ z+Xu5hcp?$Ky{2|Y=e|k-NQwYC=z|&jKBP0m!9cb-q+~;piZv;yP-UO=MX(#wGSa0 zXOzL9MCqJTU2$lJA{y~AX2IeHni&wIn*cTzV-GP2kb2L`bWMFWcJtEYr{1wx>hYt+ z6-vha2Bovzgd9zcPl9;2y9Db}fc7>kJXH6mNBX}Lpf7SHHR+lH zOzI((g>o;NlUW<(^4;#9k})efc|bI?!X#kA)6)?c0|;8VVI(J}aj7#<58K8|K}wP! z{tzY9U{v?n%$Fmykd`!awMZynID;^2G*FQX;_(57si>}LG^jMqAJ>RZXvjlpZYd`N zZ3I|VRkifJci;7^rAy(iSOMzsq(CO6y;@smuFgEQ=N~e|Ii(aCH*VaGN~wHY7>I5Lh90EaK~Qu|oJ`*yEZz1#hz>#DRgyGk+^A99E(00LqVLXn7f zVED*MXsrJf=U)6x#A8u7wuRP~W^CQC7J6F#-&OOkx?KI!#&v|y3-~WmpF|NEjv!S+9h_GfOVPb5lTS_#lrXBMorZYlvj*SnfqmQ z4Uk<$+Zit?Ael&_Bb-vNceO8*Qb0%nAq1pUsI95S-=BUIv1kV_`o^_+6Q>;ixm|ti zL_$j@M?^tn=0R*oyxG|$9?89Ow!)ZQh8yN^vAheUe4V8L6>0PZEg3Z>+yeqT;_Ncrft z)oT}YlT|*S7uQ~M6HLQ^WxM$G|K7(w`rX4PQhs2b8j();!#Vk@4BJu}qQJ~oFLOYe zj_SKa9K(lJB(~0ff6QmO`%4$Zu@7v0a}=Bkj*12I=Su(w-4VNRe4(%F`^h(7KkVP; z+S6_ooFT9D|kwfu(cq>LJ2ak}ExQ~oQ3khPG8$q*`1``))Tc_gaW1pWoRHKqr`02 zL+zI7k1JP`sJ7AJD`;k%8eC&K=gg#=q8lsOA;uQ(heQ&&(A#P=4OyqYdb-LQG+F! zro}YIm=>TB?+|Op*kY^tLN&1z2>GDK6+;hs^L^Cz`V6TV9)o&4o!s;h(qVCeO9$#a z006&y@PP+L7G-6@e*5iI#-Gwue8+kd`#NMg{h(kn9fzt7;M}=$S#ECb9c^uG4=q`| znB08bb%=cX+eqB|8?aE1U{og@jL`i3ig!nxWuZ}B4uabNkxaL&>eOs93>0Gs!`~PSBeFiX3#cZjTqlZq} zrU*1bD8g+G&@>ZMrk#!4+=7(cT}r(0?4RNF2D%;Q8RL*rf-#z|TSvFUK^J&cX)+ZA zsqO*k40M{&g%B=Wmw_{e)|NKRoP7#%b3@YreSA|>&AJ0Pja5l2-jN+7IZC0Y4Pc+4 z={n-EXxe$7^iR{M%xGGsz;lKoKu7{2BnT0yIxGOSwN>!t4#vWd-^H-uqjA9{-@a(| z@(JXK~Oq=VI~w&1eMF2|ZxYrYNOph?6NiP#^jYqouRXvNsdzC-|}YSW>b zze|?AdrRM+1p=Yt>guZ|6&03M0_2$1*6`7nU3G&RHD>hc-8;7)y>`(&?}#%`_hb(m z@r5(Qt^_&fXZOrsw0g~TM^BmFnep6q6&ZK;03baNhLY(pg8)i2HH%a<=#0ICl1+ZPd|aLKg)cm4xQ?|<}nD<68axqMJXM_t<<)03Tr@TwiKuelVF z7v8|6Pd7m*hE)N9>YsiW^5ak746Q)P)CpMg#0w~yH5(>ls9C-mV=p=t8|S`(qRB@? zx-Me%^|0d>jG{77#y~X&NQL(K%Rri1)z9v_om_bFd7wrPT01N#sc`0bCa%B!8XQ04 zOgxyY(;v0QzgJN<=KZQYoB#PQNCMayB>*I&;mjce|Ig!jIu@W|gt-o`F~6xpvrU~S zk93)jG3tYYpAZ^gL=P%rc;d7mB8lc<;D+l6X00L}7S}Da*z~)Nt_YIO+$hb8aH2e| zdVX`UCI{Q^I&l|1CAq-?YEtTWHAng+p-G)eTMEsk9;jp@iBv_7a>@aB6MT3cW5pcY zi8=WBLG%PrBn|$V4KN>?bsY&^gX7T<)aQrtTE=;uiqa_XuM54U%3YyP zpWm=2Rx|b8#;Y5m#r4f1SeM&botFTbN}bK6yLefZPa0aaD55O@-P%Jk9o8`%4R>UV zvd20Alt630shYkT_|8O-KMzJOa!bh*O|mulI(3|Ni%3zy3Oi&j-&9Hz0A( zJt>eWWy&GHdx7a;uVpH5(GU8Xq7*4AD!Mfg2;4dEqmNKtScvF%z5{33GH`zoO!Z7T zPB}Envn}cHbotX~lK?66zW-5M7CsEf^Fhcg5K;k19TH&>vH^;Igz?QE5pvnVoZHKm zy47!AtdBp#%z!T{qgG2Q3L*bLd*2;rS9M*zPPygvdDENPXw(}*0wDxQbTGw+SlHNr zE2hMbozM1%lQf{_TH3^h* zEQ=)i+7Swu;IW6F!pPAh@al_CpsTF~nr1=?7o6+Eoc{YwQ4dZn`z;G8r9NW-faiGw zU3DcDgmB@y6qGUS-P4Zium2Q&_OqYg2H>`La2oBdV{KJR&g%zYq?F*C53m4=8U=Ws zS1g9*;JCtr$L$RX#@Vp3dwyrx&#N8VMqArHOrCNY)~$XDx7>Og`g*%DYV^3$P$)Dh zm&3qs>M>T1VA2mwMUT-Qc2nM6fpwcqI%Vo>Iw z27V`6_P61pOD}^Ny!+DuQvDCf-JQ4ARF7J&YsT=3gc=*)%cn4t>06b_ z^sU;nZ#w{B!GZnKmZ>o7;cj z+&5>AawHk@ln<@|Y6$Iz5Wo1B0C5%QlyT!o=l=bA*$^YZ6BS{CV1y#ndf>no04LJ+ zo?r5Gd}wXOu6m~Y<~24)SW#SWz(kPz*~C|pE3i5i~u-;UNHiy zH-YSHn=obCRBYVxCeYQ38IvZee}D7|;&{N;eHjSZ2}XTW(gPhSl$8YV^ivOE&b&+T z)QD2LFyZ_MfDa1*pbqN(7m6|;UYrI%hJ2|L_)E#%xSQ0VhUSoCmEc?!i+|H4VM?6{ zCx}vzu;O}HlO#eIN;HYscKwWXoM>TCVlqMlHi_FI<;7L0nUmdVF-j#G(?lfGJd!F^ zb~&jGlkT3f4o{|D};){80!i4aI)P(?p4jTm$gpMTg7zKCivMXwqv$9Zp=zu> z<|w`{G=lDxnL>c>_q=TT=$h=7y`$wxocMzbKym$)OzV-Sv@U}rkLkN7&ze^mcfHu_w1mC z(?%*-f}ku2%&!BLRYv{2&1db?XKqiKHYZf)q>v+3xiA)B0hYcG3rB5j?YQsUb5A*A z4ECl?&=xF!{osRsciD0LV$<`6B;Il$UkOkRCxZb{Q&V%Jp=o!mUbPC@x z??_K(yUx;~=6R>c{n48>C zFn}>$H2;%GrBjeariKt6q!dN=fZ}bLyQ1VL`=}puy^m?a7#8%K6aZV_{WAz7LfG*1MqAIldd}-n|}WS+*AQk#t_vs5Zi`FDFlGg z7tF)HrK@1XBB-A|3AwIrfKq6Y2$b;P_9f80Y%NmHF2}iM9Dn}J{dnZQALEJ{GXYoO z|K9U6vU7hLtsTC>F)OloC?(*WB9*m~k(HRxI1bAlNhnm!hip$&hhYF{L&gD;leFy( znEr_f)l35#_h^t&H)9&uP&y%5hbKBGD1X+PEf)r3vtSWc`a(0 z3}KoRS{buy2-m5rg*`(jAu~*a^0ygD4UHL8MS{dB4HH=!prWi?Bu9pcC^zB81Cqo7 zN<=8^a1h+g!_iBS));!2jaBp)s5zmmn?(SL19UXD>5bSJosKnHIl5!JF=Zb|-$yRX z-29{I9XDTaaq8P=PR`%Esx3alWim_0M)m|p*R+(*D*5AYP8+doL7aC7k<0V=Kwfil zso)s^c`za+*D&TM7EFfBoz%_^B5_?G}|+s@@SsdMU6_9tks2x#$|6wSY|`a zOBe)TEdX8mp66nVBmq%9Xv$;?U27lpBFp=*Hh<)f%*lM-W+5D-Bx5nEG?yEOrNwC` zSmt%bP3FaAx9uUU1C|74R0BJEkgRIhAq=VqOoLP1W75#MG?TO~^Zs}Mbai$8sQe+TsBZ{JAQXis89YVdDGEz+^h8D> zIp%aE7c4~LqEDl6^^M?HUJY%^1Q14{ToWBSZ1Flp-9;F^B&E+VBIAQBXyRL7%#_&$F5v;TwEJ=+ipMtuso zt|Jr-BVY!>HO*%L3^RNi?o>diKYor9>Q4+PUJ~23;CZ4bCs0sQ!Sg({w|BsEHJo?e zxv^}z<>T)V$XH@Kg@NLjF@|6$1kd$Q$mff+e+sE29Lt91xdVO%2N&C-Xj14pE>g(^ z`g*&tZQC2z*0cd0Y)qSdCN8=1Z!of<5u+O>;!9uoHs;O06bJV2K}BUPIy%~L+RV9g z-yX2Am{d|Jr6A!K=}H#6_6M2&9XxvRa3!bjPax3M)dA0SVcYh=w1NQ%gA}ms0#>bD zk6UiO6|U#qcB1d6j*fl*oJ{xa8hTv`$miehM|0}E_jZAL?Ory!AZgo|gVKtpE?V$k z|2X~hFUO+C4+5NV(~X-~uUHi&gOK0QuR~x!HN*zwlB=#s?R(?3QIww8gr%U6pQK~* z>Q$?VYun3Cil`w^x&gN?A(h{=a0wc z|5*;t^1w6(moZ$pw*~RvEuZ>< zz4?hTfdl7+iL463t8GNfxf4{&g<*)wYLXdKLGvR_PQr%9gCRqe@T6lXBM2BKG@ThL z5R_RO$x&0I)+-NGNT$3!$NufNToHB!_O9-5>fq)@U zq7@*xfj$;ToD4SweD`5sCoM;}7Do@e2KTJ5!Tyj2M{mKzKNsK`5uDa5@v;0?%yK;@ zT1LW$_Z===(NWZmQJwj2IT zuKz|eJL}J*WXt%|y;UC{Em}uMR5r>O)1%*QXef(kM^vhwX_MqzXBeswh>1+FB$Cku zz{mRxfcIq5!r|}tEl%;CANIUIf`zmj6UU#-Up@;!!0sb@h_j&XF#~C{(rJlL>sfPt z1epq29$=sZDB(bf2J9`sGlPVObgmnDT`|Tv9HtD7);7HN06=47qcM5Xqzefla9((! zsNo!Ji1Y&hC^k%J(F34AIAI{<#7O{dzy0>`wr$&f^T@*wn`7(hQ274$fn3hd(>O2g zs$_s!3INQWN@URkKq>-9GW6O3>`ql;WA{iryBYY|3oZEJub1M!`<}&v-&ukO?_7c3 zKCu(s!7*TwFk~hJ-q3*UTemiyDi2S^|MvKxNdVN5O8Vo40s3F-2?w6*_7{F9M*=`7 zBOsJ00z)@INeMs{N=qxj7==!C7^VT!44_}_Pe_s4U)1>f|MpQ?S~Q~T9~U^Zm=!|6 z6COBWfB*<51CoGOUS5fX3$MqkufF;j0PjT4x5@FWePL2E3XpJJ7ee~wlW^|Emty4TM&$EZq>_CYF?uYf&zOVi zx{+`l8?Iv`8jWM`o@T_NaddaKp|Nq|l()@VJeT$>LkI?a3n-<7bK?d|NCHBRJjttH zS|Nmod?AZmK7v3%L3eC0#=yCR>-mlagiEbByS#rrzC+HRWA zSo)$6B0vd&?b@fGamGig*R6Y|w)Q3WoI_>Yk^Z={gP&nC1Oy-eQ3{F>kj7E->Qd#AcSDTHJ2l?YcJxBV;no3dpc56 zb&U~^q2>%5O^>ZbY}^RUtoEXqN=mt@4kb;ICS|TH# z&P^|SuC>Z-t9Z_3As#kpy-D=g#QeVbXVK7Dx(G=LDmpvkyfun1WgapLzH<@ z#~@yggbRVZ9n}7%(m>4!lzy*iw7H@)+@`{;$DI6@Bcld|h*zVx%pqvcOQL5%RSwjX zFocP)$RZ-b=pe6Q8adJXsRoM}U`86F{(Ckazxzep_V=rB)yr)dS&#@iE`&4zWs-6Q zxQNyht>U9(zV)=&kVjb}OUu11DOFexoJ0=*wE#dTpj=GwT$C0fNG1)~Jj~o&hE(pV zMzW5Sm7&qzeNLySev|}tM*h-Grlog&svG9(BV_0N5}tldQX&$bX~*Ib&q+WmJ;`1G zO_)`lLWG}*S2~YHX0Ql~&cW=tJ&0~Q>4~4A(Ew#sa_}-I5vVHcudYutT|s1d5EIU% zU>pcgAW8sBAjqsrgE}UIXK+e6OvbESo|R^I5}=X1mokP#B5~Rik3Y^-CIe(LP@MZk zzvmT4XIe2(F<6xkMgg7C`{qRE%{pWQH7dFhFHxGsT?(=`YWkDtqKIJ_U z0c;yg0R~lYBtQuPr_=;s7Nt+e{~2!CqJwn(2?AFRY~`8`xGn%v4yDF}vd>}L(lu(! zvM-P+=e-+Wqvfl-y)Rv@O}X%3LqMqrlpPZYCqJx5f z2!)QqI!0VydQ$L~~IZ3T=SHw#tOwdag*tTWd2_8!j&v-xMvz4#GIRHUb~1Nm$YO8D1} zG6u>R7-g_5e{XOc2bPsbD%}SuJtzo-V2w0QY#QN6 z40R*Mpsc(K!gJwy9&BrHuL*^tNG5t=*#+pj2?aU@KnZ}uYU~vujQE^?^y53e+~BaE z(clJA^dTUJuuKRX*99RA$y6_Ny&8^f`#uQ$0E1HCnm;+<$3OW#F1z%~|9a-xCr`9d z9J;#pttyL^e%F)Yp9_WTGto%NLy?lI{QLbRp1)|3_xhK#LtdJvT8kUGwDf z6N`iVHEcHh9ss!_0ALhl0Q7ie0R7!ALXKQ;EyiM!Lyl^t83vm(!ntlLX%NW*l;{Cl zkwE9KwM~{jW1~q`1vd!v@!^Qu%?oKa)Sc0zxk{3)kCcg0dRhrlrlv$r_e>%UKu2B+ z<`vgLl_GX9Vg>ifAWkztT~2$A+D^x1A|ay*Vk6375mQ>`X=3R&UuPG5(-MY7;S?+| z$AIO=V9@RGXbmFrL|SBbpiu>}*Nwq;*5ISRor^!t2=H7;Ql54lQ#laILY0gIM0elh zk?g)eSE|D4+||9#rE{L^=%~&Yv{KvS6|#9yM0Zk(z=~pW;hQuNdzYNu{^>-X7&-4E-C8T8y%Up*70Lot6}MDMC=8~V0HW`N`mT07W5DfR4PbCGl4;AWDxPnh@%DCu27D z6Mw%bIqx68d`tJ1rf140jfb!t)Sq)^yk*V0GP@f)T2`+6;gFaArEXf~o9$1wJU+8J zMwXHc_6PynvXIMUilZrqckU0nK2d_Mt^^2G*tcghMvR^e;kk!hGll13>5>N#&i7$X zdX!h=Rek?MwkICU06@_gYnTs!Qi{A?Q9rn>9Q`#Fs2~7{D>|5K8r%?`u1P0IC=F4N zphrw&Z(wqBP|C^}dPi5Fx1QcHhI(J?K#yM5M>*pjgU7}bitmhpdL^y29j?YGV_*Pu zjp&kcB^6+rK!E{|TgdI!(~_BxLg|!}pg|lVsp2VC(_?w%eGoLl!GaXJ5rpItoTZUt z<521qu$!DH0HD}amvKySw?Sq`8X^9y{K_|}62Y_UF}udKl6_fEDF1~k_qF`ndMWcj)7%byf9?vW_x zs>@Zb;!=7{ZpWD2wW_Ofj#_>LQ3WJue07}nR(GjviV2q0%3-(kfF^vv>7j(if z4LbMWlMejmQxSkLjz3jjM6oUKD?rUWxa+cI`5QR*nu`%R?B=f?QQMY&icDJY&^tL< z58m?C-rko#qD{IWP-Fq<;CR~EhOMFlUo_^Rl7wNwLqQ#RE0;vUOfcL&_bhzzvP+>) zn!FFdrc>qNsrcU>^aFcj&N0ukTk1MQOm`9&Fnd^7$Nc*(_Ywh3C0QrIYx` zl^5Z+zk5J!-@fhoWHPz$IM3pZ?v8!AXuKAu&z^^~=3R(cXU@mO$)};NehlKJ6)=K9 z6mnT4`g+jQ)q&pb4&<^K=$eMAnh~g|s)6tXY^wkvTz`rI@qrQ7bp|{H4p;murBKLc z(Kv1jc5L5--OXFDqiGAqj-6C{lmr_}$)kcoLk$22uwQj3sN{c7!Lkal9S0p9ZD?)X zkCv8w=;&-iTU#r3?A(S_Z-=X(U3=A4SDnnReBTGH`0tOY_uaSCW8T9`DNjLZuJp7E z$4^MzU0Z(Oj;YhW8Z)M-Jw-RvryOVY8R(|(q&l=Il{rS#r;bgP2 z(A`U_CQbO%;a=PE+_ELQp{0M)7C~*Q7A@_&KtQm5?VH%Yw-t=Py&oH645>s4ZLRG% zZT7`@ZTS<}xAQG9#s{QElrk``K{rgSdi77pIT_4#OGQJzvWmnIlAsDgGqO{aB%Z(knJ`xLo%RMK*x<`2-G5A#$lK-rR!zXz#0qqLkIFC zl2e>>jnY6B&5Ro1v`uSJ`_IxL%iGwbWd>9UVV(&{U4U~Jl7|qX38V=COvdEl!&lzf zMz2upswYt6?JS*b?PoJHNu$wq%vkC)y6V=dK({K_dyQxbXEkUxOR% z_q1*Me^z+w)7Nov+w3u>|>EGP|$pXX%NLb~Vp*+n{g+LX$YOA!K8TCfbS;_*G zt3)TQ>S$r3n^Ia?KBq^rN(&3KDpD4t?#K{vV?o^t8M>oeE_fKA-NU>9PHZd!krS~p zGaHLj$NKuAf1a#NFOuOz<{4GCLlp$g$0|kB^oy6YZZ`i!cJ%@&22w%*hk+;wb!j6? zMc>p?k*JBgy=7cFrbd)OgE`HF$!f-fyjMO7nM|hU%YXZ~3{pb%_WA|Ctokk19$y;(Arwx^lu1AtOov007l^yA7DZV zxbI1I{B*jl^QQy2;V^hICYF?<(3ijwyE01tL2Z7e@tvOYL{@tD615&d!a+c=Lv|yj zEPNxd05M|1I);G;ga9;5@#(2!@!3z`fK{tk|LSCb|EJrgaJ_W_aq0E15ikL z7Fw(fx}6*no`tMyBPSf}E2I!tb^ch80aG|wC*x2FWdZ;w=iuDGq@1xKU3|a5lv09$ z14Go#N~!@!_~0T|0idK`-!4HF9T-jL(|`S9I$y}+#?O2Le|qFk=7#QQlLZUd$KuSm=i;Rb2F-?X8 z&xgGUxdzvN5+7515dnwEz3*{{zzi z{10$&R~|45B*^Eoa6K24Fi=JzErk$(^&3~>!ZBk%_vpqI%^&8)W5!Q^)w=1cU;QuQ zI9~@PQCE2Cj1eQ#zmG(B{>{kxZ{4+g?T-U>qdeigJ{fC(`8 zl=O2oK<0nsBdNdq_K~_#GtX>3+V2<|0`SJ_sG4J9{=T=~9QBnS{J?zvnP>hdnN0pC zfYq=Rt1VKVs5fb>pFIin=2gdk;hqS8}d znAtg2a$df!^HqI)fY`B0)iQlEJ8d(UO6PEO2UIhls0~RKBu%1&RHOO`{mkQ!DS&DN zRDucV22B;xJIo2=cQ=H)m@zt=iS5mrX;Ts6AV$Jy=C+LPi&|aY+2oPGds2Pn7U?Ew z8>SzW?JF`AWO$be2|;mU!BYUK0BAl2UT?Pr4emtZDjSmsv7Kbb^W%P8dSz}m?bxuf zdSxMFk{9BaJ{!pA^Z<3jd}f7#FH|A+v0Ys{$S0`JS5Cv0@JB zyvL*ehJXx!qZ?F-JXMrYr4wptLDd%-l`&(qwPfS2ec`K&QLuUO>61WRDR4ytiM*1S z5;9`@!&*M%@t|JFggNJ$raODtqD7;{qD3eFoJt~*)33SqT8Q1d0mh(mxk1-|*Y%y{ zrG!eS4@rQ?K=X=$`uFI&I$qN>Z~W5DH~V`3rY4Y*5;#ki3^D#2VyjC4&vD@|Pky6G z^JS*t<4=Hbc$S#!A;dYldJ?ECi5)R}2F14leD01oG81BY21Z7HxS(TdjW z0XX?qMC>k9$t1?p0z&;@>VO15y}Q|hZ?}sU1+S*bkiFTo?1SDY4_gSX>k6}AZi5&xF?mUjmDf+ zAHR0vk7iBz=7vWftTj!%EgK+6U^ZK5KIGG*hh+i`q%yHU&<@)9dU70zlM8q=O^g`V zvF8&vU$=1F*=L@);mOAyo0Lo@KL=mv+CM|Ga5Ask((@O2Yw!J4XD*lP1kk?nH^0do z?seO@H{WcUk?=aB7cP;wAvYFpz4a=RiB7ca-Gb+zdLGMPS&No^t;l9_$Yt|rYi-9H z>)yiCPriUR)@}r#u=>@<(A#wYkx0nVOl`hxW!pBbe+BDS{Y7nD|B~9(^oDn!>p%eo zch|FK%lB`~KK@}X{`)tJegMEK7D>kOjsiTo{(tb>8JQsf;3`gBT?3_zwrJz`WNF2& zNmsVsFuJB=2Gf-;h=y*xq79sZauAJ6rkP+Q$Y95Vwkp?zQxmjNr2!X4fN(vqumSkW zDB#Kppp-+D8A60L$xX^iw0t=o9{gUA^gJRX3e z0*Z2I#6W;Fq7hrM^~4sdvw#W!)^&xaU)^>`%NMH7{~`YPZ+qlx^dWZD-_VHk zB$QW%ruk#=`ixcT%b%^o=7v60+YZX)dH_oSx)7klUG+~)M|def8~pcW6<)Uykf~q; znyV^!ciAMeeL<%_GL`y8=0M>5a6BljuuTFY?*u%Z3O2KH=K}o)<6>lXCGusp?XJ>T zgrs6|+8#1QtKQ@KBLTO(H`4&9uIp2DUB5OM3|7Bi58LF0An5`niZQAaN*R%ya!#pE znJ5X!YsK7&h+_0fwdTO>R5R z^JbTnlt6ZNLUnc`^u6zaR#rk7N zv3)xrCET@Z2fP3MyQUESakws|;|=6#gb)}^L(y~T*cZ#~PeuS-d{`8XN2+emhD)vbLYPR zXgQVHor(`b@V}lzJ(T2aP>!psCIHGq7y?zW5Ql{b1wONTEA|jFgaP2MNhjqZQr#QE zB?qOnKLISRb%VvJCp_p>A8<7T@iqMb0oS-c1@RzrI;j99++r8qmkKB)!5PCfpZqAE z`OC9dvGSF6+wrb{m*@CmPsiTXyLRoETUAkpNHhvi1%-b7nCv&*FV18u7XC^CiVcHW z$q?X!QdVRL2xKxT^mcb3mFPu2pF<&^!;bBnuy)nU$Y%>M%m9>hQBzZo#~1(iCIHKi zbg;T^I(!HPy8pT#Ju&ykGWvx+9b{k-0!A77(p@NtmHVCz@Ey^)ln66|*V^{&y0otP ztGm<5Q>#aR67xvf z3qaO7SU*yH4npuq9w1Yy%BrPwiVfPg50AjTAdE4qe|7&SuDaun z?deqN=KvmXUH1by`*`BS(?%!y+P-taWuHa!_Sf*UEpOrG{3Lui+lXH*djw_iT5MeR zB3k#Kh0$YYz%YY8om8nJ13;j&eHS)ucm+~;D2o~xnqpptT7toG& zQh^GD!+@m#1*R;`^mL)*0i$7Cw4-lE*>_4O_x-KgXTcO%5=_<0&T)oGOh$>GFsiz} zupxPs&Uh4zRS=45228K^8+rx@qArlIAZlWsD7B>K7W81)iQ=Pmh~K}bGRva9`9Qc& z3MO_NQ&;93n(+7;_nXQNfiOr9RKlP-Y{FrY?buEyW3u-SF7IKhpe+D_1yTWkE1Lj- z$U9zPWjim}bo8tE`EOIQXYvE;H*4;|yv!PW;!9m9Eu>H$ZpRHxdDJLiG#UnW;jL)H zWVH~GiwE|^cdD!Rk9h&WDgbH$+>Amu9buN!-gqUtt1ot!en*f>w2NqSWOKU8x;mF@ zAdwkwn3J2Rl6p+0OX6XB6h_5>2fJV;jpQ6>)eW!lSwGEzbZ1pKQ6+tFX>U;mu;`?9 zRv0XF)RG#PS@cWxaLq1x~pZ=slfxlDg z`M>__zkclU%P)_WmzTqO{Bb`o>+14{z<2@K{rl7_&;zwJy;O84Qe5coOzIQ64I~At@ zfcLA)KT2li0|A4Ec&-%iltKX%od`i7gaFadt#%IlkW{ibB95q&v8NJB0}B2KxqjNe zl)edGzbkz|HQk@T?T-soQUTO|y^sRZk>HGj6paIY*1(X?dC>?^K|y#PK7G@5c>dWX zShnmXFIPx^vc0|K-TE>~A;hI$)R6F zQ^r6*kk4k&T`c%r$A;tBNF;jEc3>}d@7Rux11%tmAsQ(~AYKB;wczBs5C}!L?%Cb+ zvA5e0O(Pg!lz|jY7LU30L4CP`&jKLBWCMg!6bf0C#43hVoeB}ov3~bf*wVe?!JRwP zriQC;h-dhNKa~>MODG@RAJB7>Sg2q(tU0HT@BOrFB01%1Wg(7#JI-3>6jWN z=Ca;UcO=lkO9(ehWWX%-LYNx|0_FWHB_I`0p(`n=R1qdj29w@U$FZdwxo9NeW{uo_ zH0-hqUfz*fpO9{$O^r#qLM1#!;6PFaMr<%*`yKV;U;qp+`VZE)ZvjXgpouN5%!`Lu zFN?{(mY|h?K>dDuPy4i9kkPiXCj@Co?P4$eU;}Rbco)Vv4g#!za<3Z^l|%(`03JaT znT_>aM<>Z+gV%>TCyoUoF#rS{uPop&#Xq1yK&M;rfmP?ewxU^&7xlbc|{ ztjmoEEyMwum(rw#+NyMLg^H^-SGJ3qT@%#ai_dhPx^*}G>fdV0(rl68y@;^!fY>r9 zNIT(0>@)Z~?Lus8{uAQAchNDCQ2IGt*OQLpJPrV(ku;a$KJR2dXp5j|`?S5R($kqT zT}Cv@Oy+8aLAk;6!LZ2G1;Gx5CXY>KVaJfCVZjJMX*`vb`O$uMcATc7OC>KjmB5Gw;h!Q&IYQvJ^x%!&9!N3@OaJg9s%QaMee5DM?b(kpjib=}#tsllQ9XYK;EKOj zZ!G&Sa{77Q@8ta7v=jfCW1AM-QQGkFiz~Nab9WuOZKHU76?7^PFLg0DcV3`61&-1{!R`f6M3r(q{Z;IzpXqx7u!;BW82?Zep82rM2=r}+W zg#&~rSOpu`U4JcBuUdJivV= z#dD#>;+cX_>dOH<57~4Q1uKt2E(gc4;W{=lnG`zPTd{j*6FLs;M?RN_&P|wR2qlp! z^pDQwneFCH$04au27liN-3`UEB z44(l&2}NJ32i(nnE@RtGrmnM^e z8>cjW>%4E@{pf{X`Rb;;H9XPK2=vu9)}C+T0ws%T62B#(2t71w>IVesMvYYQ3<4Q- zWSN0xps@M=pU!{qUlx@l5`B~XG2S2S7&~@)rS!xNjT2_U^BhPiF>c~n7}Gc%&D+=E zq21d+_Vu8mVhk?1>SpwGwV<d7`pL-p%&>nQW^T`)3-eexJonp>z$R3(|c}S&5qZ z9$uzvMwIAA6)`a@3XG`%*pNqzav&@T-IF3b2F|9JFeEHsNe?W;%y>d`grctJGRM**E*NF0;ZdY|==5caaMIG`1f z)f}fz%NS9%E8CdeolCz7Z=G40P!V24hI5`R#^MTzOXp{vA_7|A(%wiK|v7` zG!ov*&uFTW>v{uc*Oo5Cm+M{iO2ouq%&Zg;mSlzDHuF9tI-QHQ5$NIVw zsy>k;de3UQ@P0}})bX?)WGG_*a{#v6|GhZ&V?FkG0-uo#OYbV6Z5{y(C^drsHwHCr zU*2^$5WM-`(AyS(hD4ertsswt1lJVP3={%}65#;%LW!wkn}VXZ0lEh01dwq6Y2SYF z^m?eM3G&P3;9I9n@Mkw&TF@${nipr6JSw=l( zB-8MEdO!j`!A|f#i{r(003{BlN~MNIylRs zltV}fPl*2cVJCy?O8^y7P*8HX=)d22-gl}mjsPqg&`BZS5#IoBXune`e*_?@;G+51y=xbKasN-y*Vp-L3Hcu<_?-UF)(y)~tEw4U9t;K|x^6(%4R}(( zv3)HYB|bQj%VyBg-hy;80Z({foI`pZ(y0{sdb-iu(*@hIz=#IJ2*BVG7_smGtKs0z zy^sQ)beAk!w&Z9!EW#;|0ty<};kXV=BXHE>pK}e2_*ErQAy_B z{f`en%EP77^9B=+y)N2l5bz`<1&B{M83NDHV&U&wG!OvFk<_l?s7<@rO%6lNHVhP= z`1;>nzVz4k@5?*RwL?a`eW1hhoJI<+m6TRPN{Q04IC{JL0HR^i)cKe=`CM3qEHur4 z@La^pYEWJ=0+yA<+NF;m5-k~c#`^ktFniuLa2y*Yaert6qld1h`&yFt+^yfjCti3S zx8-YK1zN{{*zR9Kh*JKdB#P!}>7w~xq}UznHv)XSQGn#2KaU~)Z#hmliCxx^ESY9P#0loC%1%S3st*g3wLjeS*+ zfaZDz<1k491(HRG_?PDB;dlHO^Q*8=WAJnh2I;^CuYik00YDj&nm`x3fIWBCW^whl zq!TssC?^p$C-JoL^1Vd1-0pg!R7oJ9n=D>vke*>`DKbV%CX8wJ#uBBZ+HZ_ZR@t4r z7CTE$$75?=z^!K~*yc#QMk45zCa5ql&R&Q{?>Gu;vKyeaXy*~QMihx4^NbLaT0~!tUix9L!DU&faO#S@Puwx2A?BmgX0q$sw48ZyX~;!LBIGoCkem5x+pyQ=CF`{%oJ8w*O)CE=Wc zFc5A)IU0y*1MwJ;&qL;gK!s^ALd>8GqY!coZgIWfg>@&^>TOwAFR}Q7Zl?3tEn|E}K zzx?GdN1buznH8F*!P>kTvZV!tvBSTa5I#GB`sg|>E_B2C~Pw%cyUsF5SE>BYy3JS%~!bEctd)fPm?)BqB-?{?d4b#wRr zdr$8EfA7J(8qQ~wYue~ArBPc->MA96JI-4!Dw`4>1Q&vS>J0T=b>S8X(+v z((ga;ey4g28DB>!g>Bn7>+Cbo)6;|hyzj^8O?0dQ@RgHrvG-bq%$*xnzwi(3`*s*(4Mzixb zpF)X`EzV!G$OEu{%NM>->T24$fKb;6#{MB~yO(|MqKmq=b#?@An=AUnc1WQs<~O&Yx3>?jCtw7EgLkA-5W)o^ z6!}69(OA4_Fe(rV#|I`|6!O*)fmA{Wgy-S%ORvW3e|iN3s_R2~3#%ajK(bf}#fr(X z{&oz2gXsTsh^gRV<1XB#?#5E3W3K{9DoKLU@T6djdjR!3NY^ErRiG^E5ItQk`$qO? zk#?rTAQ6LT0qA-O%;@RCIMO+wOoxvwYr_wbhkN?{`UR z<(bBXDK*!GEldzsl^_u>QTu0WWaM%aT(_Xp9NdAWaxx|#O9!1S1?bfPt3_*g3|^nt zgwtQFKt47JZ&)@MiK1Xspfgsl+Qz_L7TBkzr7B6w$US7**2}yf{%VJI_R-k7UMect~?c%f+Dh>d(i+l7}a&fHB%F2G}l)$cJK1*BBlD&|Iglghe=wMY2)`f z=Z%%CbMBrTdS;k`Aq^lykRTXX91OUk?kDTFs~A3aSAV<8u)B&IP*#-S>cYC}A_M9I zN`@iGkR~#DdOGLos_M#bI_LcUc&mH5XL=F~D$>t&)zw|q)m5iXo%fvQxu55`?~K;C zkF-^lBURl`f+#USDFPk?u?Vas4GGmz!iM99N+<+No{^U&rn^SgRz_8~9pLTjA^$gu z0Bx~YENNMP)u`)Vcg0pcWy#4!;`}oH}blnfKh43pp zZTm3)RKl5pRhN@O;*IwIKk>v9i@yK;?-N-lKy-IQW-pJP)%rYqNHgnCK5U6?247CMUP5BO!t5@PPlE;lbT_ZPUGQY#Xg}Plc3k zeggn0hJuv%(Ymf1WkSD0f&2tX9+|)Zq?jD>L~!qxS@tK$3MU-*sSK^I>te~$g#aY( zyz}3XOb_=0xauurEC0#x;KAE=ZF#Y~W9MG%+Oi#6Hf_R7&p(S@+qPoQ&aJR>E^4b< zQ5mm8ELw#~IF5L<2DR0#h(~KMJk|@>b52-$fe-@QE_wit%dj5`Apk;{lz^)0upDc$ ztnKKF-DimPYs%#zE`u@w;4}$A0x-(ZKiG*@)A-Q19|+9a$$(=&`cbOVOr`+93yZHY zLar)$?n|vzRr2{yT-Q7Q@n4^}e)Xw;*}v)Oih$vx@mnnHP$`&CIav;##N(o8SbsdDl@yTkUVzC6y#f;#X5CS{4?L=?a0Me=pL$LpT2Lk{T z4tb`$$41K%S$Y{br^i97$rKRan8j;Lk&rpmN_CtGMoYqVh~S^{udkt*20aK1gauF5PJAtNGRY4fD3pr!zPQv z)Lc{@46bRaP%D|HtDaf!CFV4_14{zL4NHa6YB{`IBVJ9D=vw81N(xRG7*U~-I11%v zx1%Z?O!UrE6CEszYIYDcltLZ640m+Zp{FvAkzfn<#6!q=n#xQ`0!vOaUi#Y0o-u&%lN>~6dK$n^qURnvo6D}x1EQ(*HpsNf(T4u+CO@by1p#;SB-=cK*Fd- zCU60N;;MzRXWlvd+4ryEo6o<{edVeP-IqQZByJRa7VuwrU>87xI<0ONwaPgaD%xX+ zYN$L->_1yIh!IptEC4s$N$2-ds?hiIpWM7!Y*`jo#$xqaXKWsJM^@uNpaLDb39wyw zOQZpFmghZZyYBY^+$9ADC6ENLkr1-?SfJIN_-aD|Rj0kttok~DCQY!4NK~Q3R8^)Z zV2(jm*D!S_Y$~z|6{Zqa@{7<^X{d$cF5F( z8C0RGs-e-Csn*Abl);C<{uhc0b9=_ew_bhTdH>%_4?PrE_}=$I1Oh-Z3Gv8ppj!n* zE93CS#{tH`ckhPG=Y7_H$MJ*z862P-)F~AJ@(AYolQC0K7Oh;l5~9B!URT#KmbCO0 z38sYqhx}#&#ZO(G+(5*Uhl%h6diQo>&XwyR90$VlaN&g)O>V3qLz{dTrYL2`=h|qScP17sT?@|>0HN&79;TyGg%ARTDNqy@ zp64Et^^+2w$0q~*a;y84o_9>ijQgAc-18;pIQQVWzT}_lx@c}`gsL)p_q+d!vE)#; z+$%Nw7JmzOdBS;3({zMGF+?Mk2#0*4zQ(%wP!tUwcgk6N;S(7O4k0;o)kIx&D-y~6 z6DH`RgrZc+KMmlx6#%MZDHDAYs-nSltmy&#QI?LFm~(OnHlpN^vcUupKnX?B%A=af z7kB;TXC9l~D&Ckie`iB!aPQs`mM!UmIT^+9{>tOxV>#P-{`2RamwMz~XO(u}aQ&a& za@o7D&GqfqRRd0vV{Foyn2-S!lRBRM#Y6p@1f))3n)FaL6QK~@zy4Kw`hoja{^KR@ zF61re`3p8~e7mIrhFsT1v5)~F1nJ~Br1TX-2nZ-8NQ@?r1kg%F2r->Z%CSp_NJu>o zqaz7WN=LqZ5acV{mieBcr6-_wPI`?g>_NV~iGcYpsK4gh!nisd$dP`M32FSh~E zV-%o~DH`j_5y#bGwgCXp0UJT-6?Mr75g-cpw<{r}AVPw0Mmfvt6$xT8Vw@Q;mD3_> zWQh_ps!5O)tX=rbj>T7h=iL9>`EQXWftBr*o&V2dV{_JuPd-*kyVgQCjQOmA zL3DhfZBC|f;a?R$Etl0H_~5R2oq;uXjw8ayX~$!Lei|lh|)Pt((p}P;}U?-Z2J{R`5*!QMG|s9=ez=daUUeR z3wNnL7$PTq#iwA5{0lz2{f)fo`t_2ceK*tjh(ejCQfR6qQfDS~W~ipD2y1p-O%i{) zlCs6~H0TnbD!>9|NR2>}pnrLVC`etD){b^w5YViepl-z#CIUqDObt?3T~AA=OKL;7 zoB2ErCk+D31Mu7TE?d@i_nmhFkqD%1!~VrD;QstxP}2mhr~p+JKieOU_$QQQK^BXU zrP7S$|5>QWL7DVdx!|z5%kc)k*qHuKY!NinzdOwF?(C7 z0FW6UkdtWUWcR)F5zX5A#i*`Z2+Ou6P|i2Kr_FIn1xl3?Rg?%J03j5P0XHJOE zz*a&6y5JhJe!ZC8D&DwV zuyLb@jTk=gxz9yJ!3|SN1|a2)j%PK1vJc<>-uGT|Fqw?5f6qmqO)g%3Kz{G`=Rdx% z?Oi!Oc{%$X0m4sYPPPY>Axr_dH58S70to=bEF{er{`Rl0`so#yrHYPc_(bDxFSBiJ zugOIDl%%d*hb(TzFtS|J3-K>sL&5MYc>S>hDQw zo(n<XM-mttOTn>S7^aEMn|=fCxx+cn`$T2KqHjq`tAa%CqE!B} zr)OW+I}iXU02l+%P?iG>9Ip*vO7>qVzXm;4KXp6S$vSM1Ktks8T(T&aaH-@>LIIIP z5kdh+Ok}EK6b-bklHt#4fCW`RmjoefI<=IG?s04ZJRkv_Z%rap#>zI0$dPjPEM30GgSfj0c#Ci zfS1fRY^>+Wy5 zX!!D>Qirwks$QO~Y$Ua2mFHoNh_JyRZ*Nf_zd3dHoag%YRBg+6AM8zvXlIFPZeBK& zx=?2Y5fL$@NEep(M=|vIQMC4DQ6m#*^ZL<*c7SX+R-o#W7E&O=!VntZnFTMbc{CWc z(Uy(r#l_@;dMW2Opz!b6WI@JL!>lpsD2Ak)yrF0`5yy{K0(F%@4FNu;fb1`jxub)N za9$09y+akoFbS+8JFnOw&UzrmtyUqG!PEH*bLM#u{rxZSH=l_kA56e@!oDiNF*ysQ zzs59jl)h$PZ)kE2POA>j0a+b*i~wg4DQ}>Zj=?a#6|ugQU5ics@Dbe7Ct%&R9!LYg zHQ41$-BKka8Ag3o9UPk=l|3e~vJtc?5@A(QO(~WPH5eK7Of{K`fQ*<%EdWvQb|r2@9C;|y$N(uJ?n#&5m+g$ji`UdwRl(i4(+{i_#V7llkN_@$+NaNxiuvb*P87LCyvGcI-#hmFtj9Cb8n8({a}=JMfv$d6@}0P^zyewQ2DlZ9f|@!Jq= zsHzTy`pI{nb)U@e)lpEQKuQV6wNO*lj6|{zgdTmlQOc0XB_8wOolv&DqvPcq0UbH? zesrRT?Wi6(p>z@^VuvX#OgxJ*22Ihhtz$cGY@Pp=Z*1Q*FuP5>Ikw=o+p-Ij$zdsF z9spFTk5ZL?Cs!=3s}2S4`RO(5dcIv3Z~WC|Yd`U+k6+h1*s)&=GkBCv$@~ldCa2U0 z*?`liqFDeU5Q25rN3QwE4==tjYjLiC$R{(pzWMDoS0f`k3Q*|xyE?YQa~&|o@Y>5; z(bd@lRnySh-48`!hh29BoqIR?SV`H@V@!oz%42+dbn-dHVhK+@`Yg6@-HDOm1f&Ga zKoFZYK7fP!wxXu4DH5ot-uRWK+Q0r$O#js7I=jW;^k7@l;;+AhmMbscie&&mE6V`} zr?vr1>G_}N|DOo{)hUF5?CATFepi&Ryk_(UDlnp#5E2gb%ssaIUyZzMMjC?Mt3n8&$f<&^ik1qQz#7TFEPLO;W?(pH&qM zu!@1#9$fsy_Lmm#IFMh~acS|EuV-Y!(uL)rfXK!YeKH5fFT)xHp62<#=x2cBZ@x$S^l{%e#3Ax{iJB2QjWSN-;& z-rUnnha2X52bZ8#1M0#)8Kc?+tgQt8ZzHUpQ1 zrqo>k#A4;ODG4EGQsA#aa5;d>sC2IUFN_8%kgm?5V)w21&)m$wf+PhrUc^z^NRY}M zYmDpGfhNrkrqY6bRKpD#h8@;Tgp`01q7`ZoVFS=q5UP~=DqPbs)mTWc)Z|`1!u|wmUT17iCo+)FJQ<%)#Yx4edUJT`r7Vw&GpclcW@TC^xUZ_dgu7Yx$jap!y4 zTypX7Sg+DQbO3`RofsPJ!f>JsLy2w-jdo#VtnZBR%;=8*%)wjJJ~L~xHVXi}MVXhG zkD0^N=TGJ(e64E*jIg&Lle=E%TA*iwxt~(%YpY5L*LA>!uU+POE?n1v=XvFlcv-G# zp5EFlgaj92QWCIjPAeXI_(2Q~cSB0~O#rw5j=z&0+bO*ug@k1l5HzF5478_y50o-! zssYYj1cOnGXGUl2(1jLOrOE~pABR9yvy+KSGS;3Z$_u#f=Bn`g3s^4nS&!}whIWm zc`xWBM3wbu{_=l&b#(Q=-?qameVVIikJN}Wl{l*E>QLWU1N~(iottX6jE$K2emQ3> zL*w>C=2yO~DORvbj4Ey6gGwVZB#Kd*M4cm{@gPR?bFtfO#dft7DT>J|g&9tCfaLuC ze-cJoZP17Gb^J#koJTvVK`AfNupIHK6L@YAuXZka@DX_-3 zdeDQ!4TiN`JR--cA}muKGOQY1<248e0hIwP1W?UCtEmY|%F>oB0x%O$C}0Gjg-B&o z7M6x+saj`t#E{vD;*Ew3>6)rys%o{NwC_G)`Od$IYTB6(f8!enHZ(v|3j4=D_BYch zd#)@NA(BameBKZKJrD4_DdItg{3II`N$7Y2^*Fp%Q9xpDsP3eF(|{T{?IFkOd3k?_ z{_y?xLlFX`+|nh*VJ{~o;CcQSC(eMWlsW`Z%2ZY-w^Op#iT~#%8!x}S6{r8%4Hy|3 z#=BN7!Q+oVjt_qDgOg9s4EG_XYsYfZrg1GToO8+RS`lAV1MpPC%xWB5>}3bFZA`mt}%KKie;*n8pJz zakdC4;JGdu8XK^6>uc!l-U})50|0;fdkI8@d!OYL!3Bq^XeTi(e$cI{224E+*K=Sy z#c6>Hr3|@3%F1RFA8{OK$4Rc{a*NGj68S*-*yIIF-X0b8KuVP%Qo`>G2Ong2pGmefg!2 z-MMH%Zu|##Reb!cvlia)*&AA(d;GDW=h!5~;28u$C6Fossa8;>GtXQ2*h6P5s;+j0 zlnhdSap|qM4!vFHXkcJ(l2YZ*2YUBm|DIQ%s2Uh!80;ScKzvC{MFID0?A-Pwc5izg zimIThs%9FuNHiKlHZz8opZ}%bj>H(OQXadvzkr7~+y>Vk!(Xqz8Q=Que`3yp#mE+2 z%$c_cKfL{0_}+j27*`BrQDQo7jcRbEyyYFTM5jstCd+C7u`&oSwGCimo~LI2Ss5hI zrw{=i$2Oych&13z4n-;uQlZjbR(x{Z;?fHjFj&$hELR{#Vl)xiKjOtZ^39bg?|sW% zS5+Jo1yHhqY!*lDbRz)tAdt6#v<)YymGGgnKm@0Jf7&A;Bp`A%#c)lkf{!dyB-c~| z6^t;+B&8ZBQ*~B0V8bzkDI4>}ek^t!)RO0L-K`2ztIo$g>s&CefW`K+_>00`oSjqP zkQQfWpcP%=3TIfig(G_G#oJ4^HahMZ;x7scJq-bvp-TA zRHrx6T_uL*30{FjX3%lPh=}zPhWry`D2Y~-8zt9AwU~ybR`(Dl^9gb)EvX`a*^6} zPfJ7gz{2{}fm3S=eWwQuuNL7Dpcw#(0jyjBKr|2%EWfb=kRT9bKp+4kh+5GUfvGyR z0o9J1vJg6@Z{zBSI}!|eQV-ac3S&rFyY{$M0H+Y(Z`ZF|hlQ744sZ_lvBw}S>yU%y zc@W7YWI7F4w$J!KQTES0kaG52f`Egd1cn?G{2C3&L4laUzCYoy2AC#KQg)G6aqF|E z5J_(M^q-@lsv2b8JdpYGfl|p=0&rcw1)-ez7uoC)m9=z=SMB)Zu_xDtAmzL=0*&Ou zFX8hWpTXJhx)9B^l~5SP&wlnZ#N+X@A1Sb)K7PCxd~WK!vDEPOW9h-Fa4?R>y7{Pz zHNZ4OXkT?cKJsVR<9*j$i)bv0SVas~)zzr1t-|^ z2)4W>115xV&dapqe(yV-K#L{dx-N+4fhi0i3MeR~B$K`Wl=^J}l#()fD-nxE(b?63 zj)S}5apzvwwg2Mx^@UVaR6JBDj(=N91Q=x}SOIY8JCtQ|y{dQvM#g$kRnZ8AsgRHu zOZE4SXU9GW;FXh}cZuRe6@_62F*Y`Yc&r*i$iu&%!|u~*f0GhW6cxiGJ!q_J#VR-Q z=q}ui^NC|`nvZZGoFA|%0hS?wY3e%71A>%;_B)eG1T9I z;ek$QnvTqP0`nG~f}3x<8!c_~V3mp}7V~A$66ow3$HBgFES)iZmVMt0S7o_BIPmmpf^Y3nVw_Mv)*tTMS?9x}IqA-|YVyH?SNr#%22x^Sz zaJawUI`(mnRtf}zfLVYV4e27A<65n0#;jCrQfmE!p|*Xp&nmiRC`W8=Q0eK4qzZ?m z3>s|Ho79~-Rt3O%K&}O38yejqv=;=Z`ZPXuQ#A%^To}v)C4;EvA&k)ZIAFA4Umf>C z{2cP&Unx>uJT9Yot+;CID|MyT3Ozvd`Veq-99Y5-{8cABGB}S3R`fiDo6Z5XDbN)? zC;Z?=Mj=)6Z2S{mleo04;%PGPN4RlgpmsXxHx6OjU33}EvouDv#J)0e&knjjA4v4DyEeleDa6UArLf{N1aqq_G@ri%970E;bpStq= zN&m_$^Cdj~)H8V3s-*xwn*T@yTrriJqh8m{%PQjaWpZi%{{n#^_H5e-*C}A<<`@0s z8s}w+ZGz<35Q>E?Y8uY~gv82I&e2|Z_376wyI6^%aAeHdtjz)df4DB$6wT5@`*uli z{Cs2&I!ogib4n<18y5E_S?62m9OQEebnJZ&ww-%GO8M2dCRZd40S?=-VCV)wDTKr% zU(ZBKfakj49*3f;lRZ&BgFXSJ0#Y&%LSPsMMiWCgcyKTBh3qej#r$TBj;Jez>RRAjP=UzhB{p8*(oW2-_ICtx9!>2O@T z9NbSoU>IXZy1{g6`Lu%c_y}sM8<8Fz!kAI~Fy3U{b)Fs$M@xMx9d0YVwfKmg;}?0f0P! zK>(+g0f0!k3P7Dg@He&eUn_$Iq|703TzeMJB7%slg(1BX5mtzJ3JDY$+{n(*c@Hzw zj5CNTmnj8>5L2ZzAWPgSZR*X5CQTZIhNzV61k~+-cnpZ?pgsMJ>`5^tR;#InOn?-H z7W4fF_OMGvZ97j~=*bkSpJgD= z^r1rbAaX)`y9E#r)iSG%aF?sf0Osz9uTGt_c*nuZC<{MdLU?acBkudWM?V-+13|r6 z2@^zt3o8MkA1XK`UOEm) zIn$qqiXkt60@L6Mjv^>B&@l!LS*TMy*CRg*^{YP3?pjyF$Z-SkmGOA|r3df6TR*40 z9bPu;`C!hc1qmST>PhNfug)cltPPuU3l>5WBTS7oa zrzLEtqF}JM1A~1BplJpeW95;{$*R-MFZ>FxJoihO!5}=(#i^^#3vAi;!WPRaoO042 z$E?lTECBF3wn?eBsgE7*q%vGpGaqd-i)vViNC#3l-~{+&Zy#P8-iN-Pt&$MjQV#y# z^q_A3{P_{rBBmq~j$=bg2~E>LDJwT4NC+vWWT6Q>?t(D|jHzIZfl>nQ0i1A12@DPQ zqJN+huIoJPdCo`6S)|{qrL)6#DT=NSC%V5H30GA{!j)i@`CyC0j0_DE4EsJOjfCS^ zC|Wsi?)Gxe`lpgzc*A@Km#kP3%#@6=gj@U#W3-o0mZBhB2(Ltlv?WM0fceyCDwF`p zDU3-jgbg6Ys4_04%n(LIsZ=OMBNd+OT6SNe`#`7bW@fjB-z(fFv3|Xr48(j1zdpHc z-QcDsJRIYd^8{xXYpQl(ePv}k2&sUSiU3?9g(eC4{`@=d9Q`Aj64~9m`^L8Br9)i@ zw%#$8=tKMRH5lyOgHo|rR^lj=PZ4?4ZH{vR35rXu{1lj?ptrjhi`wTQ8jVbn1|A6< z_;P{KNDQwR#=#_!LqmJ|-vP@|P9Xxc$^d{>CIYN10{{m6eE7uVu`(zSEE9?G^55j~ z&Yq=MDhnt`2jkK~KxnS%IXbl&l)L~lROqH8N{N942@!%tp_vgUtdETcP+JWVR=q<2 z06BJSo=F1H5D+&&5QY2my;fe2kGYCnP^G0;*!^?ZmBvEvzW&0Hh&;;x=8JGJDNG_s zDO3J<#|sJ}*8u`p;SM2Shmk2=jeq(WAhk_+-$M$DN(!x3266EU)?F^ai~-D7PAM#W z_ND04+mj@H?XLpvifi}ffcG_kNCIrlV)K}VIw#pEm`$Rr;65yWymo1&eF@)1etR%m z^T^0xL#anD8PCWFNh2&wG&&<_5-u1~5Oxz_$OE+DIH0;w3yFf1mKNrY6Ld7iGtnFb zZaIT3{LAfYwN4V-uPo{;Xw9iAjMn4gdfF+Ysm+ z4vs2yiGEpaHF#Qh2(dfIyhx@9S}elkArLYKLTUk0m|=|9U;~$k>Gxrsa}ACTcy7mv zphmy*xeJ&wG)9fifMxA+{Xi&v*qT2Y4-=U}8h6BVzJR-1Lr5&U5%S>~h#`rd>7bR% z6si)!q$uh!Clzk*dEy@j;`D)H<3eYwZTar{Rx7S7o)`2fG${xP_?_xhow3yuBm@u> zP(46X0G9wQF(uGB)}odYVYmez6qyRC(0(Qql~Ik^S)Bp9Ik5DIxl$=TV^v!l)?R)& zgzLh6{Be*#0Fraa(NV~3*3bNN4(a)HG-+t)K>#DtM1eCnL<0wh1%@0{aFC+}|8g3A z^|)K4!cmXsk5{c;z4|x*^@AU1i=t6T&Os|H;qBW8ck^b*kr7{&VD4O?zu#9Yz!WY5 zLO=`yvQ$EeFr=YPlZ6oSpgm;k`^hWME_{wcqEVAzi+_8|&NBm&Gs1tZ8}1dcu4A*KAHlz8~9 z8f-^LM;5?EZB2_V6OycQTzfJ1yhg@YqlAb$j$I*ykdzXGDJlp^K|&;i5T+EOLP((s zAt0rIWD`hz{qkbWf%l~5mmqUk8%PS`4uC|h52lH$)@KY zT*fFX2mfXAP%a>aoH4;d2thiX#PU-w1TFJnP)70eW6$CIi_b-Mbp<@{P}>wG1fT>X zgClt1$(K+{Cb3Hkz?3Zc`>aO#ovpP)Z2+DxG=W5!{C-Zk3LsPt^h;CbLoG+f;W9u_ znj$H90@i~ZDuf9t2uebFswY(DN�A&Lt6o3QhWV#c(^#~dQQ}eQ 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

S4s4p2G(aURPP;@lUvl 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

IrQ$Pv%KkU7Em?ddh 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%0A|S4L(&*IK~ZAOJT-LK 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

Z1tNHyLr~o`TSh(Hl}I|{QJRg)1J!mt7|X8 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 literal 249068 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�A&Lt6o3QhWV#c(^#~dQQ}eQ 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

_wEfTZn28n|5bT?4SN47oy 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 z%0A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 diff --git a/spine-godot/example/spineboy/spineboy.png.import b/spine-godot/example/spineboy/spineboy.png.import index 2d273f490..8518e5044 100644 --- a/spine-godot/example/spineboy/spineboy.png.import +++ b/spine-godot/example/spineboy/spineboy.png.import @@ -28,6 +28,7 @@ process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false +process/normal_map_invert_y=false stream=false size_limit=0 detect_3d=true diff --git a/spine-godot/godot/modules/spine_godot/SpineSprite.cpp b/spine-godot/godot/modules/spine_godot/SpineSprite.cpp index dedb91940..aebb17e8d 100644 --- a/spine-godot/godot/modules/spine_godot/SpineSprite.cpp +++ b/spine-godot/godot/modules/spine_godot/SpineSprite.cpp @@ -412,10 +412,7 @@ void SpineSprite::update_mesh_from_skeleton(Ref s) { v_num = mesh->getWorldVerticesLength() / VERTEX_STRIDE; vertices.setSize(mesh->getWorldVerticesLength(), 0); - mesh->computeWorldVertices(*slot, 0, mesh->getWorldVerticesLength(), vertices, 0); - - // uvs = mesh->getUVs(); - // indices = mesh->getTriangles(); + mesh->computeWorldVertices(*slot, vertices); TEMP_COPY(uvs, mesh->getUVs()); TEMP_COPY(indices, mesh->getTriangles()); From c4d657757dcf1870753fe683f440b4b7a9978935 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Mon, 4 Apr 2022 14:57:37 +0200 Subject: [PATCH 18/18] [godot] Minor clean-up --- spine-godot/godot/modules/spine_godot/SpineSprite.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/spine-godot/godot/modules/spine_godot/SpineSprite.cpp b/spine-godot/godot/modules/spine_godot/SpineSprite.cpp index aebb17e8d..29f163c42 100644 --- a/spine-godot/godot/modules/spine_godot/SpineSprite.cpp +++ b/spine-godot/godot/modules/spine_godot/SpineSprite.cpp @@ -320,13 +320,10 @@ void SpineSprite::remove_mesh_instances() { void SpineSprite::remove_redundant_mesh_instances() { Vector ms; // remove the redundant mesh instances that added by duplicating - // print_line("start clearing"); for (size_t i = 0, n = get_child_count(); i < n; ++i) { auto node = get_child(i); - // print_line(String("get a node: ") + node->get_name()); if (node && node->is_class("SpineSpriteMeshInstance2D")) { if (mesh_instances.find((SpineSpriteMeshInstance2D *) node) == -1) { - // print_line("marked clear"); ms.push_back(node); } } @@ -336,7 +333,6 @@ void SpineSprite::remove_redundant_mesh_instances() { memdelete(ms[i]); } ms.clear(); - // print_line("end clearing"); } #define TEMP_COPY(t, get_res) \ @@ -347,6 +343,7 @@ void SpineSprite::remove_redundant_mesh_instances() { t[j] = temp_uvs[j]; \ } \ } while (false); + void SpineSprite::update_mesh_from_skeleton(Ref s) { static const unsigned short VERTEX_STRIDE = 2; static const unsigned short UV_STRIDE = 2; @@ -362,7 +359,6 @@ void SpineSprite::update_mesh_from_skeleton(Ref s) { spine::Attachment *attachment = slot->getAttachment(); if (!attachment) { - // set invisible to mesh instance mesh_instances[i]->set_visible(false); skeleton_clipper->clipEnd(*slot);

_wEfTZn28n|5bT?4SN47oy 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 z%0AdNhKw#?UI`cBME`LYy{`C5st`<)p;f>O42^Z?a^Y6zZ0F3@30jUHGj}p^O^gw(TVz zN4Vp7?!DgEU=g8Ocepg8>S11m*u;!n%l6%Hd*iTI#>Cp>^og@)H=1YW_-Mm;_eO+m zpk+h!sY_4RHuoxvV&HVlx^3 zUx(q`xnngke#RR63nF~lh%r7}y>s6!-+T8~K7Z!<%5#a>1w`x8%*F=eQf1IrcHi9< zKG;$WSWUhtqNj{%Sv9_Ovt`bnSgER!=e%M?^|h*NyO&^K3nW0jTp4~qL|9sx#d~FG zaiL9c`!402_u)S4Jvi@zIyG&QrcFNe$DiZFAO6AbO_Iu;FA+F=Gw}Xg<@V#K) z$iL_9`S-q0;ajf5%Im{*0^lY8o;Lr9_cs8vV%b$3r9x{ON%k`0Am9yl~sC z{N2F{t_2lb7UV~-jvQ#*=D=LlWBU5iix^z9(FV1vvzN%4jl6%ovO0IUE#EhBw60gZ zAXJy;8QQrQRam@m2A4J49{J+HP+(O>@Giq;X}jXD&h^wRvPPYIc8oECYXf-k9o2%k zjL_8E1vLP<>|eUb0b^d0-@f5OP~lI$>GeGNkKV<-rpAkpevaD8GKKOW#i3D>VwtSj zpjls|SzX0tX;;NPkP%`Gg~}j>$`ItlKx_Ke&M?8)2=$(Y^DlDY*(Y#m%E0zrG**|{ zdFTjYEQ`~px$x}c6b6Qf3*}CZL!JdNxNRquv2jKw_VdIif9qrCj(_QwUgG(_Q64~l z4nWdX`LA@50Hv-BfPMwQmLJ-?W>uz$R4JMu6HkreouEcZ0P7X&MIu3rdS?Y8&{03Hm?&^GZP+&J0Z&&?$ECJeO3(y{WK+kK}`^x&Xe${@k z?>AY;ZgB562tCx^z17npArLbXY!(vggeuaOn^OpF7=14N7ps^6I)zBpC!!ej7?g;N z$cNK7Kynir1gb$)7-%k2y5cEv?~DZh|4JJus!!X}e^r;u%Ja&<&rGbDQ6lNc|1}4t zfdmN5n~K4Rc7fUaJ?RF!o$5cGg#5f(jwdGx@*IEwwv918mH%$=-&P5P3VzGiukBob zw(q|q_qQF{f1U-969n2y@(;`E`kp`tcSOBwxvyW#tEZb z;Leo>uS-iDE*bVTV8F!)HHez1%byeGJ*Kf7$bf}E!;8o(Qb0I%Oqvh;m^>U;SoOl; zwPh+l@DUx@=z2W)0jcg7XAwx&7HHNK+h}rTWPlq}gE5M2&f-q3Qds*Ue?C;IE8H#m#oJi=05sq_e=#ZmSse0B9acOU&dwGTchX{^k6hshkNIu;FNE@kMUw{HD8 zF-vQ&LA4CoS$Jq;%jMApugJHC+!B2%_Lt6VR{h^~=>6LV@Ha!YoyeBYojca{H}2W< zkGG|6`CVSkK^3Wrn5n|xj#D$oKf3zY{lWYEv!9qtipgo<_r3D8h-&86Zkagz?(J9q z^n+>B>T~MMLP}ap8#b;sY9n*?=C*a{yimO)YM%CJ-KZPh+-h*l8D}pTm=PGxtR75P z8D7rp_N(Cp?;D>Otc=#PEM;!tJXteiZ7t6OXodfIZQnXWaCNx%Ip?WWtE{dr@lD_O zZM^x-Z}|R~0RAoT(fr?!3w+^g3|bxmKHlQ^6fD<=>%(;d;N@rm^r|9(Aj-2WNr@+A z8-FbOc*q{$3+4tcQVPZa4H*DAfP2LWfFvpHj*I1Rt@FN9L2n_iJULz@ulCogIe<4* z7v_8X!G%(#o$8Z@szvWGQ z;oa}#_4Nf#KlV9ltIOCp!A3EfWyGa&-u24i(k5BjM6(Q+rqq@fS-NHj?(ZbCW@&p&a(TK*RnEmf%9Me z5^1wRWo*Z~bIxZe<)Kl^quUtWbAYdW@;5(r^7Ehi-j@mf`?COS7pRZ&N`Da;=o(wo zx(NX3YX#V!{I6Ff2FgTYC}=nvQZd2&tV*OlKjP|Rz^XB^SB()Vgns8aaO(&5ZSc(c zpubHN0UKBU=?TnR-#%}B>%dOczf0=P&a$x(Jlus0%rmEeuX2U5qkoKoUZ3?<{JY<|ji z0ARQOf5@l8VCx4`Xa~!+(*N^~5j4tysfya%quv6j;We*fO9$Ax);ZPghG06?@sN)Y zQt`dPcoPEk)a0K3@LN!9Ncryp|0b9D=k51ewtyDMZ~6bVt202Wn%~L+Xb}f(xqp;* zYp|WRgT3DV76||t-?AvQ$qR3DRYW(i?*3w{m|K8Dj_bXwLh%{8$eK5pqhs; zYKNfFs^k~8b`F5ga{$=6lPp`?^2I%b<}v1lf(jS$IQ1;Jj7sX55qNDS;pDbm)F&s^ zsACWqz*Ef}^FHI^gL%;3S1Uxtguk~^<&VkR{uLZW9CzdS`Z(s8Pq78TXA#Rwr`hQY z6KTeriC8A$Vw~_CXW^gzG&iq$?()inHQXh_UFx~XXH29XXN6`{X~q?rX=s6mt79X@ z0Ixt$zht{Or_ zvzaC)zO5WlJCebE?<6+W<*A-$*MY{n)MYmq(E`YqjV(@1edXsD|E4^ApL+5)E^CsU zxA1vXW(`?tvTXNOK6~-mi|1mivuaFLZC0_O18JjiWB+}9=J>HyHH8bJI_;ed9Xgb3 zdVMzyH|s>70jWA+kHnOmrbCAgz4wZ(0jt&Obmp^1$G7cat-4I3Sz~o&g=X4phyS(i ze}M?_C@mF$r;*mF)>irKLto~d@BGg1gKJZr0Dq6rj&Chj0sK`A@6W&gFz~kP(DM3l zod9?Vu)n)fdo4(+RX%B8SR$c`XcyLK=TsuOVW{ z(gyX_#jg34xEQX@X`_bEdOPRTR~Or)K}-@YGY%_iTv zZ#RubJDO4g|3($vr{Lyc=Ac6pLv|~#~C+U-gG@j3IQ6v^%46e!i0I2=P*sYRAu40z7!&d3Kls&ufAVwx&{wjX=Pkke)KO1`gH*6=^GmUi>_s;TtA6ekr9RWI-0GovXY9~~% zD>Fd5!T?*#>reUb?O?!$YKHZh2VL7w4?!SZJEyhZjD~7*1SF~$g(4!62^kFqL?acA zMG@4C_dZl7oWmP@Wbou_06YcpRJe-gcSHYw4j}XWEiM0l_*>f&bX6-6-E9DaY~89c zZ4y9{Q0W$f>1uhGgJRzUit}o@N?s|?W%6LaTch6k^+AEACE4$&1?a2BYhLNsHW|=T z3ACrRNr85o!S<+aazfi#04*th=nmk!6gyp@UvniuPrxCjmjF=-QnOZdpO&(s+Xj#; zEL0*jCd3>#)3N~sdqyms?hL-`TF~1Lu#*FD<>5G#F%)vM{9+{3v82`_MG4oDZR4y= zzDt_NA;Pm;AwpR48NO_3Tc}1G3_Hi@=RYQA0Jc>asn;3sq2<u{yp9I16UzaCg9v+ovJdGK&qOI}g_v5YK%?3W*KrG`4B14T zl?Oi{>8ts`^9w&AC!zw&vc|53Sqkr))D8V?|LKD?M@P|`lKK*Hy}`4)$2r0ZEEO>) zp?MjK+TamW>{H}3F~vvEo&4DOziAKP7oPd}X^G<*r@V**W4zy*_x_>G z*Lks4HA|@}ETO)ln%!{l;L&wKba7n1fS5H^XRBs;(`BDKcdQo2g=am?i82;@S8*B- zuh{j?odwXkr~3Sv+^fSm$Li_|v$L~&=Xbn2 zdCObg@=e#c8(Y~+zw>H^{%zsG&I7;Qw?5a0>%(;d;2NuoO9=?HrgA)|@?jjl;Mv}Ng+H{ivTNswpl(ES2 z^WXf9Jn|3U&f8dF`ti@x@JexLl(bQ&zOn=gQK3juDhDM3xzZJg3I%Ljpfs|b((pD4 z14Bef5fddOw*@QO;6-r`G5Clb8uhiA^=*I|56VA3;E|avH?gRxpu`sz{yF(*NH^2 zD!AbPkG$q?5DB0y08x?9k6zV^VPoegobnm!5HyD2VnB&FE36FI05T~^3mf&8((;juLFYp{{KAiPdX$(fo}hQ z*bZZqjuoJ#3J4YlBW?M=@zR#RcdFsG4g6b50M&N&zXhIsNEd9Y1VYtaTO>j5_b2z% z=U_i?#n)B+?|AuxWWR5k?^XazRz5(;DbODBA*@Hxih1K(N`{sSpgaGdv;NYp zddSIzRv2Kejxc!_g}nNocL31V|Dn?Y;TS+W2cVVL0E8TXtepc89^UI+$NRWk$x^hv zK!OIqead1pK_wwwnPWeOfz&X&b30KK<7|QD$a5IaoucgXkf@2XRE{1EZ2~{|K`ngnKWQPq z_vpj~E;TqD*@b16k@={ZO$uK(SD!-dIJQXL)HU z0Dk8J;P)N*e|KxZwb~lB+6rf;7J1_vzwXDjYF$*=0eowIL%jd5_)z}a{Jei#zFyad z>%(;d;H6OkvWYxEH;@agpEJns4Pq>Fb7z^o{KBiE07y#3ir8p#vO-~X?lS5$T8>zEQ)ajW(cOx_o|JHUKEbTAKAL#@b*r0BjWG?#)`Y{TW5rv3!|I zk_7OdWj(TEBLT3-LjzO}PB41+ZESnfoebT2fb!lQly_~Tv~!Hg-W?1aoM8C&8yUWJ zKZ6H%Q@LR$#fcq6V@4Fo|ORK~Tpdw_0|5wOk@(61`!PV#Tb z`}=|cd$R^MSU&x20Cj^Zem5<+Q5Hf!xxl)4R5Yi&+GK#{58QE{34n+ZJdq+f81^U_ zkGJA6Dn7LR%YPP5a0crYyaSA*Tp#7CeW1Osi)M|k^D3xBi^ZfZ{|AWGixPE((6xxL zT>g&=He94a`oC+Rv+AUi2S6(WK}FlY8O_B{-r(~JdD|M{4T@=3|HJgqelL&;whjJ! zs{Spo-=3Ct3+U<^pj}n{uJFIyMqqma30tHBYTN784)3E2(ECp4Vcr&zuH1uM-ru_~ zT)zEbpR{HF*cRXq`&T<{IfWQPJ3#2<0JPcxI#Dg=!H#MB_-5Ho*-AQ@)`>M-kD6Yo zi&7QE7|YsPlSAbKFYHaJO-`ywQg*8{j?hR`BobyHcz|Zt74lowmiY|84@^>Ng7F!5 zigIHd@wg_eMk%_sK-|dKYlLR(xHLS#h&3#bG3;TNLK&eUxot`;bv!TPIa|zF(0R7zeWkGIIo(-c5u1DVq{6oP%BLr(T^WT1#2;%Br_invNBe=ftsy;U*jL)mn{P zCnv*2W?+ap9}%Z1K69)%s9Q*m{+?dV*DPx6K2;GkJF)3~zQG~yn|l#5Bl4-u=37ed z9{1i&sOl~w(c-z|zdYZ1Z{Kaj!FXztAQ3FKjT)ZjvdmSq8wmVde;un$RcSTf7A)xo8Eog8CpQ z_i6;Z2DEH6n7b`_(LT^lUmd$2KO4yZd&vW3lb}6%l^xw30@eZSuB87?*kAwH z>NMbc+X>Py@9!oVx;CV5+PWNs9s+|6=*_;VnuA}JJP58OEs>xA5sZfNN}CW;Jfhwh zCGskf;H~i(3m6Mx@U5-@qIeMswQxRdINY5B!q)%8?Et{610Gv)^2AHC1^grJ^Z&Pq zjE;0YoTEnCK-hGF{1zZ?1Km&+&y@{b6>=l(>VG>Zuv=133;cIl>*e!mFYs@-7Yvnu z-ys2L=Ltkz3H^Dpe*pbmN`RJvq1Unyx&j!}mjCC!S>Fl)#PkpyA@wgm{yA}CXelIG z*$8K$O4ddyZ950aR!y0a_;9RuEvl9RzrVAtpA0H34upy`|>3zkW_mZZ%j1-@AjKavFq?Tw7@lkWbpP)6Xa!;07d|eh0c?p8ZBkU_bz*3W;Ub|; zoxfaVzjs)p%nX-FjZjfT17*87hQ#B5q}mU3d56VL9WzZaebr;DthWNDCY zuUc645q9+HD|QEA;_$n-sicEqG_B7TH({Mdy-qO&HERm~cL=y;qi-7<0aedVouKGWhUkSeO% z#h3{rT8Pw)T2~$0dD9cyOK$j_7q{4KHrc!P_!W<3Tra<1EK3p;WM$FjXtO!GmGyXX zt+xD;dSk8U8F+Di0iOlGzjv-}zjNN@9z&1I9E(fyEG^HoZ|_a~#83R#Yqq%S-jcsQ z_A(yG>H-4-I|N37mqR8!*0)~QhwH<20$|GofLu$JUN%HfT@aiDhu+M@zSmw|H1JYa zILlmb%dYhRGHW(KJ!!Q{ZFzo^wFdP{eRVmnMmy3*o$B)9hPeXdDgU5h-g+(g_j5Z! z+N@!t7!kwVg|qzq+ir)J@4pL}iv?3EF?8#G25&t;G+4Rno)RON$PyJ3l955m6WbWr zzmvh6CK$SD4+A&tCD}I82@UKg0=59qQ|DQ0HhIh5z5M<=zJpJ_?Oy(YS!3zRN4PZg z9L{?RgToXDhlvZtQ2ozs5P=MMd57BAfR2_gooh}#`q^JP`@|!+*OwN48fd(Nr;lvX z3BdMs1n36*aaU)6q%Q=}Zm`_V__KAxI2cpKN`MW{E1o=`$xCa!e4L-_DIqXR1j*&u zvcBxE8~uF+1%PUgNI*BLkZ%N@yIbtBzQvwyDBbt#K)v>70d$A`_1h41{krse`q?nY zpnH3Io0IAW9TIv7(QXjj0(yCuWlRqIRRp8pwRJ#5MGY2%^O|W)8M)uzfaKEoR)swP=yp~>KCL%Uk4{y-qXOt|yJvH+zf~oSd0=4pzmF{F*a~c3 z!Oz!^mdc72lJ;7x@|`hA%CIMicz~P z0DfH%U;tXFY`1BGMf6S8S0*FU*Lt z8ilN6DSnY+i-<@P)_h8wrPMquH-WLjl?i|-&UR=uaPX&2{m$9xlfOMTd*Y8) zP$?q1&&Y%^H1@?^Q&YdXlts*|G-?cA zxzo$()6dMRFU&jDH7im zekZ^B=GXF?>MXNQKEk;ZPcT0}g9oCdNL(mkZM-RIvgx+8tpK5W!tB(^<*C2?^v|7n z{4Z`^P5%eTY$dM1@@yZupjpY0GdsfBVE=1EAEt;DU6R1ai~|k<~KqS zRPYv+2sII66d_Y>-6-2qfrc1^9RN4W6K5P5SI~C?m03a=ALED>7>y@6Wb-TLVMPjKM(+0lX z@_&(Bd1AsVt?!nOY`&-Z-ya~@4a_b5fr0qe*qsFs{Qs&(wTA@gY1v2XyK)bI7s&4p z_G<+j=G);7zU|rX1N_Jaf;Tz|?WXlUJ^NR+n^5Sl_l2B>b@!IEr{lv`&WC1338jp| z83|Q115Fch0oIHLiN8cls9_t*Y!*)Ov{_)bwJlD0qbiRAyzPTp$THMBZWLiB!VJQa zY4ZQG_wGTGWY>A$@0^>N_3G#Jy!V0K1xykcm^2B250f;P=F6f*nxZ`vO^G%|$)GKZ zmSoeCZApQKThf%=>-kJKqU=TU;V1b;f4!>;%suN@1`f zuwVfX^i}wj1wLxRM-sWbgs}2LQscANP7c5d+`jH?_DYH^_O<&^9=2Lk1fAV(+e@|$2S-J0lla!P=)*-5d5a?5-J(B||L6Il62d{m?nwL0o6hv_q;ud#YvEHyx)_x! zE!DR^{m$<^f6V(kO7t(8NP*bnF%)VRB}7@ZRL?#2)HgOZKFPg)KiwK|+*to$fyNDo zY=^Qc%Tny=NhP#5`-ASE-#gfzJX{gBx5~@tLm+rhhym|CgCeKj@3FtX%gZl+nt$?3 z|CIA*FMk)zCY=mYgSM3^kZ-LPzi7~UfKS^>U!~(NM(07c3k+2)&(!vloU z8}~72hk&xp;0TTi^v0pf_t*r`KXL+~C^n-n%82p2=d%cd{XOI)_3G;wX+|H+f{s4# zm*<$3mox8m$yy!!pj0z9EYfn0gDJo(SwiE&8Vg_i7LvvG!|5YLP$!s{!MQR`Aj7p9 zxORj7$^!jc8x(u{#Juz#uvh`6<1XM->xTd#@FlA&{Pl1AS_*{E?CkP^8#np2>!0Dn z+k5P|jI6UnYjK5Uvq_pYDl(v|hENPhvc?GLg(Alf`uIVQ?$-Un=lu_u_rEd7_ka9g z`~I!haD>l_&g&GIcQpk-GF9F$sh5B|!u;>V?c6GIZwqmX#R~j~h^cuAWmIwKmTm|h zvoK+oU#~F0{4$<4ci_(;0&E7*o++hg60i^VWzz)26!^DUq{Wy<9G;fcD3tn%npy1@ zt-ga%RqY$yzvVxxzl=68#mNja`bXy_qvMv^Jg=#Vm3>7tE zB$|rGDqlbmtWE+L&Loy%{n-kD8lmaC!i5WPaDT>S9JfZYk=r+V5~ z09VJv0V<_0;V24DoJa>4g5juDF4z$8mb9l0)e>VMY@lBf`D@fX5SM^O-Ka_r4dqb`9N9-rnEgp8z~{ znf9O$F|v}REGqOxxZg~XTLZo*Dw~$D_3Y#LTSnUy(MYGFhCXAFCh(FMZgyb*_BDEc z<2ebem&d#=)k9!i?Dd}VJog;&NB%0d(<4bif8k@KttOueeRc%i8HAl?f;1L*xd=#+ zWA}F0eam?+J^x+;>+t?{20!>-&UD&r2TwaD9B=`WF8$CTmd355gC6%)kXZ8G8`fiW zNOEThJKch38UdFiSSm!4qn`;#ykrq4&85%ITjhn@tIMU5Ms_nzUYNV7Vt>t$cY?LS z-P`)~osp*e=A}!;g?k%YS*JaC`QO~%{d}F6f99h*_aFZvxgR`VqQooypye*S_51D4 zr~dD|^S+a%3pb0wZqJ;q;$l0As6`f|@3)HPlO6cG8@t!p=KAq7y*y2BX9vYaRkot? zn2K zXm>VfHqI=6`?r7l+kfE~e&Juw*#3usw@)qm)raWj)(O`6G!JL!_ZW<(+#jEDyr=E7 zoe}_ZQNRq~D^tJK_0C6GoSWIu5bu%a_c`Zw%ZHpC0eXf}MG$**A_S?r$q!29qG)*x zp(x1O9ilJD`v){7R;GwGP~sHHGFnewpmA>X)gOygb5tp-9EfY9i9?fww9}%$u}lB{ z7Gb}K6~4-^uB8Q-otO+TV6P}&ESK6XzWa;c#`nGBOYjCax?MiGwZ#YS+~dW~d)(~y zxSJQGqC^#T_jc~4jn*rsDo!*4_Y0qYh$8=$ox3;xWn~8QxoR>6{%4T^$&}1rYWHqh zQw7Y*`9I18@X)e;7g2{rPn3vALR5iJB&d|pRf{GOf*3i52Rw#Hq`)j4Mj2&7{XZS~ zw+SlXunhhfX6#TkfoZw_VUxgmdA`FA{d4v!Gx*5igJy`uYOFxH$R?ghcFIHeF>y#-M(bQc?E_sDpnuExDJ;9FNg4R!$67F+x>J2C)M0hM>c1HcsOZsd%B` zc7*!BOR|UYd5BDv!5Q{J&0Nuj+h9~tVK`tbZfNSgB$LH=yu@gg5nwJ8*Zr7MfReBx zp3GoBf{%faBv{d7A$9C4^!vZfsxEVpNE6|P_k3Ba$?v@59f*j;Z~cC2T4d!newtS( zUsJ8#0iuo-ffQj7V7uR?ZN}vYFP_iX-dQ4*9W)pnXIK)wOPemrgW?-Y$y%k8JPUegE>}*^xJss(1-Aiy}`nK=d4Wr6^BZ4>}WXDP-ocBP+@G2-31KHXNnms~=Qbh!4B1pS|IK`!kCW>Y$`PMGQ-T|RMC{q&RlyTof z^pB6mek^@})*2aKd+8$2UcN-)93nz5M4Uh)N%_ma@+<%7Z~XRe|FJjdn3pLhf32wi zT#Y2Cn*`2^{y&5Yz+})v$RLz|rn zLn=Rge^03aYt+E3_fnp0>3@6 zWGEFk^HSpHP|_9_zOwqrGeP1I+*ix0EQOL~Iib-8_Ql&~zBT8oc+tm@iSel3hk<_C25vLNQo)LJ0Qh*a<pWIofEj zDy1_-Oj3IL2b}i-*K};%J5T>yqs(C!(5QS?;d+d?Bp^}fCpS4*|4H$@!CQEVgOx94 zsei!Am0fP!Tt)G`gzyy+9&^T*Sc0{evF;8B!ILD8&HOT*%E266q3B&lS_{x=A_rZ> zzd)4BV9LN1v~r{857-QS+M)CT9?79U*{8d#h!->zNNf_bHtDcb;Pf#+^;Bok+pdqI zn|*fX>P5t5tAxRUh}_ux^1RE7Gmv9wErz1k5}{$n3nZP7Os})`>F0Lgs`B~X8jb5( zgo9|bK%Owu^y1rEpS=Ad_hus1&0pNVy!yQxz(pjUZJ6E;SmH#oBE*#k+4b48{bHxz zGKu{?O4gtqH)z30^+5dW*3R9H)#dYRA;gJy?f%{#op!s_BSlahs^Sz82r+Ww#%&f> z7rq(zsTtdT6xY6Ka6uTC9-Y(9J%W9G{*Tqu_NHuaI1d1sD@31+?~8yNO~Gg3&~bpo zxs;uq+W?PTGS=xVhyLC+q7Ij4vvYanwd$=>*${nE&U<4(DtmSn$I^wz38BD=mb7ne z-e@97nv$(9z9z>v%=356jC6T{Y;Bp=xn-IcR>;JQ;qCqH6OGQdI`O+t#%>CC&2JE5) zohDK#Yp^HRuFV)TdpBo}qgdtsPq(bfMYq(+VeoG<3$z-ws5UnFJ)0WaCN%&&1pSd( z{{PH-!p5M#&J~MIGMx~+}W z*s_V^k3;ffBBx)(m_Y>0BV1lpyE5|*JopS9Q##diVLwJBO&FLb4Mv(MdFKv!U$__} zOF&N|doi%633mZ~*AI~tk@F&qOy7DQm-lfZEKqXXMLHnw_jx)R8(!FZeqFq~hgwPm z?rXwlF2eO9&_LLC(4QzV_y%t8f4}qxeJ+X;?n1_8QkQZEVMj_5@3Iq~S#0tar{z0j zZ@|v-%2=ZB@8Flt(98_q?j!vc!n>+GA@CuV(&s$jO$iEx+1MZW`E~J{mD-?ufO?M= zhTgo%Oyi!==(l6AE@E3xFF!Fi+8KP_uxPtRdY$KEFHRJQR-T3$i_bkbFR836mvIKuAP0wC9a_U3a5i^g;s)!mUduEm-s-4*$ zAhX-GYXlKz;%wiHAV?!5+IfJ(-wC1k3){Q*CZ;+fLU(VkM&pl5>k5L?1O7 z^4sPFDc@bm_gla)mE@~y%TD^acY^bH`~kQ5)z$Z2s4e?_r%>~>oe}^iz-}@OmCY>! zI9~3K!4#^B_kBKo?U%Xv%11r|{7;YifQ$X&ck=FDP^Ytv=Z4bw>f!gufwoKVMP3mA zaokTTWX*P&Dj~znV5uFGBFzS_-FgjbBaF{oo#GlP*;1Rv+7hkvtF+Fq&^)t(>$K2B zG1aoJQRRdRCpd5B&gw0EkFm+qLFB-s^tFw8cWT8G_zRx>6Z!caeVqwK%A?d zpkWNIQA3i5+`IRvXu(8yJkFm-;j`)T&F>NV*m2$pf_MSx=JcBq#E z1Xwr<8q9pgBxhI?p#cn3=n1GL3>+j;(6oc^cJZ0=qzJ19cL@|?sH=$i%aEFIPDccQ zX_nv$!->$YOd(=0yw7%<-Z$x8elPtaBsg!lCW4v} z`^HiN>O4DUd?Lbi6FLIVqzO-@9U7SsihK0yiEEt|a*MS48KKBDXZM<{#d@)f?O=Qag`KPzG+VkqnM|6PLK33eH z`@ZN|4>J+i6HT_SAH1+Rxx%{otox*McJbP^ec|)EUCU!Awj&WDXQRjy;`^75e#OT7 zhVF=1ED{M22cQxqS$NmGe&_)dzt2T=2T?+dV&cJK)O6tiPvE(&?Yjf#^iXhacXxMO zj@O1Mc1o6Ih;!_9x5?6lrEmMTZ~M|26BsXJ3I9+>@-@R{5AZp5&hnt!tPud8sx9}N zw$pY>0344HwDuO9yb*0Ac^@uu$2|V;-T4$B`Q4voXY0l13}X0dUyiZ4&Xx z90EX(C>bb6cnLgED!@6wXGE6}T`YeFvpB2>P(}U=%nFrqQcx!NS(puSIno#7q%?s& zz_;YstGhtW#M^= z!{l-qStdyJ9R?2J*_ptvoXAf|!jA)tlYnyqh|Y^p>){8aj=}8lpm_3n$((U9<)SaO z^~)*?6aE2Z#D5C>+b}Ia>LkQWP+py@o#1}7u{z>N;%>C9IATg_>x3h=I{_F*%UZ2g zjRZJ3iD+g*&RL0cfc+r!Rgr;`nC7%0v($J#cXwzR8iM)xL z8T%1d5@D&|LIT9Z@d*pOWD%mVAj)#8WIiKqck!`SKDoG!4@Of9f`V=iaEk{tf{_L}K|2(14+Mo~x1N1-XI-j|7KAhYU7nD*y(uXo@9!iVPOg#m>9l^$%yR7meI- zJCe+whuyf5Y?}*;upcQlxc*xcih`%#`H6ED?JX8`4Sq4_^S&kbi4sL*RU((X*xFHR zJ85kL_bh1NdO=L&AVMI9&h?`AAc_gg^E3vR6ryopMq;7gdBB6;@FD*{y4}NB1O0=8 z$@i`pNt%$R8G^92wZW~McloaG{H}K&vyTr{Kfmr(OvC9PF2X{SlD>0$7M+hcYuTvA_*~$XV zb1Sqjt&)V0K7hH2J7%`+o z^_X*11b~IouH6bz@-p(T9w-cnhXZV82yuob=L2*_{X233s^EA?e*9=R9$pe7heiGJ zfEVCoGZq>7!Hp4Tw9>3;C9;;_8oYOh~*UKaOQ|)1Vl{Wf(T0(JG(oG3I`(e zw{9U>AWIx=AIe1+o zl-%J>(7JuLUBV?o2}FDkXI*Yb;T4PARiTa1aE?a0PaHrv$j2pFyI+D&aFzHii9Q<77^!5qd|bB&g?O#MH{uR-FkgEvh&F>6o4|zQ{oCI5`x|*Lyu*x(QSy}6PP_PqX-(g_VZx?i4&khl zE%EHLb0hhA40~wY2x{Fl!4bj%m_(7Zv)_Lp&o6cTppIar0zkx_$Tfeu{n*CVEu2e7 z^L8qA?m@3N66?w6zp{GQ{{B86`rQxFAB2DZnC<^&_4D1YqMI{=++fE_6X?dP*w$B0 z9oK0)ZKnjl$)~m&=7Hns3A8J1m+3{%t-(IO*WKXPw_f3A?|y>YgMFOppN-M~&xbUR zkD37JAN=E;Td&x05`VKub8&^dcRYLyuner9?hroaAPY<=C{R3==@kFgyK*2GnyeieF6EFW+)z^zgQ zK%znt7YHjCiH)kZ`}#U^`4(ZIRdm0LHU>zVvna+=h_oysxu8+U`PJSiu3Q<9S$}|! zmGP_3(HN1-xohH!7PXX?yjV_bku5Q`L$BRt3M^5YVLp^%sM`ON)$#l)r|qwk7qU=u%Bd}DN14hA{oD@tRSN78$_LNSzzp3mCkq00MWd5a; zIr|cMpuRY2g>p`1QA-DUXQ&S4-Xc*E)w1#*5{)>N{foI6B1S?W63S8`gft_ZyEb#& z9dmz`(PKFTDj!tAGpdz18?4V=HY&1O&*Lzrn3CEU9p6t8J6-qYKkcR$bJJ>-b(oc|)rkwHoll~f!S(=v+BO`IGaf(1aD>e%@Mmst z5MxZDvqsh1vuhz8^!Jk(3nez1js3Z4cs^tYDEDF(w8H>jrK#iCeLv&0vB4>Wnwej_^Py{Z*r>IAZR{tibp zZx;Xh-oehH_ga#;iPxaTVH&FuVjx&= za{RQNw$FD001=5tLxJ%e>+K8Y`0h(z%769byZAFtemQ^fi7WiIC%=gQ^Xa$qwTsJy z5I$$-8?DaDKiGKr1=Jl+vYHu<&Jtoq-s`?f62NFKEaUS&2o(KZIn@VZ@Q6WcWsR41 z_sZP=k#smh2*ljK9v8X9KuLmYW@Kj;={#PN0NFwlar56(mZp$A90}k=xV^UraPWE) zT~lCQW&r%@<@4O<;t4^T90fiAcJ{DAUivWtxJaZZi>j*;C1MgwF93twEcAhah!y34 zs^$J0u~GrpiGi&=C}5uh#^spr*Ud0TfS>WbA!9%6~kdx7FIG9L!E${pjZ?!waPRwsuI;%l%dCi5m9_B4iTqPcYjxH9#04~YVcwH zbHJtnuE3$_x6I7T5Ss$I!)Ulo<6{{Dc@die{4jXa28I{xk<&>u(JXR@zm$2jlNcIVD7A867DA!sVWT62klFz8}&LkGo#S3s0v0h6bIRg$#(g)&J` z)b~Wh3#Je>&)P>!GN1RMIk=x_*op%`h=~;dCQ-9w_2deGt5==R%t?`Uqlu4L3^6_| zoK8w z68H~?1i&e@JZ+~0z(bIoGPm}Z)aq`Jr@^}>yc{z=8aw=IT;&(zd44Hg+fx2F&ss1)L8(MRtI$ngYIrAg?gwbj}g5mdJmLQe@(_Ty!SaP=P&bb?%!uv z5FC{@4X*t28p4cgij;iGT<6FG!u^vs>G{ z4^YeYHK9M4oftol1c-AYhtuoX5k$eP-w$2%MynbgejYYeLp3M_5gCX`59ni(BNbJ^ zxEi}K!+cBT1L+B9D>V;8nFEq#{JR{AwAYr&=4H=x0er8)##QC@z%Npu@XD%jy*H_zup51u+(_ zEJR}hq2EJ;BT;aPQutls)vIVbM`A<-)Qn9N_UfyH8Pf({0d7}1v=3$+rGI7#r$iU5cK+3(fUylThW*bF34)~i3V ztIadWjIhL%*Tlqd>MU+Mb(@+tCI(`VBok~2!8u=i!8ogjkOs`u1ZUzT`0kMrko%wb zxqVwcyV;+z|F5Iu%X0dhKB*i<^1g?@r8r1r81l z$oqrQdsnJTR>QJ@V7&O^XL-vr&-~}dybC`B{7h9c@bA7(m+9|T`~TVMcuw1CJ0$=f zm`D?ev!iV`nFyddGK;QknsK#HLlpNplzR7fc0Ln){%Z%@_h&=~hh>@V5O{Z4gQU@7 z(A|AFATC1QKPWxdREblfhcM`K{+YM)p&K_y>ydQ>LZs;RU-y)FQNcA*8Y_z|Jb8i6 z<7Y`b&622?&m5Fh0v?C}P+s2I`PaO@@+_OC zGobcV0fl;0U+NY_wSUXx`ZCjtQD%T~sZkoU3OgK$=%==Kj4Z-LtH?HBsfi>&Qk9U` zs#Ig71plR>qs55eQRky0mWlu$%k&Ps385Yh9JlAE?%S*+j5INkWQquwky|cOi&#rN zV$Q_Rc$n;(a+$P|Dj?1v!)gFLj=^%Aj=GDCBKigrYrj_!eu+}a{skf;0U=7YoO0Pn z9Ux*uv05ZF-}^o;`5@3B$2W-NkFXMAvKXenTR8E2e_^3$yYeuT#ereJSrn7$rZEOq*VbyPUa3VvjA+L7 zS8lSldgfcc`J3Ofe9S)n`|9U682sta@r3SA1K&{n`Xi^X^0b{201wxqhz2=<6j(%O zRf_^MZVdL=^8*5WgR1_pbM6lUZ+*=>Gim!W1 z+HM_9iilv1lh5nAdBN?yy`Om_ywgum3ocB7{4hll#2WYyQzSy1`u#-h-ZJI}wG;qB zrNH^5n$bHD(-^Hx1rV`;Ai0asq4X;+dfkb9R=f|LY77CuH5|An2FEfC$)D#39 zRuPEIkoL>S8$(2DW|_0Vzsv#l)9L>8Wip$f0HHu$zmTK*L*|ek<9WJ?4Nuop3~?aN zMil@gnutfD7bA*cs+0syurN&PP%JuUA4((j@K@uAB9 z4;An)mx~PVzbG=X?Wz5g%jB?{XG~bc>i9N zouy-*8%dwg-y=EjIDp5YCnZ3$-( z&I>3?@DS;jDgbqu1pL5}ufGqu`drzcS(8+aK_O^irK+Q|gsqPtc#T+37b7kzn3yF; zPGEcp9ip5wiHq~rx$}{J{~+Psi;v&ini#7wctbpBFUvY_Dr3i2)3S8XFp<=Z4K=yZ z>7*x2VO)>>xRh%Wc1(0jd^mCHW0DlHK%2$Dr4lqE@jzX8*npau*{}5T$*hf5tBrH6 z^n`MXNNF@wW~i1jqO6f&mbhkf^Yb9n)Zks8Bk=zfz>ikH{;BFXPTOfa zB>*0x6^XcB`2?_I0b?SQu`)H|84 z1#m0`e7E;Gtpsq~HFc>YTU}uBsf)B9TO;W-D^NE7(QnNb9FsyJz;C_s3ZLHI{$b{lxHmNa54$L7(WC-Ra%GgU;G|!yCup)Sb7%=ftYQSR@E%W_lXy#~Mq^wdp zGzSz%k)OC~%I4v0nmYKG3S5?lSAq9Xlc$Hubw8Pv&ccL3Kn{WV!_xb5`d9*g8AbMO zDEqG@{S_Fm%lKso=p!N(m>($tLK*p={tU?h4I|~iSPd|g`d4WLBf~%&n+R$wX`6~L z(As%v1?q>yz$B4i6Y7aEnNigytokd6m5kl+SbWuuT6rO;O%pVes*N3Bb42tEiJ$3q z4m1{Y1X>6x4%L9EAjJ-u2FyVek6r;UN>SzokOBP=AT^rNkt6|$o+31ncL1S*1S7@- zjgbQrxU5`^7B&hh~y!-({I-h*G2z@@F>C zt%OAPajJAQ(pE>zyS&oxb3-$BMa0(Mhhqolo4A{ou>CVMVu9}q8XV^&a1rRlfQCqL zQr_R@kiugoghqq>+B=XdAFEUWfy5GWm!pZ6%a(Tu?|2S*-}@#X=$px&Nu~aZ>eHiS zONnGA$dWlbKfec_3-_))x6kv>`>7XL4t6(2yBjG6e1SAygr*q|mFwo>t!vkwJ24Pn z@?9ln-6*=9_VvWR3H?T%q|s}DWpA+)#qC>gI}e!x0B|F5*~FYRs}!6fQdYJd3bd-H znHi`G{eI53eA73c1knEt;2!}k;9nR#^BPayo&o+vwZDH{?fqj>akO)~ zS*Zj#qC!A3P5AlW`}i)e6GK}oA;u9Y033=|P7(lND*9hckpp%Dpg(sgF5JfINtZ#( z=fkiPfLKjgAee~cCIl<<|NCY(7#Y%)b?A_?WZ+C7D{~$9WsbaFX2|1f>&loMklJ=d zW<>HwfLzPU6f*oNlfRGFR}h_44%7kuh?J=N5gb-D9LoDYwC-UdV>+>5qWea_m=jSo zaFvm204bCh3<(NBg%Hc=aByXXh9G75KMu=13KWgT(Wz5O(lPGbL0xL9sfi{g>S_d0 zQIB4iptGFH4p$ffRY5Een2h$1)BqEa|5%s)*Ny!~z&u7) z80Pnv(S8|5`!!Uce)#d_GA$JW)%w-K}57X2bD6k zI@4bOB*Ypq5UaF-VgJ_1mWlL>I$2ZLh^!ecPHdC{aOX~Wz2~%xXOOhaeQgYZBUR2u zL&;)VUUZAN^>v9cFp#oD#gZvq?=gdRDkPR5;wZ8{x_=P~9?1h<4MA}jg&CHlGzG3( z&c*J4^y<~>IVECiYnAz57t0Q4IYGpD!smR&n`Tm$k=!3}H;<$ea0A1+lof<5a~$mM zad-bNcXf;I`nu`HMj8EghF-pftu$#k$P-wxz$J5>1yTbaA~pyNf=3)gQ-Wl84)9k# zhHPw<xL$a(2g zKX5ojKpO|ZeW&a%CE*LG3V>S{!xQc0OqU*L{?bpUUKyFB-B=ir=cB`%!^_T+uxm!`3>c|7Ytb7E%@WM-6`@N4HOW;ZQg84q+ zBUMSi4;g&bYXttkiZa)K8TdEA_X&K#_)?s z?p>p4rBnESihHy#U!vVeXth$7R~BhB+ce`Ri>1Fb$TGB%yg`iKVA6)4sS$(rS#r*<2DJO<_(M!G=rt@a@}w z|8+J1WDZE5mg?7)07a#x_EYHqeu@ByQ{RopMf^o30l~d1m1e&Z?GJNAtN!(7M8kqG ziZOe|ydmDOTp+g+Bq4}amDIy9_gZ9@WPb|K%e0)n9%*N49jO`e&C9hv9F>t+o&iM9_d~A&^I`0D?se zr3%0Wbz_rM30MeNC@9p=n#imh&!4mLgs!X)zYUD6*)*|wDZuhGHlz~~^R=kH$W%mo z=+ZA@xM3cB=?ilR_(MISKVjxK{I^cJ_K&0eCHNng^eg`srbvK@R761e@k3HTgcA6V zL4J)OU_>sAw=YBAfH+DYK+5Bjp&9_IK!2RBC=d@-8mJKhPRHQB>g!NR|D{H>c*I1) zNR1&PHjMa}KYQi%s}VWsX7~WGKC$e@7eHK@(=U+W%9`<_7%3@mKmsUkeccj)?aEx? zoXhFO$N*zO1ub$M5pU_ZKE34xiI@qADqU~5yr7vSypR_>lN_KIFOJt=UnhXc@-9V^ z(7~}I@D@q<%Jp?i-VBp6+b8aP3JYD*gPbJE(Zq39%L~6Hp25O0u@~vxyouX>lEgQ0 zT4_hDLED5F;G!uPFcvA(GKv^64ID^@LkMYuIM}Dy%Lq3wA!}<@g#bqkIk`r%=#VI7 zwSmS*4`*IBoBJ`+$cdnmWIX%q+<9emt}tZDR4%~PnT-AFGw)fv?E2>}T=@RZ1o0@c zi?Jald(GzR7mNZxh)XE<4S7KZyW0=))g;Chjls9t+2#YyV~f6;1$DtKs^JhhASPX| zKJ;nao_^;K1_SQizQx_!x4Cis6+Zo`Pjc(#jj~#R*~krLdux}Ef9!?bll2vQRX+ZQ zD-z&&d&K1dtt|KVe6{@#1K%L<1w%-kwo?M&HEF&5gP#zpm(@fy8JWZ~Ru!=o2pB*5 z;%|~IuhMQWVphuS8_fo5YpbMLic>{Y+1uSEYpn47Klm4T_g8;QCr105s`|Gp3D2Wx zdH#{zd$)e0=pD>{JWXE!ovwK$ph~}=vvKb}8~5(g-QA(vJK+BP`}k;c%H$boqfLIW zS1KZ^bO5tR(d+W~+rONj{pd$&RRGzBGlJbNe(#N0QAbioV{N%40WPfKni;4ZnNCqw z2*?gC|J9dX;^X)4|D8ADd~b>fh*P=$MeXCKz<)lqJRIQxV8@jKJa?_^z8DZokSHi5 zxH9nV#Zd?`GK}y$3kHQiRMEmj2U7VFlz}%?Os2|0O{a5AM#Nm*ccl=R1^(ymhr<#4L(2}6A2Jc`mpMkFhqq@V!K5T2W%SNU z04$LhOl%+`Ii>|>h2qLGj=_fzs_({91)z>-j=@4QKLy}gb9FLvLsJt;s!zWLD2EmR zL&>=xM(Rz%FcqK%`fC7JhUR{8XbL+r(i=w3$IFFC)QFCWFF|9hN7-x9{!uQzXbJEc zMev8Ji6Qv+V_>gCC4fh2iU5&N|6O3D2#|@tSBjm< z6Kcz%#8Cx+aX$@7lsHPc@G`D^AhpU0wF&?t3kF?85@Qc`Dh0rh=(*NhogjdQ?TL31 zi$D?~H6znfTJEfrVKjZ9o0T5D=}pMYxKq`0cq%L~@Sd)R1?R8?Qh_2W>GtiaM!myG zN)kYYft4nLy3pa{KJvD1z`Y2K^>wRWq~&?8uZs_m1!DtP4h3Jao$}5%`h@K2x@EnB zUhZi{A&ro_7MdhHk*2hqu)7;6-tsh-u90(@G>vGwQ<5O->k=)}_5pLo8H~jkX&Xc_ zdTPW%=(&tkg@KR6enS2om$Cd7Zf6HsU$?C1DcmC75}HmCT=`7cTPqD-CrF?d7ra9U zC#ey`Jc;f=kR@V#;_TT$d)7Lc^csb5))w=N6A|g8zoW_xG}-vz#wQ(L5ba7P zB&MdDF0oH`7n&!JGQaCRiE5U4CFBQ#1g>T${c4sslPH=RVHp!ubT<`0ct{gKLI@wo zi{8}S*U=vw&^_3t*V`p{&(_u^pZNI4M#w}&DDnX>zx?Uq#Pi0Im;QR-=YS^gzZ(3u z!Mk7OMD5)M{|fjk)pma#_cl(H0liexTWC|G~Ob{xk_tfATm{nws!4 zcRs-_JYVy5zn_a2&+yn|=W!KcX*3#~Idc~05>%BmP3iY~+`4s>Z~E5n<$M0{pC-$i ze@w*v3*f>d>r|&dwsrke=#=aJY|p~+`9*}yJGXdicEF$bhA-yt{JHPtpZ=8};@AG_ zf5|`k3xAlu`6s`FZ+}aRaQCxpZ*PxO22zm->KsMCkGO>X-VUl|2zT%PZ7zQCzr+7` z`wp(IOt47k^~pDOu^8V_19J%SHA`roTVdg;i?lAR;MxtuDWdaI0t{3qNPwkglmF{? ze)mSj*1rCP{(On#bQFIG_6Jj7znCHb>Ye~cM*WX!&plTX002p-;;@Db;M80snm5sC zW>L*mHU6v^Gcx88DXRKqDuOdH6Yz7501rjKXMuh>?BqYg#sAQHvq*rN^uO-@FC(C@ z)i!jrY(xqmH5JONRDjw0ot2irjK3dJ56o2rOmxvO<-%d&s%=Fv@v72C+`!OW)Cv=V zxiS?1NxZA_cGZ<;fOtp}2CLnprHn~($5fjpNuxH#%H)xLKOd6-qLu@KHz{-ye2yaA zaRgcgts?!E9NyVP9{<>xe^S;z2FDU9w^2sbg{UKEf2~FRhmw35Mej@5z77GrAIbe? z_+gy;FIpo9%5_V?uXXT0Jibti{*M(2XsAX1BWQK}Vu+RGg$|VtOppL$qrYLrgo-p7 z5hIg*JfZX{hL4W1`Jaeduh*+80qirZ=rFv#NwPTiS@OwSSeA{-{WZ-ng-iq$V4tE?Z zHph(AA|`@2=-UjN3j&ivew1*b8%&7FohJ#)6qVmM$)w znYB(j=zC{&(TPpSzOP@qvaK%pOpyHEW6dW!UkDTQbLY-wCVoo@x1GxN+0Z{R5WZ0K zGOq*|)#H78>2VfLN&QU8kq$x#Ci^C7AJ!jgqWJjZk8cl(1GG}KiYS{~w@6${ zr@ch0wSW%={Xv&r?|_ef)%e>X*(qV98-E@F3D7#fO6Q3S zwAPkMI!!cnN2dg+8-b^nx3~G=t($)yICuk$b(`VVUzhxc876;&8VQis(gFrGQXtOQ zwmn!S0Evs;5)=lH3bo6Vz8o_C)7rKUNB?DdStjMd+{M1}{!Ozeer(b@BWA<$+)(a$j_W0uQ#2MOyA+Mo!9px}yx}NJxfdPhT|u_fB)xiVYzPQ&?-rZw z1{VzeA@KjR_vUeyopqi6`}=*)xl8TU`FU<8M%L8%7-*#+lI`K*W6^5!ogXh=EQ*)=qk@uIgIvdd~Aa-}&R5Tldzj z>Ta?y2JGkcy05x*>)cy+J@RbnEHMPp$;!&PcbIH*~Nxb-CZJY@03n z#RU;b%xqfgvTvhpI-}iO%}+UO54&DIpb|J3EeZFzASY!*d&)QA+O`#owh+)c3EFxn z0f5!TP!S&^WDw&>UE|c)<$j8NFFjv%k_L|x&y-*_oOU$2mCUCP+v9%h*s)Fw{(tl< zu_I$+(x2z{!U(Y4HNT2V4w%usj}l9`J_- z^9DB>ybt*Pp{u^u;6Ijsp9lW1yq+s>=MsV6z2N!3ur3e)k8oYG?}<+t8=L(2)a2Hw z;@GsjVze{Fg8BTTi*U&w(q!julM<9DwWC;ABBhIL)JOCeERqrfNEwNg4~tm zCEj-ZRs89%|G!+lZ41_HVR>HE^$n2)*6yI4F5ma!{oMLr-_6wWF>;@;f(MsY@Oc+e zrMYkhQ6u9F%iTc~+|c=avlSQEd$b0O~-(d~sg10GUj|_r4m2} z6#!D$1lCyrR)YbhxIZ%ZSuGU;D&>9Y5dppX-P>j$v@n)A3DSGcifMl!njmr2|1V-* zh64e6uaO#(mt@V_1_059t!V%lzpEgCHdwU^4KcbRR1C7TDCn^Wm6bMK6~r7dfw7e~ zcWHu(aPim_)8aVYZjz=j;)+~f6T>CbxT#W&6pThv!~nLm5PveBeND+B&XfYFbS9! z@{W>Ua}8EKNn%yfT_*|AGg=QUN26M)Fa^|{kxfJ5?`Ok(gCwyjF$9oWb2P1;?Qzb1 z^-orCZbpPr>*m*OIJr)$UDQTGh}-v!O;4{?0UVmA%kg7}mzVfwuqL}Z@2r|GEEu^o&}oGpI=fc*zGrX3e>TM5)8#1&I%JLeyXOw@erzO~bB ztbVT#wgU8qWX>h1D2YpGcRHM$ec->|d;c9j|45!gfujPi1FitxQ{)ja4eSSg6c|<) z{08v$^6%5-_U{3%6nLG$gBPIVg>``dcm%6jtzL26(_Z{PQ>}b{dSc5y8A$9F5f+!` zxcj~@v$!-%2!Sl?uC3!T<5;)Fi@)Q07#XQit)zu498giJ)hf<8lEmShlBN}sv{0rw zmr$uxSy@@(*s_b#$UoPvl)fo*_VE z?i5!%``h`GJ8oyHR$rq6@XapW*##ceBtQ{F6-^zeJfhp_Emx~h-#*RA&MnlYCrHOf zaJ5Qd3E1FYs0e>^|NZ{2@4ffOfyYYF!C=kb*@FN4kOH7n5&-Ri^Q}@1&>7l(BO8F7 zr6pk9+S|hWV&Y0jaAHys!;wHRas;oAP~hKKF;S6X66-KAGbt?zLaFz2t5ZkYAviTxVa<^aSs)piATEY$(7H{o9c`UmRtiYYsy zJrzKd5^!r@Y9F-c)fe>xBtSXECzK?WmmYv00Q;p4ARnj!^sAo#A{W5-u3uc2K>xZW z_}5Sb{}uOVVEW(B1}H$kt&#!d%UB-gsg zOtVdrD)nkg2$8Bq#5yECM?y-(;e+AKbHpiWG_J`5liRm&SBPvwsKz?A(@m1&j(VBrjD{&e7g7hK-K!{lHcS z%Psigi4(XjRYvm+NsXkQ;Z)G7BRlje30a5HyhCEbgbJe;sf5U>7&zML(29X(ZJb1e zb{2`-H+5DrN8H%U(2Gh5;D1x&Xaaa_WQIQZvwqA4g+^fAuZc36oO;p*TN@5yMNHuG9qGpfeajmSZ%(psA zM`g9L+0Fvk1t0SK=!v_2`p!FVeJ#U%r4OG7xJTd}<$LNW!0Unk1pMvLrZ<(BzoFc2 zkH9+w?!EvSFRTj$z$05z)0=nv;*+2DvfIYSH@*7kk+0~c>Fuk>xM${PxZ|!{c;Ljn zOipiSda9_4^?62?byp9P8_i`#$EJAUx4oP#nE+jM7LmUO_C2CUxx73dWB8?&xszv?sf&;; z%<=zy#|xRe`OBR75_~qu>k$AaAyE%XH`@cvs zb8qq3={F9DNTC97j@IHlQ@buKmT=+fd+Nw*>s{p;Ko- z0pQD%og)Zv;Ja|+b!0ETQh>seO>+rOoPd);+MioM5H&MN1)LQUe=A-9^I*lqzf=iW z@r@scr}(lC{IX8^&Us|_{fWP>0qJW%%mOE(kT;<*UZLtED={HdP7o%RsdO`{so^M|nG)s*c? z!l(mHCdjvLLKpsaV*((}SDMag2VxDMpVOZ&N%*2cv?zO~FFP%%f51I_P(bs zEuHyAz7G9V#lV6u3H%pKkZvy z@l!i@@2lPVg}-9+rX4uvSXw^A9e00`lcyixvMa9RmEZf*?7RF)10R2(-ENWR85Se+ z^D{j8y65oBZ@G$ZdFnnwh)hn6lO(S6#7pV>?}NfLO;MK=znf93)^W};H#f)pnFYGt zF8}hoUeCnD)HV_M+eaD<*vMMHv3UGQ>uh_lXvXum)R<_r$xqG^T3sxJLbjiK^2HU} z51yhsbB1hTh0e)2Vmn(0-^Q|>zxvRB0i8tU%2T; z($yWXATiQ8y@2Ka1eT^jd%!vJ0#<>&3du-~`qokjuyvBk(-0I8P%$pZY#XOzPy(h-yS! zVVsd(AElTV#aWDsXo6W4EE>e(dzDNIxw#b(S5wT=5^=Aa{;&7Nb5;-k#uI<-+XL2J zJ~*Y=MYP7Z<=4%d_D*WN=a{yG+IG6*_ zlbQD`=wkE|Y}f`6B$nZQ63d)`IFQOeDE$vmk^+4dKmnqo1XO&f3J7HgUx;Xt5wJ=E ztS0$;Sv&Fft3*JbC@8%Dy`Q}tfO7IbU=t`a0R}<>i`(#h@L#G1O4ULCerrIr-%3!1 z2gU&lz@P#GO0s0&G$8+veffVd2-de?xHy>2(DVNnuV=?pQMo%}7bUJ}JHcnK>xF{wW)lfyE5S*eu zV=)g@Fz!}i7GZzZpgJH#Y(W?YGzLxtIPPJ|jCSafNkU46 z#+E8!*DlOANqxphy-NEP4>H=RvNEAFd)n=lAmw0A)uEc;L&jp`^gACodgs%#Ec^0fZYF_iY zck%phdkryo7G{sFndpiLjm8Q~OY<~Z4ZijHFJaSEo#jS%73e34L$I@j0 zi^fO!(EtC_9KYk%;(rZ*qUG5Wh$fu6>&xuC>Ph_Nkq4QqR@Y1;{c@9h>FcbL-zXGN zrGSrimYRf(NC2lKBQRgwXnp%B0@q$D_>P)Coz+`Wt zDrhvw%FwkU91uxYU%idw?i)(r2P*Z}Oz?+6HUofK*MaXIsD~jh{}36#0QhIkN!C~f z*0uoXIW zZff0FNrO?y|Fy_;$Vq4x2lysufBzOifWtWeg>QVIN4^LC=~)2^@QH@lw*drW74%yq z47LIEYwg6vArCxdpdN8e=pGVK4P`Chz%-tqh>s9d2bBQ5pg#&AkM=-(-UsuN_on`< zU|-718MG0s0{@b<)3r5%CHPl*76A=HaX$;|f`ws;zpi@!SEv8Q@2Su zjQ#pQjZ)Sy_T>LP|G#L6tXee^>%sY+|6jFcL;n8_$$+^pvTVXEMq89|ajf_v@i7q? zYr&!h%)v-q@;<>CNy!?lM-mbslr)=`k`Vx570jq!RL7rhPt^)AJidI+=WAWl$?5fxKmQ;C_ zDA$Vcr9}9ju1d8#PsI`@eTq~Pqy^NBNKXEN58(5R(N1KP$dpAUV&r5D9B+3x9oux& z(Hf~C4m=rIClCQ`K~f2fZG%=a!B`a*mhL63*4QqNiYm=8ifh%*K8-zm_)r!st_0C$ z1`LOV4z35r>c^beeIRpr<~N-1*DCd|7CUUaI(D1S`R8yjzUP_)o6Piz2$LT7h~)Ne za&z6Hs`_e3VwzLPa-55)Q%Ng6&r;aGApzELp^C9dAVwdWb90}5vGk4A}p1Ngj{@AZRc>JqZpFVx;=gMQ7|C`GLHv?ZPPdOLXg>``dcvJ|0r_}0W zpMTmjUiOA3Jo$Rej8413U3Ywz#HHMQ-M)~gV`ANRx6>nl>WP)zH&4~x@JPQa^ zW{%&_*w{4tuDqJl^KF(^`WB%WB4(`0;ftUB27x54kXEX!teoL9|L_t1^drB*EuZ@n z#?GAP+edfuZ}&Z)cU<{m-gw#bscP~pRsGdR@9NB*4O{=_FawbG!fj%;>`d|{dH%o(~fb8DvO<~^_2|4gpk zRPB=vj4SperF5hlR-)UDv0kZ05%Q)902kInE>m80MViQGXVZMdq5x? zruq*B0B#fnICxz{tw`7~!!j`%1^Aa0M7kEqRDCy!%fu`v;>D3$#5>EQXb}b`imB3` z)Lu)5oZ~Zda9}#z&jDCTMj|U9l9)Ij3t4#~GbdBa=-B`U@&H6*Po7@*-8DvR%~V@@ zz&7?K`fC&c{kpwXD?o3e?gB~~?AKEQI3J^W6tALQ=!f4^;i-0VH4;*&)!9m5Hr*yPvRQ+zw=SlnKTnyeu(~mfJ28QR3j&W6*DFzr;`MnKxRg* zQln~0*NnDzY6(&+oFxk^0H;%B z!6m$+)q=??cZV*M5^;-dx_Ll-U`IXS1=Ue(!co2d1Sj*rbZl|jH_OK^}-~K~(#mE@1YDcz2V?J@5tQ(8f z4ht9UVmwW`Mjg*pxY~r9(#XfsGaQz{SmM}fp~wi(ypSa~GxCKKd{R{p16#!GyS|3x z`fvQzNxsEGzC#mDYTXl$Xc`kU8|$49E+ir`2A3qUYKeMZNfX?reY-cxYH*dLk|4In zuudeN{yH5)eQt4SZvXt!smISRo_gBi^6ZZScl;BL`-8wU1fEi!GA^tO>jDAr@b^FE z&mWnd-u9_~`Q1OfZ~Lw*2qDM0gqfN9>2}-rkn`;4zJh=A#&@%8_oaBBOt=N{3lU$YXEf&p1jlH%!Bu``>H4NA3pslw$^KXVBsUJ`%e_^&Hrl< zcz~!7`P#l^2CM(1s0d8QN2qU~X7r-1jPBk_XR^+X_uTu-d}F1x4uk)}41iw!Uu)ph z9;gHi13`dchyZwqb$})-yT~lkm4G1xi9roglq7~iqHiMB_hrR$)rd+ z@5$7)KdooI$9*W&ZzI{ioKiA;}GbnB|5A^{It~ z7!zWQM3m;V{~E)V266yYYu4+Fcdj0LJ@UggfZnvZFGG*fBgK?jVvh(YfqpU7E-EI= zgnkzzQF^t1Vcq0E7Lxn|M3-qnaWZcf@{~!21d(dD}V6^BU#EY>aFs2=* zsc{-%Ng|j1-cQL&gwLBXpDNFG%5wBne23Qb1TE*-p$;P<@rsh*gP?hrr93i<@C9|u zR8uaWo#Cn5MwkncW^D|oEu7CdqRJ$~^;hiWDr>WxH`v+iGSjIr+VHqmq~$%gb-O(A z&F``ofXOhh|Fxf#yR$|9hep0cAb7Yc>u}u-zrc=%x^sWgn{3>|Hb) zIg_0Zbul(!bcmeDGLB}Ej#pZ>NL$D53CPm zyycc$vA@P>Mhn;Ol`T*HWYjW4;$a8h?cMv@nyXnwM9m1| zg7apoNz9yvn1~Vtt)-^5;WmJM`(B!;<+Uhm2F+YrIeq~qU04^^H|I*ePPaR%%KP_T zcJ1q4`tl!Sd1-}qdlBanjvxCfU%B-YY};`W-~Fn$v2DjibUPg&5<(!v!0}^uZ72zk zKsq-=J36k|b*UjHh19=jz*<^rVrFDnjtF>P5CN*niR1V3h0pyN$BurLCyb2o){7s< zQ^vQ`B%y7P$50+(Cn$zl;M&POJgaqv&z`yGSIq3Q50|0r`0V`)NALf!iS2t*^93=U zd(UO#BXm3EeqNR6BZ+f-;@*3B(Un)SlI2tozWa(R3BZ59`HQ3@HGc5==V7f5dG4`1 zr?zK1TCIQ?d$&w;;JMdvbEAuMuDoeSj0I63&hfw(Kh4zBujlu^d^@k$doiYpgg`d8 zNH)JrWz+xtd?b;=3SijTLle(-U8lHO1x*sFTc^3rz(Dm-`l5En^teMA#aD-Mept`TJ|b3g!G+0BdCaIt2c8<1oN=mklWb3KdaA z%nQ;+STwU06}*-~+v0W0P~J07@Ic zO;+t}wN3}r)l78GKygVe#t;-uiWGY3nn)5QGnGW5NEXeT;xrbukv@V(6C&ngPX$oO z-$Ma(O`=5!;zZ0u#UvP}Qq~9*4hs{5fEKfHQ!AqZ%hz4R3^gp8qE;vkqEk^-i-w6r zOc7gK-C%vW#XuFUmG6TAVoeN)DjIvWh7k)u8Th9G%7y|hC;w^zQ9t1OAG9-uo zFzq)&fBH{Auwwe}%ISX+!Ai@8L@>j96RkuMGs(nIE3+A@CSs-kKQYyoiAK}8V46-E z+ymongZ&1F&Pf1-3MZ}2JdPbG&2#0!gQm?9{$gQ;t3`NR zy+*y8vAod2Z`(vtt&nD2Mu|jqm={z%olv7nB!tLe6|PAubQ9&(r{U(w%^Y2tV_Pyp z_rwhM?c2*rG%gqA$0w)wvBf5{Gc#PeeGd_+FSl?g@fL*|i&v@30UiYuR?d(n^YRju1TEZi|`Y_Y@QC!8@wT{HgnS=Hxz_q098<9X^J@@>1WP zbmGKmRD>+cF@q4`%-ktH{D<%3k3ak?>~7EV`&V4cA6<4W`^Tri0%l?LC@&$B5-5fb zhL3@l?05n@YLnw4@_Rt#VLc=5_VL!znO|$n_Eim8o^#FAINeY*rj>~WWEDpzMAYX< ztA(vJ=`J_%%MHH&lFNAMrI+&VKl~V+`XOY@jF8&jrmuml2s4W6_YNnRYE& zhTshs)QG_)F?D#t-m`f6oe)@m6 z8=^QL)m5XmYOyE(FQ)&at2qzw&hze&w`MG8!f`RWVoV2RQ9>b8kCD-C6Bi?Gg#1*( z&Sr~$bdFUp3W5oX80%^2_4*I*7HRV?Hdjq3W-`pVjRhR zWlGyJ+YP?8^_s1<^L+=J=--R76eaB1C^YcMkq<7a%AcZgI)<=!_f>lNH{(J0o~wW0 zrQT<+K^Rjv@>eHLeEghg`;$-j-s!SEVWZ=BiCJ~bI$n)LdKn*~*O71b5u@ z89V&Rt1rN_3+uxA#v%Y7C!(MESFd`*(_j6Xx6x|1X*Qa~Xng4lf5{z(KgCO5{sX+~ zHE+cw4i&+v;8ank_}p{i_}z%bayr+;cFO7blRUAqomw(V9=&bav|S8iX66hF3(MSj z=lx_^PN$O*qv3PUpZ&=P`Om-k(@blJk6i!leE8yhJfl)0w}4utLUD2!is7);-%}z< zNemp=^K=r?XR7K?JlrS7ciX>y=E1vzCWYw2Vq{aAu1-587JWX;-m|q*!FRg_cG7-b zd^gJ(U25^J7ruZ$_}tBm)T$tYUun{Q;1r?V0far1_G(R7*01TeG1Kaum0s$q%@QNfQzzy2Z0T?Lv8wSU^1^}O}T5lcL=j`eG>(cfal=bTn z888I!hXVj*fDn+uMuCCGfsL{WHmV663J6?Fa?rnD=bZja=^By5RY!#coMKy1H}+#om6 zBud!?KnSZ9bt1hWJ1y1C8lzY*i9g6-y`ESgYUro@uLsZN&yob70NYXgDlt&x0u)4m ziZ22J)yD$B=c3|OB`*nqT&48#<8pfES5M+q#m55p`-pl)y!LDXs26cXo`CkP1*?RF z_QD8PLI0Y^QP>+al)-;Jl4HR8uLIuyf-sTLdtNo7A@;-nax0<*auZEsFZ^#X{l91D zSS$ZOKOubZphOk!GovZOR;P3#_y~&_V_nBq&6z=&A#m+)9+ZYCpEBcg>UeUJ&?Qjy zFgH0)mL_b^43{Vx6C?(tZHL z+(6)r!D~P9LHU83J}962>kmou;~$XL{;SbNm^cBO@*_-%a6OSHsPZv{k4&fhuV4RJ z`EqiSs?XVPP!q+}F_U*`cZ949+3`Es((tsW#uy6$(JHPDjbQi~X+|M;Rk{j`nvu6x zklG0Geea{w7^S+>!a9poyyq%X?%BWJl3Gf(AL3MW$wB zS_@4@Ye|ed+as-&miT3Lwex=GoVe?@`@~gGV|i<5tFddNZSq>}(<*W+B0lDF4IHR! z-Fjeb*OfPH`DRFK-}9t5?GByx{}d#Zq~6b ztW;_mLnO~V_uqe?(3ieD5cluIV=$EgZ;0C z1Sq5n#cj8mEpEE`*4u#l9^;?8;fef4sr|#?J{y?$cLzv-;S7LymfPDX9Pq5`10TRA z!V1tq@ey(X6~RO`8nJ96C_q1Ai9kT;n25tfSA{LZQ-4|SWgo5pTuTfL0_Xv-F9V+Y z!O8p@f4=l9`v$@IK(OChB|u+6FnAiA{tqh%*5nMx+H8S-U|^r**svOKjk1Atfrvwm z0!8&*K>{>HWKp0A(iU}HQ@TOTM`zK5(5w0r?Z57cE4u@Q5Z$2szr6Ik@85nKK&7%d z>fDm4TPc8Kvup#z}rGh2iTN(uH+ z@kI4#8BW-r{GV0HAhG=EqzwMkq76VSh-io<8M5B{KQR3t3jgZ`Gj=+ep1Na;EIVNtWl}wx>zkRE$dU&39=y>KlusuKrw}Hm z$Jm`m7Ut)vJMfd^EJtIf8qO8_xLUW(k`L6{O4H>`g`8U}Rc0nf`O_FVIJ-o+vc{5( z(ydHVzh{m=6!>F-OoSh*)p+HOP0UxSJf+>_n$RWdMqEruPMzl1sYU+4U`d4+&o_AH z@)G0SSswq^_uBJ!+{5E8-b=lEFUx0+)96B;Wmu&OS%+osxh;5pzdFWG{mp;or=E8i zAK$;1<%0)J4<5A2o8D>L-uzD6clur~ZopV#OjT=qrv+*ee%mE{Y~gA?`<{2mnYX^x zsu5lpU?fJGL>5Bej7-tlGD?2`88mdcvLc)bP>VvEX&i(06Q=Qx z-$A`T$;yEP=v|Nk?Vsb{ZxO=1H(V5#mG%Mn6HnS6kziij# zZhJbN)M7ldeeX4|-TsY!0B)_tj~Zq!sX5nmJe-qy3THanrwknE%!RR{$>tUJLvP@Fw6pfU6$1n)kxGu)c}bqm=>hf+R^l`sTO& z?BusT?V^dQk zAN?p@?{VsICGd~PD!{K2$a`kW!ZA#hfJcc$Qk2XB&)<3#w=bU@IoVnKEi=2m1Y8ek z<=xgVpZe;pH(YYvbDX-IvY9{hxG+hz*e%c9txFut63;Z!GM~?XnI0{~HAWvZe-O;J%#a-dZ=Y z74bA3j07V?7$Kqof)ni`vTQMog0#VnKyYA9j9i2&rryMIEGlAxN%;voo5x=Z^^X)7 zw0Oy7t;fHl@cQ2W-t`P5VyoW&A_UWlfcXu)|2J4Hf_j8^BEm?C?{kZErKfxvB+VNmCmYOr&9|)mS`aQ>0sX(p5xER3tmY~~M2c99f)@Oe1QAo#WkRqTIUyz%F%>|KXof{aF##o_R+u3a zqR=mFEq^%ay-8wuVJu!9)79rnWBJ#Dtrh9j7)DegkwUt!y#Paclm9SGT1Z(RC`iB+ z3J9Y0)DE$b{=3ktP81440C7>EBvFzmVv!J{NNS=)(GVp{6tyU&_g_TJIUhx8R**wo zdh&m0QcVB9_O-(^Gh@tZad5q@nsLMH8g-@QI z=igm(DL=m%Le?R;E|X_kynE|7n}g>%C;S^rY3$s>T_@-G)@H_J8u#yiI;` znU7Cz;*zw^lYHdqOAU@{Mr*Xn6^Y|ppYS3Gfinb7Da=cq74_upoG=1DK=lXT#b^o> zW^8e=$pO)^6eCM?!3o!S;}VH{E>Z5By_)u+S4jXk@OG=`+Rj&^h$pQz9d zj<|d$zTM$p)kgSafC=9vCBY|xCMnejO%=M)levtQhjnad@xR$uZv4Dl`+|GE#{V`3{1EU46}_rfACXF>Mw+A;kmnhB z)+Nh3$G!Jo1U?9S#g`a2UWBL`~^ZP;>i;t6$+!EClX5% zAi<~;Nj1e{VA*>-!guU^A|E{RspokMuK|AlVLVs&HRfi1Yh~`_Tk4y(aofTy)x?o! z0TrP#ImVVO=c{KHc=^67XnT(n<^5my0@q)5DL?tVZ>5!c+Ia@5gjR>p?vPH6;YR8t z^%{)_PNA(1(--gHii>yQh+MmUE5S!lrE5jG^5eE`PV2@Oedh)&o=nnOlY-CTCS8h$>7?^7|kC3xLmlgM9Yl2GxIY$Oh2!`MWjP zqfY>Y4M+e#B>#^OW%56`w$9RCnq)ciOcTkZn1-fK=wfPEToPo$uo}dU2nnW5!xn+f zR=j!I0*RF^08m0Np~ne;X_0R>81T0Wv`bLe1OAlfMM{z&_Hn!wXwg=|{y+#IyD69De5?0gx*G&G^_kY(wR9}GmA}CN+Z4nZqSdid~oDEz-0t6Sm z5_OdXAc|VZB}U0BQPfOTqG%e$HKV$bC{0XV5&kF1n5kk(GGm8p7a9MDy*Ce&?5xZF zKi}s$r`Fz=S$g(0%OoKXh!8=7qIn6z%Zm;I1`UhRmrYP{L!?pMz03tFuLMC}(4YgrQfr>ah$I(5!- z-{1Rt-^_7d_y0~xXjGCn{;oa}HP|V_V6~5fK^;{~gfieNtjh?8V_`T^o(4P+X8D?_ zutA|`pvanLlWL=c^mLQ-_fVglV^BjX*5iCazENf-Dll9KP;q24P}Kq_2YVSGJI&93 z`6$mH+R7J-IqD;dFE_}|CA@90pLfME>oWmAVhpTX!~N4UTv=+%Hd)!U-*-^(&!{&f9-d5aJI=iRCqv?hYT3+IZ^Cl{#Xh3_wOWr?v3m<%A>I( zLqd?GlN#UKOTjp5E}=nzX4s(lu%me?_`)f=gCg|<2ax_fc*&%$^vjLu#>PH4yLsnN--)g6G)RvcmpC<9>->XzzE% z1CFqwqWzzFY`W-%4<$+CxkkuH(D#N@5BJLhJ&Gykip6AVYWehO zcH_y~=9!|Es1U>v8L!3|d{&$d0z(pc*EHf9xth=P>^TsWhOaFxMK+3xzHGC27M#fG zsi}RHCurLDhvx$Sr>ACFJ3N4_I@c6~;Wt`U{PT_Nz(3}4h08Z?*iL`n8p1F{Qd{rE zOL!DDiJFZK9^EiEH~FIJnTgMbp?OoeTz>dTNciOV?==3cCEn*)WB=hDqkq)>yyw4& zsM%m@YL-f+!I!`IcT7zj<)$~hi(MD(AqWgX5MTpKU~MadJDoUF&LOiUajpD!+g z&NzuE%}w$BYc3)2u5~WameF6Mi7Jy*bBrB7#nJos^Qs^JAwKnnH?rYd-y(@3?B>nT z>bW;)%j8e7Es4K{MHN6EM;1@sq^!vC`V6<8yocXA^w0eMBcI`K$L^%=l{L9ufag5k z9p>WZZ%rOLFc#Q=W05YAA*zTf-Rp!hd!i(v>3j72kmLz9Pgexp+;HSy7oYm^tyju4t6T{NYs8S#VZ@Ws_+q7(9U}HncQ@B9(pn z@F|7znDWijV`%t5t7m+<8KAX!pH`P`8VP7ZpBhp*FDCG@3DZcsBuR7X#rPzRtaD4P z0I9^?%cA_wfEb6AKcHk(l(BzMo2ru`xDnH&|*#NPPf=j@ZHWb}lLcOoDF# z{>8rk#s9xU`fuE#@t?CUZLMf|DLB_s14v8y?@|?jSZy?-R{US;)ld!!-q=vXxrSdf z|9gz`|3y|a;!zV&_YkNfr%(~a;aLw9G7too84tYi4|L?_UtnA;_r;F+LXjPjqttK= zs$p!Xk0=b-L_&fi2m>Ut6lN+sssV#4RANiNZ<6#DaYKFle(ZSb)KRuq!57yOb?4IR zbv@x7Hsosx_gcfwe1@HChIz2J$WRmB?4i2`Wtt?eigSXilo+3A@a;yKdkHvA#B5D@ zsOGr6(&XlHlXtn0-*GX2V&OfZQv9yM4K*yQNZ51;AVvVVV)sry>fQE8k1p|+5ouw63rT3RV)E?Y?>e{5T3sW!67bLyGTC|P|8)aDe69)Kx9)q8rak9Z_tSd+mv)}#qn-+U zeQ;pi<(FUjef0GXVMK7wk+>M=5}ZqjqloAJ$dBIK)M-QA?70knZlq4Q`wKg)Nu=w%dOm&!ADNag|$7ALOlv z{*`wfzLN)QC3g30<~2K>&yCxEkV259on@eY`=Gz(pg1Q6j9 zU-)XNT5o*h@fhBH4~YPO4idnv0{+|W0LhBy&gKEIk_fnfeX|?{Zg5lr&w@##uNo>i zBZRHAKJSH+2qn@0_=+eoB9*i{Elp7xf>cD>@rA~nS>a~6%zY&>aE9UDN&sy-9QId& zaI?A*;4(wNj$6lLtNQ`S@^u%jJ-k88koMzFBSZ^e3`2nP^_To|#z?2AR0e`Q~xBA{wKLFD*1=O}P zezN$Ov;q8*;oc$u7fG-tX?p`K5do5b#CVh77lC{P?PU@SiF7QdkDH~}dz<$7(;@+k zS^8XBegkdrFN;Kg>)1BeCLWf7|MveTnxy}~_iYnIk(TkFs1xzt(Oz!*D_9@52$#j) z|7POF#;NoFV)S1{CCI8VxmNYRZT>gKg^zPp?C)d~xhI-$3e*A5d2^ksAOSW6zr*(Ta(a!g@BpkbiTS!DeH zh5kIRbqRk~on&CHga&zB_b_qXM3RK}8Q}{e+%1NB)-o{I&+&m?778J6$|gKNZ-~0P zsbw5-x50IXIA5TSW!4v%1{S&<4awmohpWfbwTD@O$y%9daxBz}lpR#M9CMXk#wPFK zyMOVU@|~N1Lr#v4%CgqM(f4cNrcr&j^SoY#cZUIED&z!?W*k$ujHZ?QYj4z-W7up$ z?(~j)7O<9jn8W)JQA5Q-vo18vFx7pd#O#IMkbYmKasYx%onkjot}&2F82QlebMM~0 zYKOPtw*vWLc8X!0!b0pg90cSu3FRs+MawzHp+mbWiYW=&EuKB+1LM(Lrj!YSyr}Cp zBopXYXyEm`Jdo?z=37pBzsT0OucDfY03Yb8qT@&Ck4nqsPW+HY28|=DGXMFLU>ucktquzM89_ z`8)z^=96EpG&o;W(nNYYISP$28oNQlx7LSG!3TSs8KI3@T{SWNOXy$%-WE= z&C03MC&T9SEU)^}r}5GscqToKCbDiF!KIgiwdtfe2rxrK;Fs#(OC*3NCrUx!fqIEw zJoW%Teem0SW`2?_-5a@S=a2AnJFnx1)?Pt1Y4X8GKhH;xewk8St2UD8mVe7mch22j zpPTwhoXPX|2M<#WQZsHe76elfF^yCmYbqiw zvojITGSJ@%ip^R2=sP3#KBawSD5+H3F2i{!@p%JfJK5}Davo9+29hm z@A%wh=>;7`0i9}uv&9*np^k7M5r|WyB4QR0ErTh6X^3bfm zR09Ms>rI1ff8 z$+%cjgF107&}!5rV!U|UlDk{iN(Jbwcqby7w3ne3kLR_clHOqmxI_fFmKq>ljP*kj z@g{Cp`mqvYZ45SsG^Q^l1#FBrar(EltR_ZjuiJX9#E4BqC0+&i$AU@ha$+LxF#b!H zWdF3%1KR&{JMzysFUAR`6|tG_C-FAjZ*6nM#Cs!}?%z1@5Ua83(yG5*tp1x?&OedW ze_Ck(MZqgsK{v#)2rD0!Oz6V=NPqQuxJD9f}{Nq@H`dV<89_NQ6e*q{qgL z_vCQhS%xzqad(bQ-5CmXr8r*Y6pk227^l2&E*8wX_2jZS-n3BW*7H}&5lz(c`4<_78>k@(NQ%kiM6-BTmR?DG5$$}`!wR$ zt&;JO@s<l7|`3ICV~g-ixwD8~U&PZ86VA={H9%OI|=kH&{b zr7=2+4Bbsn5TWmXC-wf2!D^ORvxKu{Uer_IHbivK9<)D4{<8;=?mSOXM^=S{)=&=; zq_&=D&jtA%je5i!Q_(Q?@y?OU?8v#+9v{D@CTgctwA&}m9UFEY9JvsI$>fobO-vk{ zIx%@9J9qLB-@@1j6^;w$X-?zUjO_lYYv9`8dwqf5u;G6VZr!?f9eeg>07fpl;UXyp zuSnvgW~`RI^t|EZ;lKN*3z?(GVRW(h=tmH?d6CdKclUXs0(E+QsUABYyMzqtjd-o9 z_-?!%ROgCW5md_T4wr;+dFbrun0~Sg#>o#mU!$>+w91niypZU}$ZsSw8eT+;thxd+=bz2ZI zFABr(buFX7fhXbNljHyI03FG31>l`puGk^Um}zxWHnXFUtMb0=i8*lpWzM~E+AIw~<qcs1{>dfhX{#RpVp;0FYLNsyIkDj7y&o+AIJulw4iRRQiYkImlU8ypd&!q)$ zP3P#^t{}FA03wjY4w?}@n?bGNx?MX-oX3cy*59#5!hoQ+o6JBDnf@Na-fnCmi^&8? zONu4NAejJlida2+Du6!5FrJm`w-gL?e8lQX{}w)JH+6SzPbTD%BPRf+{tJQsbIJcZ z34nIhUsiYktY!eXS_^<*NwGZEiG9}=78=KyH&9e;U2!2wU@T4Nzzb!;6cisAOptbJ zi+H>-V!9QdYmqw{(1IX|VgeCwv~?^m`2nnE3Mh+em8BkUSuzX++D>qbJ_3uZQLC%F zwcAoJiRJvu`F4gZJ7AZ`@-1`pZ$GkX9AO*SbEcwU)g*u=6^x{WNhE>?sUcDVDG9n@ zj8r`m3DWRrgpgQIq9$<=IHT&503S%`MX?%VV?jepDePNm{`Yvsk{RI6<_S%bE^T`O z1VPrv)j%YNif#I4(?~WGidvj^5n|K}R>UWQ6Q|aQh;s=l))^7&940`0f~diZ6GPid z!i%<+Q@=mcGJN!HLqJ7+Ac(4{rjD~}CH0^%iW&ruZS8PX)3Tdv%S>9mD$86VJB|Sb ztjf}F$uF8r7}SXP)ETg42$+6%-qSV$l$IThS@Hr9?X3K_+8i_m{Kh1$zW*d$uLb_a zy0mqI)CkaN+6rKTRPt}s8xGfZZ ze7Kh=f-V)B+n&z)LY=V#mvUnJVY(LTWHVVPSi)L~dlJ~Fj;D7gTwHhD^+1zjSM7qH z5*eGrmK2j~BCY|MZ2H~zG$83ivJFfYIG#syBj}c6=yVlVy_9(LohYNCqoW#}&hS4Z z;l`@tn?=h@H6U9Twt654naDMnIr(jx&-+;h1>UTNOlY`8g?u54)S65O85(Pb>C1Z7 zX@C!u%9;%2KmT=_jH(%jTxjWuPci=1chT#?CKcRRo!$8Y?yuh?4};3g0AXJpzj1`k zUKv4{_wYb5N5Ln|6|3mzs9aDLK!VJ15?4ia2MwMIoH*C|aYasLUr4;)rk-bMQr)_K=i1*n#S6a7p*t?v+hp_Quk3Hu+=iSa zVcliMCy#W`!Yz*}0&jTu`gPf!-YY$EA2yh3`1tfdGgr&)e#Lg8<|ZdPXN)W~O!A)T zhySvC{&(DKH|z|q_OAI%kY@`V78`!O%mes})zZm~?~oVV5n#(U#poar?}=tUZ_ z_=!$+;P9T;ce&L2vzkgjIi4K<(FA}PW8S}W=k6;%^q~)N^wB!mAR;3FUGb1ZvgN60(UKER<*2 zvw06Es#DZllelFiynpik!-{@76ExqrbH{pWfA~jW49Noz5MF&X8pkQl3l#8yyUV= z`LnNmlb2m`F+;@yiT8_b1E?+*&b4i>7AKf`BQ*;2ZYfLLD<&I~9quQ$X+62&Uc&xv zY%Yrgc6DgD4BVWZ#l6tjKwVMFm(>r{4B7r+GnnX;so>n{Vm3r z>#n=bUA$$>^m}f(<@opLx3`)}pIhMp&?W)eCV(AaW6=OGUO^c6v$O&{-p!PKqY}O7 zCY`B8^mxc1HUyVbMa1BYm?qAbz+@E-jS#A!1|y1kX#pV+i(phW)2jZ5BFLh{|1vW_ zzs%uZMHkHg5z}fHF^lg0>GPU8!J$heQkx9W*0ComIT$$$1nxM}WH|slGYNoIJPbOG z0?n!>f#(PR0%Ejf_?Lh*)AkC=qFPF|+eB7P-K#WEb!x3suO5f92Jb?g^`Tcq3|McG zEY!Lj3;RZi&!zr&Y$|~Lnr#egk`&cXS3@(Uj6wl%NTi25K6>@a~h+7L7ljn&6N zB!O5#L`2lL7#in{!-{F`DC-o5I4j;d3;%_;-k=?Gf#2zcXG8PSVGH+BTu7^glKJYY_q78xwkC@NMV+1%q1a)!IPQ z>OZaO|FsJH9ybB-;ZbS4@trzlgb*OH9J8=npi2x}FhmlPrO62oSH2$Bd}oLSH^ZaZ zZX|Konj`6J;Q9@9XQ}pelZz8_C~MdBvu9?CZ_in>J<2zG4c8lM|iG}ex%oe%GM7$m4?!fZ#FeH}=v6FR9uIw8oARi3U82c(0Y^-Z+T*JW-y{B>U`ncfDl8gjD(WOO^NEcgIr*R+gHO5(*`|@*`DbZTdp;u93LF)ixp&vd zt}mZ_8k|N7Q{ zpb;4kJa~dytux8C5wiP3n8r>6j=%Q-0AO9i5tY4626Id$w037(@hr_4jwu3#z%kUR~fwL9x~Tn zi&iQ`U-}Yu_ijiMB%4K}D0Tnu?_;d&xuY8Mp@~O1P%pEqdxV=dT*kV5KX=VN%55jU zjzjtWp^NDYi+t|%Jq%{LIanU2?xK5D^#+H#?}^;`)n@H&!Lf(0|Jb@s{jc*0ff&Rq z<%f?`+`1mghGYhNX->@Y#_xLu`|dwLPbSN?Tepx23~}PyR@aNFfVNj&Tx-%O*B1f0 zqFAGZ{k`Niucv$GMuP5QE9$R>yo_|np3`WSR6^w!O$t|GW-q*+tSiC0ET2cO==)#x z)+_69s*ufa=+q>i`^V2RU#=WzRm$5JikEB~8Gi01yLVr@ab(@r%^Np%t=+hpo}sm5 zb2*|o;XUvD)49>n(UH;7(f=^BgH{xvuA%^N9bnyc{Ea$Vbvmp1zV%$EUx2QXE^r1| zIe!FTXPG?xn;W52J;JOQ3I+miuqeg~Ns`8U)I^i2L9-qWL?l);5mZ%;ig=%Pp@<-+ zNARJl7$8^{^S9E`zwPM0sNY!v`l`NzGZIw%;&Ho31S}F%tvJc0$bgQd0ag)4m{mwB zS@Fo~5rFA4rh_;eJ{!?f97?CLL`!^MZvSJn#DT$hfK+_wkiPu=Hbt0Om zA%P(AR=v2?>_imn6O6UENSI#}QawB1S9xq?z?mulGrgd;FXxR9#neJ?aurb(X*9fK zGgc8)B=VR*5)uMM#EHWO;1f_I;+#vVF9mN=oQSh{>oCS3O4|DbiW)^w^2m9#sn+6S6%X;QpLv=#lQ zExCVN70_Nz+hS0M7~cW@6Tx_lNj&P?j{hR24gQ@tbxzcY;KZaeeG%_t3B8F;hXNq$ z8x2(xB;Hu{Qq5^4jJ^4HsQxd4J7Ib-rY|c*)-e+cGhP`{xXi{J0k%)WeFKiQF2mC{ zj`7*4BH2cnF#~Iip?G?Nsr)8345 zn=xZPBr%X{L=0@-METT7etvqM|68i@OWQZ`a8?t~c}_4hXPFOAP`~5*DDkc{tK)BalVwZZY7!6+KZ}LE`!IdVR_9sB3=r36Ssy7;Gomn8;`$Ko zSldjA^0)p8{nZkce87-%Y{7C;Lmsh)Vq9mI0sOvw;vU1-u4w(6O71x#`jj}*Yk*Ij z^98l;?@D3esj6MNF$Tunq8K6+)q0S)ix85AXdMhi%&a7qDyR<^1N` zf0=Ec_y+sG@~^z=Rj+>ckw+i+=v{Z+HO-Ub$?@Nq0Jus-e)o-Uc_-K|zIE3@YPC8i zPfT+1O*rB|?S-4NMahA;>a5t_}2Mx)u1=qfI8#Id7PE-y}?7Z#?- zWO6u{Ff%v73)el3r}l57;bTzv+Vq3mHGB9sr|RW@0ea#jnfub`Ki~foeSNseNo;pF zZfp$c>qDzma1K+eGCSYkBS#YcdVGur%BR>;T*Irke;-?m!#r3Tx(?p!|gI{aWo*WaeLA$#s3~m%nx=AAIh!S#V8IrF!@z zCYK@X?IP?c(r8BPz5Fsxmr8v4&>^yc<%;1o^yhPgvRpnD7{eDHdYI>K+ul*L@|aA9 z!sd1KU9k(32^JLuDc%t<7EHM0p`fi=mUoDE;9bXSbcIUbLM{d@@9STsy1GsupdfQ81_}5c$w0qZ%EmuDKy61;azv`J3@?GF!a0w($ z=v@cdA^>sX`ftAZ<|}}2eGgRttHl6zMgiJZmA|try;31?wiJNX5(h5ii#lVyeWMb+ z@PF%UwNAGR)?foCsS3a-Ud6?Tsig&ODw<7%VN?HI| zRIn^z^rd!y4spoRbEZ}8Z{serT=K6ih<^qd(0)5TOVwXjLjUEsU>ij>YB4rV2s!%hI$OkxaBpTpwnplHN6dwkmPaF~$jJJ3T zfE9dAn=lSFGhWAGS1l49MPD-8>7pl|HdS0ZREui)Mi6( zYmFzg`rmoJ*gLB8d%%ycM}l#_>y^vI(&q!N5V*S+)Kk-xf0`D0!b?62nla^ttskUU;0?{JbVbiyFa%d4gO(HVFxa>bTh&m8l$`x_wk?0DDI@ z^Sa;AZPu`pCb?#Ut436;Fk6d=XXe?a@CpNc*6Uq@%7lbQ^@8T-A86P z-CbmRoDgS)L-{O`LWT_S)NrRk=!K23NB`fW>v#S51LDnYmn1*7btWArNz&7(Ljqt7xok-2E0eyeh~ebKQF6H){oTX#_YJXg*B*ZNH-3&?J3hl7{PE3&m+gJo-vDE+ zWP}f<(YsHMC&zyu0-y)D_4*(EiTpFKc|H$6a)LOHIdy89YOTqazxcNdui3zhUwR{J z*9}l8gQygtj-gS&WI{|FZ6JwN%Ov5UVnf&-0RtFQOjDoGw?X#WB6v z+@i^!2t-N3{S#CC@U|W461aWC+|2L=5(TSY2=GC`!hDJM{K;=~>jyr{FaOUM6khNH&-}?tzyE0vSZFk0>d~cb z6iG>d?j;|Ym%QX9yyY!#x%zuR0O(n6D`oqg^8Zc`fR!Y{*&+Z}>-pDnSN>NL0ZY~3 z!t*G_cQ6wvISfYBD(Zq19oZPDDM?l_Cha#7gZB+hGt6zPMDIX++LvumoB_##+IHvu za-eTIWc}^le?6nx-&O{s*sI+Z&;jPP_3j;yDY8sCvnVxCS*{;bjt zV3ws^$jZ3C4$lA;Q30o797rt2)Ik;$ra%@z>w?x4X?UaFsP!u9#FJox#2HmFp+<2` zCJZG`J0>CwbG_G7umKzaVXYi7G4E#|{;ME=h7)Rp7Mmzvar(HY8XC{@Px~8zo&TSh>VGE*u&=fJ`ajpxW|9ZJGAzQg)N|0n_Jt|#%=U89!nU<* z89#9nm5_=z{>FVkVfdRL?Fv((2b48P_Nw6?iUwbk=p zyY^a*>KkbG6^XJLilJpN0W_f=d-91RvUTE;(iBIMZIDbU)mn{tj*<)y6UqoZuX(#( z8fLg0WrH)=$We8UdFMIe9F>WA`eWs4BRoss6DoW$pCQvX$oklEVowjJC;M6BglDK{ zn<$FmVH^{gJoTZ7W2a7`cTKX@TJl-PaUy!0l8ehkQI*~(=ErvI;@1~4WN-Od8gG6N zJCFYh$HKJ?H5{8Q911d=7Nsk(OlEtD_Py*eRsR>yAsO?k+hbpUwkq4BsPY2f|DLM? zfAXP^9Ne&L@4tBUKcp(pC`INN@Ri4N4jOxi`$tA@dempSlW5?!8mu&5TW&Ge?h3Rb~(EF9G+qZoUTo$QbvpQnQVL{jB=#}`W2fMuP(7t3xdKJe9(1H2jcK$4S_~!Y+v;WpXr3wpL51htFvj{ znhT#xT3!PDF+dQQlY{*uc<=EowQ3SagqiFaWI(-9<@qnTk?(%z(?sPM+lmMG>KW)A zrfXn`nW+=xf+D+jK7}L4ALLK|@SPmE?>kK2`;8yjJFKIX{i;{LmASb&y!R|DRG67v;NZh|apKrR{QTSgkTt{o^!9d<%Vig_V|%h~ z#E>MOsF@H)331|xlX!75U8^pT&lWg6d7RC~VX`(P@eV7(KTq7-aFX2A0y*vRmtU<` zUvbho`pae9{r4l!xEc-}8Q#M)hj(KT{(0g)zBO}@OM5qQ zdEXW?CcqlQS0^9fU#A|V;p0O_^_>cT`ycfqAKJA0%}0+P`sT-Tm*?%n5A&LfFQy#F zEpXG4;`^oZXynrUvZ1GI8S|O3meZ9AAHMHCe)Ty&Ks}CH(9#p;a|}G|^5wWjmxJnb zk{x!m0kn&eW(hbY5%>;(q~Dv=J=2VM)-#^MS3Y(dZ@=z`=vqHSux>DoH%yWx;MIxQ zf)Gw0gf-j2#S{v?Y~8x$c~etUfA*h%0O<4qa4V$!rUQS-3W8uY^FM!qWWaeV|DBKR zdzrWw-J~;dLIH<0f_TUy1d?tN9Gr6ZHuy8PEV@JPsA{qM}x?2Jzrc zRzA_!o78ZB_lnzD&56Fc5{q_K1*PfvKRU?dAg5{F?rE$vc8F0%S-@(K!3kR`GzX} zPTACz=j|H|zd7>-{JvY5c*E}!t8!T=OyXE@0g(!8GZ|#_I_{n;GjeL0cNEHea{UN* z3j}e*7MrJR>bM06Uq7nR8fc`g0b0KCMj~B9K@z&WVWTJmD&$eDDry9)iVXsaV#pX6 zkS!E}9%INVL`lqohl;={?-^@E9G)*B&6uYf<+8x?ptromW~p!LVc2HqvBG^jpfPRP z;u5Y>VUs9{H#}esGeL%WCE{qb9+#P9lZjXtI}SBN3O1rEsuIsPDAcOFA}H{_pn>ac z5Wn?L7_kuxQ$bo%SeG}zBee>h{u8%$Z(IcC7zWg(4l2@tc ze{Q_wmH#sK;H~E}meVkv`eGcc-R#Bfj-7wu`dvRUb?V^XJ@|O8t%bq~7e)OCn>BmD zbTytM=tfm7VB-O=TCytQjme1mqKaIj2vj6_eRqwxZ>)ad}WAGXeR zKF6WTX`V5-i~dZJN6OQf!u`X9;gjotV4`&`m|(cu$E z_;4-5o4@u=k~kt~EZPG9ov@-4bc;eE2&hI8AGz;7_Mbe-uRZ5E)T1Q@ol&K*VmlwKt%{9*?w{D1FWcUKMMW9iF zqj$rxd!SyXyQ}-M?@@NJEMC%HWD*E!szNJ{drKrD-n7>y4{ZeG#h2553*M5IldcN~9R=!R;q6aSo{0nJTJV~o( zJVvC7$h5$WVylSMQLTV!AeyMRi3B$CE{QNCM%7!v1rj>%Q{Kde)Fi{gRUc}WD5NP7Q_n;`95A}qTfr~V8k zS+>5ISTM1OBqFW2z}EJNXaX#4lMuHbZ*8~pl9D+h9d7^2dj3fe@7v(tNa#eoPmFhx zWSlYTj8$h$=$lRF#U|d^tPdKvijDk&3Dsu1{28%-`yOBH-vz^)QAvu^%zMM9MQI3J zBFfVYtm{$+T!X{Lk>9qPekZuV5CIJrQ!tj^hsQXcv*ZP8nJg0`+z|#G@{Ub~48J|t z%g~EoL)V}Gy3DM-n7a`AU4Vp2#VE&A$XG+~Kp%eNIv&Pw&9M{QFgwpk7%-zvycjlA z9P1lO&qS8)U-~00-t>Ng4}X~Ewty2h%UCAEc$i^68$d3@+I*I)vRSUn<+vdT_!(>X z-^TC?6@JJodz@pyJ0gUmKH+n73*0ewlEahJY-l>3Vm#9s&+iT9`RKX<{I(%>_4UyB z;Jf5o5%?LyQ<^c)1~wZ<#RS}I3{z1=EzEH&vmR$>+2kBMOqS!B0+~SQsWu_n*aWIcWoa@NuR$G^l>F3*<0u(pt4w#yPaC6fqIPfY3jJ~8JW&d4W4g2O25 zG)Z1Qa@9?RbFF{$=>A5S&3^*S6ru&=-H&g%{BR zRuJ0|2`98M@bx&%e9?q*FQP|Ps0-4A(JkV12hMK9OHq8B+wM>2F8q^k3Lnq*uD#+_ z#SOa-T&6+uDn%|={5;-%J8R=l9Dm>g2hIup_v{@YR9q z1h}A%Xg%rDlV|yj|NH&+b8I}<)1Uj=T|Dc`J&RG@7cka!ET677Du@Wy1T^9*FZ!`p z5k<{2rnia`$2F43^Oj%#ZKh|^;&w!@@*%f%I|AjAn<@Wc!_tV)Y;pLO#zq$gT0Q{fp zuK$T($IeTM;)rUco`V0_^PRgsPorMp$A9AI7#ixKt1Hj$tpgl9I*0E7nkk6Y|Bt=* zjwV3o;_Wf(MY3WHA}YTijBcQh-jfCoIr?j2nnh8IJrrja?)-{?#bjP zIqBsBA(dc~LkbEcp(ddzfB^>!8{5LNEXyjRnbGvJ>ssr5p8Lnzdx|XCG67-k@%#Dg z*?Z6K>s{^lJikJtk&tC6YD$u>0MsnYqXDbcMa1BW&cQrY+c^$RK5%*|YyRqmjxoTm zzkPQ0AAW3LJzn6WCmOtY@^gG*`Y5*zT*ZrruE&e;FXQ)e&&;EgqaxeO{cP@7M?+J_ zW*%iet1RN?SHOg#$?2>%f85 ziNuD15>UHb-@j!9$VD{zc3vVtc3#(C&SMIs7bqZHEc#FWb0>B=J$w_kaMI{VggED0 zduKUzcLWqiMRGfKCrH5rGxJq(He5{Q^ULyD6--Q5R<1AWN20(ixMIQ#EXSgx9&Ltd{cl%8dudO|@w&?zv&vniK$O{;4vp?0`3m^(BwEw&af~bn~E8yQ* z$eiY}f3nK-Z*}Bf%k|$yk@~o)Zn|ME?zOKL_5Wg{x0hyI;l71VK9BKAly3%Rg5##X zghSO1W{O1yHg++(P=Pq67NA>Gy1dYc<~Wx2bCn8{F2Vx5w^$&lHF!xm=Jz{>`I#RX zF&p^~soe2qJM8DVCRLn+TJSue$~9(OSBNPNt*6vT*ifzVZR1ls*3-!&1!cwxEc%Qt zZPK@tk!qFt?Y~RobfBqqMhhjTsBlUmHk+|UazL`ljP*Er#OT0i3Y-$-NF(Ls;v&-v zRZ=y2oTtY*6u76Dab|l5Nn<@d>-yQ9Hb`9`_x8<_{^YOQrh39njf7o3rVwD#3CDv{ zSEKrzt(+PkN0w&U?IL!m=OLdFH=2|hp!0JSnh7_=LUZG0{;dFA!{f{^c5}-;OWgCC z@258_aZ6{Jq^koT$COnW>*_*&`)A}otpguB_P5hp_I}^NU`v}d=xs7Te-m)m6BYrE z+&Qsr-+_Nh8@$1UjY-=4&Mo_X@XpaAZ+}YXWz!FDt8TmQn1)JHHc4+S#ZgBR!u^HR zJrYGzc5*DFj2#?@k#obthfA(h8i-;B(@Y04TtgfcZ^>eV-ifgje_46_C+v^YX54_r88pwp8C0uua|(2a!ianJ{lhAA9(HPZ(>w zdG~j1u|~4T#I6!yz2P1xm(zP6z5mX};JyQ0mNYxPf?AdoBR6{T{=cqX_7hw4S6sC3 z5P9DJu}||Yzx|7se*Pvhzv|w(ByAw#nVdbtRoC6fnNyF^Y}V=S?j?j3qFbrd#r^kw zoFD#yk1;<#NnD6|^yGtV*|dY<;T>qR!Q0>Zvpl=2i(eVqz_w@KO6?^t;jiBHF5Z04 zCyAp1$3K3W$$7_hd)K)v&3^RPe(hI(^snCej+wc+xzEO6vtPpPKl*d* z-MgK=y9Vg%E^_3NX@ahtPc)ke)6?@zo||Rj+%(Nb!uZ(uvI$_b(cp8Reh<~fX=pUr zKeUg@#sbx>!Iu_J|9GnUmM35^eEcn&hhMmV-46NL$vOUQ@*!Tn=_YPnzlTIqK6v&p zk5X~$C*u*W-$H~cq=gebeWJsx$7UVxakG2DR%dghCp*^j&gm8 zSM`>dt5g{3>LN3xqflh1yPK;92ie)xg=HC;}2qj&xb6mqGYrH zO1oPb#d(+Cxf~$-7#{M6%uDHggp!BPwEQB&f)Pg*Mgp!K%I@2ygJm8J2EJ&}J z^_Xc1tP`Qn)cP^)0Xj{zgjz@2RDDfgLMzRpRRvnEYpi`v+wRZSuIuM1AXe&=cF8+R zlU20;)z@o)|9Rd3Z6Enn1%W4!1el1+FcL(X0*m0zijy%+rf{+-u&Cyi98xuBHIHv# z)(Fnm#Yl0MITt5EQSVxL_R2zcfywv(nba=dapi#H=6<((;f!lEx?GwrxX@Q}AuYPj z1h3_W%Tn>GO{bajrDEhlz-vgnnRgZ?KFU4oy;*SP#hYc`%sI2*y^1#M?PK zIh=ZzXGJ>9oS_agZ#c=TMwUDN=eP4pj1wWKn0G?3cIbp$oDtF9KGgC$gP5R}7X!r5 zmJfhPE(2Hw{`nTt2L8EkfGH}i|CzSU{t#6OK8QFCVrw=3;&mDPXN4dVH1GUJ+Dt6C zNP}}lbw1Uo(G@CDs!>scpKoX!_iCwB(c`^amBVui@7DiZ(dVf!0jw|?F%$wni}5^z z69)g{gfoSHKG~S%YUin*JVPa9ba=r9=$42|eTnI3-$J8VXKy26vIJ#=fgpTqz0S); zsKzlrUiLh?9x4EnMRul5x;)JL2+K0AFy%!EL*nQ`=}j`yB%vyf({aSHV$3OETA-GC zEDrg4kVJ$SGE!2X5E{jN=aDv7&Z8FVgwB9YM?_R9T1u2ToJ+Be61Am-%Aq@Hj*Q^P zpsyolIP-+lCwT0Ae@gww-$HkoXKy{>+SpMNM^Kn>#+ZX7G?*XmVB*LEeti$uiLf#C zJmLbD)QRf>TUtc2!1gS#ecN{ayc{w3N59DE&;BmY?J9EQ&@8pibG)jnlWiR_CrTxP zI8H_$f9-l6`Jo@WkU{8EAN%$lD9k7Rmoy94i?idAx3`@>=1#44puf<*WB97q-)33% zE#wvC`)j)XU*}FdsR7=3V(LGh!ZAMnZU_RAugXid9-@wNq*n*_uF)J zyhT!7hiO^GB8OWlWIA?o`_wdt4n3jU|E}xbxS>(0-)bUPo9RZd!(Ph&G5YBLI?m0v z$6FT`wguHq&f(SRxv^u{9s3G;6-Glc{G$%KcEmB;cU(a_G{n)P53{sXKFvqQ@4bIMUAhBf5AcgmC-4uD)GFU~`ir0a zf`*JpgwCFI*v1{qY}w1bW25~1i}v#qx8BMRTz4%mzv2qEmP({)LZ+I7q89d%5I_y_ zj^d_)mNa%1@>$*S*8piVH_20N_llu93u$9*-uWsQ^_4;bmrV+wA(#0kb4yqjIQOBu zSiJuj)=nU{Qn$;%Y!$ zaES;>p8e)lZ=E0o>nJ|-i6Kj}B&CJ!DNE2Mcsc$NlsQ4rb zIrTr*I5S!CN{N&jF#o@?SiP!RLNAxa4vsL z{A#*=i^hR)jwtV zb1f5*RK%w^m#L7cl8O3N-@kor!D*BQM;08}MZtfo^Z!KPKZ;UyQBx%`EW=6TWQe#V@$heRAk_PUQz+)mbf-qLx%(>GwiUWP@503Q$r?Wc6#ReVq6t}cM z)C_D+GPZ3V;4h1wty6m#`-$J=SzUdc8ToNp?3vBctgW=q< z_ne@w_CEE62MsNlNnc2t-@SRa{pOZE|MmYE-1#k6uFfJpeE84OlP3=~tX!()&1)4A z7nw-x(1PF!PQ2kV9Ih^6=ge%(GIoD*i|>l}Gxl7Ih?(;PijXMCZTsrq^z z8O<2ld@asJdw^@7ftb&Xr}KCs3Ba3n?Y_2q=dK$#H#tqc)+9+1%na4QgZF=uYp?$X zhBps0FxZcCIj9<&tl(Bff0{wPUMFOMW|HKNovNfQla4IQmUBC^ka6?6-R$bx$U}=~ zxW6(M;@HnNo6RTs4fmc+)8F{xvk&}=3DVS*hZfKB@pJdn;R`%knc(i}ho{Z#0}Af| zK4VJuG@g@Mv$AmD)E7Sez|LD=T-K1`Ou2V%3Fjha<`)QAx(3Xmx#3yP-d`oXKyZ;K z?&(^lSefQN*{H3J0YpI39Gtk;F>G1y-%0{#)3j_A=s&-(a2arO)Lo{zP|5ktrcC|o z=cs(?G1k5CS(G*pwvr2M?RRQ-WxXR?sxkS2Pa&x=QK^3VhaNeeehugQVo3nmD$~E! zegSgc^THG8|1Tsj_)0W*4WQ@cwy^k7ib+N!8P16pG>eFG-*XR*Ag+R`7m<#pi!RqM5!m-lv|h)OPC4A|lZtS*+FFAG@R^xJffxa8BxG zuIfZ8Caz&>H3xMf*Fb4HAu+KaQJf}5=90YbU`jJBFvl>J73qiAe}?(-6ri4QXhaY1 zKjii`1})1vP3LBm{w|5(!9pgM)BnX(TpU_af5ACIDyrvq{>8=W zoT+oD^Qq>33pHDeRNK1$LSelYixYNaa7sBecv-0b=a2QXqzen&UGHPB8ePE4fLSx1 z)3Lx@7IDT$4E1eddTEMH>PQ3{S%dDlNOoq1spnkF@i51(Ea4nYQdi>d%S9^9jAvCU z{B>O9f2<$py+8L`R{HIqXXcJKv!oTSXnKk+P|cK&#evTS&vQ(<4P&DSJ#oZlgaI?Q zs&W!zItWuPXB5?`r83sgoIs1Nqit58yyq(q#~(Ca&S zxfy3-NGd6XtVsxgFuzEw!hki|G`O304mfs>1|DAj2v>J?(H!}2GWxoovRh)|RUJjn zxdp%!{O|pYe8scQPapfs6Wgx-o)0C>>T4YGvY>i;>)zMfnTP*w>fCg($D3p4c**l_!8b4Y^y^>ch8M3kM7(LQ3=KW6+(9j?kcoq0k>Wr9GcUa5 zIUN4bhgn*jV|T{@H-)W)XnbWi-e}OAo8twY9aI~2c5J_fk4@jhtCp_fBPWJ=VK|5X z$cKnUnR)Zyv8mL}W5-XibJyPG=4I}i?eMEo4plQI$LAOr+|0R&lQ*`KB%T@1jIXN# zz}4d18=v>W*K+RMG$903wdJnucF3DgBv-BL zUyl82N0`}i#Mv6OlJBHCa~~Va0^(ZYYRy{R{8c27khS~(T(0$R3$fcVfb9Z+xD{~i z+EIb5^#%B9QC6JGPw}&W6^fX5NTW&p>^aW<&4(!sZ=m~{?G%SM5OtRkmxIU9Oi5=J zsGpu-;R{D`Y03xG7#|Ff0`(bul6{i}Lok zQ$ZD6!Av8TvA8U|{4YECuPOwHNz29E6eQ$8Z5jMa8~00|4j=-eB6+x=*m(?pS$WSj zDS&dG7XWLW|5;r)khUv4lG6vwTVeO4)abC zhcoB#xu2hT2j=py$kpJ#H94*2Ani)(;}#Wb3MwmrUzYPI6>mPDR}&EpsG(j3r|n{Z zh|j$ML~~z&;5Fo?f9jkCTEze{Yw7!=khT~SIruLG=YoohHAyVwrhlfsUQ+K9U5d&Y z6dDnrxLkN#x}i@0FOBM#ev9j`{vFJ#;X> zRAqN+EX0l^g>K&@92#e8{}ntkJI3x>fvG5AE=2re0Vd*Zj?66Zb7yPZ*4NLk{Pgcq zoSCI^=ZGBpso%GCwM90@5or+Wk@0Vt=a6Px6#}CHxf3c7p4T=}qbkspHwE97zLx&6Ffd&_;lTC5j@f^D(83 zSMl!hJXg=fJUHOlQ7F*)KYv2*{_Z!~v$7^{C>5#rh=%u!W{z``(f^XY-22rMEEm$L zPifqLMM%-PnpynQghEobds#XwdsNen&azaE1hX>Ed-YZkiJFsJ$7gtKEq#2~t~YL|HWqFc z>`D`^GL;9#^KhY2`of_@BiXj=-q2skk_}Okt_u<`VSdcVO>I>C=CX73dbPTESvT}W z28g++iQ;=c@=1Q+wXeAJ=8?!Bp5H9Xd}8;FuNR4H40qMRd!h#(;IEH8#^x=%s8^~y zR6obPy;D@r4pPe^_Vh2(RZNkt5{vJCH>FYs-CezCXE(o;e3+5!#k}{y-Sl)cS=U+R z?3qWY53J+d#2kwYOLX^kwro}SL-j=!CUK}CdWwN930WLcouOi?wG zB+dJKBB%zU$de{bx}p-@aR-Y@m1@bO3t44sZ0u4DRT7lfE4BmZ1*Rc)JZ*kC+VH2x z_=oxNQ$H3LOK;tH)s3WCV0hzJW@}Ys{d&y8a_4gm5;0>n2f(zYkv7Z0aLX2Jd8fO2 z=c}4)>9de~0i?~9302Jt1j_))trQ_va@fB5OT|01)@*@3u($w)B9>)Hvq58Gn#Slk zOu!clxMB)r3jLqm2v3O!qJQBs~GZieA;5~w~ysRXk1#n`bsi`bD zC(el!F=-kai}(tJoXBF%^6scB85*@S|CS8`k-X{JhSw;$p&%Z-6QM<0$s^fpIUG2T zgvVJc2{6xpUqSe`%DR6!$M5k>fb$suYYPOey!!J1$-!!4RwO>m3eQ^l-7p1!SP(+;|i|`Devngx34@w&lL)&_i2^h*s%q4L ziUgX$(X<5dMwueXXp>~>3)oVDuyYRGw+|a3Z#j$rzx>PjzW3(aE$)X+X^ks<2LrVR z6Eeq_K6+4=_3dM0_}fRU^r=q~_y)4UFEN;8bTou(fuaRYWGTaqCKDJ*rH-p7cxUvA zr!HN5azm4wbUlZuvb9uX?XCD5$@k=dk&mMo*VtLDfR6F9>JGsv^J%-U`u-$}B2sZ|?O=dFMjBDLP zd$jB;w@-|Xk;0#4UkUcy(9kz^`kwXAL+AFIf|ym+N#@X|AJm=!1o@@ra%3j(%s)sJ98r%Jo8rP zU;T09%JmeY0@YAq%iwO_GW7|5x%gsEO!RSdqMy!4h(!3?!Q*Vd;wrL`uw{4`6gSY_-Ny(1@n49dh|ca#;y9*QjEQ{2;^GqX^NSRU1>z`X zX6h`xy}c6)3ky6mo*7TqaUsMu3_Sdi_kE!2fq(x5fAWDteB(>sNU>NVgp6usf&cZ6 z|G_I?{X@L=+YhjF*A@oW_g=7wm!=sr({og74Ho8?7#*FY*=(}7SYc{v5)q+NSs;pv zeEJiALtnMYi-xY{k%hC&@7Tf@?>lrNq{*)To#)3n_ol(!*Z$hzu4@_8CfCoN;-{bg ze3CTFfxU*+?eSa!AT57$4Ty7WdhLtp*gVwE5QLyB)crQVw^nE0d5B{u6u?DmSpe3; zma47$Z5csmz2D_IpUi3vPX7JJuq>c)%zV9$nlaejP0=~BBq2-F{A@mJOBW1ro{r8= zCYnvY=itGqBWKS(4>$+V zZ1@}jw^6^g#V)Jm0Lw32?)ZyHUbAqBTApxV7$zbrNM?C4z{D_dE;B;~f{7&HmK-da zxJ9rfa1{|tz%L3ihm$42<^;E7&YIvGB32K9B*sGG3t1!t)BMXsN-gVR_R!m?t_6AL zGdke%fWQ$4N91CrfZbWmg-~#zqv15fPBXk}>Pp4PsisbYc(crzdZ&^2*n%?)&Q!cb z&Y6WA=(h|3BXiEYNgMo|Ifv;g z;Fcu;pe8Lgz)Hv8<=y|_G?QQ=K8R?G5#Tka{6|4VH5ISUTaYxUNTlK-^`4M>C&VrA zpFR%!U)c0-pM5P1!7f|~uxQkAn=`&sj2*yf6YfWu3&OvYBDzCLee@i061ZOAv^tW= z&QB+oBdhznFZVjAOB{Ngn02@Iu5XQo7!=59F#LC8HIETSn!DuIlMOdAB}F;~K8 z31y%!Bn$!lu0ZSpXFGa0e$95yp1Oj@!S9fOncVRf3d~Zhc3@E-4aVs;W1V>VC2(aB z#zM+avq`O)GGU;#22rDlMUF0%bJuR?jCOGI_ynKX*vk%IWJ6z*&zx4C->CEYVu5b& zxZev$a6B3n=#D!${f9p#m&FHZ$DSX!p^+`zW+E?g#uvo7$KtH~zLO{Kd=d|y1Ag;W zS)VjZn}a2r%()0-D)w%s$l~bn;~#!%wDy~Ck2hDRdR$uAq>&Ax(y6Mk5DKQgfLAk< znaD-6-i68POmljA`hArz_XKC_-v2TjLh%-mt0DAZcuZ!@bWF@Gijxdim`RGsgHuNy z2hwHRo;U2sG`UWVD+SwX#!(;pqe(RI`KcpstH4OKarcpaXTIbkLN)kG>>2}3xl+Vw zWQDV*k6(H8a&GhXp$`?=-Z4$io_YKjTu*uHvza@77sbU(Qgr;7T=Swox(J4Or^N1! zf*^&Mp`NV_uG>IIXKouYIWd7Cq$T5;o^90Tr+8@mIMbm*XR(XTL)#b}*u>2AG|ff> z=R7`wMyT?he>uXw?GbPI?(g9XpTFnacYN0`bWKf-m&eaODm!*vhjS4kLYg+IEY0xP zqhI9k=RZQytbZQ3^%;oy%=mg^0DS+gH{8(ml2^Wh7e4Ssrt4F@`JE%|yZ(jjyZ!|{ z^6=*=clNMj_x1Gjbhaa$E;#097tmG*dSPLS5JGOgmZocZL?KJqbM^IX4bRy zYU?j{cn6K}zxVu@s{Z=a@dukC?sweoYdKy|DEf$ImaUkYwSl-Q=G|n@S2+iu1>5oSusIt7pZL(-ntCK6=F;cyhlV>*V)NbrNX~H z_#nq-XSr(QM%%e=ovbUD=`MF7PFQL-IWs@UKYZphy#L6N4=y#EKLnh8y3BJ6r230c z|5^3eYTSCUuD_ngD0qr9^F-a@3wMiOFlnf{m;OfMVpJz;gEk%y7ZwmhWn< zSBWD7$*e{BH>4@B1hQbl5+XG*Nz6%V>gJu3`P>N0=A3gC%r$_f1gi%jab~GnA@wn# zHPKQM8r6vTmu;YS=n3QfE@$_5L}A3yeaL#*qi`lCYRxY|A5>hQg=C(t)l2|YYbIvJ zLJXvs7EH;^1!q~LKDNk=U>3xgiL)qnXyyS6A`+=Nvz!HxGXkVV`_BsjEhC70XBM1m z3-}H4f`FV?Ah$JM0BgGc;34EJ0KvBaKjakuwn>FI5tq~c!3dFxh-G=?pNi1BZg>49 zh(pDhrlRUnr=k{|E2y}j&e4wg3#&E%PYnK#8SH=BfPa9IUnU$l$Y=T=q6gS-!WCj{ z2STL0tda2%FLVuWq;_VM2h4M;OLbuW^4;hvQ%kUU`He2v0yBvDbyN7mJys1 zS&0X3*hwK1ZeCaC-*qE52BXv=96p)xEg|J~9VNO2J|~_pnd77c%B2Dezjv9yKfq(h z{__6etG>U}(uIcMzg0{NNulwrFmmvT*U5w7>``WhhQ6ucJGv8r0d>+DEJRE6bZoxr zd&bWm{j1qaKF%Hfv-B*?05fpF4_#j@bu2czn{nLlMEkrem4ldCQg3LX*qrWKmooj- zj-kWD-#I`>y2o()LeODDOCUv2SrE}vrZQ(PN?oi?fup0xl8MI|2<|&j*b)kR(J6^EVhhFkCHgN*_`8dptZdn`=NHmu{f!;vPEMVEnDN?i(q@f;fz9;w_tD$e z$NbzJantj~(FYixI89e)FSp(NA~tW^!6OfSfg?xmVO{U0R^zhChRu5jBvh7WxciGK z@A!*9Vf*&&>wo9hzxSrS*FQgf`2M>-25Ss0+vi@>z?*^Jcm`fRGrry!07c+|zkd7M zuYAKxUrOW7JK^vCjxVV36|KMRP##h+qw~sbY<$g&b85fo1sDLU=*%KH z3qYh53D~-bTY;XYD;L$v&Hy0t9Dmz;QSTrwEXNRbRIA)ytMZz^e%H&gEGu;s3fJ~^ zb?z{ccxrK>64LM>@JZn4(*pII$%;+tk)WwRp{1$!)1{ZTrlw%kqBjlPG?z}nG!a)fv#KDAAPt;k zAgM#<5Shbd9(3M0U&E{cz5&)SPg5*TgOHRWvPKgMF_Jlwjyj873DtuKpN!J`L^}Vk zq#59OOo07|97}uTd?tW~Zs|(qy=qxjM+91kU9sq$Y3fv4EC3acsjOiGSc?hZee1qD z%sIm(GIij^ygDo=VYDA>txwWo2MDz3{>!?yCuRXiy9l--3lMRuBLEEv*3$jASOLK@ zahg9bn6x_ngwUe@=iUIRc+DyQEvJ7M*aA!noDyR`F7k;~DQJo2=m{cIUSfe`K4Qikp|?bJZ#VNJBa+=dVr4v= zs8gedT9nbF8D60hLF4#Y_9rQ~JE781r;m?VrfGR8wfmKi>4V0bb~XoM>{v9HMu@j6`X5$-8&jz8RrH<$Tqu(f-^T3)Me_JjcT>=v9b4m1)@$5cy?E!n|rtF;lsn>$+wvi zw{G{{U7hp{s)p?do6X!N2z`jexfYXYL(Yh^s;Xoz(x%HeHQM1$apZB4glyS&U|rVa zI?=G%Aw7y)6z7g6X*@oCYIF)N6ccE&`Ks4nsY!Z^m@7Na@e-Rpd;IuYnwRyw=Ex^D zB8)weCiFA+9pUI>r}=@`ees$Z){Y*_y@N;*(f&QKW zHgDcZcTW$K6BC#jr_Mga{ujTR|L1q#PMS6;c;mS@Y~(es{cgT^&wV)O$g-4Mp7(NY zx^+L#d*RL0n+aF%SWmSw%d>9SSIyGK9$;)$6Sc4^a`~C@%=o%x0DR-dfq^Su^NLrH zedaUR(h^z7=!w_y>TNf0Te8R>ANv>fTy-lO2KzB=*&I+rmht4=+!D?VJOU(dw2`xOTTSW6d$P0%SmT)~YS(!64=0a5I2DQf)kOc5Zl{k(LY9Mb z4f%p|vP^epRc?9x)CAf{aFJib4p`GmZsSVvt@m@S_sX5~aX!DMT>!AP7cQ@yv~&AL zDi5E6Ldcl_jXFu1a?7=Q7#Qf^Ix#Wzj(U=Opgx;C-DlR$Gxl5E{debe@Xs#*=mm`b zE_8W{puP=+m#G~Wp^Kkq3V2Y$fde+P*pCm26Gs@ME;B4(mLV<`Ovyhdk6h2=ELs_S=5x8f zd9;=7w+sST{T_$QjRIxG93cOzg3C7xD|Mx5O zf06UHi}ROXn*|cJy&YOcfWdMC2nJCO{3Tcr6p75`UH~Q%=fJ;pTO_EsNK*;woKs0# z=6_y-h}ng}f7Iv-OTK3A0^ol+?(b{l_I9W+4-<=?L++mAv8KFKh!ef&KHe@LS;+gjahyp!XplkbP zK39ZKj!v;}vBvkFJk2jS_*DNo{;79>(J^p^1St!Pead8|j&Jm`Aqi|2q2H82gaLtW zF?!9>DMmj=S#klAVn{HSfGNp;PXo_nCX6{@UL7^p#8RUxR<@hanFcg%QV1zN%S{o7 zvW%HVlP`vlN2xZO2uj@|n$9ur9hK`NUe+w~5LKq*&Ah6olY8cBxTP_^$AnkK4kyCD zI>$p8CnHZ>EYSITKOvv~+RXN$?98T-`-aDlFKJRQo4A*TkgVTw<#+heN8bIOCw}e0 zFy>x)Zd;+Rn})Aj7JAjmwKzQ%Lqu1(YxvslpB*d46CD1t^t?vbQ&{&8296UhsXDUn zKw)ckbU>|VP=l^Fv2Ig}h&DysSu-0G+@iVQ1y>NG8VRSVxwE6A2kRFqkZihoc(XRL zEh1V}byXinkD7%OqthWBu8VjBa4>-o~7GhDN4 zJ)io_y`A6q{F^?OB#nKmB$ye`jAzFG4+;R^`RW(Hn2yoWJXhxKyP1x=_n?8dB0U*QA>X zg}6w$+)cUEMQ2Ah9pzpuF5sewVyV=M{j%hlDOxo`c-Pp``yP1TQ2B$`4GeB6$DW|t za^=@mF=p24+UK`5Nm%&8L-gNvJ!HBTdakDSL*C7Ia^C+Ge5*LHx`43E1h~xSm04iu z<>ZQoAspT1-7#KhFs%dDPn0%#X70E|}A|GB{PE))lN{%2h3 z(fd4__{F-x7ykdjgAztYZ0fUPkif7Qon&N@VJeYxk|p_i<G$pKx{}+x=S2bWS)LowB5~)z0Rlwg#GBy} zB0-$3Y&`L3+!HtS4gak@mvJO1LRhs^4}6xX#$S}2evMvAuL{+guC0+r!}+Lzb)f3iZ) zR}}6UhenkBhv;3}BW*cAI=$c+=v8P^0lI1>C^vv2N)t!h958lDij$IAmN_$VSuD;p zxY!~y4Q4?!r~l*dkwa8lP}~K{!Ty?JfSC~GlSr;5S>@>HpTq|stfTN-tk98V#|R)nhGjT)TJdA4Jy8*BB?nS=aheE>LOL=%j$imuGXcM zC{-V+`XcJ48+MV-|K+dJKBd({bl-?&7@rz9mT=sFvB_YI7fzAz;z9?XjuPsddhuz- zdlm!VTqrVFPq@zo>|}=h)K5`8a)jjIL7Diz5i7;QQ1FQNEXE#}CG@1An+ADodk=3~ znx%JQmT#Dw=S_3-3_9U(XD1(9*TK?k>UGjahK39uIeLQ9n}z?6y)zG!>nhLu z?>pz-+PZpEcWaj{%d&Q_vhji!c>|2WU_kb;h9#H;hD^em1cKX>g@h!SFk~PO69^1} zSR@e41PI_I1Y?62z?N6pmL*%(-s+{6d+#~tn?G(JIAV4u+1L%K{Q!*tA^l6K09!j4bAc-6JeW9j{U4 z)HtH4f$swkC_G{e<+7#g;~(S(e*Za~>l+5$)^+PPF1p(cCkaJWIm3DXvUy7`GmmZj z=dV8H|LMkWC7W4y@4_XhQ|%MgPL*()$3A4dKIX^j<@xo{Bg_8V?xG*wy>a6yS+_0aDKLBgi#7ETU_xq$#2qvxpL%t{(fPZ)Wbk?hC*gT7^B?Cm1*1ifB(4-}=FiDbAe*d-fh+J0kxf%g?#*fLr4r z*N=|wdQBWhJh*ue%N7st=YMe(fA|Lgk3ew0?_<&Ym8~snVDXX1Q7O-1Y;=q$j!09- z{f~_BH=pTsl1PxTmUEKVGuOh~B*14z9+trodv1Ra z_yO<_zzx&jWO^KqWAf&v2;BSKzy9k*YmYpV&prVWLmbEK-Mfn)-1u$&^ZM`b;KqAMk|r}|%%HEYZ~RiOR4_(Jn+dxf+sdvz zyV*N7#_rv_aal$+F3?@=WzOtHoOa$Tx&7`R^TQjjz0P}g-t;u>J7&(DIcrwA`0pP- zYwd|E`uk~Q*}g!$-HTBKX(jiYLd?RqUV<&g`Olr(w>~`C0DjTqtpGg1q_E40Jy*Qe@_M+_fHfI4r=tHtqf!ta|l$upjHtVTof51MPe0V0>vPq zXq19#sDO3^F;!7tL20)M>;zv%wFFYhy@gstwV-(~_gsdr1Vwz#V&M?YRLNTR^Uq3A z2%kK4j_hBxqo7RB2HC<81X0$ktCl3Nl;QF#;LSJ2s8vS znGrllo)du75N&{tsmd_M>_uhND0O2^-3tw)T8Fslh15VshBLM$H!t9Pf!e@M8aens znEZxAB?z94@0~%JY6l3RDOqpH_+-pzs7j}+8(%3H?^@x2ElYr^mv%s4ZV7Nk)f$bR zL4(9SXzWa0y2bh6xEj1MA4pG@*E66si!1rsH~7OTPR8XgD# z-Q5eqZHEi^pUeXcs=49{^qp67WPsxX%(jNA59~6z*zneZVYd?sX_?(Sw{Wsmj!iRu zglC&psP`ACH>+gVTtOxx`qsbD&PqzZ3IW5IPp~$ooG2!0k`^ntEJoZAJ-f#^q1NPV zHLMgRRk*(p@w0M;2P*}3Rbs}1;B16uF8@r+CGZ(G&2@57@K_A7@su;AGeDOHxL#1n!>jwwrd1C`vwCK$xXKQZ?=;=U) zm>+GOzvBzsaKizss&f~wTL^N#YM70|pi&p3529w5i1R_>;mkB1b;%4{HKPMwOqaFT zOxPKsft@=y%xuD-duGv(+vf9y;17$0(r-%$B$k-?I76e;WGbgZ~@ekMOZ^OQ}w@(w*q6s`#!BmY?HZnpsI)2BlQJ<3ml4l0wpkJ(rT1AYEGhwaZH$ll|`vJrw>Jc(gNkAH) z8Db~Y7$Oc8hfz=oMkG;8Q$*`QWlWF}K}RrV%%C+@TQ`=v@!C)uCz+B(mXr*a1p*bQ zW;rmYkquyt z24_@*s9HlIhz4h3jiuEgKvb<62mi5ckpSMb|7G^g02n_xCrE%P7692d0J2?&n$&8u zodIAJ7Fa3&s{(RsT{jrmk(jzeGiihnk^K z=nGM_T@S0u|C5jagIA!JUrC?!tOyZvjnM5KiGUHq!@#Zp1yUa0Jw(}AUPWM2mhp39 zMmk_@_HwemJ@~=FTuJrrK{_*-0pL;^QH&B32ZuEgo{TImqM8tUq14Qn-Aq`Pq#T`j zj?h4-F^J@JP~8YM5t`PJ(Tb83X?cP2Z(yfNQ$6*djHRAh2s9<{U~3G7Bx4lVb&B9t+N&A?_+b{0a%4prBi#n~K-4*1|_fRq%5#n?^O$~Ir^+B*lb+n(z#8SB$iuu^3Q;q;MXrHD z3?kh5vklz*vkkocH5VONJz6Ntk|i(PaiHH{Dp$WZbJo1`wmtp`!F!@O=1c!{4L`d1 z$Nbe_{7*y-ogKZ*=$^^im%f1|%T{yyPrlB-{mU2e&e0#o?9MU}NmbbhdJXV5)<$1^ z!&|O=S)(z+H~#4=KHhr$mr0r18b z%^djrH&?DScW$rqHFE@h(i4)9@riq{<0Q( z^JA*I3Yc!Dxj*(CN?VQj@I}j(edv=fy^v;>q3teIA&iHsNV`fOl)kf0r00}la^|&7 z0x*RHFjF$p#=`(7F}u&xJ!N+E87!DT_Ybyj-}&c<%REj|0mPHQe>8<0n0&sr!KIs` z1aMP31LOg9&&rV>uv)xso!VwEy^WMP&d@C$6@!Xm2`<7Ad9dQeh{gIqg!mF(N+PaX zkuIQwYSaSk1<t_CKUA%X*gXC{7)7iB zqj|+&L=aUmGJ)*0^@pprQvVUna)LoJAQO?Gn&%Yc1cYf-e+(wi4rr>_x~SF>#sV@T zm{BV_7F6p-Z5^~pOjARg;Bcl$W|gd&2Zm8Fq?HnlHFIfBRP=t4V7~(qJkLG}u&OyE zwOWU9t|pVi0fVcVs*8=P6JO3rfDjTxC`!9spsJS;oI&IKnpiYAqlF+EtSJz3fUiN6 zXdL{jdP7Vu25ABQyhG#E0Kmz&r+hYTpwGA?M9DJ7EB+XjHqaN*lpN$sYE(=VAk!T9 zN5L2$M69;k`-ycyBvNCuU`(W@UJ7~DzatnsseWfD{ti3v zKlT6d-JjHAbBrTw%6x=gRn!NH0+AXX6EFd`*#=v7)Hokukx#hA$80IY3@`9B`uflf zEAi_u&3lmi-p9494SL1`rLrd*E960ZAKZmk+GCw2y_HbmyhW7fgYe+ zl&UI4g*YfmzS<&`(+1L@grEcjuNn0as7tHTpM{AkuMK3)h;+t6{2ZX8 z3$2fEB*M|6{H%qoRz||M4DR*H>fpG@2#bv&5#gs^*cd6hjIbw#V@n-8{aJHv$DJlloQ7XrO`|w>~-hMDIKI*79&P+_>3=JHqs<9d|Mo9vGgAb)Uc0By$ z9ZQzHzO(6@i$Xz;#516Q0TKF8N-7MA=r+M@M`d?VGa4Bkvejhwrk}>6Pe|xL(7Lwd z!ovJ!)jay>s^l3Y6J*v=mkfwR{RGn?#w}BoBQ4ZLqT33=-|^5x>woEcWxe~`bCB{z zL@G}x9JQBuYq{l)4P5h`>&QajWAFVfN`?av0Qw)Y^4u36#37sxe1Ao?t8~?(MI5Tfyb1?TgD-+C*%hjuc&cb9+VrT-(j^XET^Z~MuA#Gg6pXkOdb zOR2Mq^t|&}_nq(Xt?RFE04sq_KwnpP--FAKIlVi%=?=cQXf;RA+DXw{NK?4%GXBKc zT_5?t2QCM`HjPTA$Kgr<{Mj349`S(}3>;@SQzD+EJQ84AbC@q|{!a#GEn?ZqMf|~g z-^)42tR|X0J0}SKDI@|_71b>ziz>s2#4ShQVb45GJdf%u_PE$EGa^U z#f#-fLyz$Ft#{n1s>e=G(*ei%Cofp=#ecZulGzMu#=?!lcgED zAOF9bk^|sd1i&*~%{a7NfWbjEKiN)q)?ikq^tHICU@Z~^W1WjV*dQ1q7*TJ%#~LGr z5Tv3ebQ_hbN+@awu|Z-b6hLgyASRFIw+4+tODd)ys#e>X{05H(K~c?H07`Bh5F{6P zo7@TztRhzOgu-^#W zmC=BX8Zl#_HH)nQO|_Z?rzy7JjFK58O9GjVaxmAClGF+`)-ED_ayjo)DL9^QW6;0` zVeKkewR3|>lG)O1Zri^lz!!{mIPpF*8oab^0i}``4f`Vkf~dyQRt2cWvM(8+0&(vB zp91`qAjDITHEuQ8h#3d@Oeg``pg+GoQRz=HDw5@ZUyMp>6f!lf`;&pch}E{-UyN02 zU65L&?Ua8pV>(&#A4MIyAMhW3RleK?2i0tW9^;v#Fhjr?AyQb1`Kr4>W%n056 zgx+qXm}}ZhQbaUiUI-i!3lDfl&6GGsmBy?d?zndo-Q^N5R#=I zN5pVa9C7QX{!s2cT;_V-(XTsRN#CkoBN6Km^SP}XzjDXHt|LdR*f=Xo(^Euru?7mQ z^LbZnxZA~*`yRXZ3ws6z)^)@)m}fFstx;H}8MA^gQ$&iWdKH`~9$^gFVKKYVusawt zg3%#S#>B_9BxIu7#l*9+f4S#BZ$>!f3D80`-?Fs!lv*nDo)7;y zpZn@J8G7t?_S`bi*faFN?^aJP{l#i%_<*%Qsf6jD%?GQUeCqR` z`x~I$dEj-u{R3Z`QHKx7Iqb1}_-Nw>LQsxgzLHSxyzYRd3DH<3N?%4A%KWsk4SFgUBv+H%j=qPf+3B;%5=Y8_e*Fchx?bw0aGekNx z%$}Qmj8kwe;Gbc}L4FfMvvr+dTR+Q*04IjKMz--!TW)?tRToW9(?N~ifok7+?n?mZB>8{49iTpa0^q6q{!f<_nE3hHchV6xndy}Q0+C9q zcUnL&M1r$MFdAA>d%5=B_#j0g?NCgY5<2sC_Y?>r4n`~*aL20IK9*--T9C03sUDASyxfjs&f0e?Y{j z=8p$OyogB<5`r|u=qReA7#%Ze>mg{}SX&RGX%sZclq{Blmk8H%xN?-s{%wLvC(Yiu zG}aH29Xh~&GKv3lY6Y0|U9`@ycBiZvT`I$qECIg1M|?7Dg71_rS2H1G;(fvRa?_}m zq)h~jD*{Rd(U7$)0kNQALKUDPCj&GHn%~b+!UQR>?;bRIiq$V`9k^(oA=&0oMZst$ zMv*KB`;rp?V8*NcBCX2*6yPsnwJrCTTBIV8Mo|_k|x*Hw50$q10X7-sxeh;w}DEcH{Z?kTkP4P|$nIV*GXh#?7BEq&k=qd;sR!-V1 zt)DpFovS9kHJ5H>yx(5uTy$VV>ou#eon?w0o{~?oK?#YYSS&LKM+MjvAlR5=qCkS> zXWMq-J32VkJB|}5#}PH)J`WqLlG+#*&%CJ25>w^d|Lb>T=ixTj^On4Rejxj8QSAb) zV+-HidVhBPAynaI?$X!xiMV6cvCL0?b~_no8G_u&6l1%chWxSzs-m{zWitQV$MGDF%oatGu%r#_8i@@ z4Sm&G=70L{uS@psId6R5W$m};n#u)#Qg|t!Zr%i^9?L1Gyn>TYUcs5CEp)GX^=tme zPjCClXP(J`$>}jYewhTo)o(iToZnp7(Jx^NBNrLVzi+*rd3Knu%$PxX%rV4gokih{ zGqA_z1^VWfzk*~L*|x{YhDS+v53%>hx8YnM+lK(iFB1fSZB_p#ewK;hq52;F;o<+> zp{nzy+iV>4u+?JmUB7eYnOD90)Kkq!t%igEF3ZuBbK`8QW*J?_EoIh4XF}>GQ~;B! z{)f{D9u}X>NoSn1_qN+_p935=EhKfKFTI%({AZ^q1DHYpOs@84lWtG706YtT;3*{0 zPXS0Te76=|jlL`}(+Cv>Zp))8&G(?ER zLWnhB1gwe}C0M|Us(oT%A&7u&h5QL2pco?t(GX1D9YAEt-lL}3R6D%>Yad-zy2%Lvt5sC;qjN`gs*)lZDDp6Lu zz)-Epy;+m()!B^9K8ohh_Xw-5LAeq(Y(P3z5%+gs_w2-!D(GkjI&0GJ9_d0mYUt1i zT7$5vwZ>j?#duqgC;jZ#ty8<|e2T-5Q*uyIn`=u_j}I1$qq87%sWQ?`c|3}k85dY) zU{A5kUE3ZZ)iTR5tQ1eDv1G-F9SPhao{@^7Br(MR$6FyQcJjTe-Xo2}b)E-St*aI@ z`#SI45ukM;-dGX)t&JPMG;%2KGk5OGD|B`*u#zqcKE$HYSQhMVqm2Ga<|(m_9`MLHiMnPzfSrK{beo18Jg~2{I}gMlrHmMfM8pG{)}O z68T*`S>pecv3T*i?z*9%l~R5CjH42681%E3tm_xd3Hh-wprW&YF_VYVZm}l1am&WA z=@9J+&)g2+&KnmH^8jLt`F_#1@}qR$C4F+RbWpUnlf|pg;p&flmmddJ#1On;GUa*^j9ECb5N8D^8$h-S>Wa$E_Dkdd+fU*zlLtmzXd3JE@-hLazAJ zzr=^Y!a1ERoKBiPo_uO&TrydhSW{vX z@s&q@z`1dQzn(J}cftw8r=L!I)>+tP%fLCB|9lM+0@>r+aHFF%x9wo~XB)_plnjHP z1n|?A1)z~D=tx@f|27feFl=d#@R^6M8%1?4Fg86^hcu3T4u4V(fJ_Pgi^f^# z2`d1Tm}Wmk1u$6w5T1GY|1S<}sS`~k=Mw|(%LBU5Ym4HVq zfygKYwZ1GNRDwjspuT93SPcbHS436qmK?z3c>=+Lfq-I=$)0a% zt1T2&X|;IEo5^_*g5*+vf&o!!D>JMJ77QwQRGWgSBRZy-5e+&P8?6hr8HALeP9id= zab_S3;7bwCDIo|x4uockR*EDAOS3dY^7O*~4wck-P6>jX1Ym=(rq`@$4oQ-X$+#N8 zCldO*WwI?Ggo6%^%RFI<-@JJL}WtFlZXOEMlA8)aM3FcQVo zN<$>qT$8hcC=6bS-3kQ{C7V(V1#A?d#^G%N?*!-f5}XoB6?EnR?AQr*2ByA;sJDYC zsZsDnN?As+RLIxxW{N9#G85qwPh2#VlZ--8MtZv0U9VwMSYA;2)$(vM#{CcNARFjq zeh3^T&=to>WEu93dq+pv*}sU6a*Fj4^Tn|`cy7D;kLAu^jhS9&=Pi$3fb*xKp&nF5 zMXEp8`rzlbJdHOq1FP0m;s!GWQ^I8R#Jb^K_kCk*axbL$^VgL^(e{h+eU@mzh0rI~ z72E4#2n9u&-l#YwZep^!1RYZ&dt+N39?i72r@N!U!BymQr2@@)K9pS1x_ZDSY10>N zQI3+pjG)@1ISu|Ib=hj$bFA)SU>b!p7VO|jUPnppXa?VVz8}CPK4)089%8* zRjXYy-s7tsy#2S|$I9hL^S-xTmIqVs`|dB3mFNDygDH9;@*QLB+G@4OyzRIDO46jk z=EomqY5h^wh6aCC*MGh7y05=_GQSkZ#mlZ-_=+QHyN2KSv61gpPC5HkEL(9pk&XHJ z&ws#69E8FE!*NpPwrpxy3_lXbro$Pa={ZB!{2ZGE`Kzm%Oxv&r|Tv z!ee;d+uq5S*Z<2Az~;k{0GRCYH&f*Qw)I8-WElWqQsRG@Y!7(ms{c<_@qao2aw;z$ zq&)g4Ga^T?R|+b4F=!MJ-?9RzMaVLIM2K2W79*HoFrs2zaFJ0dh@t3%6h(Y7Xeb(_ z08#=i#O zFW{g2K&}GVr`q2F`~XRkr>(X@e@*~II@#kd5@|c#U(A>q8;{HVjVb9qUjNSf^;cQ) ze-I0%Tz(~GV!ER&KSv!nh4}(65m=x~(h?*;B#xVF%45F43=xiSQ1;63Se>2f8A%PJ zolqa0OM1f4sM1?h`b>e|VhM_tnorrjN7+5M zi?~|C21}>)oS+a=xZ(4IviDbQs%Nf#?W{torw8u~1RB1y$fsC+LmhO z$p~_@Xwlk2qicZ;k2ghUBqDo?YD})c>F&mF*nodp)%PVA7U!FRe(xKzjZg?)Vll>r z;2kzBl3?a2AvGeA8qEl1J4OY}t~iPA+`M_|@be+#Bi#3c{}3BpKvc{L0Er+jg0!|P zE(4#oQZ!nJ>pggvx1lb^JoNZBdPJDf+qLhTHybnM#FrkdeWe3>cO5>uoQ&e$vwyMseXDYop4W-uh>(J^u{)XZE9-_a`+*IC=Ff{^#I_!zVs* z)z^U6j{C%>$MiT12!QrDuOljcU}g8hwa4}xQJ7Wg;WHb*!~dDn$GM%I$Vn#=pK=P( z@yBBpErKi~{r+{}eTx97(|q)CM(=%qwARSG0JP=(`vd?^5CF*(i$DVW<-Om;dp*P9 zemFf#1p^tfwRs!#sZmhh|7>H%NOI&QUf?o*XpAfc**J5Vj))p94^CJ z?$?=|{DPA{IWjW#KMv3R?6?hJsuf_eDqw0Gz^OKX$)tcDy8M4~1^AZ(5--18#|C{pv-+W_lBa5Wj6TeF%iv*WT|3$@mA} zSlyQdXdqH;Rry;afr(V4IS%;q*EQ9cNZa9lBPLd9Rs4;O$J71Wz<=E9KMwwXJtY4J z8tbl6J98sFTBFj8@KJ_lin9fd66G8*%trCK7lR!VxUCtuKcr;dF<>Hk0MaIjbJX`H zjAb?Iaf$k9fplgOzXXVm#3UnFo4c9KXcs0lu~zf`IK>PbB5ZJ2QA`39grE^gQX{Pv zNti(rIXdcl=raZ8nm}hTj9OuHyoYT!KMI{CIy0r$M062|GQ(ILlSo3d7Be=ZfX?e8 zm=Z-b93wD0#N0Ntga_8IBOt$;WYDTr>k7jzS{{O%CCZplGb$DP*ycN*A7J>vf55uJ ztY)c4q&^S{)evl?HW&?98?Y+UuNvkec%!5$vR8xI8X}X#WR%oAv~lD5UC*cUUGM+l zW5mU|#HE(c-+(Q)Yybl4A#LUb8g+Trl*=H?^2gdLy<={azE}qqleVXU;tLh0L8d z2j@JC=5@2>;h*ulzx#nZ?%8nLKEy#sN5?Exx#P4mUp;5#>KF3TSDc42GM-}?f^y2S zbNJF1Kg;j@&hOj}ycl?N8i`Dg=i`W;mP%B*sOi($-F7D0 zYIKYDXqx6B9%-60dTptXGRZ@(`(+(u%Hvb-#}ZMt1@_YH!%t7t(;aD=-ud@8-+apV zA9&y+?>Y0#-+%Qn$1plJ*2+S6`6BE*CN_-T{V=tSTbOai3G|$_0x@RaHi6H_;Ziv2 zg}m~(lXi}bjD6&=W#U9sCnV@PB}_*4b307B)+v|q_k0>hqE7^aPel|Q2!uX$@Z8l` zONQ#+wO7(8JxEttpsV0119&B!GdDE1+T$)BzU9hy@!dAAG?Zi{kL21Og$Xgs4cs6S4wnuh1+mAXz_1 z#?=Q4$|wJ9f6v)p$lp`V;qwAWw59FB4VVpUcZRkapiKlAQ_?Wn6yM)3J{dLuqgiG& zWYSg7B!r3>2%*w6SO`HyRV5FaG^jdBvYJ2#1Sffi$TkUJ#z}y3xlE(c7{8tX|LrCK zCckZ}3N=h*HCLBJDn?bLLtzYKRP$O^phDE#QxC zC@p9K|5XA0PJb<{{`(m%a%}gzKdEDd5&9`nD2`!Vfrs4~4;sUfHs*8@<{PC~g%_6$ z=TPDP%<~hP+>;5Bji?mM6w4JVp_fwX=q}euvxMxxRS@*=sF#Z`;Y(@GgumQVoHH0fqxM@franK!+KjIyT@6O6%V6hI_s z0cCc;&Jcn_7(-1>MIIsOuE>fDwy^ind;Q+$%IE)-!jVZ$VyE8rzlM7dz2C zN=;s?2opu8ahrh9dhYnDfAygsOm^xKi&mi;2qCY?I~VBb>Y}HsSnZwd761=Uebv{# zdey~i)||_m-u^}!^%}+qo3;*f&RJ)3+Nmd>@W6d{y~nxaC<>*?{l!yO0t zyejbE&zCKmxu96Yo^%rNamQhnFDF{Dg0O8H?x#OReZcM6gBuwm*|C$+JMU>(0A#%S z-@a}K05-=n046K|83s(uXCJzOO|>2G2mWe$s-BUt^rDq3Kl#41&U*3k-d;v)HN>|T zW$#;ya;^p_^i-Mg!sF>&c@z@c=cgjTJD9(MOW*#xtpDm)PXz8boF`{LDuBsq0H$OB z=#zl|r&;}fGBEkH|C&R7kHJATH|(H7ooawiV=0P5Rq!?tD1y&0Huvz8rnI8iT5M*7 zw8;PsNC-$S?xIj|_sVYN3*pzrSX+kZ{P-`&WA?>!C)}p?p z5lS+&D?*(^q6l>bq!8y9&9EBh3IJLPfM!JIGLq3@(lCO5Y!oxIN}-{2*gzMCZdJ-y zFpjzx8hD&BG}6Fmu|nOYB*!nJ)HJLLo+Bb*vn1S87@*!gf*%}|^w(>$2hEZt4^$fs z8;@BRI!bEsTE^BITaPOZvHrOL%WLBKs}^_q;5(xub9 zLO(`Is^TPguVR`aJgm+SS!SdbS1cRex@ z{FgLxC4hI3rTJxCc{-^Dbz~;mO?y9EjyZq(p&W~iqFdkamOoyzV$~{6I^}qrbNHYv zUp#}q`O7P~=f20^^xf~Q|Kik_0h`Xb;EnTt?}L9tp_tc0gDL~P6_y^+!Li34*L-Bt z!{-7&n)1497cD;K!b{e@ha|1D`q&lBo;!=_Kr`RhWSRq7zQQ-E|i_HikA6e65BX8YbPji;dFy*V!skBsxmN*SJN);s z{RNzQ%K%Au`JIg}jW z?{jebfc;ou7-M4H3p^R<&!3xz`vFV?|EIs^tXqd!^-g5>jZ_lLfQ2X(nng!4Rv@EB zDK;z;VYv}H#8C5&B+KwVP)j{~vy441P>Us35(AhP8IYu?O;K0M+j0UlV${ZH)SQ@~ zq>f1=jATSMrWi+*y`v%#9pb5o&D;K2sB36N9|aO|j2X*V+DW}^$&T!!*9*slKwku# znkf&)fs``YTxdR#DEze>X5qrubxS$xae;1>vZXNGD5jftZdm`z2#=QjWfxZqS+O^m z(5Xb7LMW{BLcxUKyqI8ujg%xY#KRi9#D*wKN@i?_x}k&Z9`Kx= zZ4dqACgS30m?&SCt26R_Su&PyS5(0zInZwt0N#NMIVqqzK>(O`>uK|^vU2UK59K)i z@XAlV|Jtv8^3S$*s>T&vLKymIWa0q(#1HqJlqoE^Z)Q?jLcfd4vr*-5Kj^wPJrvJEqg7!*as zkYy?V_}M=sOB-u|+o#v(>2bIc0F@47Hb1a@d0#1taspt*3Zz)XR;!5SJKbz_lw|i_ zhPOP<-W@{>?-*j#L7j+ttJZ&`D~vYyD&Y&7!)TFEhFP&5RBDp9FOb@?K?j$cM;Zhxy5`Wz7L zElJr}?_6H@o9}hkUVH6pfPedy+Qv=<0#2^@%YF!esn^e9+rL944GtA-J~6zmO#}=@ zRO5t75aJLaafLQM{x^15%jO(=CLS{J(V_EMkoq?=X?g zi2>s69K^o4Uyn|To|wNi$je;LqIZvMlm6zcw^DF3cx5?N14QU zlF_-OHw;b%{?9Zqb1;O=VMP!;fe2UwG^daO09lq>116IJ`P^4q*ZKWiC6EcN#uTCT z_*0?}6SqFE;qm)zun!=nps@@flR3jG4yLYays1$)MhBkfaULdP1z8s9k~`S0gE* zt?CI;P98eN;)yVMmy)0qL?{x7)F8Qth)k8lNG@CQ9#v>Y!blVtwSguxNaoC^P-t+3 z3P-ih%7?OuZE=bgA>Fo;+M(xy{A%xG7caiNt8PZ;n?SGNy2VOK1AF4Q@~|7LZGZI9 z_0LjE#6dH#YD0w@)uN>uY!nI2A{vQTQcdG#p&Xh?n$K4uc98}zPBmq$TFW|v?XbS; zRno2ZcMd6A146tlWG;A<^2!2J=pu49PlmhA83JpZMCM>oB*(T zqO7{$kd&MkUGn!!T)IN+ym`prLO z=B&9~`113~Cglt{A2{u}dHnCc{WyR0;SW6wybySN((C(y&sRFSE;`|)7qRk~Gw7&v z0m_!m_wt=@ewJplcBOOa;PfdvJq~9ApxkBc!}l*+Hmev#6i+^hXvGRf>M2_u+r!4q zLp-*9m?R6hOmQ~CiOms-dQ|g;K=CBrQx6%5cVrrH8c+=w6pK(Wh8cwpdg3a3T$A-% zZr=Ryi_Tqq>H784UwF?F5zyPwaoL+sJn%LZi zsU!eTLIUV7F8%*y0>XoN@BBGy*J@NaiK5+2B{5Vaqv%aew);Scl;A?HdMLybBtV-K zuqL+vOeO~)#n^%dpSB(=U=7AgYT|%|NTf{;(>*W8kqmGK>1;-4wxVUfXS)=fT?6a+a|!QSp=Ue z1=J<2|Ccu4pOJqeAw8(?$2Q2%$*30ak6M-eNr0bLr9X-~6kz`{f0zdT&)7mLgI5x7 zg@^`m+(}R7=o7`LFcx6UK+`tyS|rY(OEM~Iv6>P>feSreYWABMMZovk5U|%6;c)|l!9TW zH*B*)>QW>K_1a2Cr-A=djdiyF2tTtF7nX&P%~4|_QO&H?X7FZ2ZM0Qt&7F_U9vI=a zXB=qfYsI2B7rR4R?lpCVz0FOVZb-+KdP^=WE=+qXNwO>5zWwwD3Kt!0+HNvsS9(OZv+LV_b58UyFw_HiN(#-`Io=bO6C#pJW z34zm3n9GO$;C+1RQ=hu0MFI>>=7527fDgxo;+fTIuMNR7GQ4|-YWM@-AEwXC>2bId z0PzfKH{Q2w=|XIQ2j;I}!?3b@s7XddDvmvAjUCAtyOU9Nrz13dM(Pu4u1PaEvJi4( ztmbAqK`=%z7_119SiH8M<2kYSNM5txG_HQ|`@*5`} z|N9p&U4HzLU0sOF$kKEIV}=$PfTBSWV=4A`Q(eA@^5Xdv2YT`{Yg^hCbUat!fIxpT z;8!IiDQ>t%HZ(#uJVx2WeY^KQm1VVu|h z-`=^!)^S~D_*;ALnK>6yyoi)2TC!zXmVB#S+j1OV(#m$?SgzYNN#!;P(zHQ=wm=H_ z#X%o}gzZC77zNV4v=1#>AVu>KwaG){T!0o*94mEHCvg=kmStJim6k1D4|#abT=w35 zm^maROR}U$vSiK=5N8fKLkwnS@7e#q*7{doE-V%hn=fVX1fIM#Akel#LtDl(MMGyy z=!{8vX{#zhZI13(SYcqmdK4jJDrLffGoCQ0l0?E}twpm;^*?v4U%w@q&7xIe!j0lx zpWq|sB@@AlDChBQ2h)L9<4(*}Gi%QF=43s-xMOdt?q5G!ulSxG<5qN;1WwZS19k=fVZa(GE)xaAc`<*fJI|G7``?Ps6e2|NPCr#Y21z^Wn@;?<&VtVD^cUI38g#=N|3!=_vI z$N(0@Og6_$jW^jn^A@A+DVkY=7R9olMsHYWsM5!>ph~0zYC0s+Aypk>L?I$51SJYV z(4zRsGT{r%?Pb$&+)hT>I*Nh^T^R}Z|v^>((`X0`@f~IXgy2% z|4F+p`n*Ww|4JZ_XKP95W%CHSdz5glP1QrigoHLB$h!o9c6pTEF3Jv2c~TOgL9#U8 zuTwS<6n+AWg@AdopBo6~kzI{XVyI|*s_@3)QjPCqAt;S^f~{p_u_LV;l7=H?E!n%L z`Cp3rb1oel-gn}GsDC)|Es7jyz32-v$r;PSrMvRPj1(?HCBGV#Dz=RMAbScj==cyAAIEw+4@`NZf zj>rj0z=&Xrzat9YiTZc8ox|}Q)v*|YCV;7P`vaBuA&qg#5*sU;Jhf6dVH#t znMj=-544_YQJWcCb)dzL9of6jHCxr%we_H3(oknftr`Zk%-LSSMS_nquf!`gC*ICv zft?&vdi-jr@js_G#j86%i^$h<13#6!`P;1c>6ra3TBZmKJUff#*Svr{tNJZ;5Fdw@^)Qb{PF$w-}mD~hdw)4t9|5_ zp`rD^cl+&J-_=DL$HZxp7dg*I``t-w6rY<2=8Gdiw9ae1MDp({-=-)n=#+s4K%@=F zn@zrV;0?a{+P<-$9Y6lf4ZXd8w`XGF7fa>ZFERv_GqeHpr-%TB`}pN|@4vLyPT&-Aw3`! z@4Qh;l=Hr+2&SyDGb&{orRSX3b~~%50nJLJ>575SD`k~4TB$%~5?IMXuZ>pL6;A(F zi)iZV7RgO=0rq?Po<*sFInulC6QJBHKV=l&l2pMrogh528)(CY8h3{Zbcc4+1v zlY6&(|Ccz0PX=M--#`8PU#8yGM;K~`hF7w3c!&o!t>cp)`!KJ(^2(WN@joFV|MAh^ z_#i)Riv?|x7?y6*s*i`t-N+ zV9lCa9=YKLHZ1RFc~l`wQ_?KOT8p<9@BAW{SATM%`n(dX&;n5qpp>SOrW|ZE*naph zKRkSRV%O;Cf2Y=d9e5TGs+{yX0`a~JOZe=)>^krA&(N70jY%w&@= zNC`6`@CKtCI%%Vw$s_*rA&J; zSlRjw)X;GZ6GUm93QcOFiIm4Ui_Y@szbZzGDjp=oqO2lo@m_MG-w_oBl+QB=0u+IE zXlt=Sz+7yZ)WXy-G?rc)zxM*0&G2w{sQM}uQmO!%(t&ST(TY$BVX9rtd!@q6xl9?S z6?)-#CwQsk%TO&=wA0?@h796eAmXjUIxmSyRh)*|jFGG%vu5t-(QWPb^SJk~eJ3KV zd>zy$5M4z1i#C595r9QPz(Vc+xA1&H?s|0empuoC`sb)t|HBV$-pbJM4PF>d%L;d6Q{#7BI@Z|f8_zc>E6esTI)d@gHj6bJW0}GeC#Mc{?UJOK8QH`92!ZR2B^cSnKUTI-jrwLdLFDkags@}HR-flYzd4{ut%`i_k& zR;;_ezrX*sl`C1jY#Ft{P&EMowgO50MimX)U0y2C&N5nQN;6A2(rEC;#3Vl(9p&)! z^yt3v@t;pLn>&H$fFCVo(tidK;A{c_mq!3NU(&j0zmXBe$fb^aoW7oZ>sHi(K2&#t z?ha8|6B7lfmPUmd6&Ga#Hd~kvwZZEcpVV-sjkg+G%W&Rcvk2Q-jvd^CKiR~O^Qg~< zi);9Ix@?K_=_+s`r2_Al`K+T*j-26rxaTy#zx52)=_`KGYqcc%SF0fKL(Ei!8R#Nv zrBq#oidZ61L>fYyVkAIipdvw>LXs2-1H895pOSe+>@+Q>nAI80R-IP+I@+a?-<5!^ zdhObJ(5yF2G))*A!b+r-vs(EmQLd?#k#t!mJ`%(u%6l@-%S_!@hqKDvwgc^NS+41jOYp;u<1h3XZ}-Wfqw=5N$z;$Vz$OJMOyw- zBGOa%02~4S5%^nR=3S2e4Dgpq>2*E5gVeiv(b|y2b4*Q*(QY*|@A(1nXTU4v_$jf} z1c1fI3;}Bk(~E0>6@_(joji+MfP~x{c@h`{P82OP-YU}hC(6tJzCj3VEQEozl_0oz zd9BtP8Pg*oRSzUtmdwU+qY=jq=iG^65ew#V?VIwHr&29@teVw zrhQi}6l@jl?#mtR+LOYb6ApHifvIyDA$y9{vUaabr6w{(o_Hd002ovPDHLkV1hr8PEP;; literal 0 HcmV?d00001 diff --git a/spine-godot/example/spineboy.png.import b/spine-godot/example/spineboy.png.import new file mode 100644 index 000000000..022cf7873 --- /dev/null +++ b/spine-godot/example/spineboy.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/spineboy.png-846f399ad53ae6f7ed8bbfe03f0b1f88.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://spineboy.png" +dest_files=[ "res://.import/spineboy.png-846f399ad53ae6f7ed8bbfe03f0b1f88.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/spine-godot/example/spineboy.tres b/spine-godot/example/spineboy.tres new file mode 100644 index 000000000..165089c92 --- /dev/null +++ b/spine-godot/example/spineboy.tres @@ -0,0 +1,10 @@ +[gd_resource type="SpineSkeletonDataResource" load_steps=3 format=2] + +[ext_resource path="res://spineboy.atlas" type="SpineAtlasResource" id=1] +[ext_resource path="res://spineboy-pro.spjson" type="SpineSkeletonJsonDataResource" id=2] + +[resource] +atlas_res = ExtResource( 1 ) +skeleton_json_res = ExtResource( 2 ) +animations = null +skins = null diff --git a/spine-godot/example/spineboyanimdata.tres b/spine-godot/example/spineboyanimdata.tres new file mode 100644 index 000000000..f52707c8a --- /dev/null +++ b/spine-godot/example/spineboyanimdata.tres @@ -0,0 +1,7 @@ +[gd_resource type="SpineAnimationStateDataResource" load_steps=2 format=2] + +[ext_resource path="res://spineboy.tres" type="SpineSkeletonDataResource" id=1] + +[resource] +skeleton = ExtResource( 1 ) +default_mix = 1.0 diff --git a/spine-godot/example/test.tscn b/spine-godot/example/test.tscn new file mode 100644 index 000000000..ae2e48e5b --- /dev/null +++ b/spine-godot/example/test.tscn @@ -0,0 +1,13 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://spineboy.gd" type="Script" id=1] +[ext_resource path="res://spineboyanimdata.tres" type="SpineAnimationStateDataResource" id=2] + +[node name="Node2D" type="Node2D"] +position = Vector2( 2.12469, 1.06235 ) + +[node name="SpineSprite" type="SpineSprite" parent="."] +position = Vector2( 503.556, 465.311 ) +scale = Vector2( 0.5, 0.5 ) +animation_state_data_res = ExtResource( 2 ) +script = ExtResource( 1 ) diff --git a/spine-godot/spine_godot/RaiixSpineExtension.cpp b/spine-godot/spine_godot/RaiixSpineExtension.cpp deleted file mode 100644 index f4b92781d..000000000 --- a/spine-godot/spine_godot/RaiixSpineExtension.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "GodotSpineExtension.h" - -#include "core/variant_parser.h" -#include - -#include - -spine::SpineExtension *spine::getDefaultExtension() { - return new GodotSpineExtension(); -} - -GodotSpineExtension::GodotSpineExtension(){} -GodotSpineExtension::~GodotSpineExtension(){} - -void *GodotSpineExtension::_alloc(size_t size, const char *file, int line){ -// std::cout<<"_alloc "<(res.size(), __FILE__, __LINE__); - for(size_t i=0;i(); + ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); From 5ec554413243ab7c3d4f52399525a4e6fe06bdb7 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Wed, 29 Sep 2021 12:43:40 +0200 Subject: [PATCH 03/18] [godot] Formatting --- formatters/build.gradle | 4 +- .../spine_godot/GodotSpineExtension.cpp | 50 +- spine-godot/spine_godot/GodotSpineExtension.h | 5 +- .../spine_godot/PackedSpineSkinResource.cpp | 14 +- .../spine_godot/PackedSpineSkinResource.h | 5 +- .../ResourceFormatLoaderSpineAtlas.cpp | 24 +- .../ResourceFormatLoaderSpineAtlas.h | 15 +- ...ourceFormatLoaderSpineSkeletonJsonData.cpp | 24 +- ...esourceFormatLoaderSpineSkeletonJsonData.h | 11 +- .../ResourceFormatSaverSpineAtlas.cpp | 14 +- .../ResourceFormatSaverSpineAtlas.h | 13 +- ...sourceFormatSaverSpineSkeletonJsonData.cpp | 14 +- ...ResourceFormatSaverSpineSkeletonJsonData.h | 13 +- spine-godot/spine_godot/SpineAnimation.cpp | 50 +- spine-godot/spine_godot/SpineAnimation.h | 14 +- .../spine_godot/SpineAnimationState.cpp | 41 +- spine-godot/spine_godot/SpineAnimationState.h | 13 +- .../SpineAnimationStateDataResource.cpp | 65 +- .../SpineAnimationStateDataResource.h | 8 +- .../spine_godot/SpineAtlasResource.cpp | 212 +++-- spine-godot/spine_godot/SpineAtlasResource.h | 38 +- spine-godot/spine_godot/SpineAttachment.cpp | 10 +- spine-godot/spine_godot/SpineAttachment.h | 8 +- spine-godot/spine_godot/SpineBone.cpp | 453 +++++----- spine-godot/spine_godot/SpineBone.h | 7 +- spine-godot/spine_godot/SpineBoneData.cpp | 54 +- spine-godot/spine_godot/SpineBoneData.h | 7 +- .../spine_godot/SpineCollisionShapeProxy.cpp | 200 ++--- .../spine_godot/SpineCollisionShapeProxy.h | 50 +- spine-godot/spine_godot/SpineConstant.cpp | 52 +- spine-godot/spine_godot/SpineConstant.h | 71 +- .../spine_godot/SpineConstraintData.cpp | 12 +- spine-godot/spine_godot/SpineConstraintData.h | 6 +- spine-godot/spine_godot/SpineEvent.cpp | 42 +- spine-godot/spine_godot/SpineEvent.h | 12 +- spine-godot/spine_godot/SpineEventData.cpp | 5 +- spine-godot/spine_godot/SpineEventData.h | 10 +- spine-godot/spine_godot/SpineIkConstraint.cpp | 48 +- spine-godot/spine_godot/SpineIkConstraint.h | 9 +- .../spine_godot/SpineIkConstraintData.cpp | 40 +- .../spine_godot/SpineIkConstraintData.h | 7 +- .../spine_godot/SpinePathConstraint.cpp | 50 +- spine-godot/spine_godot/SpinePathConstraint.h | 10 +- .../spine_godot/SpinePathConstraintData.cpp | 58 +- .../spine_godot/SpinePathConstraintData.h | 6 +- spine-godot/spine_godot/SpineRendererObject.h | 6 +- .../spine_godot/SpineRuntimeEditorPlugin.cpp | 71 +- .../spine_godot/SpineRuntimeEditorPlugin.h | 61 +- spine-godot/spine_godot/SpineSkeleton.cpp | 273 +++--- spine-godot/spine_godot/SpineSkeleton.h | 13 +- .../spine_godot/SpineSkeletonDataResource.cpp | 206 ++--- .../spine_godot/SpineSkeletonDataResource.h | 24 +- .../SpineSkeletonJsonDataResource.cpp | 24 +- .../SpineSkeletonJsonDataResource.h | 15 +- spine-godot/spine_godot/SpineSkin.cpp | 59 +- spine-godot/spine_godot/SpineSkin.h | 6 +- .../SpineSkinAttachmentMapEntries.cpp | 28 +- .../SpineSkinAttachmentMapEntries.h | 10 +- spine-godot/spine_godot/SpineSlot.cpp | 46 +- spine-godot/spine_godot/SpineSlot.h | 8 +- spine-godot/spine_godot/SpineSlotData.cpp | 28 +- spine-godot/spine_godot/SpineSlotData.h | 6 +- spine-godot/spine_godot/SpineSprite.cpp | 825 +++++++++--------- spine-godot/spine_godot/SpineSprite.h | 46 +- .../spine_godot/SpineSpriteAnimateDialog.cpp | 445 +++++----- .../spine_godot/SpineSpriteAnimateDialog.h | 61 +- .../spine_godot/SpineSpriteMeshInstance2D.cpp | 2 +- .../spine_godot/SpineSpriteMeshInstance2D.h | 5 +- spine-godot/spine_godot/SpineTimeline.cpp | 66 +- spine-godot/spine_godot/SpineTimeline.h | 39 +- spine-godot/spine_godot/SpineTrackEntry.cpp | 96 +- spine-godot/spine_godot/SpineTrackEntry.h | 12 +- .../spine_godot/SpineTransformConstraint.cpp | 52 +- .../spine_godot/SpineTransformConstraint.h | 8 +- .../SpineTransformConstraintData.cpp | 38 +- .../SpineTransformConstraintData.h | 6 +- spine-godot/spine_godot/register_types.cpp | 31 +- spine-godot/spine_godot/register_types.h | 1 - spine-ts/spine-core/src/AnimationState.ts | 12 +- 79 files changed, 2235 insertions(+), 2268 deletions(-) diff --git a/formatters/build.gradle b/formatters/build.gradle index 1d57bab85..102f44cc3 100644 --- a/formatters/build.gradle +++ b/formatters/build.gradle @@ -25,7 +25,9 @@ spotless { 'spine-sfml/**/*.cpp', 'spine-sfml/**/*.h', 'spine-ue4/**/*.cpp', - 'spine-ue4/**/*.h' + 'spine-ue4/**/*.h', + 'spine-godot/spine_godot/**.h', + 'spine-godot/spine_godot/**.cpp' clangFormat("12.0.1").pathToExe("$System.env.CLANGFORMAT").style('file') } diff --git a/spine-godot/spine_godot/GodotSpineExtension.cpp b/spine-godot/spine_godot/GodotSpineExtension.cpp index 87ce758a1..6813a2cc2 100644 --- a/spine-godot/spine_godot/GodotSpineExtension.cpp +++ b/spine-godot/spine_godot/GodotSpineExtension.cpp @@ -35,42 +35,42 @@ #include spine::SpineExtension *spine::getDefaultExtension() { - return new GodotSpineExtension(); + return new GodotSpineExtension(); } -GodotSpineExtension::GodotSpineExtension(){} -GodotSpineExtension::~GodotSpineExtension(){} +GodotSpineExtension::GodotSpineExtension() {} +GodotSpineExtension::~GodotSpineExtension() {} -void *GodotSpineExtension::_alloc(size_t size, const char *file, int line){ - return memalloc(size); +void *GodotSpineExtension::_alloc(size_t size, const char *file, int line) { + return memalloc(size); } -void *GodotSpineExtension::_calloc(size_t size, const char *file, int line){ - auto p = memalloc(size); - memset(p, 0, size); - return p; +void *GodotSpineExtension::_calloc(size_t size, const char *file, int line) { + auto p = memalloc(size); + memset(p, 0, size); + return p; } -void *GodotSpineExtension::_realloc(void *ptr, size_t size, const char *file, int line){ - return memrealloc(ptr, size); +void *GodotSpineExtension::_realloc(void *ptr, size_t size, const char *file, int line) { + return memrealloc(ptr, size); } -void GodotSpineExtension::_free(void *mem, const char *file, int line){ - memfree(mem); +void GodotSpineExtension::_free(void *mem, const char *file, int line) { + memfree(mem); } -char *GodotSpineExtension::_readFile(const spine::String &path, int *length){ - Error error; - auto res = FileAccess::get_file_as_array(String(path.buffer()), &error); +char *GodotSpineExtension::_readFile(const spine::String &path, int *length) { + Error error; + auto res = FileAccess::get_file_as_array(String(path.buffer()), &error); - if (error != OK){ - if(length) *length = 0; - return NULL; - } + if (error != OK) { + if (length) *length = 0; + return NULL; + } - if(length) *length = res.size(); - auto r = alloc(res.size(), __FILE__, __LINE__); - for(size_t i=0;i(res.size(), __FILE__, __LINE__); + for (size_t i = 0; i < res.size(); ++i) + r[i] = res[i]; + return r; } \ No newline at end of file diff --git a/spine-godot/spine_godot/GodotSpineExtension.h b/spine-godot/spine_godot/GodotSpineExtension.h index 1d2bca6be..e00726051 100644 --- a/spine-godot/spine_godot/GodotSpineExtension.h +++ b/spine-godot/spine_godot/GodotSpineExtension.h @@ -51,7 +51,4 @@ protected: }; - - - -#endif //GODOT_SPINEEXTENSION_H +#endif//GODOT_SPINEEXTENSION_H diff --git a/spine-godot/spine_godot/PackedSpineSkinResource.cpp b/spine-godot/spine_godot/PackedSpineSkinResource.cpp index 34bababcb..1521f1770 100644 --- a/spine-godot/spine_godot/PackedSpineSkinResource.cpp +++ b/spine-godot/spine_godot/PackedSpineSkinResource.cpp @@ -29,7 +29,7 @@ #include "PackedSpineSkinResource.h" -void PackedSpineSkinResource::_bind_methods(){ +void PackedSpineSkinResource::_bind_methods() { ClassDB::bind_method(D_METHOD("set_skin_name", "v"), &PackedSpineSkinResource::set_skin_name); ClassDB::bind_method(D_METHOD("get_skin_name"), &PackedSpineSkinResource::get_skin_name); ClassDB::bind_method(D_METHOD("set_sub_skin_names", "v"), &PackedSpineSkinResource::set_sub_skin_names); @@ -41,21 +41,21 @@ void PackedSpineSkinResource::_bind_methods(){ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "sub_skin_names"), "set_sub_skin_names", "get_sub_skin_names"); } -PackedSpineSkinResource::PackedSpineSkinResource():skin_name("custom_skin_name"){} -PackedSpineSkinResource::~PackedSpineSkinResource(){} +PackedSpineSkinResource::PackedSpineSkinResource() : skin_name("custom_skin_name") {} +PackedSpineSkinResource::~PackedSpineSkinResource() {} -void PackedSpineSkinResource::set_skin_name(const String &v){ +void PackedSpineSkinResource::set_skin_name(const String &v) { skin_name = v; emit_signal("property_changed"); } -String PackedSpineSkinResource::get_skin_name(){ +String PackedSpineSkinResource::get_skin_name() { return skin_name; } -void PackedSpineSkinResource::set_sub_skin_names(Array v){ +void PackedSpineSkinResource::set_sub_skin_names(Array v) { sub_skin_names = v; emit_signal("property_changed"); } -Array PackedSpineSkinResource::get_sub_skin_names(){ +Array PackedSpineSkinResource::get_sub_skin_names() { return sub_skin_names; } diff --git a/spine-godot/spine_godot/PackedSpineSkinResource.h b/spine-godot/spine_godot/PackedSpineSkinResource.h index a4cc5ff3f..f3e979c2b 100644 --- a/spine-godot/spine_godot/PackedSpineSkinResource.h +++ b/spine-godot/spine_godot/PackedSpineSkinResource.h @@ -34,7 +34,7 @@ #include "SpineSkin.h" -class PackedSpineSkinResource : public Resource{ +class PackedSpineSkinResource : public Resource { GDCLASS(PackedSpineSkinResource, Resource); protected: @@ -53,7 +53,6 @@ public: void set_sub_skin_names(Array v); Array get_sub_skin_names(); - }; -#endif //GODOT_PACKEDSPINESKINRESOURCE_H +#endif//GODOT_PACKEDSPINESKINRESOURCE_H diff --git a/spine-godot/spine_godot/ResourceFormatLoaderSpineAtlas.cpp b/spine-godot/spine_godot/ResourceFormatLoaderSpineAtlas.cpp index 7524071d4..f3c5c8ada 100644 --- a/spine-godot/spine_godot/ResourceFormatLoaderSpineAtlas.cpp +++ b/spine-godot/spine_godot/ResourceFormatLoaderSpineAtlas.cpp @@ -31,26 +31,26 @@ #include "SpineAtlasResource.h" RES ResourceFormatLoaderSpineAtlas::load(const String &p_path, const String &p_original_path, Error *r_error) { - Ref atlas = memnew(SpineAtlasResource); - atlas->load_from_file(p_path); + Ref atlas = memnew(SpineAtlasResource); + atlas->load_from_file(p_path); - if(r_error){ - *r_error = OK; - } - return atlas; + if (r_error) { + *r_error = OK; + } + return atlas; } void ResourceFormatLoaderSpineAtlas::get_recognized_extensions(List *r_extensions) const { - const char atlas_ext[] = "spatlas"; - if(!r_extensions->find(atlas_ext)) { - r_extensions->push_back(atlas_ext); - } + const char atlas_ext[] = "spatlas"; + if (!r_extensions->find(atlas_ext)) { + r_extensions->push_back(atlas_ext); + } } String ResourceFormatLoaderSpineAtlas::get_resource_type(const String &p_path) const { - return "SpineAtlasResource"; + return "SpineAtlasResource"; } bool ResourceFormatLoaderSpineAtlas::handles_type(const String &p_type) const { - return p_type == "SpineAtlasResource" || ClassDB::is_parent_class(p_type, "SpineAtlasResource"); + return p_type == "SpineAtlasResource" || ClassDB::is_parent_class(p_type, "SpineAtlasResource"); } \ No newline at end of file diff --git a/spine-godot/spine_godot/ResourceFormatLoaderSpineAtlas.h b/spine-godot/spine_godot/ResourceFormatLoaderSpineAtlas.h index e6d1610da..27133afca 100644 --- a/spine-godot/spine_godot/ResourceFormatLoaderSpineAtlas.h +++ b/spine-godot/spine_godot/ResourceFormatLoaderSpineAtlas.h @@ -32,14 +32,15 @@ #include "core/io/resource_loader.h" -class ResourceFormatLoaderSpineAtlas : public ResourceFormatLoader{ - GDCLASS(ResourceFormatLoaderSpineAtlas, ResourceFormatLoader); +class ResourceFormatLoaderSpineAtlas : public ResourceFormatLoader { + GDCLASS(ResourceFormatLoaderSpineAtlas, ResourceFormatLoader); + public: - virtual RES load(const String &p_path, const String &p_original_path, Error *r_error = NULL); - virtual void get_recognized_extensions(List *r_extensions) const; - virtual bool handles_type(const String &p_type) const; - virtual String get_resource_type(const String &p_path) const; + virtual RES load(const String &p_path, const String &p_original_path, Error *r_error = NULL); + virtual void get_recognized_extensions(List *r_extensions) const; + virtual bool handles_type(const String &p_type) const; + virtual String get_resource_type(const String &p_path) const; }; -#endif //GODOT_RESOURCEFORMATLOADERSPINEATLAS_H +#endif//GODOT_RESOURCEFORMATLOADERSPINEATLAS_H diff --git a/spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.cpp b/spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.cpp index 34a7a7ae2..9c1cc80e5 100644 --- a/spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.cpp +++ b/spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.cpp @@ -31,26 +31,26 @@ #include "SpineSkeletonJsonDataResource.h" RES ResourceFormatLoaderSpineSkeletonJsonData::load(const String &p_path, const String &p_original_path, Error *r_error) { - Ref skeleton = memnew(SpineSkeletonJsonDataResource); - skeleton->load_from_file(p_path); + Ref skeleton = memnew(SpineSkeletonJsonDataResource); + skeleton->load_from_file(p_path); - if(r_error){ - *r_error = OK; - } - return skeleton; + if (r_error) { + *r_error = OK; + } + return skeleton; } void ResourceFormatLoaderSpineSkeletonJsonData::get_recognized_extensions(List *r_extensions) const { - const char json_ext[] = "spjson"; - if(!r_extensions->find(json_ext)) { - r_extensions->push_back(json_ext); - } + const char json_ext[] = "spjson"; + if (!r_extensions->find(json_ext)) { + r_extensions->push_back(json_ext); + } } String ResourceFormatLoaderSpineSkeletonJsonData::get_resource_type(const String &p_path) const { - return "SpineSkeletonJsonDataResource"; + return "SpineSkeletonJsonDataResource"; } bool ResourceFormatLoaderSpineSkeletonJsonData::handles_type(const String &p_type) const { - return p_type == "SpineSkeletonJsonDataResource" || ClassDB::is_parent_class(p_type, "SpineSkeletonJsonDataResource"); + return p_type == "SpineSkeletonJsonDataResource" || ClassDB::is_parent_class(p_type, "SpineSkeletonJsonDataResource"); } \ No newline at end of file diff --git a/spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.h b/spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.h index 13509ba21..9736655f6 100644 --- a/spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.h +++ b/spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.h @@ -34,11 +34,12 @@ class ResourceFormatLoaderSpineSkeletonJsonData : public ResourceFormatLoader { GDCLASS(ResourceFormatLoaderSpineSkeletonJsonData, ResourceFormatLoader); + public: - virtual RES load(const String &p_path, const String &p_original_path, Error *r_error = NULL); - virtual void get_recognized_extensions(List *r_extensions) const; - virtual bool handles_type(const String &p_type) const; - virtual String get_resource_type(const String &p_path) const; + virtual RES load(const String &p_path, const String &p_original_path, Error *r_error = NULL); + virtual void get_recognized_extensions(List *r_extensions) const; + virtual bool handles_type(const String &p_type) const; + virtual String get_resource_type(const String &p_path) const; }; -#endif //GODOT_RESOURCEFORMATLOADERSPINESKELETONJSONDATA_H +#endif//GODOT_RESOURCEFORMATLOADERSPINESKELETONJSONDATA_H diff --git a/spine-godot/spine_godot/ResourceFormatSaverSpineAtlas.cpp b/spine-godot/spine_godot/ResourceFormatSaverSpineAtlas.cpp index d976133a1..ef051f31c 100644 --- a/spine-godot/spine_godot/ResourceFormatSaverSpineAtlas.cpp +++ b/spine-godot/spine_godot/ResourceFormatSaverSpineAtlas.cpp @@ -32,17 +32,17 @@ #include "SpineAtlasResource.h" Error ResourceFormatSaverSpineAtlas::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { - Ref res = p_resource.get_ref_ptr(); - Error error = res->save_to_file(p_path); - return error; + Ref res = p_resource.get_ref_ptr(); + Error error = res->save_to_file(p_path); + return error; } void ResourceFormatSaverSpineAtlas::get_recognized_extensions(const RES &p_resource, List *p_extensions) const { - if (Object::cast_to(*p_resource)) { - p_extensions->push_back("spatlas"); - } + if (Object::cast_to(*p_resource)) { + p_extensions->push_back("spatlas"); + } } bool ResourceFormatSaverSpineAtlas::recognize(const RES &p_resource) const { - return Object::cast_to(*p_resource) != nullptr; + return Object::cast_to(*p_resource) != nullptr; } diff --git a/spine-godot/spine_godot/ResourceFormatSaverSpineAtlas.h b/spine-godot/spine_godot/ResourceFormatSaverSpineAtlas.h index 4feb076fc..b20420772 100644 --- a/spine-godot/spine_godot/ResourceFormatSaverSpineAtlas.h +++ b/spine-godot/spine_godot/ResourceFormatSaverSpineAtlas.h @@ -32,13 +32,14 @@ #include "core/io/resource_saver.h" -class ResourceFormatSaverSpineAtlas : public ResourceFormatSaver{ - GDCLASS(ResourceFormatSaverSpineAtlas, ResourceFormatSaver); +class ResourceFormatSaverSpineAtlas : public ResourceFormatSaver { + GDCLASS(ResourceFormatSaverSpineAtlas, ResourceFormatSaver); + public: - Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0) override; - void get_recognized_extensions(const RES &p_resource, List *p_extensions) const override; - bool recognize(const RES &p_resource) const override; + Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0) override; + void get_recognized_extensions(const RES &p_resource, List *p_extensions) const override; + bool recognize(const RES &p_resource) const override; }; -#endif //GODOT_RESOURCEFORMATSAVERSPINEATLAS_H +#endif//GODOT_RESOURCEFORMATSAVERSPINEATLAS_H diff --git a/spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.cpp b/spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.cpp index 01c4b7e1c..5fa669c04 100644 --- a/spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.cpp +++ b/spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.cpp @@ -32,17 +32,17 @@ #include "SpineSkeletonJsonDataResource.h" Error ResourceFormatSaverSpineSkeletonJsonData::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { - Ref res = p_resource.get_ref_ptr(); - Error error = res->save_to_file(p_path); - return error; + Ref res = p_resource.get_ref_ptr(); + Error error = res->save_to_file(p_path); + return error; } void ResourceFormatSaverSpineSkeletonJsonData::get_recognized_extensions(const RES &p_resource, List *p_extensions) const { - if (Object::cast_to(*p_resource)) { - p_extensions->push_back("spjson"); - } + if (Object::cast_to(*p_resource)) { + p_extensions->push_back("spjson"); + } } bool ResourceFormatSaverSpineSkeletonJsonData::recognize(const RES &p_resource) const { - return Object::cast_to(*p_resource) != nullptr; + return Object::cast_to(*p_resource) != nullptr; } diff --git a/spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.h b/spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.h index e63993125..2c42ee5d0 100644 --- a/spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.h +++ b/spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.h @@ -32,13 +32,14 @@ #include "core/io/resource_saver.h" -class ResourceFormatSaverSpineSkeletonJsonData : public ResourceFormatSaver{ - GDCLASS(ResourceFormatSaverSpineSkeletonJsonData, ResourceFormatSaver); +class ResourceFormatSaverSpineSkeletonJsonData : public ResourceFormatSaver { + GDCLASS(ResourceFormatSaverSpineSkeletonJsonData, ResourceFormatSaver); + public: - Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0) override; - void get_recognized_extensions(const RES &p_resource, List *p_extensions) const override; - bool recognize(const RES &p_resource) const override; + Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0) override; + void get_recognized_extensions(const RES &p_resource, List *p_extensions) const override; + bool recognize(const RES &p_resource) const override; }; -#endif //GODOT_RESOURCEFORMATSAVERSPINESKELETONJSONDATA_H +#endif//GODOT_RESOURCEFORMATSAVERSPINESKELETONJSONDATA_H diff --git a/spine-godot/spine_godot/SpineAnimation.cpp b/spine-godot/spine_godot/SpineAnimation.cpp index d0e76d54e..a646460f1 100644 --- a/spine-godot/spine_godot/SpineAnimation.cpp +++ b/spine-godot/spine_godot/SpineAnimation.cpp @@ -46,8 +46,8 @@ void SpineAnimation::_bind_methods() { ClassDB::bind_method(D_METHOD("has_timeline", "ids"), &SpineAnimation::has_timeline); } -SpineAnimation::SpineAnimation():animation(NULL) {} -SpineAnimation::~SpineAnimation(){} +SpineAnimation::SpineAnimation() : animation(NULL) {} +SpineAnimation::~SpineAnimation() {} String SpineAnimation::get_anim_name() { return animation->getName().buffer(); @@ -61,36 +61,36 @@ void SpineAnimation::set_duration(float v) { } void SpineAnimation::apply(Ref skeleton, float lastTime, float time, bool loop, - Array pEvents, float alpha, SpineConstant::MixBlend blend, - SpineConstant::MixDirection direction) { - spine::Vector events; - events.setSize(pEvents.size(), nullptr); - for (size_t i=0; i)(pEvents[i]))->get_spine_object(); - } - animation->apply(*(skeleton->get_spine_object()), lastTime, time, loop, &events, alpha, (spine::MixBlend) blend, (spine::MixDirection) direction); + Array pEvents, float alpha, SpineConstant::MixBlend blend, + SpineConstant::MixDirection direction) { + spine::Vector events; + events.setSize(pEvents.size(), nullptr); + for (size_t i = 0; i < events.size(); ++i) { + events[i] = ((Ref) (pEvents[i]))->get_spine_object(); + } + animation->apply(*(skeleton->get_spine_object()), lastTime, time, loop, &events, alpha, (spine::MixBlend) blend, (spine::MixDirection) direction); } Array SpineAnimation::get_timelines() { - auto &timelines = animation->getTimelines(); - Array res; - res.resize(timelines.size()); + auto &timelines = animation->getTimelines(); + Array res; + res.resize(timelines.size()); - for (size_t i=0; i(memnew(SpineTimeline)); - a->set_spine_object(timelines[i]); - res.set(i, a); - } + for (size_t i = 0; i < res.size(); ++i) { + auto a = Ref(memnew(SpineTimeline)); + a->set_spine_object(timelines[i]); + res.set(i, a); + } - return res; + return res; } bool SpineAnimation::has_timeline(Array ids) { - spine::Vector list; - list.setSize(ids.size(), 0); + spine::Vector list; + list.setSize(ids.size(), 0); - for (size_t i=0; ihasTimeline(list); + for (size_t i = 0; i < list.size(); ++i) { + list[i] = ids[i]; + } + return animation->hasTimeline(list); } diff --git a/spine-godot/spine_godot/SpineAnimation.h b/spine-godot/spine_godot/SpineAnimation.h index 22b330f8b..98dbed587 100644 --- a/spine-godot/spine_godot/SpineAnimation.h +++ b/spine-godot/spine_godot/SpineAnimation.h @@ -40,7 +40,7 @@ class SpineEvent; class SpineSkeleton; class SpineTimeline; -class SpineAnimation : public Reference{ +class SpineAnimation : public Reference { GDCLASS(SpineAnimation, Reference); private: @@ -53,22 +53,22 @@ public: SpineAnimation(); ~SpineAnimation(); - inline void set_spine_object(spine::Animation *a){ + inline void set_spine_object(spine::Animation *a) { animation = a; } - inline spine::Animation *get_spine_object(){ + inline spine::Animation *get_spine_object() { return animation; } // Vector> pEvents - void apply(Ref skeleton, float lastTime, float time, bool loop, Array pEvents, float alpha, SpineConstant::MixBlend blend, SpineConstant::MixDirection direction); + void apply(Ref skeleton, float lastTime, float time, bool loop, Array pEvents, float alpha, SpineConstant::MixBlend blend, SpineConstant::MixDirection direction); - Array get_timelines(); // Vector> - bool has_timeline(Array ids); // Vector + Array get_timelines(); // Vector> + bool has_timeline(Array ids);// Vector String get_anim_name(); float get_duration(); void set_duration(float v); }; -#endif //GODOT_SPINEANIMATION_H +#endif//GODOT_SPINEANIMATION_H diff --git a/spine-godot/spine_godot/SpineAnimationState.cpp b/spine-godot/spine_godot/SpineAnimationState.cpp index 0dcbaa107..2d9f6c8f6 100644 --- a/spine-godot/spine_godot/SpineAnimationState.cpp +++ b/spine-godot/spine_godot/SpineAnimationState.cpp @@ -44,25 +44,22 @@ void SpineAnimationState::_bind_methods() { ClassDB::bind_method(D_METHOD("set_time_scale", "time_scale"), &SpineAnimationState::set_time_scale); ClassDB::bind_method(D_METHOD("disable_queue"), &SpineAnimationState::disable_queue); ClassDB::bind_method(D_METHOD("enable_queue"), &SpineAnimationState::enable_queue); -// ClassDB::bind_method(D_METHOD("reload"), &SpineAnimationState::reload_animation_state); + // ClassDB::bind_method(D_METHOD("reload"), &SpineAnimationState::reload_animation_state); ClassDB::bind_method(D_METHOD("get_current", "track_id"), &SpineAnimationState::get_current); } -SpineAnimationState::SpineAnimationState():animation_state(NULL) { - +SpineAnimationState::SpineAnimationState() : animation_state(NULL) { } SpineAnimationState::~SpineAnimationState() { - if(animation_state) - { + if (animation_state) { delete animation_state; animation_state = NULL; } } void SpineAnimationState::load_animation_state(Ref ad) { - if(animation_state) - { + if (animation_state) { delete animation_state; animation_state = NULL; } @@ -71,28 +68,33 @@ void SpineAnimationState::load_animation_state(Refget_animation_state_data()); } -#define CHECK_V if(!animation_state){ERR_PRINT("The animation state is not loaded yet!");return;} -#define CHECK_X(x) if(!animation_state){ERR_PRINT("The animation state is not loaded yet!");return x;} +#define CHECK_V \ + if (!animation_state) { \ + ERR_PRINT("The animation state is not loaded yet!"); \ + return; \ + } +#define CHECK_X(x) \ + if (!animation_state) { \ + ERR_PRINT("The animation state is not loaded yet!"); \ + return x; \ + } #define S_T(x) (spine::String(x.utf8())) Ref SpineAnimationState::set_animation(const String &anim_name, bool loop, uint64_t track) { CHECK_X(NULL); auto skeleton_data = anim_state_data_res->get_skeleton(); auto anim = skeleton_data->find_animation(anim_name); - if(!anim.is_valid() || anim->get_spine_object() == NULL) - { + if (!anim.is_valid() || anim->get_spine_object() == NULL) { ERR_PRINT(String("Can not find animation: ") + anim_name) return NULL; } @@ -105,8 +107,7 @@ Ref SpineAnimationState::add_animation(const String &anim_name, CHECK_X(NULL); auto skeleton_data = anim_state_data_res->get_skeleton(); auto anim = skeleton_data->find_animation(anim_name); - if(!anim.is_valid() || anim->get_spine_object() == NULL) - { + if (!anim.is_valid() || anim->get_spine_object() == NULL) { ERR_PRINT(String("Can not find animation: ") + anim_name) return NULL; } @@ -135,11 +136,11 @@ void SpineAnimationState::set_empty_animations(float mix_duration) { animation_state->setEmptyAnimations(mix_duration); } -void SpineAnimationState::update(float delta){ +void SpineAnimationState::update(float delta) { CHECK_V; animation_state->update(delta); } -bool SpineAnimationState::apply(Ref skeleton){ +bool SpineAnimationState::apply(Ref skeleton) { CHECK_X(false); return animation_state->apply(*(skeleton->get_spine_object())); } @@ -181,7 +182,7 @@ Ref SpineAnimationState::get_current(uint64_t track_index) { CHECK_X(NULL); Ref gd_entry(memnew(SpineTrackEntry)); auto entry = animation_state->getCurrent(track_index); - if(entry == NULL) return NULL; + if (entry == NULL) return NULL; gd_entry->set_spine_object(entry); return gd_entry; } diff --git a/spine-godot/spine_godot/SpineAnimationState.h b/spine-godot/spine_godot/SpineAnimationState.h index 531a63472..097be72ac 100644 --- a/spine-godot/spine_godot/SpineAnimationState.h +++ b/spine-godot/spine_godot/SpineAnimationState.h @@ -36,7 +36,7 @@ #include "SpineSkeleton.h" #include "SpineTrackEntry.h" -class SpineAnimationState : public Reference{ +class SpineAnimationState : public Reference { GDCLASS(SpineAnimationState, Reference); protected: @@ -46,21 +46,22 @@ private: spine::AnimationState *animation_state; Ref anim_state_data_res; + public: void load_animation_state(Ref ad); - inline void set_animation_state(spine::AnimationState *a){ + inline void set_animation_state(spine::AnimationState *a) { animation_state = a; } - inline spine::AnimationState *get_animation_state(){ + inline spine::AnimationState *get_animation_state() { return animation_state; } void reload_animation_state(); Ref set_animation(const String &anim_name, bool loop, uint64_t track_id); - inline void set_animation_by_ref(Ref anim, bool loop, uint64_t track_id){ - if(anim.is_valid()){ + inline void set_animation_by_ref(Ref anim, bool loop, uint64_t track_id) { + if (anim.is_valid()) { animation_state->setAnimation(track_id, anim->get_spine_object(), loop); } } @@ -90,4 +91,4 @@ public: ~SpineAnimationState(); }; -#endif //GODOT_SPINEANIMATIONSTATE_H +#endif//GODOT_SPINEANIMATIONSTATE_H diff --git a/spine-godot/spine_godot/SpineAnimationStateDataResource.cpp b/spine-godot/spine_godot/SpineAnimationStateDataResource.cpp index c17a1d585..de4041ec2 100644 --- a/spine-godot/spine_godot/SpineAnimationStateDataResource.cpp +++ b/spine-godot/spine_godot/SpineAnimationStateDataResource.cpp @@ -29,12 +29,10 @@ #include "SpineAnimationStateDataResource.h" -SpineAnimationStateDataResource::SpineAnimationStateDataResource():animation_state_data(NULL),animation_state_data_created(false),default_mix(0.5f) { - +SpineAnimationStateDataResource::SpineAnimationStateDataResource() : animation_state_data(NULL), animation_state_data_created(false), default_mix(0.5f) { } SpineAnimationStateDataResource::~SpineAnimationStateDataResource() { - if(animation_state_data) - { + if (animation_state_data) { delete animation_state_data; animation_state_data = NULL; } @@ -63,27 +61,22 @@ void SpineAnimationStateDataResource::set_skeleton(const Refconnect("skeleton_data_loaded", this, "_on_skeleton_data_loaded"); skeleton->connect("atlas_res_changed", this, "_on_skeleton_data_changed"); skeleton->connect("skeleton_json_res_changed", this, "_on_skeleton_data_changed"); - if(skeleton->is_skeleton_data_loaded()) - { + if (skeleton->is_skeleton_data_loaded()) { _on_skeleton_data_loaded(); } - }else{ - if(animation_state_data) - { + } else { + if (animation_state_data) { delete animation_state_data; animation_state_data = NULL; animation_state_data_created = false; -// print_line("Animation state data deleted."); + // print_line("Animation state data deleted."); } } - - } Ref SpineAnimationStateDataResource::get_skeleton() { return skeleton; @@ -91,18 +84,17 @@ Ref SpineAnimationStateDataResource::get_skeleton() { void SpineAnimationStateDataResource::set_default_mix(float m) { default_mix = m; - if(!is_animation_state_data_created()) - { -// ERR_PRINT("'set_default_mix' fail. Animation state data is not created!"); + if (!is_animation_state_data_created()) { + // ERR_PRINT("'set_default_mix' fail. Animation state data is not created!"); return; } - animation_state_data->setDefaultMix(((m >= 0 && m <= 1) ? m : m <= 0 ? 0 : 1)); -// emit_signal("animation_state_data_changed"); + animation_state_data->setDefaultMix(((m >= 0 && m <= 1) ? m : m <= 0 ? 0 + : 1)); + // emit_signal("animation_state_data_changed"); } float SpineAnimationStateDataResource::get_default_mix() { - if(!is_animation_state_data_created()) - { -// ERR_PRINT("'get_default_mix' fail. Animation state data is not created!"); + if (!is_animation_state_data_created()) { + // ERR_PRINT("'get_default_mix' fail. Animation state data is not created!"); return default_mix; } default_mix = animation_state_data->getDefaultMix(); @@ -110,40 +102,34 @@ float SpineAnimationStateDataResource::get_default_mix() { } void SpineAnimationStateDataResource::set_mix(const String &from, const String &to, float mix_duration) { - if(!is_animation_state_data_created()) - { + if (!is_animation_state_data_created()) { ERR_PRINT("'set_mix' fail. Animation state data is not created!"); return; } auto anim_from = get_skeleton()->find_animation(from); auto anim_to = get_skeleton()->find_animation(to); - if(!anim_from.is_valid()) - { + if (!anim_from.is_valid()) { ERR_PRINT("'set_mix' fail. From animation animation not found!"); return; } - if(!anim_to.is_valid()) - { + if (!anim_to.is_valid()) { ERR_PRINT("'set_mix' fail. To animation animation not found!"); return; } animation_state_data->setMix(anim_from->get_spine_object(), anim_to->get_spine_object(), mix_duration); } float SpineAnimationStateDataResource::get_mix(const String &from, const String &to) { - if(!is_animation_state_data_created()) - { + if (!is_animation_state_data_created()) { ERR_PRINT("'set_mix' fail. Animation state data is not created!"); return 0; } auto anim_from = get_skeleton()->find_animation(from); auto anim_to = get_skeleton()->find_animation(to); - if(!anim_from.is_valid()) - { + if (!anim_from.is_valid()) { ERR_PRINT("'set_mix' fail. From animation animation not found!"); return 0; } - if(!anim_to.is_valid()) - { + if (!anim_to.is_valid()) { ERR_PRINT("'set_mix' fail. To animation animation not found!"); return 0; } @@ -152,7 +138,7 @@ float SpineAnimationStateDataResource::get_mix(const String &from, const String void SpineAnimationStateDataResource::_on_skeleton_data_loaded() { animation_state_data = new spine::AnimationStateData(skeleton->get_skeleton_data()); -// print_line("Animation state data created."); + // print_line("Animation state data created."); emit_signal("animation_state_data_created"); @@ -162,17 +148,16 @@ void SpineAnimationStateDataResource::_on_skeleton_data_loaded() { void SpineAnimationStateDataResource::_on_skeleton_data_changed() { animation_state_data_created = false; - if(animation_state_data) - { + if (animation_state_data) { delete animation_state_data; animation_state_data = NULL; -// print_line("Animation state data deleted."); + // print_line("Animation state data deleted."); } -// print_line("skeleton_data_res_changed emitted"); + // print_line("skeleton_data_res_changed emitted"); emit_signal("skeleton_data_res_changed"); } -bool SpineAnimationStateDataResource::is_animation_state_data_created(){ +bool SpineAnimationStateDataResource::is_animation_state_data_created() { return animation_state_data_created; } \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineAnimationStateDataResource.h b/spine-godot/spine_godot/SpineAnimationStateDataResource.h index 9da9f8fe2..58f0cd536 100644 --- a/spine-godot/spine_godot/SpineAnimationStateDataResource.h +++ b/spine-godot/spine_godot/SpineAnimationStateDataResource.h @@ -34,7 +34,7 @@ #include "SpineSkeletonDataResource.h" -class SpineAnimationStateDataResource : public Resource{ +class SpineAnimationStateDataResource : public Resource { GDCLASS(SpineAnimationStateDataResource, Resource); protected: @@ -48,12 +48,12 @@ private: bool animation_state_data_created; float default_mix; -public: +public: void set_skeleton(const Ref &s); Ref get_skeleton(); - inline spine::AnimationStateData *get_animation_state_data(){ + inline spine::AnimationStateData *get_animation_state_data() { return animation_state_data; } @@ -73,4 +73,4 @@ public: ~SpineAnimationStateDataResource(); }; -#endif //GODOT_SPINEANIMATIONSTATEDATARESOURCE_H +#endif//GODOT_SPINEANIMATIONSTATEDATARESOURCE_H diff --git a/spine-godot/spine_godot/SpineAtlasResource.cpp b/spine-godot/spine_godot/SpineAtlasResource.cpp index 08177ac2c..91eb5828f 100644 --- a/spine-godot/spine_godot/SpineAtlasResource.cpp +++ b/spine-godot/spine_godot/SpineAtlasResource.cpp @@ -34,97 +34,93 @@ class GodotSpineTextureLoader : public spine::TextureLoader { private: - Array *tex_list, *ntex_list; - String normal_tex_prefix; + Array *textures, *normal_maps; + String normal_maps_prefix; + public: + GodotSpineTextureLoader(Array *t, Array *nt, const String &p) : textures(t), normal_maps(nt), normal_maps_prefix(p) { + if (textures) textures->clear(); + if (normal_maps) normal_maps->clear(); + } - GodotSpineTextureLoader(Array *t, Array *nt, const String &p):tex_list(t), ntex_list(nt), normal_tex_prefix(p){ - if (tex_list) tex_list->clear(); - if (ntex_list) ntex_list->clear(); - } + String fixPathIssue(const String &path) { + if (path.size() > 5 && path[4] == '/' && path[5] == '/') return path; + const String prefix = "res:/"; + auto i = path.find(prefix); + auto sub_str_pos = i + prefix.size() - 1; + if (sub_str_pos < 0) return path; + auto res = path.substr(sub_str_pos); - String fixPathIssue(const String &path){ - if(path.size() > 5 && path[4] == '/' && path[5] == '/') return path; - const String prefix = "res:/"; - auto i = path.find(prefix); -// print_line(String("Found i at ") + String(Variant(i))); - auto sub_str_pos = i+prefix.size()-1; - if(sub_str_pos < 0) return path; - auto res = path.substr(sub_str_pos); -// print_line(String("rest of it: ") + res); - if(res.size() > 0) - { - if(res[0] != '/') - { - return prefix + "/" + res; - } else - { - return prefix + res; - } - } - return path; - } + if (res.size() > 0) { + if (res[0] != '/') { + return prefix + "/" + res; + } else { + return prefix + res; + } + } + return path; + } - virtual void load(spine::AtlasPage &page, const spine::String &path){ - Error err = OK; + virtual void load(spine::AtlasPage &page, const spine::String &path) { + Error err = OK; -// print_line(String("Spine is loading texture: ") + String(path.buffer())); - auto fixed_path = fixPathIssue(String(path.buffer())); -// print_line("Fixed path: " + fixed_path); + // print_line(String("Spine is loading texture: ") + String(path.buffer())); + auto fixed_path = fixPathIssue(String(path.buffer())); + // print_line("Fixed path: " + fixed_path); // Load texture (e.g. tex.png) Ref tex = ResourceLoader::load(fixed_path, "", false, &err); if (err != OK) { - print_error(vformat("Can't load texture: \"%s\"", String(path.buffer()))); - page.setRendererObject((void*)memnew(SpineRendererObject {nullptr})); - return; + print_error(vformat("Can't load texture: \"%s\"", String(path.buffer()))); + page.setRendererObject((void *) memnew(SpineRendererObject{nullptr})); + return; } - if (tex_list) tex_list->append(tex); + if (textures) textures->append(tex); auto p_spine_renderer_object = memnew(SpineRendererObject); p_spine_renderer_object->tex = tex; // Load normal texture (e.g. n_tex.png) String temppath = fixed_path; - String newpath = vformat("%s/%s_%s", temppath.get_base_dir(), normal_tex_prefix, temppath.get_file()); -// print_line(vformat("try n tex: %s", newpath)); - if (ResourceLoader::exists(newpath)){ + String newpath = vformat("%s/%s_%s", temppath.get_base_dir(), normal_maps_prefix, temppath.get_file()); + // print_line(vformat("try n tex: %s", newpath)); + if (ResourceLoader::exists(newpath)) { Ref normal_tex = ResourceLoader::load(newpath); - if (ntex_list) ntex_list->append(normal_tex); + if (normal_maps) normal_maps->append(normal_tex); p_spine_renderer_object->normal_tex = normal_tex; // print_line(String("From atlas resource load: ") + String(" ro ") + String(Variant((long long) p_spine_renderer_object))); // print_line(String("From atlas resource load: ") + String(Variant(p_spine_renderer_object->tex)) + String(", ") + String(Variant(p_spine_renderer_object->normal_tex))); } - page.setRendererObject((void*)p_spine_renderer_object); + page.setRendererObject((void *) p_spine_renderer_object); page.width = tex->get_width(); page.height = tex->get_height(); - } + } - virtual void unload(void *p){ + virtual void unload(void *p) { // print_line("I'm out."); - auto p_spine_renderer_object = (SpineRendererObject*) p; - Ref &tex = p_spine_renderer_object->tex; + auto p_spine_renderer_object = (SpineRendererObject *) p; + Ref &tex = p_spine_renderer_object->tex; Ref &normal_tex = p_spine_renderer_object->normal_tex; if (tex.is_valid()) tex.unref(); if (normal_tex.is_valid()) normal_tex.unref(); memdelete(p_spine_renderer_object); - } + } }; -SpineAtlasResource::SpineAtlasResource():atlas(nullptr), normal_texture_prefix("n"){} -SpineAtlasResource::~SpineAtlasResource(){ - if (atlas) delete atlas; +SpineAtlasResource::SpineAtlasResource() : atlas(nullptr), normal_texture_prefix("n") {} +SpineAtlasResource::~SpineAtlasResource() { + if (atlas) delete atlas; } -void SpineAtlasResource::_bind_methods(){ - ClassDB::bind_method(D_METHOD("load_from_atlas_file", "path"), &SpineAtlasResource::load_from_atlas_file); +void SpineAtlasResource::_bind_methods() { + ClassDB::bind_method(D_METHOD("load_from_atlas_file", "path"), &SpineAtlasResource::load_from_atlas_file); - ClassDB::bind_method(D_METHOD("get_source_path"), &SpineAtlasResource::get_source_path); + ClassDB::bind_method(D_METHOD("get_source_path"), &SpineAtlasResource::get_source_path); ClassDB::bind_method(D_METHOD("get_textures"), &SpineAtlasResource::get_textures); ClassDB::bind_method(D_METHOD("get_normal_textures"), &SpineAtlasResource::get_normal_textures); @@ -140,90 +136,90 @@ Array SpineAtlasResource::get_textures() { } Array SpineAtlasResource::get_normal_textures() { - return ntex_list; + return ntex_list; } String SpineAtlasResource::get_source_path() { - return source_path; + return source_path; } Error SpineAtlasResource::load_from_atlas_file(const String &p_path) { -// print_line(vformat("Importing atlas file: %s", p_path)); - source_path = p_path; + // print_line(vformat("Importing atlas file: %s", p_path)); + source_path = p_path; - Error err; + Error err; - atlas_data = FileAccess::get_file_as_string(p_path, &err); - if (err != OK) return err; + atlas_data = FileAccess::get_file_as_string(p_path, &err); + if (err != OK) return err; - if (atlas) delete atlas; - tex_list.clear(); - ntex_list.clear(); - atlas = new spine::Atlas(atlas_data.utf8(), atlas_data.size(), source_path.get_base_dir().utf8(), new GodotSpineTextureLoader(&tex_list, &ntex_list, normal_texture_prefix)); + if (atlas) delete atlas; + tex_list.clear(); + ntex_list.clear(); + atlas = new spine::Atlas(atlas_data.utf8(), atlas_data.size(), source_path.get_base_dir().utf8(), new GodotSpineTextureLoader(&tex_list, &ntex_list, normal_texture_prefix)); -// print_line(vformat("atlas loaded!")); + // print_line(vformat("atlas loaded!")); - if (atlas) - return OK; + if (atlas) + return OK; - tex_list.clear(); - ntex_list.clear(); + tex_list.clear(); + ntex_list.clear(); - return ERR_FILE_UNRECOGNIZED; + return ERR_FILE_UNRECOGNIZED; } Error SpineAtlasResource::load_from_file(const String &p_path) { - Error err; + Error err; - String json_string = FileAccess::get_file_as_string(p_path, &err); - if (err != OK) return err; + String json_string = FileAccess::get_file_as_string(p_path, &err); + if (err != OK) return err; - String error_string; - int error_line; - JSON json; - Variant result; - err = json.parse(json_string, result, error_string, error_line); - if (err != OK) { - return err; - } + String error_string; + int error_line; + JSON json; + Variant result; + err = json.parse(json_string, result, error_string, error_line); + if (err != OK) { + return err; + } - Dictionary content = Dictionary(result); + Dictionary content = Dictionary(result); - source_path = content["source_path"]; - atlas_data = content["atlas_data"]; - normal_texture_prefix = content["normal_texture_prefix"]; + source_path = content["source_path"]; + atlas_data = content["atlas_data"]; + normal_texture_prefix = content["normal_texture_prefix"]; - if (atlas) delete atlas; - tex_list.clear(); - ntex_list.clear(); - atlas = new spine::Atlas(atlas_data.utf8(), atlas_data.size(), source_path.get_base_dir().utf8(), new GodotSpineTextureLoader(&tex_list, &ntex_list, normal_texture_prefix)); + if (atlas) delete atlas; + tex_list.clear(); + ntex_list.clear(); + atlas = new spine::Atlas(atlas_data.utf8(), atlas_data.size(), source_path.get_base_dir().utf8(), new GodotSpineTextureLoader(&tex_list, &ntex_list, normal_texture_prefix)); - if (atlas) - return OK; + if (atlas) + return OK; - tex_list.clear(); - ntex_list.clear(); - return ERR_FILE_UNRECOGNIZED; + tex_list.clear(); + ntex_list.clear(); + return ERR_FILE_UNRECOGNIZED; } Error SpineAtlasResource::save_to_file(const String &p_path) { - Error err; - FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &err); - if (err != OK) { -// print_line(vformat("save file err: %d", err)); - if (file) file->close(); - return err; - } + Error err; + FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &err); + if (err != OK) { + // print_line(vformat("save file err: %d", err)); + if (file) file->close(); + return err; + } - Dictionary content; - content["source_path"] = source_path; - content["atlas_data"] = atlas_data; - content["normal_texture_prefix"] = normal_texture_prefix; + Dictionary content; + content["source_path"] = source_path; + content["atlas_data"] = atlas_data; + content["normal_texture_prefix"] = normal_texture_prefix; -// print_line(vformat("storing source_path: %s", source_path)); + // print_line(vformat("storing source_path: %s", source_path)); - file->store_string(JSON::print(content)); - file->close(); + file->store_string(JSON::print(content)); + file->close(); - return OK; + return OK; } diff --git a/spine-godot/spine_godot/SpineAtlasResource.h b/spine-godot/spine_godot/SpineAtlasResource.h index 862f554ef..881d17664 100644 --- a/spine-godot/spine_godot/SpineAtlasResource.h +++ b/spine-godot/spine_godot/SpineAtlasResource.h @@ -31,7 +31,6 @@ #define GODOT_SPINEATLASRESOURCE_H - #include "core/variant_parser.h" #include @@ -41,39 +40,40 @@ #include #include "SpineRendererObject.h" -class SpineAtlasResource : public Resource{ - GDCLASS(SpineAtlasResource, Resource); +class SpineAtlasResource : public Resource { + GDCLASS(SpineAtlasResource, Resource); protected: - static void _bind_methods(); + static void _bind_methods(); - spine::Atlas *atlas; + spine::Atlas *atlas; - String source_path; - String atlas_data; - String normal_texture_prefix; + String source_path; + String atlas_data; + String normal_texture_prefix; + + Array tex_list; + Array ntex_list; - Array tex_list; - Array ntex_list; public: - inline String &get_atlas_data() {return atlas_data;} + inline String &get_atlas_data() { return atlas_data; } - inline spine::Atlas *get_spine_atlas() {return atlas;} + inline spine::Atlas *get_spine_atlas() { return atlas; } - inline void set_normal_texture_prefix(const String &p) {normal_texture_prefix = p;} + inline void set_normal_texture_prefix(const String &p) { normal_texture_prefix = p; } - Error load_from_atlas_file(const String &p_path); // .atlas + Error load_from_atlas_file(const String &p_path);// .atlas - Error load_from_file(const String &p_path); // .spatlas - Error save_to_file(const String &p_path); // .spatlas + Error load_from_file(const String &p_path);// .spatlas + Error save_to_file(const String &p_path); // .spatlas - String get_source_path(); + String get_source_path(); Array get_textures(); Array get_normal_textures(); SpineAtlasResource(); - virtual ~SpineAtlasResource(); + virtual ~SpineAtlasResource(); }; -#endif //GODOT_SPINEATLASRESOURCE_H +#endif//GODOT_SPINEATLASRESOURCE_H diff --git a/spine-godot/spine_godot/SpineAttachment.cpp b/spine-godot/spine_godot/SpineAttachment.cpp index 319cae442..e25f54c5e 100644 --- a/spine-godot/spine_godot/SpineAttachment.cpp +++ b/spine-godot/spine_godot/SpineAttachment.cpp @@ -34,21 +34,21 @@ void SpineAttachment::_bind_methods() { ClassDB::bind_method(D_METHOD("copy"), &SpineAttachment::copy); } -SpineAttachment::SpineAttachment():attachment(NULL) {} +SpineAttachment::SpineAttachment() : attachment(NULL) {} SpineAttachment::~SpineAttachment() { - if(attachment){ + if (attachment) { attachment->dereference(); attachment = NULL; } } -String SpineAttachment::get_attachment_name(){ +String SpineAttachment::get_attachment_name() { return attachment->getName().buffer(); } -Ref SpineAttachment::copy(){ +Ref SpineAttachment::copy() { auto a = attachment->copy(); - if(a == NULL) return NULL; + if (a == NULL) return NULL; Ref gd_attachment(memnew(SpineAttachment)); gd_attachment->set_spine_object(a); return gd_attachment; diff --git a/spine-godot/spine_godot/SpineAttachment.h b/spine-godot/spine_godot/SpineAttachment.h index 4575a50d1..81ec52c9d 100644 --- a/spine-godot/spine_godot/SpineAttachment.h +++ b/spine-godot/spine_godot/SpineAttachment.h @@ -47,12 +47,12 @@ public: SpineAttachment(); ~SpineAttachment(); - inline void set_spine_object(spine::Attachment *a){ + inline void set_spine_object(spine::Attachment *a) { attachment = a; - if(attachment) + if (attachment) attachment->reference(); } - inline spine::Attachment *get_spine_object(){ + inline spine::Attachment *get_spine_object() { return attachment; } @@ -61,4 +61,4 @@ public: Ref copy(); }; -#endif //GODOT_SPINEATTACHMENT_H +#endif//GODOT_SPINEATTACHMENT_H diff --git a/spine-godot/spine_godot/SpineBone.cpp b/spine-godot/spine_godot/SpineBone.cpp index 59f495aa3..afde7a781 100644 --- a/spine-godot/spine_godot/SpineBone.cpp +++ b/spine-godot/spine_godot/SpineBone.cpp @@ -34,52 +34,52 @@ void SpineBone::_bind_methods() { ClassDB::bind_method(D_METHOD("update_world_transform"), &SpineBone::update_world_transform); -// void set_to_setup_pose(); -// -// Vector2 world_to_local(Vector2 world_position); -// -// Vector2 local_to_world(Vector2 local_position); -// -// float world_to_local_rotation(float world_rotation); -// -// float local_to_world_rotation(float local_rotation); -// -// void rotate_world(float degrees); + // void set_to_setup_pose(); + // + // Vector2 world_to_local(Vector2 world_position); + // + // Vector2 local_to_world(Vector2 local_position); + // + // float world_to_local_rotation(float world_rotation); + // + // float local_to_world_rotation(float local_rotation); + // + // void rotate_world(float degrees); ClassDB::bind_method(D_METHOD("set_to_setup_pose"), &SpineBone::set_to_setup_pose); ClassDB::bind_method(D_METHOD("world_to_local", "world_position"), &SpineBone::world_to_local); ClassDB::bind_method(D_METHOD("local_to_world", "local_position"), &SpineBone::local_to_world); ClassDB::bind_method(D_METHOD("world_to_local_rotation", "world_rotation"), &SpineBone::world_to_local_rotation); ClassDB::bind_method(D_METHOD("local_to_world_rotation", "local_rotation"), &SpineBone::local_to_world_rotation); ClassDB::bind_method(D_METHOD("rotate_world"), &SpineBone::rotate_world); -// -// float get_world_to_local_rotation_x(); -// float get_world_to_local_rotation_y(); -// -// Ref get_data(); -// -// Ref get_skeleton(); -// -// Ref get_parent(); -// -// Array get_children(); + // + // float get_world_to_local_rotation_x(); + // float get_world_to_local_rotation_y(); + // + // Ref get_data(); + // + // Ref get_skeleton(); + // + // Ref get_parent(); + // + // Array get_children(); ClassDB::bind_method(D_METHOD("get_world_to_local_rotation_x"), &SpineBone::get_world_to_local_rotation_x); ClassDB::bind_method(D_METHOD("get_world_to_local_rotation_y"), &SpineBone::get_world_to_local_rotation_y); ClassDB::bind_method(D_METHOD("get_data"), &SpineBone::get_data); ClassDB::bind_method(D_METHOD("get_skeleton"), &SpineBone::get_skeleton); ClassDB::bind_method(D_METHOD("get_parent"), &SpineBone::get_parent); ClassDB::bind_method(D_METHOD("get_children"), &SpineBone::get_children); -// -// float get_x(); -// void set_x(float v); -// -// float get_y(); -// void set_y(float v); -// -// float get_rotation(); -// void set_rotation(float v); -// -// float get_scale_x(); -// void set_scale_x(float v); + // + // float get_x(); + // void set_x(float v); + // + // float get_y(); + // void set_y(float v); + // + // float get_rotation(); + // void set_rotation(float v); + // + // float get_scale_x(); + // void set_scale_x(float v); ClassDB::bind_method(D_METHOD("get_x"), &SpineBone::get_x); ClassDB::bind_method(D_METHOD("set_x", "v"), &SpineBone::set_x); ClassDB::bind_method(D_METHOD("get_y"), &SpineBone::get_y); @@ -88,18 +88,18 @@ void SpineBone::_bind_methods() { ClassDB::bind_method(D_METHOD("set_rotation", "v"), &SpineBone::set_rotation); ClassDB::bind_method(D_METHOD("get_scale_x"), &SpineBone::get_scale_x); ClassDB::bind_method(D_METHOD("set_scale_x", "v"), &SpineBone::set_scale_x); -// -// float get_scale_y(); -// void set_scale_y(float v); -// -// float get_shear_x(); -// void set_shear_x(float v); -// -// float get_shear_y(); -// void set_shear_y(float v); -// -// float get_applied_rotation(); -// void set_applied_rotation(float v); + // + // float get_scale_y(); + // void set_scale_y(float v); + // + // float get_shear_x(); + // void set_shear_x(float v); + // + // float get_shear_y(); + // void set_shear_y(float v); + // + // float get_applied_rotation(); + // void set_applied_rotation(float v); ClassDB::bind_method(D_METHOD("get_scale_y"), &SpineBone::get_scale_y); ClassDB::bind_method(D_METHOD("set_scale_y", "v"), &SpineBone::set_scale_y); ClassDB::bind_method(D_METHOD("get_shear_x"), &SpineBone::get_shear_x); @@ -108,18 +108,18 @@ void SpineBone::_bind_methods() { ClassDB::bind_method(D_METHOD("set_shear_y", "v"), &SpineBone::set_shear_y); ClassDB::bind_method(D_METHOD("get_applied_rotation"), &SpineBone::get_applied_rotation); ClassDB::bind_method(D_METHOD("set_applied_rotation", "v"), &SpineBone::set_applied_rotation); -// -// float get_a_x(); -// void set_a_x(float v); -// -// float get_a_y(); -// void set_a_y(float v); -// -// float get_a_scale_x(); -// void set_a_scale_x(float v); -// -// float get_a_scale_y(); -// void set_a_scale_y(float v); + // + // float get_a_x(); + // void set_a_x(float v); + // + // float get_a_y(); + // void set_a_y(float v); + // + // float get_a_scale_x(); + // void set_a_scale_x(float v); + // + // float get_a_scale_y(); + // void set_a_scale_y(float v); ClassDB::bind_method(D_METHOD("get_a_x"), &SpineBone::get_a_x); ClassDB::bind_method(D_METHOD("set_a_x", "v"), &SpineBone::set_a_x); ClassDB::bind_method(D_METHOD("get_a_y"), &SpineBone::get_a_y); @@ -128,18 +128,18 @@ void SpineBone::_bind_methods() { ClassDB::bind_method(D_METHOD("set_a_scale_x", "v"), &SpineBone::set_a_scale_x); ClassDB::bind_method(D_METHOD("get_a_scale_y"), &SpineBone::get_a_scale_y); ClassDB::bind_method(D_METHOD("set_a_scale_y", "v"), &SpineBone::set_a_scale_y); -// -// float get_a_shear_x(); -// void set_a_shear_x(float v); -// -// float get_a_shear_y(); -// void set_a_shear_y(float v); -// -// float get_a(); -// void set_a(float v); -// -// float get_b(); -// void set_b(float v); + // + // float get_a_shear_x(); + // void set_a_shear_x(float v); + // + // float get_a_shear_y(); + // void set_a_shear_y(float v); + // + // float get_a(); + // void set_a(float v); + // + // float get_b(); + // void set_b(float v); ClassDB::bind_method(D_METHOD("get_a_shear_x"), &SpineBone::get_a_shear_x); ClassDB::bind_method(D_METHOD("set_a_shear_x", "v"), &SpineBone::set_a_shear_x); ClassDB::bind_method(D_METHOD("get_a_shear_y"), &SpineBone::get_a_shear_y); @@ -148,18 +148,18 @@ void SpineBone::_bind_methods() { ClassDB::bind_method(D_METHOD("set_a", "v"), &SpineBone::set_a); ClassDB::bind_method(D_METHOD("get_b"), &SpineBone::get_b); ClassDB::bind_method(D_METHOD("set_b", "v"), &SpineBone::set_b); -// -// float get_c(); -// void set_c(float v); -// -// float get_d(); -// void set_d(float v); -// -// float get_world_x(); -// void set_world_x(float v); -// -// float get_world_y(); -// void set_world_y(float v); + // + // float get_c(); + // void set_c(float v); + // + // float get_d(); + // void set_d(float v); + // + // float get_world_x(); + // void set_world_x(float v); + // + // float get_world_y(); + // void set_world_y(float v); ClassDB::bind_method(D_METHOD("get_c"), &SpineBone::get_c); ClassDB::bind_method(D_METHOD("set_c", "v"), &SpineBone::set_c); ClassDB::bind_method(D_METHOD("get_d"), &SpineBone::get_d); @@ -168,18 +168,18 @@ void SpineBone::_bind_methods() { ClassDB::bind_method(D_METHOD("set_world_x", "v"), &SpineBone::set_world_x); ClassDB::bind_method(D_METHOD("get_world_y"), &SpineBone::get_world_y); ClassDB::bind_method(D_METHOD("set_world_y", "v"), &SpineBone::set_world_y); -// -// float get_world_rotation_x(); -// float get_world_rotation_y(); -// -// float get_world_scale_x(); -// float get_world_scale_y(); -// -// bool is_applied_valid(); -// void set_applied_valid(bool v); -// -// bool is_active(); -// void set_active(bool v); + // + // float get_world_rotation_x(); + // float get_world_rotation_y(); + // + // float get_world_scale_x(); + // float get_world_scale_y(); + // + // bool is_applied_valid(); + // void set_applied_valid(bool v); + // + // bool is_active(); + // void set_active(bool v); ClassDB::bind_method(D_METHOD("get_world_rotation_x"), &SpineBone::get_world_rotation_x); ClassDB::bind_method(D_METHOD("get_world_rotation_y"), &SpineBone::get_world_rotation_y); ClassDB::bind_method(D_METHOD("get_world_scale_x"), &SpineBone::get_world_scale_x); @@ -189,62 +189,62 @@ void SpineBone::_bind_methods() { ClassDB::bind_method(D_METHOD("get_godot_transform"), &SpineBone::get_godot_transform); ClassDB::bind_method(D_METHOD("set_godot_transform", "local_transform"), &SpineBone::set_godot_transform); - ClassDB::bind_method(D_METHOD("get_godot_global_transform"), &SpineBone::get_godot_global_transform); - ClassDB::bind_method(D_METHOD("set_godot_global_transform", "global_transform"), &SpineBone::set_godot_global_transform); + ClassDB::bind_method(D_METHOD("get_godot_global_transform"), &SpineBone::get_godot_global_transform); + ClassDB::bind_method(D_METHOD("set_godot_global_transform", "global_transform"), &SpineBone::set_godot_global_transform); ClassDB::bind_method(D_METHOD("apply_world_transform_2d", "node2d"), &SpineBone::apply_world_transform_2d); } -SpineBone::SpineBone():bone(NULL), the_sprite(nullptr) {} +SpineBone::SpineBone() : bone(NULL), the_sprite(nullptr) {} SpineBone::~SpineBone() {} -void SpineBone::update_world_transform(){ +void SpineBone::update_world_transform() { bone->updateWorldTransform(); } -void SpineBone::set_to_setup_pose(){ +void SpineBone::set_to_setup_pose() { bone->setToSetupPose(); } -Vector2 SpineBone::world_to_local(Vector2 world_position){ +Vector2 SpineBone::world_to_local(Vector2 world_position) { float x, y; bone->worldToLocal(world_position.x, world_position.y, x, y); return Vector2(x, y); } -Vector2 SpineBone::local_to_world(Vector2 local_position){ +Vector2 SpineBone::local_to_world(Vector2 local_position) { float x, y; bone->localToWorld(local_position.x, local_position.y, x, y); return Vector2(x, y); } -float SpineBone::world_to_local_rotation(float world_rotation){ +float SpineBone::world_to_local_rotation(float world_rotation) { return bone->worldToLocalRotation(world_rotation); } -float SpineBone::local_to_world_rotation(float local_rotation){ +float SpineBone::local_to_world_rotation(float local_rotation) { return bone->localToWorldRotation(local_rotation); } -void SpineBone::rotate_world(float degrees){ +void SpineBone::rotate_world(float degrees) { bone->rotateWorld(degrees); } -float SpineBone::get_world_to_local_rotation_x(){ +float SpineBone::get_world_to_local_rotation_x() { return bone->getWorldToLocalRotationX(); } -float SpineBone::get_world_to_local_rotation_y(){ +float SpineBone::get_world_to_local_rotation_y() { return bone->getWorldToLocalRotationY(); } -Ref SpineBone::get_data(){ +Ref SpineBone::get_data() { auto &bd = bone->getData(); Ref gd_bd(memnew(SpineBoneData)); gd_bd->set_spine_object(&bd); return gd_bd; } -Ref SpineBone::get_skeleton(){ +Ref SpineBone::get_skeleton() { auto &s = bone->getSkeleton(); Ref gd_s(memnew(SpineSkeleton)); gd_s->set_spine_object(&s); @@ -252,22 +252,22 @@ Ref SpineBone::get_skeleton(){ return gd_s; } -Ref SpineBone::get_parent(){ +Ref SpineBone::get_parent() { auto b = bone->getParent(); - if(b == NULL) return NULL; + if (b == NULL) return NULL; Ref gd_b(memnew(SpineBone)); gd_b->set_spine_object(b); gd_b->set_spine_sprite(the_sprite); return gd_b; } -Array SpineBone::get_children(){ +Array SpineBone::get_children() { auto bs = bone->getChildren(); Array gd_bs; gd_bs.resize(bs.size()); - for(size_t i=0; i < bs.size(); ++i){ + for (size_t i = 0; i < bs.size(); ++i) { auto b = bs[i]; - if(b == NULL) gd_bs[i] = Ref(NULL); + if (b == NULL) gd_bs[i] = Ref(NULL); Ref gd_b(memnew(SpineBone)); gd_b->set_spine_object(b); gd_b->set_spine_sprite(the_sprite); @@ -276,179 +276,178 @@ Array SpineBone::get_children(){ return gd_bs; } -float SpineBone::get_x(){ +float SpineBone::get_x() { return bone->getX(); } -void SpineBone::set_x(float v){ +void SpineBone::set_x(float v) { bone->setX(v); } -float SpineBone::get_y(){ +float SpineBone::get_y() { return bone->getY(); } -void SpineBone::set_y(float v){ +void SpineBone::set_y(float v) { bone->setY(v); } -float SpineBone::get_rotation(){ +float SpineBone::get_rotation() { return bone->getRotation(); } -void SpineBone::set_rotation(float v){ +void SpineBone::set_rotation(float v) { bone->setRotation(v); } -float SpineBone::get_scale_x(){ +float SpineBone::get_scale_x() { return bone->getScaleX(); } -void SpineBone::set_scale_x(float v){ +void SpineBone::set_scale_x(float v) { bone->setScaleX(v); } -float SpineBone::get_scale_y(){ +float SpineBone::get_scale_y() { return bone->getScaleY(); } -void SpineBone::set_scale_y(float v){ +void SpineBone::set_scale_y(float v) { bone->setScaleY(v); } -float SpineBone::get_shear_x(){ +float SpineBone::get_shear_x() { return bone->getShearX(); } -void SpineBone::set_shear_x(float v){ +void SpineBone::set_shear_x(float v) { bone->setShearX(v); } -float SpineBone::get_shear_y(){ +float SpineBone::get_shear_y() { return bone->getShearY(); } -void SpineBone::set_shear_y(float v){ +void SpineBone::set_shear_y(float v) { bone->setShearY(v); } -float SpineBone::get_applied_rotation(){ +float SpineBone::get_applied_rotation() { return bone->getAppliedRotation(); } -void SpineBone::set_applied_rotation(float v){ +void SpineBone::set_applied_rotation(float v) { bone->setAppliedRotation(v); } -float SpineBone::get_a_x(){ +float SpineBone::get_a_x() { return bone->getAX(); } -void SpineBone::set_a_x(float v){ +void SpineBone::set_a_x(float v) { bone->setAX(v); } -float SpineBone::get_a_y(){ +float SpineBone::get_a_y() { return bone->getAY(); } -void SpineBone::set_a_y(float v){ +void SpineBone::set_a_y(float v) { bone->setAY(v); } -float SpineBone::get_a_scale_x(){ +float SpineBone::get_a_scale_x() { return bone->getAScaleX(); } -void SpineBone::set_a_scale_x(float v){ +void SpineBone::set_a_scale_x(float v) { bone->setAScaleX(v); } -float SpineBone::get_a_scale_y(){ +float SpineBone::get_a_scale_y() { return bone->getAScaleY(); } -void SpineBone::set_a_scale_y(float v){ +void SpineBone::set_a_scale_y(float v) { bone->setAScaleY(v); } -float SpineBone::get_a_shear_x(){ +float SpineBone::get_a_shear_x() { return bone->getAShearX(); } -void SpineBone::set_a_shear_x(float v){ +void SpineBone::set_a_shear_x(float v) { bone->setAShearX(v); } -float SpineBone::get_a_shear_y(){ +float SpineBone::get_a_shear_y() { return bone->getAShearY(); } -void SpineBone::set_a_shear_y(float v){ +void SpineBone::set_a_shear_y(float v) { bone->setAShearY(v); } -float SpineBone::get_a(){ +float SpineBone::get_a() { return bone->getA(); } -void SpineBone::set_a(float v){ +void SpineBone::set_a(float v) { bone->setA(v); } -float SpineBone::get_b(){ +float SpineBone::get_b() { return bone->getB(); } -void SpineBone::set_b(float v){ +void SpineBone::set_b(float v) { bone->setB(v); } -float SpineBone::get_c(){ +float SpineBone::get_c() { return bone->getC(); } -void SpineBone::set_c(float v){ +void SpineBone::set_c(float v) { bone->setC(v); } -float SpineBone::get_d(){ +float SpineBone::get_d() { return bone->getD(); } -void SpineBone::set_d(float v){ +void SpineBone::set_d(float v) { bone->setD(v); } -float SpineBone::get_world_x(){ +float SpineBone::get_world_x() { return bone->getWorldX(); } -void SpineBone::set_world_x(float v){ +void SpineBone::set_world_x(float v) { bone->setWorldX(v); } -float SpineBone::get_world_y(){ +float SpineBone::get_world_y() { return bone->getWorldY(); } -void SpineBone::set_world_y(float v){ +void SpineBone::set_world_y(float v) { bone->setWorldY(v); } -float SpineBone::get_world_rotation_x(){ +float SpineBone::get_world_rotation_x() { return bone->getWorldRotationX(); } -float SpineBone::get_world_rotation_y(){ +float SpineBone::get_world_rotation_y() { return bone->getWorldRotationY(); } -float SpineBone::get_world_scale_x(){ +float SpineBone::get_world_scale_x() { return bone->getWorldScaleX(); } -float SpineBone::get_world_scale_y(){ +float SpineBone::get_world_scale_y() { return bone->getWorldScaleY(); } -bool SpineBone::is_active(){ +bool SpineBone::is_active() { return bone->isActive(); } -void SpineBone::set_active(bool v){ +void SpineBone::set_active(bool v) { bone->setActive(v); } // External feature functions -void SpineBone::apply_world_transform_2d(Variant o){ - if(o.get_type() == Variant::OBJECT){ - auto node = (Node*) o; - if(node->is_class("Node2D")){ - auto node2d = (Node2D*) node; +void SpineBone::apply_world_transform_2d(Variant o) { + if (o.get_type() == Variant::OBJECT) { + auto node = (Node *) o; + if (node->is_class("Node2D")) { + auto node2d = (Node2D *) node; // In godot the y-axis is nag to spine node2d->set_transform(Transform2D( get_a(), get_c(), get_b(), get_d(), - get_world_x(), -get_world_y()) - ); + get_world_x(), -get_world_y())); // Fix the rotation auto pos = node2d->get_position(); node2d->translate(-pos); @@ -459,79 +458,79 @@ void SpineBone::apply_world_transform_2d(Variant o){ } Transform2D SpineBone::get_godot_transform() { - if (get_spine_object() == nullptr) - return Transform2D(); - Transform2D trans; - trans.translate(get_x(), -get_y()); - // It seems that spine uses degree for rotation - trans.rotate(Math::deg2rad(-get_rotation())); - trans.scale(Size2(get_scale_x(), get_scale_y())); - return trans; + if (get_spine_object() == nullptr) + return Transform2D(); + Transform2D trans; + trans.translate(get_x(), -get_y()); + // It seems that spine uses degree for rotation + trans.rotate(Math::deg2rad(-get_rotation())); + trans.scale(Size2(get_scale_x(), get_scale_y())); + return trans; } void SpineBone::set_godot_transform(Transform2D trans) { - if (get_spine_object() == nullptr) - return; - Vector2 position = trans.get_origin(); - position.y *= -1; - real_t rotation = trans.get_rotation(); - rotation = Math::rad2deg(-rotation); - Vector2 scale = trans.get_scale(); + if (get_spine_object() == nullptr) + return; + Vector2 position = trans.get_origin(); + position.y *= -1; + real_t rotation = trans.get_rotation(); + rotation = Math::rad2deg(-rotation); + Vector2 scale = trans.get_scale(); - set_x(position.x); - set_y(position.y); - set_rotation(rotation); - set_scale_x(scale.x); - set_scale_y(scale.y); + set_x(position.x); + set_y(position.y); + set_rotation(rotation); + set_scale_x(scale.x); + set_scale_y(scale.y); } Transform2D SpineBone::get_godot_global_transform() { - if (get_spine_object() == nullptr) - return Transform2D(); - if (the_sprite == nullptr) - return get_godot_transform(); - Transform2D res = the_sprite->get_transform(); - res.translate(get_world_x(), -get_world_y()); - res.rotate(Math::deg2rad(-get_world_rotation_x())); - res.scale(Vector2(get_world_scale_x(), get_world_scale_y())); - auto p = the_sprite->get_parent() ? Object::cast_to(the_sprite->get_parent()) : nullptr; - if (p) { - return p->get_global_transform() * res; - } - return res; + if (get_spine_object() == nullptr) + return Transform2D(); + if (the_sprite == nullptr) + return get_godot_transform(); + Transform2D res = the_sprite->get_transform(); + res.translate(get_world_x(), -get_world_y()); + res.rotate(Math::deg2rad(-get_world_rotation_x())); + res.scale(Vector2(get_world_scale_x(), get_world_scale_y())); + auto p = the_sprite->get_parent() ? Object::cast_to(the_sprite->get_parent()) : nullptr; + if (p) { + return p->get_global_transform() * res; + } + return res; } void SpineBone::set_godot_global_transform(Transform2D transform) { - if (get_spine_object() == nullptr) - return; - if (the_sprite == nullptr) - set_godot_transform(transform); - transform = the_sprite->get_global_transform().affine_inverse() * transform; - Vector2 position = transform.get_origin(); - real_t rotation = transform.get_rotation(); - Vector2 scale = transform.get_scale(); - position.y *= -1; - auto parent = get_parent(); - if (parent.is_valid()) { - position = parent->world_to_local(position); - if (parent->get_world_scale_x() != 0) - scale.x /= parent->get_world_scale_x(); - else - print_error("The parent scale.x is zero."); - if (parent->get_world_scale_y() != 0) - scale.y /= parent->get_world_scale_y(); - else - print_error("The parent scale.y is zero."); - } - rotation = world_to_local_rotation(Math::rad2deg(-rotation)); + if (get_spine_object() == nullptr) + return; + if (the_sprite == nullptr) + set_godot_transform(transform); + transform = the_sprite->get_global_transform().affine_inverse() * transform; + Vector2 position = transform.get_origin(); + real_t rotation = transform.get_rotation(); + Vector2 scale = transform.get_scale(); + position.y *= -1; + auto parent = get_parent(); + if (parent.is_valid()) { + position = parent->world_to_local(position); + if (parent->get_world_scale_x() != 0) + scale.x /= parent->get_world_scale_x(); + else + print_error("The parent scale.x is zero."); + if (parent->get_world_scale_y() != 0) + scale.y /= parent->get_world_scale_y(); + else + print_error("The parent scale.y is zero."); + } + rotation = world_to_local_rotation(Math::rad2deg(-rotation)); - set_x(position.x); - set_y(position.y); - set_rotation(rotation); - set_scale_x(scale.x); - set_scale_y(scale.y); + set_x(position.x); + set_y(position.y); + set_rotation(rotation); + set_scale_x(scale.x); + set_scale_y(scale.y); } void SpineBone::set_spine_sprite(SpineSprite *s) { - the_sprite = s; + the_sprite = s; } diff --git a/spine-godot/spine_godot/SpineBone.h b/spine-godot/spine_godot/SpineBone.h index 1661d751b..b7efd1381 100644 --- a/spine-godot/spine_godot/SpineBone.h +++ b/spine-godot/spine_godot/SpineBone.h @@ -54,14 +54,15 @@ private: spine::Bone *bone; SpineSprite *the_sprite; + public: SpineBone(); ~SpineBone(); - inline void set_spine_object(spine::Bone *b){ + inline void set_spine_object(spine::Bone *b) { bone = b; } - inline spine::Bone *get_spine_object(){ + inline spine::Bone *get_spine_object() { return bone; } @@ -171,4 +172,4 @@ public: void set_godot_global_transform(Transform2D trans); }; -#endif //GODOT_SPINEBONE_H +#endif//GODOT_SPINEBONE_H diff --git a/spine-godot/spine_godot/SpineBoneData.cpp b/spine-godot/spine_godot/SpineBoneData.cpp index e46ade5a2..b870527dc 100644 --- a/spine-godot/spine_godot/SpineBoneData.cpp +++ b/spine-godot/spine_godot/SpineBoneData.cpp @@ -71,93 +71,93 @@ void SpineBoneData::_bind_methods() { BIND_ENUM_CONSTANT(TRANSFORMMODE_NOSCALEORREFLECTION); } -SpineBoneData::SpineBoneData():bone_data(NULL) {} +SpineBoneData::SpineBoneData() : bone_data(NULL) {} SpineBoneData::~SpineBoneData() {} -int SpineBoneData::get_index(){ +int SpineBoneData::get_index() { return bone_data->getIndex(); } -String SpineBoneData::get_bone_name(){ +String SpineBoneData::get_bone_name() { return bone_data->getName().buffer(); } -Ref SpineBoneData::get_parent(){ +Ref SpineBoneData::get_parent() { auto p = bone_data->getParent(); - if(p == NULL) return NULL; + if (p == NULL) return NULL; Ref gd_bone_data(memnew(SpineBoneData)); gd_bone_data->set_spine_object(p); return gd_bone_data; } -float SpineBoneData::get_length(){ +float SpineBoneData::get_length() { return bone_data->getLength(); } -void SpineBoneData::set_length(float v){ +void SpineBoneData::set_length(float v) { bone_data->setLength(v); } -float SpineBoneData::get_x(){ +float SpineBoneData::get_x() { return bone_data->getX(); } -void SpineBoneData::set_x(float v){ +void SpineBoneData::set_x(float v) { bone_data->setX(v); } -float SpineBoneData::get_y(){ +float SpineBoneData::get_y() { return bone_data->getY(); } -void SpineBoneData::set_y(float v){ +void SpineBoneData::set_y(float v) { bone_data->setY(v); } -float SpineBoneData::get_rotation(){ +float SpineBoneData::get_rotation() { return bone_data->getRotation(); } -void SpineBoneData::set_rotation(float v){ +void SpineBoneData::set_rotation(float v) { bone_data->setRotation(v); } -float SpineBoneData::get_scale_x(){ +float SpineBoneData::get_scale_x() { return bone_data->getScaleX(); } -void SpineBoneData::set_scale_x(float v){ +void SpineBoneData::set_scale_x(float v) { bone_data->setScaleX(v); } -float SpineBoneData::get_scale_y(){ +float SpineBoneData::get_scale_y() { return bone_data->getScaleY(); } -void SpineBoneData::set_scale_y(float v){ +void SpineBoneData::set_scale_y(float v) { bone_data->setScaleY(v); } -float SpineBoneData::get_shear_x(){ +float SpineBoneData::get_shear_x() { return bone_data->getShearX(); } -void SpineBoneData::set_shear_x(float v){ +void SpineBoneData::set_shear_x(float v) { bone_data->setShearX(v); } -float SpineBoneData::get_shear_y(){ +float SpineBoneData::get_shear_y() { return bone_data->getShearY(); } -void SpineBoneData::set_shear_y(float v){ +void SpineBoneData::set_shear_y(float v) { bone_data->setShearY(v); } -SpineBoneData::TransformMode SpineBoneData::get_transform_mode(){ - auto tm = (int)bone_data->getTransformMode(); +SpineBoneData::TransformMode SpineBoneData::get_transform_mode() { + auto tm = (int) bone_data->getTransformMode(); return (TransformMode) tm; } -void SpineBoneData::set_transform_mode(TransformMode v){ +void SpineBoneData::set_transform_mode(TransformMode v) { auto tm = (int) v; - bone_data->setTransformMode((spine::TransformMode)tm); + bone_data->setTransformMode((spine::TransformMode) tm); } -bool SpineBoneData::is_skin_required(){ +bool SpineBoneData::is_skin_required() { return bone_data->isSkinRequired(); } -void SpineBoneData::set_skin_required(bool v){ +void SpineBoneData::set_skin_required(bool v) { bone_data->setSkinRequired(v); } \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineBoneData.h b/spine-godot/spine_godot/SpineBoneData.h index 3bef4c023..dc3e3feb6 100644 --- a/spine-godot/spine_godot/SpineBoneData.h +++ b/spine-godot/spine_godot/SpineBoneData.h @@ -47,10 +47,10 @@ public: SpineBoneData(); ~SpineBoneData(); - inline void set_spine_object(spine::BoneData *b){ + inline void set_spine_object(spine::BoneData *b) { bone_data = b; } - inline spine::BoneData *get_spine_object(){ + inline spine::BoneData *get_spine_object() { return bone_data; } @@ -97,8 +97,7 @@ public: bool is_skin_required(); void set_skin_required(bool v); - }; VARIANT_ENUM_CAST(SpineBoneData::TransformMode); -#endif //GODOT_SPINEBONEDATA_H +#endif//GODOT_SPINEBONEDATA_H diff --git a/spine-godot/spine_godot/SpineCollisionShapeProxy.cpp b/spine-godot/spine_godot/SpineCollisionShapeProxy.cpp index e41b28faf..9015db60d 100644 --- a/spine-godot/spine_godot/SpineCollisionShapeProxy.cpp +++ b/spine-godot/spine_godot/SpineCollisionShapeProxy.cpp @@ -32,173 +32,165 @@ #include "SpineSprite.h" void SpineCollisionShapeProxy::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_spine_sprite_path"), &SpineCollisionShapeProxy::get_spine_sprite_path); - ClassDB::bind_method(D_METHOD("set_spine_sprite_path", "v"), &SpineCollisionShapeProxy::set_spine_sprite_path); + ClassDB::bind_method(D_METHOD("get_spine_sprite_path"), &SpineCollisionShapeProxy::get_spine_sprite_path); + ClassDB::bind_method(D_METHOD("set_spine_sprite_path", "v"), &SpineCollisionShapeProxy::set_spine_sprite_path); - ClassDB::bind_method(D_METHOD("get_slot"), &SpineCollisionShapeProxy::get_slot); - ClassDB::bind_method(D_METHOD("set_slot", "v"), &SpineCollisionShapeProxy::set_slot); + ClassDB::bind_method(D_METHOD("get_slot"), &SpineCollisionShapeProxy::get_slot); + ClassDB::bind_method(D_METHOD("set_slot", "v"), &SpineCollisionShapeProxy::set_slot); - ClassDB::bind_method(D_METHOD("get_sync_transform"), &SpineCollisionShapeProxy::get_sync_transform); - ClassDB::bind_method(D_METHOD("set_sync_transform", "v"), &SpineCollisionShapeProxy::set_sync_transform); + ClassDB::bind_method(D_METHOD("get_sync_transform"), &SpineCollisionShapeProxy::get_sync_transform); + ClassDB::bind_method(D_METHOD("set_sync_transform", "v"), &SpineCollisionShapeProxy::set_sync_transform); - ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "spine_sprite_path"), "set_spine_sprite_path", "get_spine_sprite_path"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync_transform"), "set_sync_transform", "get_sync_transform"); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "spine_sprite_path"), "set_spine_sprite_path", "get_spine_sprite_path"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync_transform"), "set_sync_transform", "get_sync_transform"); } -SpineCollisionShapeProxy::SpineCollisionShapeProxy():sync_transform(true) { - +SpineCollisionShapeProxy::SpineCollisionShapeProxy() : sync_transform(true) { } SpineCollisionShapeProxy::~SpineCollisionShapeProxy() { - } void SpineCollisionShapeProxy::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_READY: { - set_process_internal(true); - } break; - case NOTIFICATION_INTERNAL_PROCESS: { - if (!disabled) { - if (sync_transform) _sync_transform(get_spine_sprite()); - _update_polygon_from_spine_sprite(get_spine_sprite()); - if (is_visible()) update(); - } - } break; - } + switch (p_what) { + case NOTIFICATION_READY: { + set_process_internal(true); + } break; + case NOTIFICATION_INTERNAL_PROCESS: { + if (!disabled) { + if (sync_transform) _sync_transform(get_spine_sprite()); + _update_polygon_from_spine_sprite(get_spine_sprite()); + if (is_visible()) update(); + } + } break; + } } SpineSprite *SpineCollisionShapeProxy::get_spine_sprite() const { - return (SpineSprite*) get_node_or_null(spine_sprite_path); + return (SpineSprite *) get_node_or_null(spine_sprite_path); } NodePath SpineCollisionShapeProxy::get_spine_sprite_path() { - return spine_sprite_path; + return spine_sprite_path; } void SpineCollisionShapeProxy::set_spine_sprite_path(NodePath v) { - spine_sprite_path = v; + spine_sprite_path = v; - _update_polygon_from_spine_sprite(get_spine_sprite()); + _update_polygon_from_spine_sprite(get_spine_sprite()); } String SpineCollisionShapeProxy::get_slot() const { - return slot; + return slot; } void SpineCollisionShapeProxy::set_slot(const String &v) { - slot = v; - _update_polygon_from_spine_sprite(get_spine_sprite()); + slot = v; + _update_polygon_from_spine_sprite(get_spine_sprite()); } void SpineCollisionShapeProxy::_update_polygon_from_spine_sprite(SpineSprite *sprite) { - _clear_polygon(); - if (sprite == nullptr || slot.empty()) { - return; - } + _clear_polygon(); + if (sprite == nullptr || slot.empty()) { + return; + } - if (!sprite->get_skeleton().is_valid()) { - return; - } + if (!sprite->get_skeleton().is_valid()) { + return; + } - auto sk = sprite->get_skeleton()->get_spine_object(); + auto sk = sprite->get_skeleton()->get_spine_object(); - spine::Vector vertices; + spine::Vector vertices; - spine::Slot *s = sk->findSlot(spine::String(slot.utf8())); - if (!s) { - return; - } - spine::Attachment *attachment = s->getAttachment(); - if(!attachment){ - return; - } + spine::Slot *s = sk->findSlot(spine::String(slot.utf8())); + if (!s) { + return; + } + spine::Attachment *attachment = s->getAttachment(); + if (!attachment) { + return; + } - if (attachment->getRTTI().isExactly(spine::BoundingBoxAttachment::rtti)) { - auto *box = (spine::BoundingBoxAttachment*) attachment; + if (attachment->getRTTI().isExactly(spine::BoundingBoxAttachment::rtti)) { + auto *box = (spine::BoundingBoxAttachment *) attachment; - vertices.setSize(box->getWorldVerticesLength(), 0); - box->computeWorldVertices(*s, vertices); - } else { - return; - } + vertices.setSize(box->getWorldVerticesLength(), 0); + box->computeWorldVertices(*s, vertices); + } else { + return; + } - polygon.resize(vertices.size()/2); - for (size_t j=0; j < vertices.size(); j+=2) { - polygon.set(j/2, Vector2(vertices[j], -vertices[j + 1])); - } + polygon.resize(vertices.size() / 2); + for (size_t j = 0; j < vertices.size(); j += 2) { + polygon.set(j / 2, Vector2(vertices[j], -vertices[j + 1])); + } - set_polygon(polygon); + set_polygon(polygon); } void SpineCollisionShapeProxy::_clear_polygon() { - polygon.clear(); - set_polygon(polygon); + polygon.clear(); + set_polygon(polygon); } void SpineCollisionShapeProxy::_sync_transform(SpineSprite *sprite) { - if (sprite == nullptr) return; - set_global_transform(sprite->get_global_transform()); + if (sprite == nullptr) return; + set_global_transform(sprite->get_global_transform()); } bool SpineCollisionShapeProxy::get_sync_transform() { - return sync_transform; + return sync_transform; } void SpineCollisionShapeProxy::set_sync_transform(bool v) { - sync_transform = v; + sync_transform = v; } void SpineCollisionShapeProxy::_get_property_list(List *p_list) const { - PropertyInfo p; - Vector res; + PropertyInfo p; + Vector res; - p.name = "slot"; - p.type = Variant::STRING; - _get_slot_list(res); - if (res.empty()) res.push_back("No Slot"); - p.hint_string = String(",").join(res); - p.hint = PROPERTY_HINT_ENUM; - p_list->push_back(p); + p.name = "slot"; + p.type = Variant::STRING; + _get_slot_list(res); + if (res.empty()) res.push_back("No Slot"); + p.hint_string = String(",").join(res); + p.hint = PROPERTY_HINT_ENUM; + p_list->push_back(p); } bool SpineCollisionShapeProxy::_get(const StringName &p_property, Variant &r_value) const { - if (p_property == "slot") { - r_value = get_slot(); - return true; - } - return false; + if (p_property == "slot") { + r_value = get_slot(); + return true; + } + return false; } bool SpineCollisionShapeProxy::_set(const StringName &p_property, const Variant &p_value) { - if (p_property == "slot") { - set_slot(p_value); - return true; - } - return false; + if (p_property == "slot") { + set_slot(p_value); + return true; + } + return false; } void SpineCollisionShapeProxy::_get_slot_list(Vector &res) const { - if (get_spine_sprite() == nullptr) { - return; - } + if (get_spine_sprite() == nullptr) { + return; + } - auto sprite = get_spine_sprite(); - if (!sprite->get_skeleton().is_valid()) { - return; - } + auto sprite = get_spine_sprite(); + if (!sprite->get_skeleton().is_valid()) { + return; + } - auto slots = sprite->get_skeleton()->get_slots(); - res.resize(slots.size()); - for (size_t i=0; i < res.size(); ++i) { - auto slot = (Ref)slots[i]; - if (slot.is_valid()) - res.set(i, slot->get_data()->get_slot_name()); - } + auto slots = sprite->get_skeleton()->get_slots(); + res.resize(slots.size()); + for (size_t i = 0; i < res.size(); ++i) { + auto slot = (Ref) slots[i]; + if (slot.is_valid()) + res.set(i, slot->get_data()->get_slot_name()); + } } - - - - - - diff --git a/spine-godot/spine_godot/SpineCollisionShapeProxy.h b/spine-godot/spine_godot/SpineCollisionShapeProxy.h index 5dd2dd683..c29eaa591 100644 --- a/spine-godot/spine_godot/SpineCollisionShapeProxy.h +++ b/spine-godot/spine_godot/SpineCollisionShapeProxy.h @@ -36,43 +36,45 @@ class SpineSprite; class SpineAnimationState; class SpineSkeleton; -class SpineCollisionShapeProxy : public CollisionPolygon2D{ - GDCLASS(SpineCollisionShapeProxy, CollisionPolygon2D) +class SpineCollisionShapeProxy : public CollisionPolygon2D { + GDCLASS(SpineCollisionShapeProxy, CollisionPolygon2D) protected: - static void _bind_methods(); + static void _bind_methods(); - NodePath spine_sprite_path; + NodePath spine_sprite_path; - String slot; + String slot; + + bool sync_transform; - bool sync_transform; protected: - void _notification(int p_what); - void _get_property_list(List *p_list) const; - bool _get(const StringName &p_property, Variant &r_value) const; - bool _set(const StringName &p_property, const Variant &p_value); + void _notification(int p_what); + void _get_property_list(List *p_list) const; + bool _get(const StringName &p_property, Variant &r_value) const; + bool _set(const StringName &p_property, const Variant &p_value); - SpineSprite *get_spine_sprite() const; + SpineSprite *get_spine_sprite() const; - void _update_polygon_from_spine_sprite(SpineSprite *sprite); - void _clear_polygon(); - void _sync_transform(SpineSprite *sprite); + void _update_polygon_from_spine_sprite(SpineSprite *sprite); + void _clear_polygon(); + void _sync_transform(SpineSprite *sprite); + + void _get_slot_list(Vector &res) const; - void _get_slot_list(Vector &res) const; public: - SpineCollisionShapeProxy(); - ~SpineCollisionShapeProxy(); + SpineCollisionShapeProxy(); + ~SpineCollisionShapeProxy(); - NodePath get_spine_sprite_path(); - void set_spine_sprite_path(NodePath v); + NodePath get_spine_sprite_path(); + void set_spine_sprite_path(NodePath v); - String get_slot() const; - void set_slot(const String &v); + String get_slot() const; + void set_slot(const String &v); - bool get_sync_transform(); - void set_sync_transform(bool v); + bool get_sync_transform(); + void set_sync_transform(bool v); }; -#endif //GODOT_SPINECOLLISIONSHAPEPROXY_H +#endif//GODOT_SPINECOLLISIONSHAPEPROXY_H diff --git a/spine-godot/spine_godot/SpineConstant.cpp b/spine-godot/spine_godot/SpineConstant.cpp index 9e0406103..760ff668a 100644 --- a/spine-godot/spine_godot/SpineConstant.cpp +++ b/spine-godot/spine_godot/SpineConstant.cpp @@ -30,33 +30,31 @@ #include "SpineConstant.h" void SpineConstant::_bind_methods() { - BIND_ENUM_CONSTANT(MixBlend_Setup); - BIND_ENUM_CONSTANT(MixBlend_First); - BIND_ENUM_CONSTANT(MixBlend_Replace); - BIND_ENUM_CONSTANT(MixBlend_Add); - - BIND_ENUM_CONSTANT(MixDirection_In); - BIND_ENUM_CONSTANT(MixDirection_Out); - - BIND_ENUM_CONSTANT(Property_Rotate); - BIND_ENUM_CONSTANT(Property_X); - BIND_ENUM_CONSTANT(Property_Y); - BIND_ENUM_CONSTANT(Property_ScaleX); - BIND_ENUM_CONSTANT( Property_ScaleY); - BIND_ENUM_CONSTANT(Property_ShearX); - BIND_ENUM_CONSTANT(Property_ShearY); - BIND_ENUM_CONSTANT(Property_Rgb); - BIND_ENUM_CONSTANT(Property_Alpha); - BIND_ENUM_CONSTANT(Property_Rgb2); - BIND_ENUM_CONSTANT(Property_Attachment); - BIND_ENUM_CONSTANT(Property_Deform); - BIND_ENUM_CONSTANT(Property_Event); - BIND_ENUM_CONSTANT(Property_DrawOrder); - BIND_ENUM_CONSTANT(Property_IkConstraint); - BIND_ENUM_CONSTANT(Property_TransformConstraint); - BIND_ENUM_CONSTANT(Property_PathConstraintPosition); - BIND_ENUM_CONSTANT(Property_PathConstraintSpacing); - BIND_ENUM_CONSTANT(Property_PathConstraintMix); + BIND_ENUM_CONSTANT(MixBlend_Setup); + BIND_ENUM_CONSTANT(MixBlend_First); + BIND_ENUM_CONSTANT(MixBlend_Replace); + BIND_ENUM_CONSTANT(MixBlend_Add); + BIND_ENUM_CONSTANT(MixDirection_In); + BIND_ENUM_CONSTANT(MixDirection_Out); + BIND_ENUM_CONSTANT(Property_Rotate); + BIND_ENUM_CONSTANT(Property_X); + BIND_ENUM_CONSTANT(Property_Y); + BIND_ENUM_CONSTANT(Property_ScaleX); + BIND_ENUM_CONSTANT(Property_ScaleY); + BIND_ENUM_CONSTANT(Property_ShearX); + BIND_ENUM_CONSTANT(Property_ShearY); + BIND_ENUM_CONSTANT(Property_Rgb); + BIND_ENUM_CONSTANT(Property_Alpha); + BIND_ENUM_CONSTANT(Property_Rgb2); + BIND_ENUM_CONSTANT(Property_Attachment); + BIND_ENUM_CONSTANT(Property_Deform); + BIND_ENUM_CONSTANT(Property_Event); + BIND_ENUM_CONSTANT(Property_DrawOrder); + BIND_ENUM_CONSTANT(Property_IkConstraint); + BIND_ENUM_CONSTANT(Property_TransformConstraint); + BIND_ENUM_CONSTANT(Property_PathConstraintPosition); + BIND_ENUM_CONSTANT(Property_PathConstraintSpacing); + BIND_ENUM_CONSTANT(Property_PathConstraintMix); } \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineConstant.h b/spine-godot/spine_godot/SpineConstant.h index fb2d01ece..c7f86d8b9 100644 --- a/spine-godot/spine_godot/SpineConstant.h +++ b/spine-godot/spine_godot/SpineConstant.h @@ -32,49 +32,50 @@ #include "core/variant_parser.h" -class SpineConstant : public Object{ - GDCLASS(SpineConstant, Object); +class SpineConstant : public Object { + GDCLASS(SpineConstant, Object); protected: - static void _bind_methods(); + static void _bind_methods(); + public: - enum MixBlend { - MixBlend_Setup = 0, - MixBlend_First, - MixBlend_Replace, - MixBlend_Add - }; + enum MixBlend { + MixBlend_Setup = 0, + MixBlend_First, + MixBlend_Replace, + MixBlend_Add + }; - enum MixDirection { - MixDirection_In = 0, - MixDirection_Out - }; + enum MixDirection { + MixDirection_In = 0, + MixDirection_Out + }; - enum PropertyId { - 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 - }; + enum PropertyId { + 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 + }; }; VARIANT_ENUM_CAST(SpineConstant::MixBlend); VARIANT_ENUM_CAST(SpineConstant::MixDirection); VARIANT_ENUM_CAST(SpineConstant::PropertyId); -#endif //GODOT_SPINECONSTANT_H +#endif//GODOT_SPINECONSTANT_H diff --git a/spine-godot/spine_godot/SpineConstraintData.cpp b/spine-godot/spine_godot/SpineConstraintData.cpp index 52d054efe..16bbac435 100644 --- a/spine-godot/spine_godot/SpineConstraintData.cpp +++ b/spine-godot/spine_godot/SpineConstraintData.cpp @@ -37,23 +37,23 @@ void SpineConstraintData::_bind_methods() { ClassDB::bind_method(D_METHOD("set_skin_required", "v"), &SpineConstraintData::set_skin_required); } -SpineConstraintData::SpineConstraintData():constraint_data(NULL) {} +SpineConstraintData::SpineConstraintData() : constraint_data(NULL) {} SpineConstraintData::~SpineConstraintData() {} -String SpineConstraintData::get_constraint_data_name(){ +String SpineConstraintData::get_constraint_data_name() { return constraint_data->getName().buffer(); } -uint64_t SpineConstraintData::get_order(){ +uint64_t SpineConstraintData::get_order() { return constraint_data->getOrder(); } -void SpineConstraintData::set_order(uint64_t v){ +void SpineConstraintData::set_order(uint64_t v) { constraint_data->setOrder(v); } -bool SpineConstraintData::is_skin_required(){ +bool SpineConstraintData::is_skin_required() { return constraint_data->isSkinRequired(); } -void SpineConstraintData::set_skin_required(bool v){ +void SpineConstraintData::set_skin_required(bool v) { constraint_data->setSkinRequired(v); } \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineConstraintData.h b/spine-godot/spine_godot/SpineConstraintData.h index ff0517a46..35b9dd52a 100644 --- a/spine-godot/spine_godot/SpineConstraintData.h +++ b/spine-godot/spine_godot/SpineConstraintData.h @@ -47,10 +47,10 @@ public: SpineConstraintData(); ~SpineConstraintData(); - inline void set_spine_object(spine::ConstraintData *c){ + inline void set_spine_object(spine::ConstraintData *c) { constraint_data = c; } - virtual inline spine::ConstraintData *get_spine_object(){ + virtual inline spine::ConstraintData *get_spine_object() { return constraint_data; } @@ -63,4 +63,4 @@ public: void set_skin_required(bool v); }; -#endif //GODOT_SPINECONSTRAINTDATA_H +#endif//GODOT_SPINECONSTRAINTDATA_H diff --git a/spine-godot/spine_godot/SpineEvent.cpp b/spine-godot/spine_godot/SpineEvent.cpp index f33582045..9d753db33 100644 --- a/spine-godot/spine_godot/SpineEvent.cpp +++ b/spine-godot/spine_godot/SpineEvent.cpp @@ -43,19 +43,19 @@ void SpineEvent::_bind_methods() { ClassDB::bind_method(D_METHOD("set_volume", "v"), &SpineEvent::set_volume); ClassDB::bind_method(D_METHOD("get_balance"), &SpineEvent::get_balance); ClassDB::bind_method(D_METHOD("set_balance", "v"), &SpineEvent::set_balance); -// -// BIND_ENUM_CONSTANT(EVENTTYPE_START); -// BIND_ENUM_CONSTANT(EVENTTYPE_INTERRUPT); -// BIND_ENUM_CONSTANT(EVENTTYPE_END); -// BIND_ENUM_CONSTANT(EVENTTYPE_COMPLETE); -// BIND_ENUM_CONSTANT(EVENTTYPE_DISPOSE); -// BIND_ENUM_CONSTANT(EVENTTYPE_EVENT); + // + // BIND_ENUM_CONSTANT(EVENTTYPE_START); + // BIND_ENUM_CONSTANT(EVENTTYPE_INTERRUPT); + // BIND_ENUM_CONSTANT(EVENTTYPE_END); + // BIND_ENUM_CONSTANT(EVENTTYPE_COMPLETE); + // BIND_ENUM_CONSTANT(EVENTTYPE_DISPOSE); + // BIND_ENUM_CONSTANT(EVENTTYPE_EVENT); } -SpineEvent::SpineEvent():event(NULL) {} -SpineEvent::~SpineEvent(){} +SpineEvent::SpineEvent() : event(NULL) {} +SpineEvent::~SpineEvent() {} -Ref SpineEvent::get_data(){ +Ref SpineEvent::get_data() { Ref event_data(memnew(SpineEventData)); event_data->set_spine_object(&(event->getData())); return event_data; @@ -65,46 +65,46 @@ String SpineEvent::get_event_name() { return event->getData().getName().buffer(); } -float SpineEvent::get_time(){ +float SpineEvent::get_time() { return event->getTime(); } -int SpineEvent::get_int_value(){ +int SpineEvent::get_int_value() { return event->getIntValue(); } -void SpineEvent::set_int_value(int v){ +void SpineEvent::set_int_value(int v) { event->setIntValue(v); } -float SpineEvent::get_float_value(){ +float SpineEvent::get_float_value() { return event->getFloatValue(); } -void SpineEvent::set_float_value(float v){ +void SpineEvent::set_float_value(float v) { event->setFloatValue(v); } -String SpineEvent::get_string_value(){ +String SpineEvent::get_string_value() { return event->getStringValue().buffer(); } -void SpineEvent::set_string_value(const String &v){ +void SpineEvent::set_string_value(const String &v) { event->setStringValue(spine::String(v.utf8())); } -float SpineEvent::get_volume(){ +float SpineEvent::get_volume() { return event->getVolume(); } -void SpineEvent::set_volume(float v){ +void SpineEvent::set_volume(float v) { event->setVolume(v); } -float SpineEvent::get_balance(){ +float SpineEvent::get_balance() { return event->getBalance(); } -void SpineEvent::set_balance(float v){ +void SpineEvent::set_balance(float v) { event->setBalance(v); } \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineEvent.h b/spine-godot/spine_godot/SpineEvent.h index 4824eeaff..bbbf0b986 100644 --- a/spine-godot/spine_godot/SpineEvent.h +++ b/spine-godot/spine_godot/SpineEvent.h @@ -36,25 +36,27 @@ #include "SpineEventData.h" -class SpineEvent : public Reference{ +class SpineEvent : public Reference { GDCLASS(SpineEvent, Reference); protected: static void _bind_methods(); + private: spine::Event *event; + public: SpineEvent(); ~SpineEvent(); - inline void set_spine_object(spine::Event *e){ + inline void set_spine_object(spine::Event *e) { event = e; } - inline spine::Event *get_spine_object() const{ + inline spine::Event *get_spine_object() const { return event; } - enum EventType{ + enum EventType { EVENTTYPE_START = spine::EventType_Start, EVENTTYPE_INTERRUPT = spine::EventType_Interrupt, EVENTTYPE_END = spine::EventType_End, @@ -86,4 +88,4 @@ public: void set_balance(float inValue); }; -#endif //GODOT_SPINEEVENT_H +#endif//GODOT_SPINEEVENT_H diff --git a/spine-godot/spine_godot/SpineEventData.cpp b/spine-godot/spine_godot/SpineEventData.cpp index a1367ce96..bca195e79 100644 --- a/spine-godot/spine_godot/SpineEventData.cpp +++ b/spine-godot/spine_godot/SpineEventData.cpp @@ -30,8 +30,7 @@ #include "SpineEventData.h" void SpineEventData::_bind_methods() { - } -SpineEventData::SpineEventData():event_data(NULL) {} -SpineEventData::~SpineEventData(){} +SpineEventData::SpineEventData() : event_data(NULL) {} +SpineEventData::~SpineEventData() {} diff --git a/spine-godot/spine_godot/SpineEventData.h b/spine-godot/spine_godot/SpineEventData.h index eb6279717..1cf669f26 100644 --- a/spine-godot/spine_godot/SpineEventData.h +++ b/spine-godot/spine_godot/SpineEventData.h @@ -34,23 +34,25 @@ #include -class SpineEventData : public Reference{ +class SpineEventData : public Reference { GDCLASS(SpineEventData, Reference); protected: static void _bind_methods(); + private: const spine::EventData *event_data; + public: SpineEventData(); ~SpineEventData(); - inline void set_spine_object(const spine::EventData *e){ + inline void set_spine_object(const spine::EventData *e) { event_data = e; } - inline const spine::EventData *get_spine_object(){ + inline const spine::EventData *get_spine_object() { return event_data; } }; -#endif //GODOT_SPINEEVENTDATA_H +#endif//GODOT_SPINEEVENTDATA_H diff --git a/spine-godot/spine_godot/SpineIkConstraint.cpp b/spine-godot/spine_godot/SpineIkConstraint.cpp index 2c613ee90..d88492b48 100644 --- a/spine-godot/spine_godot/SpineIkConstraint.cpp +++ b/spine-godot/spine_godot/SpineIkConstraint.cpp @@ -52,35 +52,35 @@ void SpineIkConstraint::_bind_methods() { ClassDB::bind_method(D_METHOD("set_active", "v"), &SpineIkConstraint::set_active); } -SpineIkConstraint::SpineIkConstraint():ik_constraint(NULL) {} +SpineIkConstraint::SpineIkConstraint() : ik_constraint(NULL) {} SpineIkConstraint::~SpineIkConstraint() {} // void SpineIkConstraint::apply(){ // ik_constraint->apply(); // } -void SpineIkConstraint::update(){ +void SpineIkConstraint::update() { ik_constraint->update(); } -int SpineIkConstraint::get_order(){ +int SpineIkConstraint::get_order() { return ik_constraint->getOrder(); } -Ref SpineIkConstraint::get_data(){ +Ref SpineIkConstraint::get_data() { auto &ikc = ik_constraint->getData(); Ref gd_ikc(memnew(SpineIkConstraintData)); gd_ikc->set_spine_object(&ikc); return gd_ikc; } -Array SpineIkConstraint::get_bones(){ +Array SpineIkConstraint::get_bones() { auto &bs = ik_constraint->getBones(); Array gd_bs; gd_bs.resize(bs.size()); - for(size_t i=0; i(NULL); + if (b == NULL) gd_bs[i] = Ref(NULL); Ref gd_b(memnew(SpineBone)); gd_b->set_spine_object(b); gd_bs[i] = gd_b; @@ -88,59 +88,59 @@ Array SpineIkConstraint::get_bones(){ return gd_bs; } -Ref SpineIkConstraint::get_target(){ +Ref SpineIkConstraint::get_target() { auto b = ik_constraint->getTarget(); - if(b == NULL) return NULL; + if (b == NULL) return NULL; Ref gd_b(memnew(SpineBone)); gd_b->set_spine_object(b); return gd_b; } -void SpineIkConstraint::set_target(Ref v){ - if(v.is_valid()){ +void SpineIkConstraint::set_target(Ref v) { + if (v.is_valid()) { ik_constraint->setTarget(v->get_spine_object()); - } else{ + } else { ik_constraint->setTarget(NULL); } } -int SpineIkConstraint::get_bend_direction(){ +int SpineIkConstraint::get_bend_direction() { return ik_constraint->getBendDirection(); } -void SpineIkConstraint::set_bend_direction(int v){ +void SpineIkConstraint::set_bend_direction(int v) { ik_constraint->setBendDirection(v); } -bool SpineIkConstraint::get_compress(){ +bool SpineIkConstraint::get_compress() { return ik_constraint->getCompress(); } -void SpineIkConstraint::set_compress(bool v){ +void SpineIkConstraint::set_compress(bool v) { ik_constraint->setCompress(v); } -bool SpineIkConstraint::get_stretch(){ +bool SpineIkConstraint::get_stretch() { return ik_constraint->getStretch(); } -void SpineIkConstraint::set_stretch(bool v){ +void SpineIkConstraint::set_stretch(bool v) { ik_constraint->setStretch(v); } -float SpineIkConstraint::get_mix(){ +float SpineIkConstraint::get_mix() { return ik_constraint->getMix(); } -void SpineIkConstraint::set_mix(float v){ +void SpineIkConstraint::set_mix(float v) { ik_constraint->setMix(v); } -float SpineIkConstraint::get_softness(){ +float SpineIkConstraint::get_softness() { return ik_constraint->getSoftness(); } -void SpineIkConstraint::set_softness(float v){ +void SpineIkConstraint::set_softness(float v) { ik_constraint->setSoftness(v); } -bool SpineIkConstraint::is_active(){ +bool SpineIkConstraint::is_active() { return ik_constraint->isActive(); } -void SpineIkConstraint::set_active(bool v){ +void SpineIkConstraint::set_active(bool v) { ik_constraint->setActive(v); } \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineIkConstraint.h b/spine-godot/spine_godot/SpineIkConstraint.h index 2be633115..c7c4aeefe 100644 --- a/spine-godot/spine_godot/SpineIkConstraint.h +++ b/spine-godot/spine_godot/SpineIkConstraint.h @@ -51,15 +51,15 @@ public: SpineIkConstraint(); ~SpineIkConstraint(); - inline void set_spine_object(spine::IkConstraint * ic){ + inline void set_spine_object(spine::IkConstraint *ic) { ik_constraint = ic; } - inline spine::IkConstraint *get_spine_object(){ + inline spine::IkConstraint *get_spine_object() { return ik_constraint; } // The spine-runtime-cpp 4.0 seems to not have a apply function implementation. - // void apply(); + // void apply(); void update(); @@ -89,7 +89,6 @@ public: bool is_active(); void set_active(bool v); - }; -#endif //GODOT_SPINEIKCONSTRAINT_H +#endif//GODOT_SPINEIKCONSTRAINT_H diff --git a/spine-godot/spine_godot/SpineIkConstraintData.cpp b/spine-godot/spine_godot/SpineIkConstraintData.cpp index be9dfe080..62731aecf 100644 --- a/spine-godot/spine_godot/SpineIkConstraintData.cpp +++ b/spine-godot/spine_godot/SpineIkConstraintData.cpp @@ -50,12 +50,12 @@ void SpineIkConstraintData::_bind_methods() { SpineIkConstraintData::SpineIkConstraintData() {} SpineIkConstraintData::~SpineIkConstraintData() {} -Array SpineIkConstraintData::get_bones(){ +Array SpineIkConstraintData::get_bones() { auto bs = get_spine_data()->getBones(); Array gd_bs; gd_bs.resize(bs.size()); - for(size_t i=0; i < bs.size(); ++i){ - if(bs[i] == NULL) gd_bs[i] = Ref(NULL); + for (size_t i = 0; i < bs.size(); ++i) { + if (bs[i] == NULL) gd_bs[i] = Ref(NULL); else { Ref gd_b(memnew(SpineBoneData)); gd_b->set_spine_object(bs[i]); @@ -65,59 +65,59 @@ Array SpineIkConstraintData::get_bones(){ return gd_bs; } -Ref SpineIkConstraintData::get_target(){ +Ref SpineIkConstraintData::get_target() { auto b = get_spine_data()->getTarget(); - if(b == NULL) return NULL; + if (b == NULL) return NULL; Ref gd_b(memnew(SpineBoneData)); gd_b->set_spine_object(b); return gd_b; } -void SpineIkConstraintData::set_target(Ref v){ - if(v.is_valid()){ +void SpineIkConstraintData::set_target(Ref v) { + if (v.is_valid()) { get_spine_data()->setTarget(v->get_spine_object()); - }else{ + } else { get_spine_data()->setTarget(NULL); } } -int SpineIkConstraintData::get_bend_direction(){ +int SpineIkConstraintData::get_bend_direction() { return get_spine_data()->getBendDirection(); } -void SpineIkConstraintData::set_bend_direction(int v){ +void SpineIkConstraintData::set_bend_direction(int v) { get_spine_data()->setBendDirection(v); } -bool SpineIkConstraintData::get_compress(){ +bool SpineIkConstraintData::get_compress() { return get_spine_data()->getCompress(); } -void SpineIkConstraintData::set_compress(bool v){ +void SpineIkConstraintData::set_compress(bool v) { get_spine_data()->setCompress(v); } -bool SpineIkConstraintData::get_stretch(){ +bool SpineIkConstraintData::get_stretch() { return get_spine_data()->getStretch(); } -void SpineIkConstraintData::set_stretch(bool v){ +void SpineIkConstraintData::set_stretch(bool v) { get_spine_data()->setStretch(v); } -bool SpineIkConstraintData::get_uniform(){ +bool SpineIkConstraintData::get_uniform() { return get_spine_data()->getUniform(); } -void SpineIkConstraintData::set_uniform(bool v){ +void SpineIkConstraintData::set_uniform(bool v) { get_spine_data()->setUniform(v); } -float SpineIkConstraintData::get_mix(){ +float SpineIkConstraintData::get_mix() { return get_spine_data()->getMix(); } -void SpineIkConstraintData::set_mix(float v){ +void SpineIkConstraintData::set_mix(float v) { get_spine_data()->setMix(v); } -float SpineIkConstraintData::get_softness(){ +float SpineIkConstraintData::get_softness() { return get_spine_data()->getSoftness(); } -void SpineIkConstraintData::set_softness(float v){ +void SpineIkConstraintData::set_softness(float v) { get_spine_data()->setSoftness(v); } \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineIkConstraintData.h b/spine-godot/spine_godot/SpineIkConstraintData.h index 97ecac686..da0434d0b 100644 --- a/spine-godot/spine_godot/SpineIkConstraintData.h +++ b/spine-godot/spine_godot/SpineIkConstraintData.h @@ -47,8 +47,8 @@ public: SpineIkConstraintData(); ~SpineIkConstraintData(); - virtual inline spine::IkConstraintData *get_spine_data(){ - return (spine::IkConstraintData*) SpineConstraintData::get_spine_object(); + virtual inline spine::IkConstraintData *get_spine_data() { + return (spine::IkConstraintData *) SpineConstraintData::get_spine_object(); } Array get_bones(); @@ -73,7 +73,6 @@ public: float get_softness(); void set_softness(float v); - }; -#endif //GODOT_SPINEIKCONSTRAINTDATA_H +#endif//GODOT_SPINEIKCONSTRAINTDATA_H diff --git a/spine-godot/spine_godot/SpinePathConstraint.cpp b/spine-godot/spine_godot/SpinePathConstraint.cpp index 4db07fb45..3df032a22 100644 --- a/spine-godot/spine_godot/SpinePathConstraint.cpp +++ b/spine-godot/spine_godot/SpinePathConstraint.cpp @@ -29,7 +29,7 @@ #include "SpinePathConstraint.h" -void SpinePathConstraint::_bind_methods(){ +void SpinePathConstraint::_bind_methods() { // ClassDB::bind_method(D_METHOD("apply"), &SpinePathConstraint::apply); ClassDB::bind_method(D_METHOD("update"), &SpinePathConstraint::update); ClassDB::bind_method(D_METHOD("get_order"), &SpinePathConstraint::get_order); @@ -51,63 +51,63 @@ void SpinePathConstraint::_bind_methods(){ ClassDB::bind_method(D_METHOD("set_active", "v"), &SpinePathConstraint::set_active); } -SpinePathConstraint::SpinePathConstraint():path_constraint(NULL) {} +SpinePathConstraint::SpinePathConstraint() : path_constraint(NULL) {} SpinePathConstraint::~SpinePathConstraint() {} // void SpinePathConstraint::apply(){ // path_constraint->apply(); // } -void SpinePathConstraint::update(){ +void SpinePathConstraint::update() { path_constraint->update(); } -int SpinePathConstraint::get_order(){ +int SpinePathConstraint::get_order() { return path_constraint->getOrder(); } -float SpinePathConstraint::get_position(){ +float SpinePathConstraint::get_position() { return path_constraint->getPosition(); } -void SpinePathConstraint::set_position(float v){ +void SpinePathConstraint::set_position(float v) { path_constraint->setPosition(v); } -float SpinePathConstraint::get_spacing(){ +float SpinePathConstraint::get_spacing() { return path_constraint->getSpacing(); } -void SpinePathConstraint::set_spacing(float v){ +void SpinePathConstraint::set_spacing(float v) { path_constraint->setSpacing(v); } -float SpinePathConstraint::get_mix_rotate(){ +float SpinePathConstraint::get_mix_rotate() { return path_constraint->getMixRotate(); } -void SpinePathConstraint::set_mix_rotate(float v){ +void SpinePathConstraint::set_mix_rotate(float v) { path_constraint->setMixRotate(v); } -float SpinePathConstraint::get_mix_x(){ +float SpinePathConstraint::get_mix_x() { return path_constraint->getMixX(); } -void SpinePathConstraint::set_mix_x(float v){ +void SpinePathConstraint::set_mix_x(float v) { path_constraint->setMixX(v); } -float SpinePathConstraint::get_mix_y(){ +float SpinePathConstraint::get_mix_y() { return path_constraint->getMixY(); } -void SpinePathConstraint::set_mix_y(float v){ +void SpinePathConstraint::set_mix_y(float v) { path_constraint->setMixY(v); } -Array SpinePathConstraint::get_bones(){ +Array SpinePathConstraint::get_bones() { auto &bs = path_constraint->getBones(); Array gd_bs; gd_bs.resize(bs.size()); - for(size_t i=0; i(NULL); + if (b == NULL) gd_bs[i] = Ref(NULL); Ref gd_b(memnew(SpineBone)); gd_b->set_spine_object(b); gd_bs[i] = gd_b; @@ -115,31 +115,31 @@ Array SpinePathConstraint::get_bones(){ return gd_bs; } -Ref SpinePathConstraint::get_target(){ +Ref SpinePathConstraint::get_target() { auto s = path_constraint->getTarget(); - if(s == NULL) return NULL; + if (s == NULL) return NULL; Ref gd_s(memnew(SpineSlot)); gd_s->set_spine_object(s); return gd_s; } -void SpinePathConstraint::set_target(Ref v){ - if(v.is_valid()){ +void SpinePathConstraint::set_target(Ref v) { + if (v.is_valid()) { path_constraint->setTarget(v->get_spine_object()); - }else{ + } else { path_constraint->setTarget(NULL); } } -Ref SpinePathConstraint::get_data(){ +Ref SpinePathConstraint::get_data() { auto &sd = path_constraint->getData(); Ref gd_sd(memnew(SpinePathConstraintData)); gd_sd->set_spine_object(&sd); return gd_sd; } -bool SpinePathConstraint::is_active(){ +bool SpinePathConstraint::is_active() { return path_constraint->isActive(); } -void SpinePathConstraint::set_active(bool v){ +void SpinePathConstraint::set_active(bool v) { path_constraint->setActive(v); } \ No newline at end of file diff --git a/spine-godot/spine_godot/SpinePathConstraint.h b/spine-godot/spine_godot/SpinePathConstraint.h index 8ab822f12..dcd41d09e 100644 --- a/spine-godot/spine_godot/SpinePathConstraint.h +++ b/spine-godot/spine_godot/SpinePathConstraint.h @@ -38,7 +38,7 @@ #include "SpineSlot.h" #include "SpinePathConstraintData.h" -class SpinePathConstraint : public Reference{ +class SpinePathConstraint : public Reference { GDCLASS(SpinePathConstraint, Reference); protected: @@ -51,15 +51,15 @@ public: SpinePathConstraint(); ~SpinePathConstraint(); - inline void set_spine_object(spine::PathConstraint *pc){ + inline void set_spine_object(spine::PathConstraint *pc) { path_constraint = pc; } - inline spine::PathConstraint *get_spine_object(){ + inline spine::PathConstraint *get_spine_object() { return path_constraint; } // The spine-runtime-cpp 4.0 seems to not have a apply function implementation. - // void apply(); + // void apply(); void update(); @@ -91,4 +91,4 @@ public: void set_active(bool v); }; -#endif //GODOT_SPINEPATHCONSTRAINT_H +#endif//GODOT_SPINEPATHCONSTRAINT_H diff --git a/spine-godot/spine_godot/SpinePathConstraintData.cpp b/spine-godot/spine_godot/SpinePathConstraintData.cpp index 24541eeed..5d0f34b64 100644 --- a/spine-godot/spine_godot/SpinePathConstraintData.cpp +++ b/spine-godot/spine_godot/SpinePathConstraintData.cpp @@ -68,12 +68,12 @@ void SpinePathConstraintData::_bind_methods() { SpinePathConstraintData::SpinePathConstraintData() {} SpinePathConstraintData::~SpinePathConstraintData() {} -Array SpinePathConstraintData::get_bones(){ +Array SpinePathConstraintData::get_bones() { auto bs = get_spine_data()->getBones(); Array gd_bs; gd_bs.resize(bs.size()); - for(size_t i=0; i < bs.size(); ++i){ - if(bs[i] == NULL) gd_bs[i] = Ref(NULL); + for (size_t i = 0; i < bs.size(); ++i) { + if (bs[i] == NULL) gd_bs[i] = Ref(NULL); else { Ref gd_b(memnew(SpineBoneData)); gd_b->set_spine_object(bs[i]); @@ -83,86 +83,86 @@ Array SpinePathConstraintData::get_bones(){ return gd_bs; } -Ref SpinePathConstraintData::get_target(){ +Ref SpinePathConstraintData::get_target() { auto s = get_spine_data()->getTarget(); - if(s == NULL) return NULL; + if (s == NULL) return NULL; Ref gd_s(memnew(SpineSlotData)); gd_s->set_spine_object(s); return gd_s; } -void SpinePathConstraintData::set_target(Ref v){ - if(v.is_valid()){ +void SpinePathConstraintData::set_target(Ref v) { + if (v.is_valid()) { get_spine_data()->setTarget(v->get_spine_object()); - }else{ + } else { get_spine_data()->setTarget(NULL); } } -SpinePathConstraintData::PositionMode SpinePathConstraintData::get_position_mode(){ +SpinePathConstraintData::PositionMode SpinePathConstraintData::get_position_mode() { auto m = (int) get_spine_data()->getPositionMode(); return (PositionMode) m; } -void SpinePathConstraintData::set_position_mode(PositionMode v){ +void SpinePathConstraintData::set_position_mode(PositionMode v) { auto m = (int) v; - get_spine_data()->setPositionMode((spine::PositionMode)m); + get_spine_data()->setPositionMode((spine::PositionMode) m); } -SpinePathConstraintData::SpacingMode SpinePathConstraintData::get_spacing_mode(){ +SpinePathConstraintData::SpacingMode SpinePathConstraintData::get_spacing_mode() { auto m = (int) get_spine_data()->getSpacingMode(); return (SpacingMode) m; } -void SpinePathConstraintData::set_spacing_mode(SpacingMode v){ +void SpinePathConstraintData::set_spacing_mode(SpacingMode v) { auto m = (int) v; - get_spine_data()->setSpacingMode((spine::SpacingMode)m); + get_spine_data()->setSpacingMode((spine::SpacingMode) m); } -SpinePathConstraintData::RotateMode SpinePathConstraintData::get_rotate_mode(){ +SpinePathConstraintData::RotateMode SpinePathConstraintData::get_rotate_mode() { auto m = (int) get_spine_data()->getRotateMode(); return (RotateMode) m; } -void SpinePathConstraintData::set_rotate_mode(RotateMode v){ +void SpinePathConstraintData::set_rotate_mode(RotateMode v) { auto m = (int) v; - get_spine_data()->setRotateMode((spine::RotateMode)m); + get_spine_data()->setRotateMode((spine::RotateMode) m); } -float SpinePathConstraintData::get_offset_rotation(){ +float SpinePathConstraintData::get_offset_rotation() { return get_spine_data()->getOffsetRotation(); } -void SpinePathConstraintData::set_offset_rotation(float v){ +void SpinePathConstraintData::set_offset_rotation(float v) { get_spine_data()->setOffsetRotation(v); } -float SpinePathConstraintData::get_position(){ +float SpinePathConstraintData::get_position() { return get_spine_data()->getPosition(); } -void SpinePathConstraintData::set_position(float v){ +void SpinePathConstraintData::set_position(float v) { get_spine_data()->setPosition(v); } -float SpinePathConstraintData::get_spacing(){ +float SpinePathConstraintData::get_spacing() { return get_spine_data()->getSpacing(); } -void SpinePathConstraintData::set_spacing(float v){ +void SpinePathConstraintData::set_spacing(float v) { get_spine_data()->setSpacing(v); } -float SpinePathConstraintData::get_mix_rotate(){ +float SpinePathConstraintData::get_mix_rotate() { return get_spine_data()->getMixRotate(); } -void SpinePathConstraintData::set_mix_rotate(float v){ +void SpinePathConstraintData::set_mix_rotate(float v) { get_spine_data()->setMixRotate(v); } -float SpinePathConstraintData::get_mix_x(){ +float SpinePathConstraintData::get_mix_x() { return get_spine_data()->getMixX(); } -void SpinePathConstraintData::set_mix_x(float v){ +void SpinePathConstraintData::set_mix_x(float v) { get_spine_data()->setMixX(v); } -float SpinePathConstraintData::get_mix_y(){ +float SpinePathConstraintData::get_mix_y() { return get_spine_data()->getMixY(); } -void SpinePathConstraintData::set_mix_y(float v){ +void SpinePathConstraintData::set_mix_y(float v) { get_spine_data()->setMixY(v); } \ No newline at end of file diff --git a/spine-godot/spine_godot/SpinePathConstraintData.h b/spine-godot/spine_godot/SpinePathConstraintData.h index 1152998a4..068a68ec0 100644 --- a/spine-godot/spine_godot/SpinePathConstraintData.h +++ b/spine-godot/spine_godot/SpinePathConstraintData.h @@ -48,8 +48,8 @@ public: SpinePathConstraintData(); ~SpinePathConstraintData(); - virtual inline spine::PathConstraintData *get_spine_data(){ - return (spine::PathConstraintData*) SpineConstraintData::get_spine_object(); + virtual inline spine::PathConstraintData *get_spine_data() { + return (spine::PathConstraintData *) SpineConstraintData::get_spine_object(); } enum PositionMode { @@ -105,4 +105,4 @@ public: VARIANT_ENUM_CAST(SpinePathConstraintData::PositionMode); VARIANT_ENUM_CAST(SpinePathConstraintData::SpacingMode); VARIANT_ENUM_CAST(SpinePathConstraintData::RotateMode); -#endif //GODOT_SPINEPATHCONSTRAINTDATA_H +#endif//GODOT_SPINEPATHCONSTRAINTDATA_H diff --git a/spine-godot/spine_godot/SpineRendererObject.h b/spine-godot/spine_godot/SpineRendererObject.h index e8cb3b333..1076d52bd 100644 --- a/spine-godot/spine_godot/SpineRendererObject.h +++ b/spine-godot/spine_godot/SpineRendererObject.h @@ -34,9 +34,9 @@ struct SpineRendererObject { - Ref tex; - Ref normal_tex; + Ref tex; + Ref normal_tex; }; -#endif +#endif diff --git a/spine-godot/spine_godot/SpineRuntimeEditorPlugin.cpp b/spine-godot/spine_godot/SpineRuntimeEditorPlugin.cpp index 773e199c7..80de73af7 100644 --- a/spine-godot/spine_godot/SpineRuntimeEditorPlugin.cpp +++ b/spine-godot/spine_godot/SpineRuntimeEditorPlugin.cpp @@ -36,64 +36,63 @@ #include "SpineSprite.h" -Error SpineAtlasResourceImportPlugin::import(const String &p_source_file, const String &p_save_path, const Map &p_options, List *r_platform_variants, List *r_gen_files, Variant *r_metadata){ - Ref res(memnew(SpineAtlasResource)); - res->set_normal_texture_prefix(p_options["normal_texture_prefix"]); - res->load_from_atlas_file(p_source_file); +Error SpineAtlasResourceImportPlugin::import(const String &p_source_file, const String &p_save_path, const Map &p_options, List *r_platform_variants, List *r_gen_files, Variant *r_metadata) { + Ref res(memnew(SpineAtlasResource)); + res->set_normal_texture_prefix(p_options["normal_texture_prefix"]); + res->load_from_atlas_file(p_source_file); - String file_name = vformat("%s.%s", p_save_path, get_save_extension()); - auto err = ResourceSaver::save(file_name, res); - return err; + String file_name = vformat("%s.%s", p_save_path, get_save_extension()); + auto err = ResourceSaver::save(file_name, res); + return err; } void SpineAtlasResourceImportPlugin::get_import_options(List *r_options, int p_preset) const { - if (p_preset == 0) { - ImportOption op; - op.option.name = "normal_texture_prefix"; - op.option.type = Variant::STRING; - op.option.hint_string = "String"; - op.default_value = String("n"); - r_options->push_back(op); - } + if (p_preset == 0) { + ImportOption op; + op.option.name = "normal_texture_prefix"; + op.option.type = Variant::STRING; + op.option.hint_string = "String"; + op.default_value = String("n"); + r_options->push_back(op); + } } -Error SpineJsonResourceImportPlugin::import(const String &p_source_file, const String &p_save_path, const Map &p_options, List *r_platform_variants, List *r_gen_files, Variant *r_metadata){ - Ref res(memnew(SpineSkeletonJsonDataResource)); - res->load_from_file(p_source_file); +Error SpineJsonResourceImportPlugin::import(const String &p_source_file, const String &p_save_path, const Map &p_options, List *r_platform_variants, List *r_gen_files, Variant *r_metadata) { + Ref res(memnew(SpineSkeletonJsonDataResource)); + res->load_from_file(p_source_file); - String file_name = vformat("%s.%s", p_save_path, get_save_extension()); - auto err = ResourceSaver::save(file_name, res); - return err; + String file_name = vformat("%s.%s", p_save_path, get_save_extension()); + auto err = ResourceSaver::save(file_name, res); + return err; } //=======================| SpineRuntimeEditorPlugin |============================ SpineRuntimeEditorPlugin::SpineRuntimeEditorPlugin(EditorNode *p_node) { - add_import_plugin(memnew(SpineAtlasResourceImportPlugin)); - add_import_plugin(memnew(SpineJsonResourceImportPlugin)); + add_import_plugin(memnew(SpineAtlasResourceImportPlugin)); + add_import_plugin(memnew(SpineJsonResourceImportPlugin)); - auto animate_button = memnew(ToolButton); - animate_button->set_text("Animate"); - add_control_to_container(CONTAINER_CANVAS_EDITOR_MENU, animate_button); + auto animate_button = memnew(ToolButton); + animate_button->set_text("Animate"); + add_control_to_container(CONTAINER_CANVAS_EDITOR_MENU, animate_button); - animate_dialog = memnew(SpineSpriteAnimateDialog); - get_editor_interface()->get_base_control()->add_child(animate_dialog); - animate_dialog->set_animate_button(animate_button); - animate_dialog->set_plugin(this); + animate_dialog = memnew(SpineSpriteAnimateDialog); + get_editor_interface()->get_base_control()->add_child(animate_dialog); + animate_dialog->set_animate_button(animate_button); + animate_dialog->set_plugin(this); } SpineRuntimeEditorPlugin::~SpineRuntimeEditorPlugin() { - } bool SpineRuntimeEditorPlugin::handles(Object *p_object) const { - return p_object->is_class("SpineSprite"); + return p_object->is_class("SpineSprite"); } void SpineRuntimeEditorPlugin::make_visible(bool p_visible) { - if (get_editor_interface()->get_selection()->get_selected_node_list().size() != 1) { - p_visible = false; - } - animate_dialog->get_animate_button()->set_visible(p_visible); + if (get_editor_interface()->get_selection()->get_selected_node_list().size() != 1) { + p_visible = false; + } + animate_dialog->get_animate_button()->set_visible(p_visible); } diff --git a/spine-godot/spine_godot/SpineRuntimeEditorPlugin.h b/spine-godot/spine_godot/SpineRuntimeEditorPlugin.h index e5233a00c..cf95ec696 100644 --- a/spine-godot/spine_godot/SpineRuntimeEditorPlugin.h +++ b/spine-godot/spine_godot/SpineRuntimeEditorPlugin.h @@ -34,35 +34,43 @@ #include "editor/editor_node.h" class SpineAtlasResourceImportPlugin : public EditorImportPlugin { - GDCLASS(SpineAtlasResourceImportPlugin, EditorImportPlugin); + GDCLASS(SpineAtlasResourceImportPlugin, EditorImportPlugin); public: - String get_importer_name() const override {return "spine.atlas";} - String get_visible_name() const override {return "Spine Runtime Atlas";} - void get_recognized_extensions(List *p_extensions) const override {p_extensions->push_back("atlas");} - String get_preset_name(int p_idx) const override {if (p_idx == 0) return "Default"; else return "Unknown";} - int get_preset_count() const override {return 1;} - String get_save_extension() const override {return "spatlas";} - String get_resource_type() const override {return "SpineAtlasResource";} - void get_import_options(List *r_options, int p_preset) const override; - bool get_option_visibility(const String &p_option, const Map &p_options) const override {return true;} - Error import(const String &p_source_file, const String &p_save_path, const Map &p_options, List *r_platform_variants, List *r_gen_files, Variant *r_metadata) override; + String get_importer_name() const override { return "spine.atlas"; } + String get_visible_name() const override { return "Spine Runtime Atlas"; } + void get_recognized_extensions(List *p_extensions) const override { p_extensions->push_back("atlas"); } + String get_preset_name(int p_idx) const override { + if (p_idx == 0) return "Default"; + else + return "Unknown"; + } + int get_preset_count() const override { return 1; } + String get_save_extension() const override { return "spatlas"; } + String get_resource_type() const override { return "SpineAtlasResource"; } + void get_import_options(List *r_options, int p_preset) const override; + bool get_option_visibility(const String &p_option, const Map &p_options) const override { return true; } + Error import(const String &p_source_file, const String &p_save_path, const Map &p_options, List *r_platform_variants, List *r_gen_files, Variant *r_metadata) override; }; class SpineJsonResourceImportPlugin : public EditorImportPlugin { -GDCLASS(SpineJsonResourceImportPlugin, EditorImportPlugin); + GDCLASS(SpineJsonResourceImportPlugin, EditorImportPlugin); public: - String get_importer_name() const override {return "spine.json";} - String get_visible_name() const override {return "Spine Runtime Json";} - void get_recognized_extensions(List *p_extensions) const override {p_extensions->push_back("json");} - String get_preset_name(int p_idx) const override {if (p_idx == 0) return "Default"; else return "Unknown";} - int get_preset_count() const override {return 1;} - String get_save_extension() const override {return "spjson";} - String get_resource_type() const override {return "SpineSkeletonJsonDataResource";} - void get_import_options(List *r_options, int p_preset) const override {} - bool get_option_visibility(const String &p_option, const Map &p_options) const override {return true;} - Error import(const String &p_source_file, const String &p_save_path, const Map &p_options, List *r_platform_variants, List *r_gen_files, Variant *r_metadata) override; + String get_importer_name() const override { return "spine.json"; } + String get_visible_name() const override { return "Spine Runtime Json"; } + void get_recognized_extensions(List *p_extensions) const override { p_extensions->push_back("json"); } + String get_preset_name(int p_idx) const override { + if (p_idx == 0) return "Default"; + else + return "Unknown"; + } + int get_preset_count() const override { return 1; } + String get_save_extension() const override { return "spjson"; } + String get_resource_type() const override { return "SpineSkeletonJsonDataResource"; } + void get_import_options(List *r_options, int p_preset) const override {} + bool get_option_visibility(const String &p_option, const Map &p_options) const override { return true; } + Error import(const String &p_source_file, const String &p_save_path, const Map &p_options, List *r_platform_variants, List *r_gen_files, Variant *r_metadata) override; }; class SpineSpriteAnimateDialog; @@ -71,10 +79,11 @@ class SpineRuntimeEditorPlugin : public EditorPlugin { GDCLASS(SpineRuntimeEditorPlugin, EditorPlugin); protected: - SpineSpriteAnimateDialog *animate_dialog; + SpineSpriteAnimateDialog *animate_dialog; + public: - SpineRuntimeEditorPlugin(EditorNode *p_node); - ~SpineRuntimeEditorPlugin(); + SpineRuntimeEditorPlugin(EditorNode *p_node); + ~SpineRuntimeEditorPlugin(); String get_name() const override { return "SpineRuntimeEditorPlugin"; } bool has_main_screen() const { return false; } @@ -86,4 +95,4 @@ public: }; #endif -#endif //GODOT_SPINERUNTIMEEDITORPLUGIN_H +#endif//GODOT_SPINERUNTIMEEDITORPLUGIN_H diff --git a/spine-godot/spine_godot/SpineSkeleton.cpp b/spine-godot/spine_godot/SpineSkeleton.cpp index c8d207ea1..b8cedf0d5 100644 --- a/spine-godot/spine_godot/SpineSkeleton.cpp +++ b/spine-godot/spine_godot/SpineSkeleton.cpp @@ -30,49 +30,49 @@ #include "SpineSkeleton.h" void SpineSkeleton::_bind_methods() { -//void update_world_transform(); -// -// void set_to_setup_pose(); -// -// void set_bones_to_setup_pose(); -// -// void set_slots_to_setup_pose(); + //void update_world_transform(); + // + // void set_to_setup_pose(); + // + // void set_bones_to_setup_pose(); + // + // void set_slots_to_setup_pose(); ClassDB::bind_method(D_METHOD("update_world_transform"), &SpineSkeleton::update_world_transform); ClassDB::bind_method(D_METHOD("set_to_setup_pose"), &SpineSkeleton::set_to_setup_pose); ClassDB::bind_method(D_METHOD("set_bones_to_setup_pose"), &SpineSkeleton::set_bones_to_setup_pose); ClassDB::bind_method(D_METHOD("set_slots_to_setup_pose"), &SpineSkeleton::set_slots_to_setup_pose); -// -// Ref find_bone(const String &name); -// int find_bone_index(const String &name); -// -// Ref find_slot(const String &name); -// int find_slot_index(const String &name); -// -// void set_skin_by_name(const String &skin_name); -// void set_skin(Ref new_skin); -// -// Ref get_attachment_by_slot_name(const String &slot_name, const String &attachment_name); -// Ref get_attachment_by_slot_index(int slot_index, const String &attachment_name); - ClassDB::bind_method(D_METHOD("find_bone", "bone_name"), &SpineSkeleton::find_bone); - ClassDB::bind_method(D_METHOD("find_slot", "slot_name"), &SpineSkeleton::find_slot); + // + // Ref find_bone(const String &name); + // int find_bone_index(const String &name); + // + // Ref find_slot(const String &name); + // int find_slot_index(const String &name); + // + // void set_skin_by_name(const String &skin_name); + // void set_skin(Ref new_skin); + // + // Ref get_attachment_by_slot_name(const String &slot_name, const String &attachment_name); + // Ref get_attachment_by_slot_index(int slot_index, const String &attachment_name); + ClassDB::bind_method(D_METHOD("find_bone", "bone_name"), &SpineSkeleton::find_bone); + ClassDB::bind_method(D_METHOD("find_slot", "slot_name"), &SpineSkeleton::find_slot); ClassDB::bind_method(D_METHOD("set_skin_by_name", "skin_name"), &SpineSkeleton::set_skin_by_name); ClassDB::bind_method(D_METHOD("set_skin", "new_skin"), &SpineSkeleton::set_skin); ClassDB::bind_method(D_METHOD("get_attachment_by_slot_name", "slot_name", "attachment_name"), &SpineSkeleton::get_attachment_by_slot_name); ClassDB::bind_method(D_METHOD("get_attachment_by_slot_index", "slot_index", "attachment_name"), &SpineSkeleton::get_attachment_by_slot_index); -// -// void set_attachment(const String &slot_name, const String &attachment_name); -// -// Ref find_ik_constraint(const String &constraint_name); -// Ref find_transform_constraint(const String &constraint_name); -// Ref find_path_constraint(const String &constraint_name); -// -// void update(float delta); -// -// Dictionary get_bounds(); -// -// Ref get_root_bone(); -// -// Ref get_data(); + // + // void set_attachment(const String &slot_name, const String &attachment_name); + // + // Ref find_ik_constraint(const String &constraint_name); + // Ref find_transform_constraint(const String &constraint_name); + // Ref find_path_constraint(const String &constraint_name); + // + // void update(float delta); + // + // Dictionary get_bounds(); + // + // Ref get_root_bone(); + // + // Ref get_data(); ClassDB::bind_method(D_METHOD("set_attachment", "slot_name", "attachment_name"), &SpineSkeleton::set_attachment); ClassDB::bind_method(D_METHOD("find_ik_constraint", "constraint_name"), &SpineSkeleton::find_ik_constraint); ClassDB::bind_method(D_METHOD("find_transform_constraint", "constraint_name"), &SpineSkeleton::find_transform_constraint); @@ -81,15 +81,15 @@ void SpineSkeleton::_bind_methods() { ClassDB::bind_method(D_METHOD("get_bounds"), &SpineSkeleton::get_bounds); ClassDB::bind_method(D_METHOD("get_root_bone"), &SpineSkeleton::get_root_bone); ClassDB::bind_method(D_METHOD("get_data"), &SpineSkeleton::get_data); -// -// Array get_bones(); -// Array get_slots(); -// Array get_draw_orders(); -// Array get_ik_constraints(); -// Array get_path_constraints(); -// Array get_transform_constraints(); -// -// Ref get_skin(); + // + // Array get_bones(); + // Array get_slots(); + // Array get_draw_orders(); + // Array get_ik_constraints(); + // Array get_path_constraints(); + // Array get_transform_constraints(); + // + // Ref get_skin(); ClassDB::bind_method(D_METHOD("get_bones"), &SpineSkeleton::get_bones); ClassDB::bind_method(D_METHOD("get_slots"), &SpineSkeleton::get_slots); ClassDB::bind_method(D_METHOD("get_draw_orders"), &SpineSkeleton::get_draw_orders); @@ -97,31 +97,31 @@ void SpineSkeleton::_bind_methods() { ClassDB::bind_method(D_METHOD("get_path_constraints"), &SpineSkeleton::get_path_constraints); ClassDB::bind_method(D_METHOD("get_transform_constraints"), &SpineSkeleton::get_transform_constraints); ClassDB::bind_method(D_METHOD("get_skin"), &SpineSkeleton::get_skin); -// -// Color get_color(); -// void set_color(Color v); -// -// float get_time(); -// void set_time(float v); -// -// void set_position(Vector2 pos); + // + // Color get_color(); + // void set_color(Color v); + // + // float get_time(); + // void set_time(float v); + // + // void set_position(Vector2 pos); ClassDB::bind_method(D_METHOD("get_color"), &SpineSkeleton::get_color); ClassDB::bind_method(D_METHOD("set_color", "v"), &SpineSkeleton::set_color); ClassDB::bind_method(D_METHOD("get_time"), &SpineSkeleton::get_time); ClassDB::bind_method(D_METHOD("set_time", "v"), &SpineSkeleton::set_time); ClassDB::bind_method(D_METHOD("set_position", "pos"), &SpineSkeleton::set_position); -// -// float get_x(); -// void set_x(float v); -// -// float get_y(); -// void set_y(float v); -// -// float get_scale_x(); -// void set_scale_x(float v); -// -// float get_scale_y(); -// void set_scale_y(float v); + // + // float get_x(); + // void set_x(float v); + // + // float get_y(); + // void set_y(float v); + // + // float get_scale_x(); + // void set_scale_x(float v); + // + // float get_scale_y(); + // void set_scale_y(float v); ClassDB::bind_method(D_METHOD("get_x"), &SpineSkeleton::get_x); ClassDB::bind_method(D_METHOD("set_x", "v"), &SpineSkeleton::set_x); ClassDB::bind_method(D_METHOD("get_y"), &SpineSkeleton::get_y); @@ -132,21 +132,18 @@ void SpineSkeleton::_bind_methods() { ClassDB::bind_method(D_METHOD("set_scale_y", "v"), &SpineSkeleton::set_scale_y); } -SpineSkeleton::SpineSkeleton():skeleton(NULL),spine_object(false),the_sprite(nullptr) { - +SpineSkeleton::SpineSkeleton() : skeleton(NULL), spine_object(false), the_sprite(nullptr) { } SpineSkeleton::~SpineSkeleton() { - if(skeleton && !spine_object) - { + if (skeleton && !spine_object) { delete skeleton; skeleton = NULL; } } void SpineSkeleton::load_skeleton(Ref sd) { - if(skeleton && !spine_object) - { + if (skeleton && !spine_object) { delete skeleton; skeleton = NULL; } @@ -155,103 +152,103 @@ void SpineSkeleton::load_skeleton(Ref sd) { } #define S_T(x) (spine::String(x.utf8())) -void SpineSkeleton::update_world_transform(){ +void SpineSkeleton::update_world_transform() { skeleton->updateWorldTransform(); } -void SpineSkeleton::set_to_setup_pose(){ +void SpineSkeleton::set_to_setup_pose() { skeleton->setToSetupPose(); } -void SpineSkeleton::set_bones_to_setup_pose(){ +void SpineSkeleton::set_bones_to_setup_pose() { skeleton->setBonesToSetupPose(); } -void SpineSkeleton::set_slots_to_setup_pose(){ +void SpineSkeleton::set_slots_to_setup_pose() { skeleton->setSlotsToSetupPose(); } -Ref SpineSkeleton::find_bone(const String &name){ - if(name.empty()) return NULL; +Ref SpineSkeleton::find_bone(const String &name) { + if (name.empty()) return NULL; auto b = skeleton->findBone(S_T(name)); - if(b == NULL) return NULL; + if (b == NULL) return NULL; Ref gd_b(memnew(SpineBone)); gd_b->set_spine_object(b); gd_b->set_spine_sprite(the_sprite); return gd_b; } -Ref SpineSkeleton::find_slot(const String &name){ - if(name.empty()) return NULL; +Ref SpineSkeleton::find_slot(const String &name) { + if (name.empty()) return NULL; auto s = skeleton->findSlot(S_T(name)); - if(s == NULL) return NULL; + if (s == NULL) return NULL; Ref gd_s(memnew(SpineSlot)); gd_s->set_spine_object(s); return gd_s; } -void SpineSkeleton::set_skin_by_name(const String &skin_name){ +void SpineSkeleton::set_skin_by_name(const String &skin_name) { skeleton->setSkin(S_T(skin_name)); } -void SpineSkeleton::set_skin(Ref new_skin){ - if(new_skin.is_valid()){ +void SpineSkeleton::set_skin(Ref new_skin) { + if (new_skin.is_valid()) { skeleton->setSkin(new_skin->get_spine_object()); - }else{ + } else { skeleton->setSkin(NULL); } } -Ref SpineSkeleton::get_attachment_by_slot_name(const String &slot_name, const String &attachment_name){ +Ref SpineSkeleton::get_attachment_by_slot_name(const String &slot_name, const String &attachment_name) { auto a = skeleton->getAttachment(S_T(slot_name), S_T(attachment_name)); - if(a == NULL) return NULL; + if (a == NULL) return NULL; Ref gd_a(memnew(SpineAttachment)); gd_a->set_spine_object(a); return gd_a; } -Ref SpineSkeleton::get_attachment_by_slot_index(int slot_index, const String &attachment_name){ +Ref SpineSkeleton::get_attachment_by_slot_index(int slot_index, const String &attachment_name) { auto a = skeleton->getAttachment(slot_index, S_T(attachment_name)); - if(a == NULL) return NULL; + if (a == NULL) return NULL; Ref gd_a(memnew(SpineAttachment)); gd_a->set_spine_object(a); return gd_a; } -void SpineSkeleton::set_attachment(const String &slot_name, const String &attachment_name){ +void SpineSkeleton::set_attachment(const String &slot_name, const String &attachment_name) { ERR_FAIL_COND(slot_name.empty()); ERR_FAIL_COND(get_attachment_by_slot_name(slot_name, attachment_name) == NULL); skeleton->setAttachment(S_T(slot_name), S_T(attachment_name)); } -Ref SpineSkeleton::find_ik_constraint(const String &constraint_name){ - if(constraint_name.empty()) return NULL; +Ref SpineSkeleton::find_ik_constraint(const String &constraint_name) { + if (constraint_name.empty()) return NULL; auto c = skeleton->findIkConstraint(S_T(constraint_name)); - if(c == NULL) return NULL; + if (c == NULL) return NULL; Ref gd_c(memnew(SpineIkConstraint)); gd_c->set_spine_object(c); return gd_c; } -Ref SpineSkeleton::find_transform_constraint(const String &constraint_name){ - if(constraint_name.empty()) return NULL; +Ref SpineSkeleton::find_transform_constraint(const String &constraint_name) { + if (constraint_name.empty()) return NULL; auto c = skeleton->findTransformConstraint(S_T(constraint_name)); - if(c == NULL) return NULL; + if (c == NULL) return NULL; Ref gd_c(memnew(SpineTransformConstraint)); gd_c->set_spine_object(c); return gd_c; } -Ref SpineSkeleton::find_path_constraint(const String &constraint_name){ - if(constraint_name.empty()) return NULL; +Ref SpineSkeleton::find_path_constraint(const String &constraint_name) { + if (constraint_name.empty()) return NULL; auto c = skeleton->findPathConstraint(S_T(constraint_name)); - if(c == NULL) return NULL; + if (c == NULL) return NULL; Ref gd_c(memnew(SpinePathConstraint)); gd_c->set_spine_object(c); return gd_c; } -void SpineSkeleton::update(float delta){ +void SpineSkeleton::update(float delta) { skeleton->update(delta); } -Dictionary SpineSkeleton::get_bounds(){ +Dictionary SpineSkeleton::get_bounds() { float x, y, w, h; spine::Vector vertex_buffer; skeleton->getBounds(x, y, w, h, vertex_buffer); @@ -264,7 +261,7 @@ Dictionary SpineSkeleton::get_bounds(){ Array gd_a; gd_a.resize(vertex_buffer.size()); - for(size_t i=0; i SpineSkeleton::get_root_bone(){ +Ref SpineSkeleton::get_root_bone() { auto b = skeleton->getRootBone(); - if(b == NULL) return NULL; + if (b == NULL) return NULL; Ref gd_b(memnew(SpineBone)); gd_b->set_spine_object(b); gd_b->set_spine_sprite(the_sprite); @@ -283,19 +280,19 @@ Ref SpineSkeleton::get_root_bone(){ Ref SpineSkeleton::get_data() const { auto sd = skeleton->getData(); - if(sd == NULL) return NULL; + if (sd == NULL) return NULL; Ref gd_sd(memnew(SpineSkeletonDataResource)); gd_sd->set_spine_object(sd); return gd_sd; } -Array SpineSkeleton::get_bones(){ +Array SpineSkeleton::get_bones() { auto &as = skeleton->getBones(); Array gd_as; gd_as.resize(as.size()); - for(size_t i=0; i(NULL); + if (b == NULL) gd_as[i] = Ref(NULL); Ref gd_a(memnew(SpineBone)); gd_a->set_spine_object(b); gd_a->set_spine_sprite(the_sprite); @@ -303,65 +300,65 @@ Array SpineSkeleton::get_bones(){ } return gd_as; } -Array SpineSkeleton::get_slots(){ +Array SpineSkeleton::get_slots() { auto &as = skeleton->getSlots(); Array gd_as; gd_as.resize(as.size()); - for(size_t i=0; i(NULL); + if (b == NULL) gd_as[i] = Ref(NULL); Ref gd_a(memnew(SpineSlot)); gd_a->set_spine_object(b); gd_as[i] = gd_a; } return gd_as; } -Array SpineSkeleton::get_draw_orders(){ +Array SpineSkeleton::get_draw_orders() { auto &as = skeleton->getDrawOrder(); Array gd_as; gd_as.resize(as.size()); - for(size_t i=0; i(NULL); + if (b == NULL) gd_as[i] = Ref(NULL); Ref gd_a(memnew(SpineSlot)); gd_a->set_spine_object(b); gd_as[i] = gd_a; } return gd_as; } -Array SpineSkeleton::get_ik_constraints(){ +Array SpineSkeleton::get_ik_constraints() { auto &as = skeleton->getIkConstraints(); Array gd_as; gd_as.resize(as.size()); - for(size_t i=0; i(NULL); + if (b == NULL) gd_as[i] = Ref(NULL); Ref gd_a(memnew(SpineIkConstraint)); gd_a->set_spine_object(b); gd_as[i] = gd_a; } return gd_as; } -Array SpineSkeleton::get_path_constraints(){ +Array SpineSkeleton::get_path_constraints() { auto &as = skeleton->getPathConstraints(); Array gd_as; gd_as.resize(as.size()); - for(size_t i=0; i(NULL); + if (b == NULL) gd_as[i] = Ref(NULL); Ref gd_a(memnew(SpinePathConstraint)); gd_a->set_spine_object(b); gd_as[i] = gd_a; } return gd_as; } -Array SpineSkeleton::get_transform_constraints(){ +Array SpineSkeleton::get_transform_constraints() { auto &as = skeleton->getTransformConstraints(); Array gd_as; gd_as.resize(as.size()); - for(size_t i=0; i(NULL); + if (b == NULL) gd_as[i] = Ref(NULL); Ref gd_a(memnew(SpineTransformConstraint)); gd_a->set_spine_object(b); gd_as[i] = gd_a; @@ -369,62 +366,62 @@ Array SpineSkeleton::get_transform_constraints(){ return gd_as; } -Ref SpineSkeleton::get_skin(){ +Ref SpineSkeleton::get_skin() { auto s = skeleton->getSkin(); - if(s == NULL) return NULL; + if (s == NULL) return NULL; Ref gd_s(memnew(SpineSkin)); gd_s->set_spine_object(s); return gd_s; } -Color SpineSkeleton::get_color(){ +Color SpineSkeleton::get_color() { auto &c = skeleton->getColor(); return Color(c.r, c.g, c.b, c.a); } -void SpineSkeleton::set_color(Color v){ +void SpineSkeleton::set_color(Color v) { auto &c = skeleton->getColor(); c.set(v.r, v.g, v.b, v.a); } -float SpineSkeleton::get_time(){ +float SpineSkeleton::get_time() { return skeleton->getTime(); } -void SpineSkeleton::set_time(float v){ +void SpineSkeleton::set_time(float v) { skeleton->setTime(v); } -void SpineSkeleton::set_position(Vector2 pos){ +void SpineSkeleton::set_position(Vector2 pos) { skeleton->setPosition(pos.x, pos.y); } -float SpineSkeleton::get_x(){ +float SpineSkeleton::get_x() { return skeleton->getX(); } -void SpineSkeleton::set_x(float v){ +void SpineSkeleton::set_x(float v) { skeleton->setX(v); } -float SpineSkeleton::get_y(){ +float SpineSkeleton::get_y() { return skeleton->getY(); } -void SpineSkeleton::set_y(float v){ +void SpineSkeleton::set_y(float v) { skeleton->setY(v); } -float SpineSkeleton::get_scale_x(){ +float SpineSkeleton::get_scale_x() { return skeleton->getScaleX(); } -void SpineSkeleton::set_scale_x(float v){ +void SpineSkeleton::set_scale_x(float v) { skeleton->setScaleX(v); } -float SpineSkeleton::get_scale_y(){ +float SpineSkeleton::get_scale_y() { return skeleton->getScaleY(); } -void SpineSkeleton::set_scale_y(float v){ +void SpineSkeleton::set_scale_y(float v) { skeleton->setScaleY(v); } void SpineSkeleton::set_spine_sprite(SpineSprite *s) { - the_sprite = s; + the_sprite = s; } diff --git a/spine-godot/spine_godot/SpineSkeleton.h b/spine-godot/spine_godot/SpineSkeleton.h index fa488bfa4..14e5bc3bb 100644 --- a/spine-godot/spine_godot/SpineSkeleton.h +++ b/spine-godot/spine_godot/SpineSkeleton.h @@ -40,7 +40,7 @@ class SpineSprite; -class SpineSkeleton : public Reference{ +class SpineSkeleton : public Reference { GDCLASS(SpineSkeleton, Reference); protected: @@ -51,18 +51,18 @@ private: bool spine_object; SpineSprite *the_sprite; -public: +public: SpineSkeleton(); ~SpineSkeleton(); void load_skeleton(Ref sd); - inline void set_spine_object(spine::Skeleton *s){ + inline void set_spine_object(spine::Skeleton *s) { skeleton = s; spine_object = true; } - inline spine::Skeleton *get_spine_object(){ + inline spine::Skeleton *get_spine_object() { return skeleton; } @@ -79,7 +79,7 @@ public: Ref find_bone(const String &name); - Ref find_slot(const String &name); + Ref find_slot(const String &name); void set_skin_by_name(const String &skin_name); void set_skin(Ref new_skin); @@ -129,7 +129,6 @@ public: float get_scale_y(); void set_scale_y(float v); - }; -#endif //GODOT_SPINESKELETON_H +#endif//GODOT_SPINESKELETON_H diff --git a/spine-godot/spine_godot/SpineSkeletonDataResource.cpp b/spine-godot/spine_godot/SpineSkeletonDataResource.cpp index d6f5c87a6..f360433f3 100644 --- a/spine-godot/spine_godot/SpineSkeletonDataResource.cpp +++ b/spine-godot/spine_godot/SpineSkeletonDataResource.cpp @@ -34,7 +34,7 @@ void SpineSkeletonDataResource::_bind_methods() { ClassDB::bind_method(D_METHOD("get_atlas_res"), &SpineSkeletonDataResource::get_atlas_res); ClassDB::bind_method(D_METHOD("set_skeleton_json_res", "skeleton_json_res"), &SpineSkeletonDataResource::set_skeleton_json_res); ClassDB::bind_method(D_METHOD("get_skeleton_json_res"), &SpineSkeletonDataResource::get_skeleton_json_res); - ClassDB::bind_method(D_METHOD("is_skeleton_data_loaded"), &SpineSkeletonDataResource::is_skeleton_data_loaded); + ClassDB::bind_method(D_METHOD("is_skeleton_data_loaded"), &SpineSkeletonDataResource::is_skeleton_data_loaded); ClassDB::bind_method(D_METHOD("find_animation", "animation_name"), &SpineSkeletonDataResource::find_animation); ClassDB::bind_method(D_METHOD("get_sk_name"), &SpineSkeletonDataResource::get_sk_name); ClassDB::bind_method(D_METHOD("set_sk_name", "sk_name"), &SpineSkeletonDataResource::set_sk_name); @@ -74,18 +74,16 @@ void SpineSkeletonDataResource::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "skeleton_json_res", PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "SpineSkeletonJsonDataResource"), "set_skeleton_json_res", "get_skeleton_json_res"); } -SpineSkeletonDataResource::SpineSkeletonDataResource():valid(false),spine_object(false),skeleton_data(NULL) { - +SpineSkeletonDataResource::SpineSkeletonDataResource() : valid(false), spine_object(false), skeleton_data(NULL) { } SpineSkeletonDataResource::~SpineSkeletonDataResource() { - if(skeleton_data && !spine_object) - { + if (skeleton_data && !spine_object) { delete skeleton_data; skeleton_data = NULL; } } -bool SpineSkeletonDataResource::is_skeleton_data_loaded() const{ +bool SpineSkeletonDataResource::is_skeleton_data_loaded() const { return valid || spine_object; } @@ -94,29 +92,25 @@ void SpineSkeletonDataResource::load_res(spine::Atlas *a, const String &json_str auto path = get_path(); spine::SkeletonJson json(a); auto temp_skeleton_data = json.readSkeletonData(json_string.utf8()); - if(!temp_skeleton_data) - { + if (!temp_skeleton_data) { print_error(String("Error happened while loading skeleton json data: ") + path); print_error(String("Error msg: ") + json.getError().buffer()); return; } - if(skeleton_data) - { + if (skeleton_data) { delete skeleton_data; skeleton_data = NULL; } skeleton_data = temp_skeleton_data; valid = true; -// print_line("Skeleton json data loaded!"); + // print_line("Skeleton json data loaded!"); } void SpineSkeletonDataResource::update_skeleton_data() { - if(atlas_res.is_valid() && skeleton_json_res.is_valid()) - { + if (atlas_res.is_valid() && skeleton_json_res.is_valid()) { load_res(atlas_res->get_spine_atlas(), skeleton_json_res->get_json_string()); - if(valid) - { + if (valid) { emit_signal("skeleton_data_loaded"); } } @@ -125,12 +119,12 @@ void SpineSkeletonDataResource::update_skeleton_data() { void SpineSkeletonDataResource::set_atlas_res(const Ref &a) { atlas_res = a; valid = false; -// print_line("atlas_res_changed emitted"); + // print_line("atlas_res_changed emitted"); emit_signal("atlas_res_changed"); update_skeleton_data(); } Ref SpineSkeletonDataResource::get_atlas_res() { - if(spine_object){ + if (spine_object) { print_line("Getting atlas res from a spine_object skeleton! The result may be NULL!"); } return atlas_res; @@ -139,27 +133,35 @@ Ref SpineSkeletonDataResource::get_atlas_res() { void SpineSkeletonDataResource::set_skeleton_json_res(const Ref &s) { skeleton_json_res = s; valid = false; -// print_line("skeleton_json_res_changed emitted"); + // print_line("skeleton_json_res_changed emitted"); emit_signal("skeleton_json_res_changed"); update_skeleton_data(); } Ref SpineSkeletonDataResource::get_skeleton_json_res() { - if(spine_object){ + if (spine_object) { print_line("Getting atlas res from a spine_object skeleton! The result may be NULL!"); } return skeleton_json_res; } -#define CHECK_V if(!is_skeleton_data_loaded()){ERR_PRINT("skeleton data has not loaded yet!");return;} -#define CHECK_X(x) if(!is_skeleton_data_loaded()){ERR_PRINT("skeleton data has not loaded yet!");return x;} +#define CHECK_V \ + if (!is_skeleton_data_loaded()) { \ + ERR_PRINT("skeleton data has not loaded yet!"); \ + return; \ + } +#define CHECK_X(x) \ + if (!is_skeleton_data_loaded()) { \ + ERR_PRINT("skeleton data has not loaded yet!"); \ + return x; \ + } #define S_T(x) (spine::String(x.utf8())) Ref SpineSkeletonDataResource::find_animation(const String &animation_name) { CHECK_X(NULL); - if(animation_name.empty()){ + if (animation_name.empty()) { return NULL; } auto a = skeleton_data->findAnimation(S_T(animation_name)); - if(!a) return NULL; + if (!a) return NULL; Ref sa(memnew(SpineAnimation)); sa->set_spine_object(a); return sa; @@ -209,73 +211,73 @@ void SpineSkeletonDataResource::set_fps(float v) { skeleton_data->setFps(v); } -Ref SpineSkeletonDataResource::find_bone(const String &bone_name){ - if(bone_name.empty()) return NULL; +Ref SpineSkeletonDataResource::find_bone(const String &bone_name) { + if (bone_name.empty()) return NULL; auto b = skeleton_data->findBone(S_T(bone_name)); - if(b == NULL) return NULL; + if (b == NULL) return NULL; Ref gd_b(memnew(SpineBoneData)); gd_b->set_spine_object(b); return gd_b; } -Ref SpineSkeletonDataResource::find_slot(const String &slot_name){ - if(slot_name.empty()) return NULL; +Ref SpineSkeletonDataResource::find_slot(const String &slot_name) { + if (slot_name.empty()) return NULL; auto b = skeleton_data->findSlot(S_T(slot_name)); - if(b == NULL) return NULL; + if (b == NULL) return NULL; Ref gd_b(memnew(SpineSlotData)); gd_b->set_spine_object(b); return gd_b; } -Ref SpineSkeletonDataResource::find_skin(const String &skin_name){ - if(skin_name.empty()) return NULL; +Ref SpineSkeletonDataResource::find_skin(const String &skin_name) { + if (skin_name.empty()) return NULL; auto b = skeleton_data->findSkin(S_T(skin_name)); - if(b == NULL) return NULL; + if (b == NULL) return NULL; Ref gd_b(memnew(SpineSkin)); gd_b->set_spine_object(b); return gd_b; } -Ref SpineSkeletonDataResource::find_event(const String &event_data_name){ - if(event_data_name.empty()) return NULL; +Ref SpineSkeletonDataResource::find_event(const String &event_data_name) { + if (event_data_name.empty()) return NULL; auto b = skeleton_data->findEvent(S_T(event_data_name)); - if(b == NULL) return NULL; + if (b == NULL) return NULL; Ref gd_b(memnew(SpineEventData)); gd_b->set_spine_object(b); return gd_b; } -Ref SpineSkeletonDataResource::find_ik_constraint(const String &constraint_name){ - if(constraint_name.empty()) return NULL; +Ref SpineSkeletonDataResource::find_ik_constraint(const String &constraint_name) { + if (constraint_name.empty()) return NULL; auto b = skeleton_data->findIkConstraint(S_T(constraint_name)); - if(b == NULL) return NULL; + if (b == NULL) return NULL; Ref gd_b(memnew(SpineIkConstraintData)); gd_b->set_spine_object(b); return gd_b; } -Ref SpineSkeletonDataResource::find_transform_constraint(const String &constraint_name){ - if(constraint_name.empty()) return NULL; +Ref SpineSkeletonDataResource::find_transform_constraint(const String &constraint_name) { + if (constraint_name.empty()) return NULL; auto b = skeleton_data->findTransformConstraint(S_T(constraint_name)); - if(b == NULL) return NULL; + if (b == NULL) return NULL; Ref gd_b(memnew(SpineTransformConstraintData)); gd_b->set_spine_object(b); return gd_b; } -Ref SpineSkeletonDataResource::find_path_constraint(const String &constraint_name){ - if(constraint_name.empty()) return NULL; +Ref SpineSkeletonDataResource::find_path_constraint(const String &constraint_name) { + if (constraint_name.empty()) return NULL; auto b = skeleton_data->findPathConstraint(S_T(constraint_name)); - if(b == NULL) return NULL; + if (b == NULL) return NULL; Ref gd_b(memnew(SpinePathConstraintData)); gd_b->set_spine_object(b); return gd_b; } -Array SpineSkeletonDataResource::get_bones(){ +Array SpineSkeletonDataResource::get_bones() { auto bs = skeleton_data->getBones(); Array gd_bs; gd_bs.resize(bs.size()); - for(size_t i=0; i < bs.size(); ++i){ - if(bs[i] == NULL) gd_bs[i] = Ref(NULL); + for (size_t i = 0; i < bs.size(); ++i) { + if (bs[i] == NULL) gd_bs[i] = Ref(NULL); else { Ref gd_b(memnew(SpineBoneData)); gd_b->set_spine_object(bs[i]); @@ -284,12 +286,12 @@ Array SpineSkeletonDataResource::get_bones(){ } return gd_bs; } -Array SpineSkeletonDataResource::get_slots(){ +Array SpineSkeletonDataResource::get_slots() { auto bs = skeleton_data->getSlots(); Array gd_bs; gd_bs.resize(bs.size()); - for(size_t i=0; i < bs.size(); ++i){ - if(bs[i] == NULL) gd_bs[i] = Ref(NULL); + for (size_t i = 0; i < bs.size(); ++i) { + if (bs[i] == NULL) gd_bs[i] = Ref(NULL); else { Ref gd_b(memnew(SpineSlotData)); gd_b->set_spine_object(bs[i]); @@ -298,12 +300,12 @@ Array SpineSkeletonDataResource::get_slots(){ } return gd_bs; } -Array SpineSkeletonDataResource::get_skins() const{ +Array SpineSkeletonDataResource::get_skins() const { auto bs = skeleton_data->getSkins(); Array gd_bs; gd_bs.resize(bs.size()); - for(size_t i=0; i < bs.size(); ++i){ - if(bs[i] == NULL) gd_bs[i] = Ref(NULL); + for (size_t i = 0; i < bs.size(); ++i) { + if (bs[i] == NULL) gd_bs[i] = Ref(NULL); else { Ref gd_b(memnew(SpineSkin)); gd_b->set_spine_object(bs[i]); @@ -313,26 +315,26 @@ Array SpineSkeletonDataResource::get_skins() const{ return gd_bs; } -Ref SpineSkeletonDataResource::get_default_skin(){ +Ref SpineSkeletonDataResource::get_default_skin() { auto b = skeleton_data->getDefaultSkin(); - if(b == NULL) return NULL; + if (b == NULL) return NULL; Ref gd_b(memnew(SpineSkin)); gd_b->set_spine_object(b); return gd_b; } -void SpineSkeletonDataResource::set_default_skin(Ref v){ - if(v.is_valid()){ +void SpineSkeletonDataResource::set_default_skin(Ref v) { + if (v.is_valid()) { skeleton_data->setDefaultSkin(v->get_spine_object()); } else skeleton_data->setDefaultSkin(NULL); } -Array SpineSkeletonDataResource::get_events(){ +Array SpineSkeletonDataResource::get_events() { auto bs = skeleton_data->getEvents(); Array gd_bs; gd_bs.resize(bs.size()); - for(size_t i=0; i < bs.size(); ++i){ - if(bs[i] == NULL) gd_bs[i] = Ref(NULL); + for (size_t i = 0; i < bs.size(); ++i) { + if (bs[i] == NULL) gd_bs[i] = Ref(NULL); else { Ref gd_b(memnew(SpineEventData)); gd_b->set_spine_object(bs[i]); @@ -341,12 +343,12 @@ Array SpineSkeletonDataResource::get_events(){ } return gd_bs; } -Array SpineSkeletonDataResource::get_animations(){ +Array SpineSkeletonDataResource::get_animations() { auto bs = skeleton_data->getAnimations(); Array gd_bs; gd_bs.resize(bs.size()); - for(size_t i=0; i < bs.size(); ++i){ - if(bs[i] == NULL) gd_bs[i] = Ref(NULL); + for (size_t i = 0; i < bs.size(); ++i) { + if (bs[i] == NULL) gd_bs[i] = Ref(NULL); else { Ref gd_b(memnew(SpineAnimation)); gd_b->set_spine_object(bs[i]); @@ -355,12 +357,12 @@ Array SpineSkeletonDataResource::get_animations(){ } return gd_bs; } -Array SpineSkeletonDataResource::get_ik_constraints(){ +Array SpineSkeletonDataResource::get_ik_constraints() { auto bs = skeleton_data->getIkConstraints(); Array gd_bs; gd_bs.resize(bs.size()); - for(size_t i=0; i < bs.size(); ++i){ - if(bs[i] == NULL) gd_bs[i] = Ref(NULL); + for (size_t i = 0; i < bs.size(); ++i) { + if (bs[i] == NULL) gd_bs[i] = Ref(NULL); else { Ref gd_b(memnew(SpineIkConstraintData)); gd_b->set_spine_object(bs[i]); @@ -369,12 +371,12 @@ Array SpineSkeletonDataResource::get_ik_constraints(){ } return gd_bs; } -Array SpineSkeletonDataResource::get_transform_constraints(){ +Array SpineSkeletonDataResource::get_transform_constraints() { auto bs = skeleton_data->getTransformConstraints(); Array gd_bs; gd_bs.resize(bs.size()); - for(size_t i=0; i < bs.size(); ++i){ - if(bs[i] == NULL) gd_bs[i] = Ref(NULL); + for (size_t i = 0; i < bs.size(); ++i) { + if (bs[i] == NULL) gd_bs[i] = Ref(NULL); else { Ref gd_b(memnew(SpineTransformConstraintData)); gd_b->set_spine_object(bs[i]); @@ -383,12 +385,12 @@ Array SpineSkeletonDataResource::get_transform_constraints(){ } return gd_bs; } -Array SpineSkeletonDataResource::get_path_constraints(){ +Array SpineSkeletonDataResource::get_path_constraints() { auto bs = skeleton_data->getPathConstraints(); Array gd_bs; gd_bs.resize(bs.size()); - for(size_t i=0; i < bs.size(); ++i){ - if(bs[i] == NULL) gd_bs[i] = Ref(NULL); + for (size_t i = 0; i < bs.size(); ++i) { + if (bs[i] == NULL) gd_bs[i] = Ref(NULL); else { Ref gd_b(memnew(SpinePathConstraintData)); gd_b->set_spine_object(bs[i]); @@ -402,53 +404,53 @@ Array SpineSkeletonDataResource::get_path_constraints(){ #undef CHECK_X //External feature functions -void SpineSkeletonDataResource::get_animation_names(Vector &res) const{ - res.clear(); - if(!is_skeleton_data_loaded()){ +void SpineSkeletonDataResource::get_animation_names(Vector &res) const { + res.clear(); + if (!is_skeleton_data_loaded()) { return; } auto as = skeleton_data->getAnimations(); - for(size_t i=0; igetName().buffer()); - }else{ - res.push_back(""); + if (a) { + res.push_back(a->getName().buffer()); + } else { + res.push_back(""); } } } -void SpineSkeletonDataResource::get_skin_names(Vector &res) const{ - res.clear(); - if(!is_skeleton_data_loaded()){ +void SpineSkeletonDataResource::get_skin_names(Vector &res) const { + res.clear(); + if (!is_skeleton_data_loaded()) { return; } auto as = get_skins(); res.resize(as.size()); - for(size_t i=0; i(as[i]); - if(a.is_valid()){ + if (a.is_valid()) { res.push_back(a->get_skin_name()); - }else{ - res.push_back(""); + } else { + res.push_back(""); } } } -void SpineSkeletonDataResource::_get_property_list(List *p_list) const{ - PropertyInfo p; - Vector res; +void SpineSkeletonDataResource::_get_property_list(List *p_list) const { + PropertyInfo p; + Vector res; - p.name = "animations"; - p.type = Variant::STRING; - get_animation_names(res); - p.hint_string = String(",").join(res); - p.hint = PROPERTY_HINT_ENUM; - p_list->push_back(p); + p.name = "animations"; + p.type = Variant::STRING; + get_animation_names(res); + p.hint_string = String(",").join(res); + p.hint = PROPERTY_HINT_ENUM; + p_list->push_back(p); - p.name = "skins"; - p.type = Variant::STRING; - get_skin_names(res); - p.hint_string = String(",").join(res); - p.hint = PROPERTY_HINT_ENUM; - p_list->push_back(p); + p.name = "skins"; + p.type = Variant::STRING; + get_skin_names(res); + p.hint_string = String(",").join(res); + p.hint = PROPERTY_HINT_ENUM; + p_list->push_back(p); } diff --git a/spine-godot/spine_godot/SpineSkeletonDataResource.h b/spine-godot/spine_godot/SpineSkeletonDataResource.h index 14fc17c19..eaabaa11c 100644 --- a/spine-godot/spine_godot/SpineSkeletonDataResource.h +++ b/spine-godot/spine_godot/SpineSkeletonDataResource.h @@ -45,7 +45,7 @@ #include "SpinePathConstraintData.h" #include "SpineEventData.h" -class SpineSkeletonDataResource : public Resource{ +class SpineSkeletonDataResource : public Resource { GDCLASS(SpineSkeletonDataResource, Resource); protected: @@ -60,14 +60,14 @@ private: spine::SkeletonData *skeleton_data; void update_skeleton_data(); -public: - inline void set_spine_object(spine::SkeletonData *s){ +public: + inline void set_spine_object(spine::SkeletonData *s) { skeleton_data = s; - if(s) + if (s) spine_object = true; } - inline spine::SkeletonData *get_spine_object(){ + inline spine::SkeletonData *get_spine_object() { return skeleton_data; } @@ -76,7 +76,7 @@ public: SpineSkeletonDataResource(); virtual ~SpineSkeletonDataResource(); - void _get_property_list(List *p_list) const; + void _get_property_list(List *p_list) const; void set_atlas_res(const Ref &a); Ref get_atlas_res(); @@ -84,17 +84,17 @@ public: void set_skeleton_json_res(const Ref &s); Ref get_skeleton_json_res(); - inline spine::SkeletonData *get_skeleton_data(){return skeleton_data;} + inline spine::SkeletonData *get_skeleton_data() { return skeleton_data; } bool is_skeleton_data_loaded() const; void get_animation_names(Vector &l) const; - void get_skin_names(Vector &l) const; + void get_skin_names(Vector &l) const; // spine api - Ref find_bone(const String &bone_name); + Ref find_bone(const String &bone_name); - Ref find_slot(const String &slot_name); + Ref find_slot(const String &slot_name); Ref find_skin(const String &skin_name); @@ -104,7 +104,7 @@ public: Ref find_ik_constraint(const String &constraint_name); Ref find_transform_constraint(const String &constraint_name); - Ref find_path_constraint(const String &constraint_name); + Ref find_path_constraint(const String &constraint_name); Array get_bones(); Array get_slots(); @@ -137,4 +137,4 @@ public: void set_fps(float v); }; -#endif //GODOT_SPINESKELETONDATARESOURCE_H +#endif//GODOT_SPINESKELETONDATARESOURCE_H diff --git a/spine-godot/spine_godot/SpineSkeletonJsonDataResource.cpp b/spine-godot/spine_godot/SpineSkeletonJsonDataResource.cpp index ef4c18afb..d332a791a 100644 --- a/spine-godot/spine_godot/SpineSkeletonJsonDataResource.cpp +++ b/spine-godot/spine_godot/SpineSkeletonJsonDataResource.cpp @@ -34,22 +34,22 @@ void SpineSkeletonJsonDataResource::_bind_methods() { } Error SpineSkeletonJsonDataResource::load_from_file(const String &p_path) { - Error err; + Error err; - json_string = FileAccess::get_file_as_string(p_path, &err); - return err; + json_string = FileAccess::get_file_as_string(p_path, &err); + return err; } Error SpineSkeletonJsonDataResource::save_to_file(const String &p_path) { - Error err; - FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &err); - if (err != OK) { - if (file) file->close(); - return err; - } + Error err; + FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &err); + if (err != OK) { + if (file) file->close(); + return err; + } - file->store_string(json_string); - file->close(); + file->store_string(json_string); + file->close(); - return OK; + return OK; } diff --git a/spine-godot/spine_godot/SpineSkeletonJsonDataResource.h b/spine-godot/spine_godot/SpineSkeletonJsonDataResource.h index 54e2fe650..8b6045bf6 100644 --- a/spine-godot/spine_godot/SpineSkeletonJsonDataResource.h +++ b/spine-godot/spine_godot/SpineSkeletonJsonDataResource.h @@ -32,18 +32,19 @@ #include "core/variant_parser.h" -class SpineSkeletonJsonDataResource : public Resource{ +class SpineSkeletonJsonDataResource : public Resource { GDCLASS(SpineSkeletonJsonDataResource, Resource); protected: static void _bind_methods(); - String json_string; -public: - inline const String &get_json_string() {return json_string;} + String json_string; - Error load_from_file(const String &p_path); - Error save_to_file(const String &p_path); +public: + inline const String &get_json_string() { return json_string; } + + Error load_from_file(const String &p_path); + Error save_to_file(const String &p_path); }; -#endif //GODOT_SPINESKELETONJSONDATARESOURCE_H +#endif//GODOT_SPINESKELETONJSONDATARESOURCE_H diff --git a/spine-godot/spine_godot/SpineSkin.cpp b/spine-godot/spine_godot/SpineSkin.cpp index 92ece10de..b30f01ae5 100644 --- a/spine-godot/spine_godot/SpineSkin.cpp +++ b/spine-godot/spine_godot/SpineSkin.cpp @@ -47,53 +47,53 @@ void SpineSkin::_bind_methods() { ClassDB::bind_method(D_METHOD("get_all_constraint_data"), &SpineSkin::get_constraint); } -SpineSkin::SpineSkin():skin(NULL) {} +SpineSkin::SpineSkin() : skin(NULL) {} SpineSkin::~SpineSkin() {} #define S_T(x) (spine::String(x.utf8())) -Ref SpineSkin::init(const String &name){ +Ref SpineSkin::init(const String &name) { skin = new spine::Skin(S_T(name)); return this; } -void SpineSkin::set_attachment(uint64_t slot_index, const String &name, Ref attachment){ - if(!attachment.is_valid()){ +void SpineSkin::set_attachment(uint64_t slot_index, const String &name, Ref attachment) { + if (!attachment.is_valid()) { ERR_PRINT("attachment is invalid!"); return; } skin->setAttachment(slot_index, S_T(name), attachment->get_spine_object()); } -Ref SpineSkin::get_attachment(uint64_t slot_index, const String &name){ +Ref SpineSkin::get_attachment(uint64_t slot_index, const String &name) { auto a = skin->getAttachment(slot_index, S_T(name)); - if(a == NULL) return NULL; + if (a == NULL) return NULL; Ref gd_attachment(memnew(SpineAttachment)); gd_attachment->set_spine_object(a); return gd_attachment; } -void SpineSkin::remove_attachment(uint64_t slot_index, const String &name){ +void SpineSkin::remove_attachment(uint64_t slot_index, const String &name) { skin->removeAttachment(slot_index, S_T(name)); } -Array SpineSkin::find_names_for_slot(uint64_t slot_index){ +Array SpineSkin::find_names_for_slot(uint64_t slot_index) { spine::Vector names; skin->findNamesForSlot(slot_index, names); Array gd_names; gd_names.resize(names.size()); - for(size_t i=0; i < names.size(); ++i){ + for (size_t i = 0; i < names.size(); ++i) { gd_names[i] = names[i].buffer(); } return gd_names; } -Array SpineSkin::find_attachments_for_slot(uint64_t slot_index){ - spine::Vector as; +Array SpineSkin::find_attachments_for_slot(uint64_t slot_index) { + spine::Vector as; skin->findAttachmentsForSlot(slot_index, as); Array gd_as; gd_as.resize(as.size()); - for(size_t i=0; i < as.size(); ++i){ - if(as[i] == NULL) gd_as[i] = Ref(NULL); + for (size_t i = 0; i < as.size(); ++i) { + if (as[i] == NULL) gd_as[i] = Ref(NULL); else { Ref gd_a(memnew(SpineAttachment)); gd_a->set_spine_object(as[i]); @@ -103,41 +103,40 @@ Array SpineSkin::find_attachments_for_slot(uint64_t slot_index){ return gd_as; } -String SpineSkin::get_skin_name(){ +String SpineSkin::get_skin_name() { return skin->getName().buffer(); } -void SpineSkin::add_skin(Ref other){ - if(other.is_valid() && other->get_spine_object()){ +void SpineSkin::add_skin(Ref other) { + if (other.is_valid() && other->get_spine_object()) { skin->addSkin(other->get_spine_object()); - } else{ + } else { ERR_PRINT("other is NULL!"); } } -void SpineSkin::copy_skin(Ref other){ - if(other.is_valid() && other->get_spine_object()){ +void SpineSkin::copy_skin(Ref other) { + if (other.is_valid() && other->get_spine_object()) { skin->copySkin(other->get_spine_object()); - } else{ + } else { ERR_PRINT("other is NULL!"); } } -Ref SpineSkin::get_attachments(){ +Ref SpineSkin::get_attachments() { auto *es = new spine::Skin::AttachmentMap::Entries(skin->getAttachments()); Ref gd_es(memnew(SpineSkinAttachmentMapEntries)); gd_es->set_spine_object(es); return gd_es; - } -Array SpineSkin::get_bones(){ +Array SpineSkin::get_bones() { auto bs = skin->getBones(); Array gd_bs; gd_bs.resize(bs.size()); - for(size_t i=0; i < bs.size(); ++i){ - if(bs[i] == NULL) gd_bs[i] = Ref(NULL); - else{ + for (size_t i = 0; i < bs.size(); ++i) { + if (bs[i] == NULL) gd_bs[i] = Ref(NULL); + else { Ref gd_b(memnew(SpineBoneData)); gd_b->set_spine_object(bs[i]); gd_bs[i] = gd_b; @@ -146,13 +145,13 @@ Array SpineSkin::get_bones(){ return gd_bs; } -Array SpineSkin::get_constraint(){ +Array SpineSkin::get_constraint() { auto cs = skin->getConstraints(); Array gd_cs; gd_cs.resize(cs.size()); - for(size_t i=0; i < cs.size(); ++i){ - if(cs[i] == NULL) gd_cs[i] = Ref(NULL); - else{ + for (size_t i = 0; i < cs.size(); ++i) { + if (cs[i] == NULL) gd_cs[i] = Ref(NULL); + else { Ref gd_c(memnew(SpineConstraintData)); gd_c->set_spine_object(cs[i]); gd_cs[i] = gd_c; diff --git a/spine-godot/spine_godot/SpineSkin.h b/spine-godot/spine_godot/SpineSkin.h index 1b6533414..3e1780f2a 100644 --- a/spine-godot/spine_godot/SpineSkin.h +++ b/spine-godot/spine_godot/SpineSkin.h @@ -50,10 +50,10 @@ public: SpineSkin(); ~SpineSkin(); - inline void set_spine_object(spine::Skin *s){ + inline void set_spine_object(spine::Skin *s) { skin = s; } - spine::Skin *get_spine_object(){ + spine::Skin *get_spine_object() { return skin; } @@ -82,4 +82,4 @@ public: Array get_constraint(); }; -#endif //GODOT_SPINESKIN_H +#endif//GODOT_SPINESKIN_H diff --git a/spine-godot/spine_godot/SpineSkinAttachmentMapEntries.cpp b/spine-godot/spine_godot/SpineSkinAttachmentMapEntries.cpp index 03e15203f..67089b011 100644 --- a/spine-godot/spine_godot/SpineSkinAttachmentMapEntries.cpp +++ b/spine-godot/spine_godot/SpineSkinAttachmentMapEntries.cpp @@ -38,33 +38,33 @@ void SpineSkinAttachmentMapEntry::_bind_methods() { ClassDB::bind_method(D_METHOD("set_attachment", "v"), &SpineSkinAttachmentMapEntry::set_attachment); } -SpineSkinAttachmentMapEntry::SpineSkinAttachmentMapEntry():entry(NULL) {} +SpineSkinAttachmentMapEntry::SpineSkinAttachmentMapEntry() : entry(NULL) {} SpineSkinAttachmentMapEntry::~SpineSkinAttachmentMapEntry() {} -uint64_t SpineSkinAttachmentMapEntry::get_slot_index(){ +uint64_t SpineSkinAttachmentMapEntry::get_slot_index() { return entry->_slotIndex; } -void SpineSkinAttachmentMapEntry::set_slot_index(uint64_t v){ +void SpineSkinAttachmentMapEntry::set_slot_index(uint64_t v) { entry->_slotIndex = v; } -String SpineSkinAttachmentMapEntry::get_entry_name(){ +String SpineSkinAttachmentMapEntry::get_entry_name() { return entry->_name.buffer(); } -void SpineSkinAttachmentMapEntry::set_entry_name(const String &v){ +void SpineSkinAttachmentMapEntry::set_entry_name(const String &v) { entry->_name = spine::String(v.utf8()); } -Ref SpineSkinAttachmentMapEntry::get_attachment(){ - if(entry->_attachment == NULL) return NULL; +Ref SpineSkinAttachmentMapEntry::get_attachment() { + if (entry->_attachment == NULL) return NULL; Ref gd_attachment(memnew(SpineAttachment)); gd_attachment->set_spine_object(entry->_attachment); return gd_attachment; } -void SpineSkinAttachmentMapEntry::set_attachment(Ref v){ - if(v.is_valid()){ +void SpineSkinAttachmentMapEntry::set_attachment(Ref v) { + if (v.is_valid()) { entry->_attachment = v->get_spine_object(); - }else{ + } else { entry->_attachment = NULL; } } @@ -74,18 +74,18 @@ void SpineSkinAttachmentMapEntries::_bind_methods() { ClassDB::bind_method(D_METHOD("next"), &SpineSkinAttachmentMapEntries::next); } -SpineSkinAttachmentMapEntries::SpineSkinAttachmentMapEntries():entries(NULL) {} +SpineSkinAttachmentMapEntries::SpineSkinAttachmentMapEntries() : entries(NULL) {} SpineSkinAttachmentMapEntries::~SpineSkinAttachmentMapEntries() { - if(entries){ + if (entries) { delete entries; return; } } -bool SpineSkinAttachmentMapEntries::has_next(){ +bool SpineSkinAttachmentMapEntries::has_next() { return entries->hasNext(); } -Ref SpineSkinAttachmentMapEntries::next(){ +Ref SpineSkinAttachmentMapEntries::next() { auto &e = entries->next(); Ref gd_entry(memnew(SpineSkinAttachmentMapEntry)); gd_entry->set_spine_object(&e); diff --git a/spine-godot/spine_godot/SpineSkinAttachmentMapEntries.h b/spine-godot/spine_godot/SpineSkinAttachmentMapEntries.h index 9f5db61e3..b0f3922ef 100644 --- a/spine-godot/spine_godot/SpineSkinAttachmentMapEntries.h +++ b/spine-godot/spine_godot/SpineSkinAttachmentMapEntries.h @@ -49,10 +49,10 @@ public: SpineSkinAttachmentMapEntry(); ~SpineSkinAttachmentMapEntry(); - inline void set_spine_object(spine::Skin::AttachmentMap::Entry *e){ + inline void set_spine_object(spine::Skin::AttachmentMap::Entry *e) { entry = e; } - inline spine::Skin::AttachmentMap::Entry *get_spine_object(){ + inline spine::Skin::AttachmentMap::Entry *get_spine_object() { return entry; } @@ -79,10 +79,10 @@ public: SpineSkinAttachmentMapEntries(); ~SpineSkinAttachmentMapEntries(); - inline void set_spine_object(spine::Skin::AttachmentMap::Entries *e){ + inline void set_spine_object(spine::Skin::AttachmentMap::Entries *e) { entries = e; } - inline spine::Skin::AttachmentMap::Entries *get_spine_object(){ + inline spine::Skin::AttachmentMap::Entries *get_spine_object() { return entries; } @@ -90,4 +90,4 @@ public: Ref next(); }; -#endif //GODOT_SPINESKINATTACHMENTMAPENTRIES_H +#endif//GODOT_SPINESKINATTACHMENTMAPENTRIES_H diff --git a/spine-godot/spine_godot/SpineSlot.cpp b/spine-godot/spine_godot/SpineSlot.cpp index c26b98448..b1bbab708 100644 --- a/spine-godot/spine_godot/SpineSlot.cpp +++ b/spine-godot/spine_godot/SpineSlot.cpp @@ -51,98 +51,98 @@ void SpineSlot::_bind_methods() { ClassDB::bind_method(D_METHOD("set_deform", "v"), &SpineSlot::set_deform); } -SpineSlot::SpineSlot():slot(NULL) {} +SpineSlot::SpineSlot() : slot(NULL) {} SpineSlot::~SpineSlot() {} -void SpineSlot::set_to_setup_pos(){ +void SpineSlot::set_to_setup_pos() { slot->setToSetupPose(); } -Ref SpineSlot::get_data(){ +Ref SpineSlot::get_data() { auto &sd = slot->getData(); Ref gd_sd(memnew(SpineSlotData)); gd_sd->set_spine_object(&sd); return gd_sd; } -Ref SpineSlot::get_bone(){ +Ref SpineSlot::get_bone() { auto &b = slot->getBone(); Ref gd_b(memnew(SpineBone)); gd_b->set_spine_object(&b); return gd_b; } -Ref SpineSlot::get_skeleton(){ +Ref SpineSlot::get_skeleton() { auto &s = slot->getSkeleton(); Ref gd_s(memnew(SpineSkeleton)); gd_s->set_spine_object(&s); return gd_s; } -Color SpineSlot::get_color(){ +Color SpineSlot::get_color() { auto &c = slot->getColor(); return Color(c.r, c.g, c.b, c.a); } -void SpineSlot::set_color(Color v){ +void SpineSlot::set_color(Color v) { auto &c = slot->getColor(); c.set(v.r, v.g, v.b, v.a); } -Color SpineSlot::get_dark_color(){ +Color SpineSlot::get_dark_color() { auto &c = slot->getDarkColor(); return Color(c.r, c.g, c.b, c.a); } -void SpineSlot::set_dark_color(Color v){ +void SpineSlot::set_dark_color(Color v) { auto &c = slot->getDarkColor(); c.set(v.r, v.g, v.b, v.a); } -bool SpineSlot::has_dark_color(){ +bool SpineSlot::has_dark_color() { return slot->hasDarkColor(); } -Ref SpineSlot::get_attachment(){ +Ref SpineSlot::get_attachment() { auto a = slot->getAttachment(); - if(a == NULL) return NULL; + if (a == NULL) return NULL; Ref gd_a(memnew(SpineAttachment)); gd_a->set_spine_object(a); return gd_a; } -void SpineSlot::set_attachment(Ref v){ - if(v.is_valid()){ +void SpineSlot::set_attachment(Ref v) { + if (v.is_valid()) { slot->setAttachment(v->get_spine_object()); - }else{ + } else { slot->setAttachment(NULL); } } -int SpineSlot::get_attachment_state(){ +int SpineSlot::get_attachment_state() { return slot->getAttachmentState(); } -void SpineSlot::set_attachment_state(int v){ +void SpineSlot::set_attachment_state(int v) { slot->setAttachmentState(v); } -float SpineSlot::get_attachment_time(){ +float SpineSlot::get_attachment_time() { return slot->getAttachmentTime(); } -void SpineSlot::set_attachment_time(float v){ +void SpineSlot::set_attachment_time(float v) { slot->setAttachmentTime(v); } -Array SpineSlot::get_deform(){ +Array SpineSlot::get_deform() { auto &ds = slot->getDeform(); Array gd_ds; gd_ds.resize(ds.size()); - for(size_t i=0; i < ds.size(); ++i){ + for (size_t i = 0; i < ds.size(); ++i) { gd_ds[i] = ds[i]; } return gd_ds; } -void SpineSlot::set_deform(Array gd_ds){ +void SpineSlot::set_deform(Array gd_ds) { auto &ds = slot->getDeform(); ds.setSize(gd_ds.size(), 0); - for(size_t i=0; i < gd_ds.size(); ++i){ + for (size_t i = 0; i < gd_ds.size(); ++i) { ds[i] = gd_ds[i]; } } \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineSlot.h b/spine-godot/spine_godot/SpineSlot.h index dff4cebcf..1d71eddb1 100644 --- a/spine-godot/spine_godot/SpineSlot.h +++ b/spine-godot/spine_godot/SpineSlot.h @@ -41,7 +41,7 @@ class SpineSkeleton; class SpineBone; -class SpineSlot : public Reference{ +class SpineSlot : public Reference { GDCLASS(SpineSlot, Reference); protected: @@ -54,10 +54,10 @@ public: SpineSlot(); ~SpineSlot(); - inline void set_spine_object(spine::Slot *s){ + inline void set_spine_object(spine::Slot *s) { slot = s; } - inline spine::Slot *get_spine_object(){ + inline spine::Slot *get_spine_object() { return slot; } @@ -90,4 +90,4 @@ public: void set_deform(Array v); }; -#endif //GODOT_SPINESLOT_H +#endif//GODOT_SPINESLOT_H diff --git a/spine-godot/spine_godot/SpineSlotData.cpp b/spine-godot/spine_godot/SpineSlotData.cpp index 82d77b9e1..bf3c48f20 100644 --- a/spine-godot/spine_godot/SpineSlotData.cpp +++ b/spine-godot/spine_godot/SpineSlotData.cpp @@ -51,62 +51,62 @@ void SpineSlotData::_bind_methods() { BIND_ENUM_CONSTANT(BLENDMODE_SCREEN); } -SpineSlotData::SpineSlotData():slot_data(NULL) {} +SpineSlotData::SpineSlotData() : slot_data(NULL) {} SpineSlotData::~SpineSlotData() {} #define S_T(x) (spine::String(x.utf8())) -int SpineSlotData::get_index(){ +int SpineSlotData::get_index() { return slot_data->getIndex(); } -String SpineSlotData::get_slot_name(){ +String SpineSlotData::get_slot_name() { return slot_data->getName().buffer(); } -Ref SpineSlotData::get_bone_data(){ +Ref SpineSlotData::get_bone_data() { auto &bd = slot_data->getBoneData(); Ref gd_bone_data(memnew(SpineBoneData)); gd_bone_data->set_spine_object(&bd); return gd_bone_data; } -Color SpineSlotData::get_color(){ +Color SpineSlotData::get_color() { auto &c = slot_data->getColor(); return Color(c.r, c.g, c.b, c.a); } -void SpineSlotData::set_color(Color v){ +void SpineSlotData::set_color(Color v) { auto &c = slot_data->getColor(); c.set(v.r, v.g, v.b, v.a); } -Color SpineSlotData::get_dark_color(){ +Color SpineSlotData::get_dark_color() { auto &c = slot_data->getDarkColor(); return Color(c.r, c.g, c.b, c.a); } -void SpineSlotData::set_dark_color(Color v){ +void SpineSlotData::set_dark_color(Color v) { auto &c = slot_data->getDarkColor(); c.set(v.r, v.g, v.b, v.a); } -bool SpineSlotData::has_dark_color(){ +bool SpineSlotData::has_dark_color() { return slot_data->hasDarkColor(); } -void SpineSlotData::set_has_dark_color(bool v){ +void SpineSlotData::set_has_dark_color(bool v) { slot_data->setHasDarkColor(v); } -String SpineSlotData::get_attachment_name(){ +String SpineSlotData::get_attachment_name() { return slot_data->getAttachmentName().buffer(); } -void SpineSlotData::set_attachment_name(const String &v){ +void SpineSlotData::set_attachment_name(const String &v) { slot_data->setAttachmentName(S_T(v)); } -SpineSlotData::BlendMode SpineSlotData::get_blend_mode(){ +SpineSlotData::BlendMode SpineSlotData::get_blend_mode() { auto bm = (int) slot_data->getBlendMode(); return (BlendMode) bm; } -void SpineSlotData::set_blend_mode(BlendMode v){ +void SpineSlotData::set_blend_mode(BlendMode v) { auto bm = (int) v; slot_data->setBlendMode((spine::BlendMode) bm); } diff --git a/spine-godot/spine_godot/SpineSlotData.h b/spine-godot/spine_godot/SpineSlotData.h index 0b2f9abf5..1778bba55 100644 --- a/spine-godot/spine_godot/SpineSlotData.h +++ b/spine-godot/spine_godot/SpineSlotData.h @@ -48,10 +48,10 @@ public: SpineSlotData(); ~SpineSlotData(); - inline void set_spine_object(spine::SlotData *s){ + inline void set_spine_object(spine::SlotData *s) { slot_data = s; } - inline spine::SlotData *get_spine_object(){ + inline spine::SlotData *get_spine_object() { return slot_data; } @@ -85,4 +85,4 @@ public: }; VARIANT_ENUM_CAST(SpineSlotData::BlendMode); -#endif //GODOT_SPINESLOTDATA_H +#endif//GODOT_SPINESLOTDATA_H diff --git a/spine-godot/spine_godot/SpineSprite.cpp b/spine-godot/spine_godot/SpineSprite.cpp index 894545755..eb8c2c309 100644 --- a/spine-godot/spine_godot/SpineSprite.cpp +++ b/spine-godot/spine_godot/SpineSprite.cpp @@ -33,8 +33,8 @@ #include "SpineEvent.h" void SpineSprite::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_animation_state_data_res", "animation_state_data_res"), &SpineSprite::set_animation_state_data_res); - ClassDB::bind_method(D_METHOD("get_animation_state_data_res"), &SpineSprite::get_animation_state_data_res); + ClassDB::bind_method(D_METHOD("set_animation_state_data_res", "animation_state_data_res"), &SpineSprite::set_animation_state_data_res); + ClassDB::bind_method(D_METHOD("get_animation_state_data_res"), &SpineSprite::get_animation_state_data_res); ClassDB::bind_method(D_METHOD("_on_animation_data_created"), &SpineSprite::_on_animation_data_created); ClassDB::bind_method(D_METHOD("get_skeleton"), &SpineSprite::get_skeleton); ClassDB::bind_method(D_METHOD("get_animation_state"), &SpineSprite::get_animation_state); @@ -60,7 +60,7 @@ void SpineSprite::_bind_methods() { ClassDB::bind_method(D_METHOD("get_bind_slot_nodes"), &SpineSprite::get_bind_slot_nodes); ClassDB::bind_method(D_METHOD("set_bind_slot_nodes", "v"), &SpineSprite::set_bind_slot_nodes); ClassDB::bind_method(D_METHOD("get_overlap"), &SpineSprite::get_overlap); - ClassDB::bind_method(D_METHOD("set_overlap", "v"), &SpineSprite::set_overlap); + ClassDB::bind_method(D_METHOD("set_overlap", "v"), &SpineSprite::set_overlap); ClassDB::bind_method(D_METHOD("set_skin", "v"), &SpineSprite::set_skin); ClassDB::bind_method(D_METHOD("get_skin"), &SpineSprite::get_skin); ClassDB::bind_method(D_METHOD("_on_skin_property_changed"), &SpineSprite::_on_skin_property_changed); @@ -69,10 +69,10 @@ void SpineSprite::_bind_methods() { ClassDB::bind_method(D_METHOD("bone_get_global_transform", "bone_name"), &SpineSprite::bone_get_global_transform); ClassDB::bind_method(D_METHOD("bone_set_global_transform", "bone_name", "global_transform"), &SpineSprite::bone_set_global_transform); - ClassDB::bind_method(D_METHOD("set_process_mode", "v"), &SpineSprite::set_process_mode); - ClassDB::bind_method(D_METHOD("get_process_mode"), &SpineSprite::get_process_mode); + ClassDB::bind_method(D_METHOD("set_process_mode", "v"), &SpineSprite::set_process_mode); + ClassDB::bind_method(D_METHOD("get_process_mode"), &SpineSprite::get_process_mode); - ClassDB::bind_method(D_METHOD("manual_update", "delta"), &SpineSprite::_update_all); + ClassDB::bind_method(D_METHOD("manual_update", "delta"), &SpineSprite::_update_all); ADD_SIGNAL(MethodInfo("animation_state_ready", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "skeleton", PROPERTY_HINT_TYPE_STRING, "SpineSkeleton"))); ADD_SIGNAL(MethodInfo("animation_start", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent"))); @@ -82,27 +82,25 @@ void SpineSprite::_bind_methods() { ADD_SIGNAL(MethodInfo("animation_dispose", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent"))); ADD_SIGNAL(MethodInfo("animation_event", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent"))); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "animation_state_data_res", PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "SpineAnimationStateDataResource"), "set_animation_state_data_res", "get_animation_state_data_res"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "animation_state_data_res", PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "SpineAnimationStateDataResource"), "set_animation_state_data_res", "get_animation_state_data_res"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "overlap"), "set_overlap", "get_overlap"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "overlap"), "set_overlap", "get_overlap"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "bind_slot_nodes"), "set_bind_slot_nodes", "get_bind_slot_nodes"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "packed_skin_resource", PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "PackedSpineSkinResource"), "set_skin", "get_skin"); - ADD_GROUP("animation", ""); - ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Process,Physics,Manually"), "set_process_mode", "get_process_mode"); + ADD_GROUP("animation", ""); + ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Process,Physics,Manually"), "set_process_mode", "get_process_mode"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "current_animations"), "set_current_animations", "get_current_animations"); - BIND_ENUM_CONSTANT(ProcessMode::ProcessMode_Process); - BIND_ENUM_CONSTANT(ProcessMode::ProcessMode_Physics); - BIND_ENUM_CONSTANT(ProcessMode::ProcessMode_Manual); + BIND_ENUM_CONSTANT(ProcessMode::ProcessMode_Process); + BIND_ENUM_CONSTANT(ProcessMode::ProcessMode_Physics); + BIND_ENUM_CONSTANT(ProcessMode::ProcessMode_Manual); } -SpineSprite::SpineSprite() : - select_track_id(0), empty_animation_duration(0.2f), skeleton_clipper(NULL), - overlap(false), - process_mode(ProcessMode_Process) - { +SpineSprite::SpineSprite() : select_track_id(0), empty_animation_duration(0.2f), skeleton_clipper(NULL), + overlap(false), + process_mode(ProcessMode_Process) { skeleton_clipper = new spine::SkeletonClipping(); } SpineSprite::~SpineSprite() { @@ -111,133 +109,129 @@ SpineSprite::~SpineSprite() { void SpineSprite::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_READY:{ - set_process_internal(process_mode == ProcessMode_Process); - set_physics_process_internal(process_mode == ProcessMode_Physics); + case NOTIFICATION_READY: { + set_process_internal(process_mode == ProcessMode_Process); + set_physics_process_internal(process_mode == ProcessMode_Physics); remove_redundant_mesh_instances(); } break; case NOTIFICATION_INTERNAL_PROCESS: { - if (process_mode == ProcessMode_Process) - _update_all(get_process_delta_time()); + if (process_mode == ProcessMode_Process) + _update_all(get_process_delta_time()); } break; case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { - if (process_mode == ProcessMode_Physics) - _update_all(get_physics_process_delta_time()); - } break; + if (process_mode == ProcessMode_Physics) + _update_all(get_physics_process_delta_time()); + } break; } } void SpineSprite::_update_all(float delta) { - if (!(skeleton.is_valid() && animation_state.is_valid()) || mesh_instances.empty()) - return; + if (!(skeleton.is_valid() && animation_state.is_valid()) || mesh_instances.empty()) + return; - animation_state->update(delta); - if (!is_visible_in_tree()) - return; + animation_state->update(delta); + if (!is_visible_in_tree()) + return; - animation_state->apply(skeleton); + animation_state->apply(skeleton); - skeleton->update_world_transform(); + skeleton->update_world_transform(); - update_mesh_from_skeleton(skeleton); + update_mesh_from_skeleton(skeleton); - update(); + update(); - update_bind_slot_nodes(); + update_bind_slot_nodes(); } -void SpineSprite::update_bind_slot_nodes(){ - if(animation_state.is_valid() && skeleton.is_valid()){ - for(size_t i=0, n=bind_slot_nodes.size(); iis_class("Node2D")){ - Node2D *node2d = (Node2D*) node; + if (node && node->is_class("Node2D")) { + Node2D *node2d = (Node2D *) node; String slot_name = d["slot_name"]; auto slot = skeleton->find_slot(slot_name); - if(slot.is_valid()){ + if (slot.is_valid()) { auto bone = slot->get_bone(); - if(bone.is_valid()) - { + if (bone.is_valid()) { update_bind_slot_node_transform(bone, node2d); update_bind_slot_node_draw_order(slot_name, node2d); } } - } } - }else if(a.get_type() == Variant::ARRAY){ + } else if (a.get_type() == Variant::ARRAY) { auto as = (Array) a;// 0: slot_name, 1: node_path - if(as.size() >= 2 && as[0].get_type() == Variant::STRING && as[1].get_type() == Variant::NODE_PATH){ + if (as.size() >= 2 && as[0].get_type() == Variant::STRING && as[1].get_type() == Variant::NODE_PATH) { NodePath node_path = as[1]; Node *node = get_node_or_null(node_path); - if(node && node->is_class("Node2D")){ - Node2D *node2d = (Node2D*) node; + if (node && node->is_class("Node2D")) { + Node2D *node2d = (Node2D *) node; String slot_name = as[0]; auto slot = skeleton->find_slot(slot_name); - if(slot.is_valid()){ + if (slot.is_valid()) { auto bone = slot->get_bone(); - if(bone.is_valid()) - { + if (bone.is_valid()) { update_bind_slot_node_transform(bone, node2d); update_bind_slot_node_draw_order(slot_name, node2d); } } - } } } } } } -void SpineSprite::update_bind_slot_node_transform(Ref bone, Node2D *node2d){ +void SpineSprite::update_bind_slot_node_transform(Ref bone, Node2D *node2d) { bone->apply_world_transform_2d(node2d); } -void SpineSprite::update_bind_slot_node_draw_order(const String &slot_name, Node2D *node2d){ +void SpineSprite::update_bind_slot_node_draw_order(const String &slot_name, Node2D *node2d) { auto mesh_ins = find_node(slot_name); - if(mesh_ins){ + if (mesh_ins) { auto pos = mesh_ins->get_index(); // get child auto node = find_child_node_by_node(node2d); - if(node && node->get_index() != pos+1){ - move_child(node, pos+1); + if (node && node->get_index() != pos + 1) { + move_child(node, pos + 1); } } } -Node *SpineSprite::find_child_node_by_node(Node *node){ - if(node == NULL) return NULL; - while(node && node->get_parent() != this) node = node->get_parent(); +Node *SpineSprite::find_child_node_by_node(Node *node) { + if (node == NULL) return NULL; + while (node && node->get_parent() != this) node = node->get_parent(); return node; } void SpineSprite::set_animation_state_data_res(const Ref &s) { - animation_state_data_res = s; + animation_state_data_res = s; // update run time skeleton and meshes _on_animation_data_changed(); } Ref SpineSprite::get_animation_state_data_res() { - return animation_state_data_res; + return animation_state_data_res; } -void SpineSprite::_on_animation_data_created(){ -// print_line("_on_animation_data_created"); +void SpineSprite::_on_animation_data_created() { + // print_line("_on_animation_data_created"); skeleton = Ref(memnew(SpineSkeleton)); skeleton->load_skeleton(animation_state_data_res->get_skeleton()); skeleton->set_spine_sprite(this); -// print_line("Run time skeleton created."); + // print_line("Run time skeleton created."); animation_state = Ref(memnew(SpineAnimationState)); animation_state->load_animation_state(animation_state_data_res); animation_state->get_animation_state()->setListener(this); -// print_line("Run time animation state created."); + // print_line("Run time animation state created."); // add mesh instances related by current skeleton animation_state->update(0); @@ -246,29 +240,27 @@ void SpineSprite::_on_animation_data_created(){ gen_mesh_from_skeleton(skeleton); if (process_mode == ProcessMode_Process) { - _notification(NOTIFICATION_INTERNAL_PROCESS); - } else if (process_mode == ProcessMode_Physics) { - _notification(NOTIFICATION_INTERNAL_PHYSICS_PROCESS); + _notification(NOTIFICATION_INTERNAL_PROCESS); + } else if (process_mode == ProcessMode_Physics) { + _notification(NOTIFICATION_INTERNAL_PHYSICS_PROCESS); } emit_signal("animation_state_ready", animation_state, skeleton); } void SpineSprite::_on_animation_data_changed() { -// print_line("_on_animation_data_changed"); + // print_line("_on_animation_data_changed"); remove_mesh_instances(); skeleton.unref(); animation_state.unref(); - if(!animation_state_data_res.is_null()) - { - if(!animation_state_data_res->is_connected("animation_state_data_created", this, "_on_animation_data_created")) + if (!animation_state_data_res.is_null()) { + if (!animation_state_data_res->is_connected("animation_state_data_created", this, "_on_animation_data_created")) animation_state_data_res->connect("animation_state_data_created", this, "_on_animation_data_created"); - if(!animation_state_data_res->is_connected("skeleton_data_res_changed", this, "_on_animation_data_changed")) + if (!animation_state_data_res->is_connected("skeleton_data_res_changed", this, "_on_animation_data_changed")) animation_state_data_res->connect("skeleton_data_res_changed", this, "_on_animation_data_changed"); - if(!animation_state_data_res->is_connected("animation_state_data_changed", this, "_on_animation_data_changed")) + if (!animation_state_data_res->is_connected("animation_state_data_changed", this, "_on_animation_data_changed")) animation_state_data_res->connect("animation_state_data_changed", this, "_on_animation_data_changed"); - if(animation_state_data_res->is_animation_state_data_created()) - { + if (animation_state_data_res->is_animation_state_data_created()) { _on_animation_data_created(); } } @@ -283,8 +275,7 @@ Ref SpineSprite::get_animation_state() { void SpineSprite::gen_mesh_from_skeleton(Ref s) { auto sk = s->get_spine_object(); - for(size_t i=0, n = sk->getSlots().size(); i < n; ++i) - { + for (size_t i = 0, n = sk->getSlots().size(); i < n; ++i) { // creat a mesh instance 2d for every slot auto mesh_ins = memnew(SpineSpriteMeshInstance2D); add_child(mesh_ins); @@ -316,15 +307,14 @@ void SpineSprite::gen_mesh_from_skeleton(Ref s) { break; default: blend_mode = CanvasItemMaterial::BLEND_MODE_MIX; - } - mat->set_blend_mode(blend_mode); + } + mat->set_blend_mode(blend_mode); mesh_ins->set_material(mat); } } void SpineSprite::remove_mesh_instances() { - for(size_t i=0;i < mesh_instances.size();++i) - { + for (size_t i = 0; i < mesh_instances.size(); ++i) { remove_child(mesh_instances[i]); memdelete(mesh_instances[i]); } @@ -332,43 +322,42 @@ void SpineSprite::remove_mesh_instances() { } void SpineSprite::remove_redundant_mesh_instances() { - Vector ms; + Vector ms; // remove the redundant mesh instances that added by duplicating -// print_line("start clearing"); - for(size_t i=0, n=get_child_count(); iget_name()); - if(node && node->is_class("SpineSpriteMeshInstance2D")){ - if(mesh_instances.find((SpineSpriteMeshInstance2D*)node) == -1) - { -// print_line("marked clear"); + // print_line(String("get a node: ") + node->get_name()); + if (node && node->is_class("SpineSpriteMeshInstance2D")) { + if (mesh_instances.find((SpineSpriteMeshInstance2D *) node) == -1) { + // print_line("marked clear"); ms.push_back(node); } - } } - for(size_t i=0, n=ms.size(); i s) { static const unsigned short VERTEX_STRIDE = 2; static const unsigned short UV_STRIDE = 2; - static unsigned short quad_indices[] = { 0, 1, 2, 2, 3, 0 }; + static unsigned short quad_indices[] = {0, 1, 2, 2, 3, 0}; auto sk = s->get_spine_object(); - for(size_t i=0, n = sk->getSlots().size(); i < n; ++i) - { + for (size_t i = 0, n = sk->getSlots().size(); i < n; ++i) { spine::Vector vertices; spine::Vector uvs; spine::Vector indices; @@ -376,7 +365,7 @@ void SpineSprite::update_mesh_from_skeleton(Ref s) { spine::Slot *slot = sk->getDrawOrder()[i]; spine::Attachment *attachment = slot->getAttachment(); - if(!attachment){ + if (!attachment) { // set invisible to mesh instance mesh_instances[i]->set_visible(false); @@ -393,11 +382,10 @@ void SpineSprite::update_mesh_from_skeleton(Ref s) { Ref normal_tex; size_t v_num = 0; - if(attachment->getRTTI().isExactly(spine::RegionAttachment::rtti)) - { - spine::RegionAttachment *region_attachment = (spine::RegionAttachment*)attachment; + if (attachment->getRTTI().isExactly(spine::RegionAttachment::rtti)) { + spine::RegionAttachment *region_attachment = (spine::RegionAttachment *) attachment; - auto p_spine_renderer_object = (SpineRendererObject*) ((spine::AtlasRegion*)region_attachment->getRendererObject())->page->getRendererObject(); + auto p_spine_renderer_object = (SpineRendererObject *) ((spine::AtlasRegion *) region_attachment->getRendererObject())->page->getRendererObject(); tex = p_spine_renderer_object->tex; normal_tex = p_spine_renderer_object->normal_tex; @@ -409,7 +397,7 @@ void SpineSprite::update_mesh_from_skeleton(Ref s) { TEMP_COPY(uvs, region_attachment->getUVs()); indices.setSize(sizeof(quad_indices) / sizeof(unsigned short), 0); - for (size_t j = 0, qn = indices.size();j s) { tint.g *= attachment_color.g; tint.b *= attachment_color.b; tint.a *= attachment_color.a; - }else if(attachment->getRTTI().isExactly(spine::MeshAttachment::rtti)) { - spine::MeshAttachment *mesh = (spine::MeshAttachment*) attachment; + } else if (attachment->getRTTI().isExactly(spine::MeshAttachment::rtti)) { + spine::MeshAttachment *mesh = (spine::MeshAttachment *) attachment; - auto p_spine_renderer_object = (SpineRendererObject*) ((spine::AtlasRegion*)mesh->getRendererObject())->page->getRendererObject(); + auto p_spine_renderer_object = (SpineRendererObject *) ((spine::AtlasRegion *) mesh->getRendererObject())->page->getRendererObject(); tex = p_spine_renderer_object->tex; normal_tex = p_spine_renderer_object->normal_tex; - v_num = mesh->getWorldVerticesLength()/VERTEX_STRIDE; + v_num = mesh->getWorldVerticesLength() / VERTEX_STRIDE; vertices.setSize(mesh->getWorldVerticesLength(), 0); mesh->computeWorldVertices(*slot, vertices); -// uvs = mesh->getUVs(); -// indices = mesh->getTriangles(); + // uvs = mesh->getUVs(); + // indices = mesh->getTriangles(); TEMP_COPY(uvs, mesh->getUVs()); TEMP_COPY(indices, mesh->getTriangles()); @@ -450,7 +438,7 @@ void SpineSprite::update_mesh_from_skeleton(Ref s) { } auto mesh_ins = mesh_instances[i]; - VisualServer::get_singleton()->canvas_item_clear(mesh_ins->get_canvas_item()); + VisualServer::get_singleton()->canvas_item_clear(mesh_ins->get_canvas_item()); if (skeleton_clipper->isClipping()) { skeleton_clipper->clipTriangles(vertices, indices, uvs, VERTEX_STRIDE); @@ -461,7 +449,7 @@ void SpineSprite::update_mesh_from_skeleton(Ref s) { } auto &clipped_vertices = skeleton_clipper->getClippedVertices(); - v_num = clipped_vertices.size()/VERTEX_STRIDE; + v_num = clipped_vertices.size() / VERTEX_STRIDE; auto &clipped_uvs = skeleton_clipper->getClippedUVs(); auto &clipped_indices = skeleton_clipper->getClippedTriangles(); @@ -473,8 +461,8 @@ void SpineSprite::update_mesh_from_skeleton(Ref s) { p_uvs.resize(v_num); p_colors.resize(v_num); for (size_t j = 0; j < v_num; j++) { - p_points.set(j, Vector2(clipped_vertices[j*VERTEX_STRIDE], -clipped_vertices[j*VERTEX_STRIDE+1])); - p_uvs.set(j, Vector2(clipped_uvs[j*VERTEX_STRIDE], clipped_uvs[j*VERTEX_STRIDE+1])); + p_points.set(j, Vector2(clipped_vertices[j * VERTEX_STRIDE], -clipped_vertices[j * VERTEX_STRIDE + 1])); + p_uvs.set(j, Vector2(clipped_uvs[j * VERTEX_STRIDE], clipped_uvs[j * VERTEX_STRIDE + 1])); p_colors.set(j, Color(tint.r, tint.g, tint.b, tint.a)); } p_indices.resize(clipped_indices.size()); @@ -493,7 +481,7 @@ void SpineSprite::update_mesh_from_skeleton(Ref s) { -1, normal_tex.is_null() ? RID() : normal_tex->get_rid()); } - }else { + } else { if (indices.size() > 0) { Vector p_points, p_uvs; Vector p_colors; @@ -502,8 +490,8 @@ void SpineSprite::update_mesh_from_skeleton(Ref s) { p_uvs.resize(v_num); p_colors.resize(v_num); for (size_t j = 0; j < v_num; j++) { - p_points.set(j, Vector2(vertices[j*VERTEX_STRIDE], -vertices[j*VERTEX_STRIDE+1])); - p_uvs.set(j, Vector2(uvs[j*VERTEX_STRIDE], uvs[j*VERTEX_STRIDE+1])); + p_points.set(j, Vector2(vertices[j * VERTEX_STRIDE], -vertices[j * VERTEX_STRIDE + 1])); + p_uvs.set(j, Vector2(uvs[j * VERTEX_STRIDE], uvs[j * VERTEX_STRIDE + 1])); p_colors.set(j, Color(tint.r, tint.g, tint.b, tint.a)); } p_indices.resize(indices.size()); @@ -525,7 +513,7 @@ void SpineSprite::update_mesh_from_skeleton(Ref s) { } skeleton_clipper->clipEnd(*slot); - if (mesh_ins->get_material()->is_class("CanvasItemMaterial")){ + if (mesh_ins->get_material()->is_class("CanvasItemMaterial")) { Ref mat = mesh_ins->get_material(); CanvasItemMaterial::BlendMode blend_mode; switch (slot->getData().getBlendMode()) { @@ -543,7 +531,7 @@ void SpineSprite::update_mesh_from_skeleton(Ref s) { break; default: blend_mode = CanvasItemMaterial::BLEND_MODE_MIX; - } + } mat->set_blend_mode(blend_mode); } } @@ -554,40 +542,34 @@ void SpineSprite::callback(spine::AnimationState *state, spine::EventType type, Ref gd_entry(NULL); Ref gd_event(NULL); - if(entry){ + if (entry) { gd_entry = Ref(memnew(SpineTrackEntry)); gd_entry->set_spine_object(entry); } - if(event){ + if (event) { gd_event = Ref(memnew(SpineEvent)); gd_event->set_spine_object(event); } switch (type) { - case spine::EventType_Start: - { + case spine::EventType_Start: { emit_signal("animation_start", animation_state, gd_entry, gd_event); - }break; - case spine::EventType_Interrupt: - { + } break; + case spine::EventType_Interrupt: { emit_signal("animation_interrupt", animation_state, gd_entry, gd_event); - }break; - case spine::EventType_End: - { + } break; + case spine::EventType_End: { emit_signal("animation_end", animation_state, gd_entry, gd_event); - }break; - case spine::EventType_Complete: - { + } break; + case spine::EventType_Complete: { emit_signal("animation_complete", animation_state, gd_entry, gd_event); - }break; - case spine::EventType_Dispose: - { + } break; + case spine::EventType_Dispose: { emit_signal("animation_dispose", animation_state, gd_entry, gd_event); - }break; - case spine::EventType_Event: - { + } break; + case spine::EventType_Event: { emit_signal("animation_event", animation_state, gd_entry, gd_event); - }break; + } break; } } @@ -602,141 +584,137 @@ void SpineSprite::set_current_animations(Array as) { _validate_and_play_current_animations(); } -int SpineSprite::get_select_track_id(){ +int SpineSprite::get_select_track_id() { return select_track_id; } -void SpineSprite::set_select_track_id(int v){ +void SpineSprite::set_select_track_id(int v) { select_track_id = v; - if(select_track_id < 0) select_track_id = 0; + if (select_track_id < 0) select_track_id = 0; } -bool SpineSprite::get_clear_track(){ +bool SpineSprite::get_clear_track() { return false; } -void SpineSprite::set_clear_track(bool v){ - if(v && animation_state.is_valid() && skeleton.is_valid()) +void SpineSprite::set_clear_track(bool v) { + if (v && animation_state.is_valid() && skeleton.is_valid()) animation_state->clear_track(select_track_id); } -bool SpineSprite::get_clear_tracks(){ +bool SpineSprite::get_clear_tracks() { return false; } -void SpineSprite::set_clear_tracks(bool v){ - if(v && animation_state.is_valid() && skeleton.is_valid()) +void SpineSprite::set_clear_tracks(bool v) { + if (v && animation_state.is_valid() && skeleton.is_valid()) animation_state->clear_tracks(); } -float SpineSprite::get_empty_animation_duration(){ +float SpineSprite::get_empty_animation_duration() { return empty_animation_duration; } -void SpineSprite::set_empty_animation_duration(float v){ +void SpineSprite::set_empty_animation_duration(float v) { empty_animation_duration = v; } -bool SpineSprite::get_set_empty_animation(){ +bool SpineSprite::get_set_empty_animation() { return false; } -void SpineSprite::set_set_empty_animation(bool v){ - if(v && animation_state.is_valid() && skeleton.is_valid()) +void SpineSprite::set_set_empty_animation(bool v) { + if (v && animation_state.is_valid() && skeleton.is_valid()) animation_state->set_empty_animation(select_track_id, empty_animation_duration); } -bool SpineSprite::get_set_empty_animations(){ +bool SpineSprite::get_set_empty_animations() { return false; } -void SpineSprite::set_set_empty_animations(bool v){ - if(v && animation_state.is_valid() && skeleton.is_valid()) +void SpineSprite::set_set_empty_animations(bool v) { + if (v && animation_state.is_valid() && skeleton.is_valid()) animation_state->set_empty_animations(empty_animation_duration); } -Array SpineSprite::get_bind_slot_nodes(){ +Array SpineSprite::get_bind_slot_nodes() { return bind_slot_nodes; } void SpineSprite::set_bind_slot_nodes(Array v) { bind_slot_nodes = v; } -bool SpineSprite::get_overlap(){ +bool SpineSprite::get_overlap() { return overlap; } -void SpineSprite::set_overlap(bool v){ +void SpineSprite::set_overlap(bool v) { overlap = v; } -void SpineSprite::set_skin(Ref v) -{ - if(v != skin && skin.is_valid()){ - if(skin->is_connected("property_changed", this, "_on_skin_property_changed")) +void SpineSprite::set_skin(Ref v) { + if (v != skin && skin.is_valid()) { + if (skin->is_connected("property_changed", this, "_on_skin_property_changed")) skin->disconnect("property_changed", this, "_on_skin_property_changed"); } skin = v; - if(skin.is_valid()){ - if(!skin->is_connected("property_changed", this, "_on_skin_property_changed")) + if (skin.is_valid()) { + if (!skin->is_connected("property_changed", this, "_on_skin_property_changed")) skin->connect("property_changed", this, "_on_skin_property_changed"); update_runtime_skin(); } } -Ref SpineSprite::get_skin(){ +Ref SpineSprite::get_skin() { return skin; } -void SpineSprite::update_runtime_skin(){ +void SpineSprite::update_runtime_skin() { auto new_skin = gen_spine_skin_from_packed_resource(skin); - if(new_skin.is_valid()) - { + if (new_skin.is_valid()) { skeleton->set_skin(new_skin); skeleton->set_to_setup_pose(); } } -void SpineSprite::_on_skin_property_changed(){ +void SpineSprite::_on_skin_property_changed() { update_runtime_skin(); } -Ref SpineSprite::gen_spine_skin_from_packed_resource(Ref res){ - if(!(animation_state.is_valid() && skeleton.is_valid())) +Ref SpineSprite::gen_spine_skin_from_packed_resource(Ref res) { + if (!(animation_state.is_valid() && skeleton.is_valid())) return NULL; - if(!res.is_valid()) + if (!res.is_valid()) return NULL; - if(res->get_skin_name().empty()) + if (res->get_skin_name().empty()) return NULL; auto exist_skin = animation_state_data_res->get_skeleton()->find_skin(res->get_skin_name()); - if(exist_skin.is_valid()) - { + if (exist_skin.is_valid()) { return exist_skin; } auto new_skin = Ref(memnew(SpineSkin))->init(res->get_skin_name()); auto sub_skin_names = res->get_sub_skin_names(); - for(size_t i=0;iget_skeleton()->find_skin(skin_name); - if(sub_skin.is_valid()) + if (sub_skin.is_valid()) new_skin->add_skin(sub_skin); } return new_skin; } -void SpineSprite::bind_slot_with_node_2d(const String &slot_name, Node2D *n){ +void SpineSprite::bind_slot_with_node_2d(const String &slot_name, Node2D *n) { auto node_path = n->get_path_to(this); // check if has the same binding - for(size_t i=0, size=bind_slot_nodes.size(); i= 2 && as[0].get_type() == Variant::STRING && as[1].get_type() == Variant::NODE_PATH){ - if(slot_name == as[0] && node_path == as[1]){ + if (as.size() >= 2 && as[0].get_type() == Variant::STRING && as[1].get_type() == Variant::NODE_PATH) { + if (slot_name == as[0] && node_path == as[1]) { return; } } @@ -750,23 +728,23 @@ void SpineSprite::bind_slot_with_node_2d(const String &slot_name, Node2D *n){ bind_slot_nodes.append(bound); } -void SpineSprite::unbind_slot_with_node_2d(const String &slot_name, Node2D *n){ +void SpineSprite::unbind_slot_with_node_2d(const String &slot_name, Node2D *n) { auto node_path = n->get_path_to(this); - for(size_t i=0, size=bind_slot_nodes.size(); i= 2 && as[0].get_type() == Variant::STRING && as[1].get_type() == Variant::NODE_PATH){ - if(slot_name == as[0] && node_path == as[1]){ + if (as.size() >= 2 && as[0].get_type() == Variant::STRING && as[1].get_type() == Variant::NODE_PATH) { + if (slot_name == as[0] && node_path == as[1]) { bind_slot_nodes.remove(i); return; } @@ -776,264 +754,267 @@ void SpineSprite::unbind_slot_with_node_2d(const String &slot_name, Node2D *n){ } Transform2D SpineSprite::bone_get_global_transform(const String &bone_name) { - if (!animation_state.is_valid() && !skeleton.is_valid()) { - return get_global_transform(); - } - auto bone = skeleton->find_bone(bone_name); - if (!bone.is_valid()) { - print_error(vformat("Bone: '%s' not found.", bone_name)); - return get_global_transform(); - } - return bone->get_godot_global_transform(); + if (!animation_state.is_valid() && !skeleton.is_valid()) { + return get_global_transform(); + } + auto bone = skeleton->find_bone(bone_name); + if (!bone.is_valid()) { + print_error(vformat("Bone: '%s' not found.", bone_name)); + return get_global_transform(); + } + return bone->get_godot_global_transform(); } void SpineSprite::bone_set_global_transform(const String &bone_name, Transform2D transform) { - if (!animation_state.is_valid() && !skeleton.is_valid()) { - return; - } - auto bone = skeleton->find_bone(bone_name); - if (!bone.is_valid()) { - return; - } - bone->set_godot_global_transform(transform); + if (!animation_state.is_valid() && !skeleton.is_valid()) { + return; + } + auto bone = skeleton->find_bone(bone_name); + if (!bone.is_valid()) { + return; + } + bone->set_godot_global_transform(transform); } SpineSprite::ProcessMode SpineSprite::get_process_mode() { - return process_mode; + return process_mode; } void SpineSprite::set_process_mode(SpineSprite::ProcessMode v) { - process_mode = v; - set_process_internal(process_mode == ProcessMode_Process); - set_physics_process_internal(process_mode == ProcessMode_Physics); + process_mode = v; + set_process_internal(process_mode == ProcessMode_Process); + set_physics_process_internal(process_mode == ProcessMode_Physics); } void SpineSprite::_get_property_list(List *p_list) const { - p_list->push_back(PropertyInfo(Variant::NIL, "Current Animation Editor", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_CATEGORY)); - p_list->push_back(PropertyInfo(Variant::BOOL, "setup_pose_trigger", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - p_list->push_back(PropertyInfo(Variant::BOOL, "clear_tracks_trigger", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - p_list->push_back(PropertyInfo(Variant::BOOL, "set_empty_animations_trigger", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - p_list->push_back(PropertyInfo(Variant::REAL, "empty_animation_duration")); - p_list->push_back(PropertyInfo(Variant::INT, "track_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + p_list->push_back(PropertyInfo(Variant::NIL, "Current Animation Editor", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_CATEGORY)); + p_list->push_back(PropertyInfo(Variant::BOOL, "setup_pose_trigger", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + p_list->push_back(PropertyInfo(Variant::BOOL, "clear_tracks_trigger", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + p_list->push_back(PropertyInfo(Variant::BOOL, "set_empty_animations_trigger", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + p_list->push_back(PropertyInfo(Variant::REAL, "empty_animation_duration")); + p_list->push_back(PropertyInfo(Variant::INT, "track_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - for (size_t i=0; ipush_back(PropertyInfo(Variant::NIL, vformat("ID %d", (unsigned int)i), PROPERTY_HINT_NONE, prefix, PROPERTY_USAGE_GROUP)); - p_list->push_back(PropertyInfo(Variant::INT, vformat("%strack_id", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + for (size_t i = 0; i < current_animations.size(); ++i) { + String prefix = vformat("ca/%d/", (unsigned int) i); + p_list->push_back(PropertyInfo(Variant::NIL, vformat("ID %d", (unsigned int) i), PROPERTY_HINT_NONE, prefix, PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::INT, vformat("%strack_id", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - Vector anim_list; - if (skeleton.is_valid() && skeleton->get_data().is_valid()) { - skeleton->get_data()->get_animation_names(anim_list); - } - if (anim_list.empty()) anim_list.push_back("No Animation"); - p_list->push_back(PropertyInfo(Variant::STRING, vformat("%sanimation", prefix), PROPERTY_HINT_ENUM, String(",").join(anim_list), PROPERTY_USAGE_EDITOR)); + Vector anim_list; + if (skeleton.is_valid() && skeleton->get_data().is_valid()) { + skeleton->get_data()->get_animation_names(anim_list); + } + if (anim_list.empty()) anim_list.push_back("No Animation"); + p_list->push_back(PropertyInfo(Variant::STRING, vformat("%sanimation", prefix), PROPERTY_HINT_ENUM, String(",").join(anim_list), PROPERTY_USAGE_EDITOR)); - p_list->push_back(PropertyInfo(Variant::REAL, vformat("%sdelay", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + p_list->push_back(PropertyInfo(Variant::REAL, vformat("%sdelay", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - p_list->push_back(PropertyInfo(Variant::BOOL, vformat("%sloop", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + p_list->push_back(PropertyInfo(Variant::BOOL, vformat("%sloop", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - p_list->push_back(PropertyInfo(Variant::BOOL, vformat("%sempty", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - p_list->push_back(PropertyInfo(Variant::REAL, vformat("%sempty_animation_duration", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + p_list->push_back(PropertyInfo(Variant::BOOL, vformat("%sempty", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + p_list->push_back(PropertyInfo(Variant::REAL, vformat("%sempty_animation_duration", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - p_list->push_back(PropertyInfo(Variant::BOOL, vformat("%sclear", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - } + p_list->push_back(PropertyInfo(Variant::BOOL, vformat("%sclear", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + } } bool SpineSprite::_get(const StringName &p_property, Variant &r_value) const { - if (p_property == "setup_pose_trigger" || p_property == "clear_tracks_trigger" || p_property == "set_empty_animations_trigger") { - r_value = false; - return true; - } - if (p_property == "empty_animation_duration") { - r_value = empty_animation_duration; - return true; - } - if (p_property == "track_count") { - r_value = get_current_animation_count(); - return true; - } - String p = p_property; - if (p.size() > 2 && p[0] == 'c' && p[1] == 'a' && p[2] == '/') { - Vector sp = p.split("/"); - if (sp.size() > 2) { - int64_t id = sp[1].to_int64(); - if (id >= 0 && id < current_animations.size()) { - auto &key = sp[2]; - if (current_animations[id].get_type() == Variant::DICTIONARY) { - Dictionary dic = current_animations.get(id); - if (dic.has(key)) { - r_value = dic[key]; - } else { - if (key == "track_id") r_value = 0; - else if (key == "animation") r_value = ""; - else if (key == "loop") r_value = true; - else if (key == "empty") r_value = false; - else if (key == "empty_animation_duration") r_value = 0.3; - else if (key == "clear") r_value = false; - else if (key == "delay") r_value = 0; - else return false; - } - return true; - } - } - } - } - return false; + if (p_property == "setup_pose_trigger" || p_property == "clear_tracks_trigger" || p_property == "set_empty_animations_trigger") { + r_value = false; + return true; + } + if (p_property == "empty_animation_duration") { + r_value = empty_animation_duration; + return true; + } + if (p_property == "track_count") { + r_value = get_current_animation_count(); + return true; + } + String p = p_property; + if (p.size() > 2 && p[0] == 'c' && p[1] == 'a' && p[2] == '/') { + Vector sp = p.split("/"); + if (sp.size() > 2) { + int64_t id = sp[1].to_int64(); + if (id >= 0 && id < current_animations.size()) { + auto &key = sp[2]; + if (current_animations[id].get_type() == Variant::DICTIONARY) { + Dictionary dic = current_animations.get(id); + if (dic.has(key)) { + r_value = dic[key]; + } else { + if (key == "track_id") r_value = 0; + else if (key == "animation") + r_value = ""; + else if (key == "loop") + r_value = true; + else if (key == "empty") + r_value = false; + else if (key == "empty_animation_duration") + r_value = 0.3; + else if (key == "clear") + r_value = false; + else if (key == "delay") + r_value = 0; + else + return false; + } + return true; + } + } + } + } + return false; } bool SpineSprite::_set(const StringName &p_property, const Variant &p_value) { - if (p_property == "setup_pose_trigger") { - if (p_value) { - if (skeleton.is_valid()) { - skeleton->set_bones_to_setup_pose(); - skeleton->set_slots_to_setup_pose(); - } - } - return true; - } - if (p_property == "clear_tracks_trigger") { - if (p_value) { - if (animation_state.is_valid() && skeleton.is_valid()) { - animation_state->clear_tracks(); - } - } - return true; - } - if (p_property == "set_empty_animations_trigger") { - if (p_value) { - if (animation_state.is_valid() && skeleton.is_valid()) { - animation_state->set_empty_animations(empty_animation_duration); - } - } - return true; - } - if (p_property == "empty_animation_duration") { - empty_animation_duration = p_value; - return true; - } - if (p_property == "track_count") { - set_current_animation_count(p_value); - return true; - } - String p = p_property; - if (p.size() > 2 && p[0] == 'c' && p[1] == 'a' && p[2] == '/') { - Vector sp = p.split("/"); - if (sp.size() > 2) { - int64_t id = sp[1].to_int64(); - if (id >= 0 && id < current_animations.size()) { - auto &key = sp[2]; - if (current_animations[id].get_type() != Variant::DICTIONARY) { - current_animations.set(id, Dictionary()); - } + if (p_property == "setup_pose_trigger") { + if (p_value) { + if (skeleton.is_valid()) { + skeleton->set_bones_to_setup_pose(); + skeleton->set_slots_to_setup_pose(); + } + } + return true; + } + if (p_property == "clear_tracks_trigger") { + if (p_value) { + if (animation_state.is_valid() && skeleton.is_valid()) { + animation_state->clear_tracks(); + } + } + return true; + } + if (p_property == "set_empty_animations_trigger") { + if (p_value) { + if (animation_state.is_valid() && skeleton.is_valid()) { + animation_state->set_empty_animations(empty_animation_duration); + } + } + return true; + } + if (p_property == "empty_animation_duration") { + empty_animation_duration = p_value; + return true; + } + if (p_property == "track_count") { + set_current_animation_count(p_value); + return true; + } + String p = p_property; + if (p.size() > 2 && p[0] == 'c' && p[1] == 'a' && p[2] == '/') { + Vector sp = p.split("/"); + if (sp.size() > 2) { + int64_t id = sp[1].to_int64(); + if (id >= 0 && id < current_animations.size()) { + auto &key = sp[2]; + if (current_animations[id].get_type() != Variant::DICTIONARY) { + current_animations.set(id, Dictionary()); + } - Dictionary dic = current_animations.get(id); - dic[key] = p_value; + Dictionary dic = current_animations.get(id); + dic[key] = p_value; - _validate_and_play_current_animations(); - return true; - } - } - } - return false; + _validate_and_play_current_animations(); + return true; + } + } + } + return false; } int64_t SpineSprite::get_current_animation_count() const { - return current_animations.size(); + return current_animations.size(); } void SpineSprite::set_current_animation_count(int64_t v) { - if (v < 0) v = 0; - while (current_animations.size() < v) { - Dictionary d; - d["track_id"] = current_animations.size(); - d["animation"] = ""; - d["delay"] = 0; - d["loop"] = true; - d["empty"] = false; - d["empty_animation_duration"] = 0.3; - d["clear"] = false; - current_animations.push_back(d); - } - while (current_animations.size() > v) { - if (animation_state.is_valid() && skeleton.is_valid()) { - if (current_animations.back().get_type() == Variant::DICTIONARY) { - Dictionary back = current_animations.back(); - if (back.has("track_id")) { - int64_t track_id = back["track_id"]; - int track_cnt = 0; - for (size_t i=0; iclear_track(track_id); - } - } - } - current_animations.pop_back(); - } - property_list_changed_notify(); + if (v < 0) v = 0; + while (current_animations.size() < v) { + Dictionary d; + d["track_id"] = current_animations.size(); + d["animation"] = ""; + d["delay"] = 0; + d["loop"] = true; + d["empty"] = false; + d["empty_animation_duration"] = 0.3; + d["clear"] = false; + current_animations.push_back(d); + } + while (current_animations.size() > v) { + if (animation_state.is_valid() && skeleton.is_valid()) { + if (current_animations.back().get_type() == Variant::DICTIONARY) { + Dictionary back = current_animations.back(); + if (back.has("track_id")) { + int64_t track_id = back["track_id"]; + int track_cnt = 0; + for (size_t i = 0; i < current_animations.size(); ++i) { + if (current_animations[i].get_type() == Variant::DICTIONARY) { + Dictionary d = current_animations[i]; + if (d.has("track_id") && track_id == (int64_t) d["track_id"]) { + track_cnt += 1; + } + } + } + if (track_cnt == 0) + animation_state->clear_track(track_id); + } + } + } + current_animations.pop_back(); + } + property_list_changed_notify(); } void SpineSprite::_validate_and_play_current_animations() { - if(animation_state.is_valid() && skeleton.is_valid()){ - int64_t track_cnt = 0; - HashMap has_track; - for(size_t i=0; i has_track; + for (size_t i = 0; i < current_animations.size(); ++i) { + auto a = current_animations[i]; + if (a.get_type() == Variant::DICTIONARY) { + Dictionary d = a; - int64_t track_id = 0; - String animation = ""; - float delay = 0; - bool loop = true; - bool empty = false; - float empty_animation_duration = 0.3; - bool clear = false; + int64_t track_id = 0; + String animation = ""; + float delay = 0; + bool loop = true; + bool empty = false; + float empty_animation_duration = 0.3; + bool clear = false; - if (d.has("track_id")) track_id = d["track_id"]; - if (d.has("animation")) animation = d["animation"]; - if (d.has("delay")) delay = d["delay"]; - if (d.has("loop")) loop = d["loop"]; - if (d.has("empty")) empty = d["empty"]; - if (d.has("empty_animation_duration")) empty_animation_duration = d["empty_animation_duration"]; - if (d.has("clear")) clear = d["clear"]; + if (d.has("track_id")) track_id = d["track_id"]; + if (d.has("animation")) animation = d["animation"]; + if (d.has("delay")) delay = d["delay"]; + if (d.has("loop")) loop = d["loop"]; + if (d.has("empty")) empty = d["empty"]; + if (d.has("empty_animation_duration")) empty_animation_duration = d["empty_animation_duration"]; + if (d.has("clear")) clear = d["clear"]; - if (track_id < 0) { - print_line(vformat("track_id at 'ID %d' can not be less than 0!", (unsigned int)i)); - continue; - } + if (track_id < 0) { + print_line(vformat("track_id at 'ID %d' can not be less than 0!", (unsigned int) i)); + continue; + } - track_cnt += 1; + track_cnt += 1; - if (empty) { - if (has_track.has(track_id)) - animation_state->add_empty_animation(track_id, empty_animation_duration, delay); - else - animation_state->set_empty_animation(track_id, empty_animation_duration); - has_track[track_id] = true; - } else if (clear) { - animation_state->clear_track(track_id); - } else if (skeleton->get_data()->find_animation(animation).is_valid()) { - if (has_track.has(track_id)) - animation_state->add_animation(animation, delay, loop, track_id); - else - animation_state->set_animation(animation, loop, track_id); - has_track[track_id] = true; - } + if (empty) { + if (has_track.has(track_id)) + animation_state->add_empty_animation(track_id, empty_animation_duration, delay); + else + animation_state->set_empty_animation(track_id, empty_animation_duration); + has_track[track_id] = true; + } else if (clear) { + animation_state->clear_track(track_id); + } else if (skeleton->get_data()->find_animation(animation).is_valid()) { + if (has_track.has(track_id)) + animation_state->add_animation(animation, delay, loop, track_id); + else + animation_state->set_animation(animation, loop, track_id); + has_track[track_id] = true; + } + } + } - } - } - - if (track_cnt == 0) animation_state->clear_tracks(); - } + if (track_cnt == 0) animation_state->clear_tracks(); + } } - - - diff --git a/spine-godot/spine_godot/SpineSprite.h b/spine-godot/spine_godot/SpineSprite.h index 48c9d9f29..0bf686584 100644 --- a/spine-godot/spine_godot/SpineSprite.h +++ b/spine-godot/spine_godot/SpineSprite.h @@ -41,31 +41,33 @@ #include "PackedSpineSkinResource.h" class SpineSprite : public Node2D, public spine::AnimationStateListenerObject { - GDCLASS(SpineSprite, Node2D); + GDCLASS(SpineSprite, Node2D); + protected: - static void _bind_methods(); + static void _bind_methods(); void _notification(int p_what); - void _get_property_list(List *p_list) const; - bool _get(const StringName &p_property, Variant &r_value) const; - bool _set(const StringName &p_property, const Variant &p_value); + void _get_property_list(List *p_list) const; + bool _get(const StringName &p_property, Variant &r_value) const; + bool _set(const StringName &p_property, const Variant &p_value); + + void _validate_and_play_current_animations(); - void _validate_and_play_current_animations(); public: - enum ProcessMode { - ProcessMode_Process, - ProcessMode_Physics, - ProcessMode_Manual - }; -private: + enum ProcessMode { + ProcessMode_Process, + ProcessMode_Physics, + ProcessMode_Manual + }; - Ref animation_state_data_res; +private: + Ref animation_state_data_res; Ref skeleton; Ref animation_state; - Vector mesh_instances; + Vector mesh_instances; Array current_animations; int select_track_id; @@ -75,7 +77,7 @@ private: bool overlap; Ref skin; - ProcessMode process_mode; + ProcessMode process_mode; spine::SkeletonClipping *skeleton_clipper; @@ -83,8 +85,8 @@ public: SpineSprite(); ~SpineSprite(); - void set_animation_state_data_res(const Ref &a); - Ref get_animation_state_data_res(); + void set_animation_state_data_res(const Ref &a); + Ref get_animation_state_data_res(); Ref get_skeleton(); Ref get_animation_state(); @@ -100,7 +102,7 @@ public: void update_bind_slot_node_draw_order(const String &slot_name, Node2D *node2d); Node *find_child_node_by_node(Node *node); - virtual void callback(spine::AnimationState* state, spine::EventType type, spine::TrackEntry* entry, spine::Event* event); + virtual void callback(spine::AnimationState *state, spine::EventType type, spine::TrackEntry *entry, spine::Event *event); void _on_animation_data_created(); void _on_animation_data_changed(); @@ -150,13 +152,13 @@ public: Ref gen_spine_skin_from_packed_resource(Ref res); - // current animation count - int64_t get_current_animation_count() const; - void set_current_animation_count(int64_t v); + // current animation count + int64_t get_current_animation_count() const; + void set_current_animation_count(int64_t v); ProcessMode get_process_mode(); void set_process_mode(ProcessMode v); }; VARIANT_ENUM_CAST(SpineSprite::ProcessMode); -#endif //GODOT_SPINESPRITE_H +#endif//GODOT_SPINESPRITE_H diff --git a/spine-godot/spine_godot/SpineSpriteAnimateDialog.cpp b/spine-godot/spine_godot/SpineSpriteAnimateDialog.cpp index 2d102a451..33bebdd66 100644 --- a/spine-godot/spine_godot/SpineSpriteAnimateDialog.cpp +++ b/spine-godot/spine_godot/SpineSpriteAnimateDialog.cpp @@ -34,316 +34,317 @@ #include "SpineSprite.h" void SpineSpriteAnimateDialog::_bind_methods() { - ClassDB::bind_method(D_METHOD("_on_animate_button_pressed"), &SpineSpriteAnimateDialog::_on_animate_button_pressed); - ClassDB::bind_method(D_METHOD("_on_scene_tree_selected"), &SpineSpriteAnimateDialog::_on_scene_tree_selected); - ClassDB::bind_method(D_METHOD("_on_scene_tree_hide"), &SpineSpriteAnimateDialog::_on_scene_tree_hide); - ClassDB::bind_method(D_METHOD("_on_animate_dialog_action"), &SpineSpriteAnimateDialog::_on_animate_dialog_action); + ClassDB::bind_method(D_METHOD("_on_animate_button_pressed"), &SpineSpriteAnimateDialog::_on_animate_button_pressed); + ClassDB::bind_method(D_METHOD("_on_scene_tree_selected"), &SpineSpriteAnimateDialog::_on_scene_tree_selected); + ClassDB::bind_method(D_METHOD("_on_scene_tree_hide"), &SpineSpriteAnimateDialog::_on_scene_tree_hide); + ClassDB::bind_method(D_METHOD("_on_animate_dialog_action"), &SpineSpriteAnimateDialog::_on_animate_dialog_action); } SpineSpriteAnimateDialog::SpineSpriteAnimateDialog() { - animate_dialog = memnew(ConfirmationDialog); - add_child(animate_dialog); - animate_dialog->get_ok()->set_text("Generate"); - animate_dialog_override_button = animate_dialog->add_button("Override", false, "override"); - animate_dialog_override_button->set_visible(false); - animate_dialog->set_title("Animations Generator"); - animate_dialog->set_resizable(true); - animate_dialog->set_custom_minimum_size(Vector2(550, 400)); - animate_dialog->set_hide_on_ok(false); - animate_dialog->connect("custom_action", this, "_on_animate_dialog_action"); - Vector al; - al.push_back("confirmed"); - animate_dialog->connect("confirmed", this, "_on_animate_dialog_action", al); + animate_dialog = memnew(ConfirmationDialog); + add_child(animate_dialog); + animate_dialog->get_ok()->set_text("Generate"); + animate_dialog_override_button = animate_dialog->add_button("Override", false, "override"); + animate_dialog_override_button->set_visible(false); + animate_dialog->set_title("Animations Generator"); + animate_dialog->set_resizable(true); + animate_dialog->set_custom_minimum_size(Vector2(550, 400)); + animate_dialog->set_hide_on_ok(false); + animate_dialog->connect("custom_action", this, "_on_animate_dialog_action"); + Vector al; + al.push_back("confirmed"); + animate_dialog->connect("confirmed", this, "_on_animate_dialog_action", al); - auto vb = memnew(VBoxContainer); - animate_dialog->add_child(vb); + auto vb = memnew(VBoxContainer); + animate_dialog->add_child(vb); - auto scroll = memnew(ScrollContainer); - scroll->set_h_size_flags(SIZE_EXPAND_FILL); - scroll->set_v_size_flags(SIZE_EXPAND_FILL); -// vb->add_margin_child("Animations", scroll); - vb->add_child(scroll); + auto scroll = memnew(ScrollContainer); + scroll->set_h_size_flags(SIZE_EXPAND_FILL); + scroll->set_v_size_flags(SIZE_EXPAND_FILL); + // vb->add_margin_child("Animations", scroll); + vb->add_child(scroll); - animate_dialog_tree = memnew(Tree); - animate_dialog_tree->set_h_size_flags(SIZE_EXPAND_FILL); - animate_dialog_tree->set_v_size_flags(SIZE_EXPAND_FILL); - scroll->add_child(animate_dialog_tree); + animate_dialog_tree = memnew(Tree); + animate_dialog_tree->set_h_size_flags(SIZE_EXPAND_FILL); + animate_dialog_tree->set_v_size_flags(SIZE_EXPAND_FILL); + scroll->add_child(animate_dialog_tree); - animate_dialog_tree->set_columns(3); - animate_dialog_tree->set_column_titles_visible(true); - animate_dialog_tree->set_hide_folding(true); - animate_dialog_tree->set_hide_root(true); + animate_dialog_tree->set_columns(3); + animate_dialog_tree->set_column_titles_visible(true); + animate_dialog_tree->set_hide_folding(true); + animate_dialog_tree->set_hide_root(true); - animate_dialog_tree->set_column_title(0, TTR("Animation")); - animate_dialog_tree->set_column_title(1, TTR("Loop")); - animate_dialog_tree->set_column_title(2, TTR("Track ID")); + animate_dialog_tree->set_column_title(0, TTR("Animation")); + animate_dialog_tree->set_column_title(1, TTR("Loop")); + animate_dialog_tree->set_column_title(2, TTR("Track ID")); - animate_dialog_tree->create_item(); - add_row("test1"); - add_row("test12"); - add_row("test13"); + animate_dialog_tree->create_item(); + add_row("test1"); + add_row("test12"); + add_row("test13"); - auto l = memnew(Label); - l->set_text("W.I.P"); - vb->add_child(l); + auto l = memnew(Label); + l->set_text("W.I.P"); + vb->add_child(l); - scene_tree_dialog = memnew(SceneTreeDialog); - scene_tree_dialog->set_title("Choose a AnimationPlayer to override, or choose none to create a new one."); - Vector valid_types; - valid_types.push_back("AnimationPlayer"); - scene_tree_dialog->get_scene_tree()->set_valid_types(valid_types); - scene_tree_dialog->get_scene_tree()->set_show_enabled_subscene(true); - scene_tree_dialog->get_ok()->hide(); - add_child(scene_tree_dialog); - scene_tree_dialog->connect("selected", this, "_on_scene_tree_selected"); - scene_tree_dialog->connect("popup_hide", this, "_on_scene_tree_hide"); + scene_tree_dialog = memnew(SceneTreeDialog); + scene_tree_dialog->set_title("Choose a AnimationPlayer to override, or choose none to create a new one."); + Vector valid_types; + valid_types.push_back("AnimationPlayer"); + scene_tree_dialog->get_scene_tree()->set_valid_types(valid_types); + scene_tree_dialog->get_scene_tree()->set_show_enabled_subscene(true); + scene_tree_dialog->get_ok()->hide(); + add_child(scene_tree_dialog); + scene_tree_dialog->connect("selected", this, "_on_scene_tree_selected"); + scene_tree_dialog->connect("popup_hide", this, "_on_scene_tree_hide"); - error_dialog = memnew(AcceptDialog); - add_child(error_dialog); + error_dialog = memnew(AcceptDialog); + add_child(error_dialog); } SpineSpriteAnimateDialog::~SpineSpriteAnimateDialog() { - } void SpineSpriteAnimateDialog::set_animate_button(ToolButton *b) { - animate_button = b; - animate_button->connect("pressed", this, "_on_animate_button_pressed"); + animate_button = b; + animate_button->connect("pressed", this, "_on_animate_button_pressed"); } void SpineSpriteAnimateDialog::add_row(const String &animation, bool loop, int64_t track_id) { - auto item = animate_dialog_tree->create_item(); - item->set_text(0, animation); + auto item = animate_dialog_tree->create_item(); + item->set_text(0, animation); - item->set_cell_mode(1, TreeItem::CELL_MODE_CHECK); - item->set_checked(1, loop); - item->set_editable(1, true); + item->set_cell_mode(1, TreeItem::CELL_MODE_CHECK); + item->set_checked(1, loop); + item->set_editable(1, true); - item->set_cell_mode(2, TreeItem::CELL_MODE_RANGE); - item->set_range(2, track_id); - item->set_editable(2, true); + item->set_cell_mode(2, TreeItem::CELL_MODE_RANGE); + item->set_range(2, track_id); + item->set_editable(2, true); } void SpineSpriteAnimateDialog::clear_tree() { - animate_dialog_tree->clear(); - animate_dialog_tree->create_item(); + animate_dialog_tree->clear(); + animate_dialog_tree->create_item(); } void SpineSpriteAnimateDialog::error(const String &text, const String &title) { - error_dialog->set_text(text); - error_dialog->set_title(title); - error_dialog->popup_centered(); + error_dialog->set_text(text); + error_dialog->set_title(title); + error_dialog->popup_centered(); } -#define ERROR_MSG(x) do{error(x);err=true;return;}while(false) +#define ERROR_MSG(x) \ + do { \ + error(x); \ + err = true; \ + return; \ + } while (false) void SpineSpriteAnimateDialog::load_data_from_sprite(SpineSprite *sprite, bool &err) { - if (sprite == nullptr) { - ERROR_MSG("The sprite is null."); - } - if (!sprite->get_animation_state().is_valid() || !sprite->get_skeleton().is_valid()) { - ERROR_MSG("The sprite is not loaded."); - } - clear_tree(); + if (sprite == nullptr) { + ERROR_MSG("The sprite is null."); + } + if (!sprite->get_animation_state().is_valid() || !sprite->get_skeleton().is_valid()) { + ERROR_MSG("The sprite is not loaded."); + } + clear_tree(); - Vector animations; - sprite->get_skeleton()->get_data()->get_animation_names(animations); + Vector animations; + sprite->get_skeleton()->get_data()->get_animation_names(animations); - for (size_t i=0; iget_animation_state().is_valid() || !sprite->get_skeleton().is_valid()) { - ERROR_MSG("The sprite is not loaded."); - } - auto p = sprite->get_parent(); - if (p == nullptr) { - p = sprite; - } + if (sprite == nullptr) { + ERROR_MSG("The sprite player is null."); + } + if (!sprite->get_animation_state().is_valid() || !sprite->get_skeleton().is_valid()) { + ERROR_MSG("The sprite is not loaded."); + } + auto p = sprite->get_parent(); + if (p == nullptr) { + p = sprite; + } - auto anim_player = memnew(AnimationPlayer); - anim_player->set_name("AnimationPlayer"); - p->add_child(anim_player); - anim_player->set_owner(sprite->get_owner()); - anim_player->set_root(anim_player->get_path_to(p)); + auto anim_player = memnew(AnimationPlayer); + anim_player->set_name("AnimationPlayer"); + p->add_child(anim_player); + anim_player->set_owner(sprite->get_owner()); + anim_player->set_root(anim_player->get_path_to(p)); - gen_animations(sprite, anim_player, get_data_from_tree(), MIN_TRACK_LENGTH, err); + gen_animations(sprite, anim_player, get_data_from_tree(), MIN_TRACK_LENGTH, err); } Dictionary SpineSpriteAnimateDialog::get_data_from_tree() { - Dictionary res; - if (animate_dialog_tree->get_root() == nullptr) return res; + Dictionary res; + if (animate_dialog_tree->get_root() == nullptr) return res; - auto item = animate_dialog_tree->get_root()->get_children(); - while (item) { - Dictionary row; - row["loop"] = item->is_checked(1); - row["track_id"] = item->get_range(2); + auto item = animate_dialog_tree->get_root()->get_children(); + while (item) { + Dictionary row; + row["loop"] = item->is_checked(1); + row["track_id"] = item->get_range(2); - res[item->get_text(0)] = row; - item = item->get_next(); - } - return res; + res[item->get_text(0)] = row; + item = item->get_next(); + } + return res; } void SpineSpriteAnimateDialog::gen_animations(SpineSprite *sprite, AnimationPlayer *anim_player, const Dictionary &config, float min_duration, bool &err) { - if (sprite == nullptr || anim_player == nullptr) { - ERROR_MSG("The sprite or animation player is null."); - } - if (!sprite->get_animation_state().is_valid() || !sprite->get_skeleton().is_valid()) { - ERROR_MSG("The sprite is not loaded."); - } - if (anim_player->get_node_or_null(anim_player->get_root()) == nullptr) { - ERROR_MSG("The root node of animation player is null."); - } + if (sprite == nullptr || anim_player == nullptr) { + ERROR_MSG("The sprite or animation player is null."); + } + if (!sprite->get_animation_state().is_valid() || !sprite->get_skeleton().is_valid()) { + ERROR_MSG("The sprite is not loaded."); + } + if (anim_player->get_node_or_null(anim_player->get_root()) == nullptr) { + ERROR_MSG("The root node of animation player is null."); + } - auto path_to_sprite = anim_player->get_node(anim_player->get_root())->get_path_to(sprite); + auto path_to_sprite = anim_player->get_node(anim_player->get_root())->get_path_to(sprite); - Array animations = sprite->get_skeleton()->get_data()->get_animations(); - for (size_t i=0; i) animations[i]; + Array animations = sprite->get_skeleton()->get_data()->get_animations(); + for (size_t i = 0; i < animations.size(); ++i) { + auto spine_anim = (Ref) animations[i]; - Dictionary ca; - if (config.has(spine_anim->get_anim_name())) { - ca = config[spine_anim->get_anim_name()]; - } + Dictionary ca; + if (config.has(spine_anim->get_anim_name())) { + ca = config[spine_anim->get_anim_name()]; + } - if (!ca.has("loop")) ca["loop"] = true; - if (!ca.has("track_id")) ca["track_id"] = 0; + if (!ca.has("loop")) ca["loop"] = true; + if (!ca.has("track_id")) ca["track_id"] = 0; - Array key_frame_value; - key_frame_value.push_back(gen_current_animation_data(spine_anim->get_anim_name(), ca["track_id"], ca["loop"], false, false, 0.3, 0)); + Array key_frame_value; + key_frame_value.push_back(gen_current_animation_data(spine_anim->get_anim_name(), ca["track_id"], ca["loop"], false, false, 0.3, 0)); - auto anim = Ref(memnew(Animation)); - auto track_index = anim->add_track(Animation::TYPE_VALUE); - anim->set_length(min_duration > spine_anim->get_duration() ? min_duration : spine_anim->get_duration()); - anim->track_set_path(track_index, NodePath(vformat("%s:current_animations", path_to_sprite))); - anim->track_insert_key(track_index, 0.0, key_frame_value); - anim->value_track_set_update_mode(track_index, Animation::UPDATE_DISCRETE); + auto anim = Ref(memnew(Animation)); + auto track_index = anim->add_track(Animation::TYPE_VALUE); + anim->set_length(min_duration > spine_anim->get_duration() ? min_duration : spine_anim->get_duration()); + anim->track_set_path(track_index, NodePath(vformat("%s:current_animations", path_to_sprite))); + anim->track_insert_key(track_index, 0.0, key_frame_value); + anim->value_track_set_update_mode(track_index, Animation::UPDATE_DISCRETE); - if (anim_player->has_animation(spine_anim->get_anim_name())) - anim_player->remove_animation(spine_anim->get_anim_name()); - anim_player->add_animation(spine_anim->get_anim_name(), anim); - } + if (anim_player->has_animation(spine_anim->get_anim_name())) + anim_player->remove_animation(spine_anim->get_anim_name()); + anim_player->add_animation(spine_anim->get_anim_name(), anim); + } - err = false; + err = false; } Dictionary SpineSpriteAnimateDialog::gen_current_animation_data(const String &animation, int64_t track_id, bool loop, bool clear, bool empty, bool empty_duration, float delay) { - Dictionary res; - res["animation"] = animation; - res["track_id"] = track_id; - res["loop"] = loop; - res["clear"] = clear; - res["empty"] = empty; - res["empty_animation_duration"] = empty_duration; - res["delay"] = delay; - return res; + Dictionary res; + res["animation"] = animation; + res["track_id"] = track_id; + res["loop"] = loop; + res["clear"] = clear; + res["empty"] = empty; + res["empty_animation_duration"] = empty_duration; + res["delay"] = delay; + return res; } void SpineSpriteAnimateDialog::load_data_from_anim_player(AnimationPlayer *anim_player, bool &err) { - if (anim_player == nullptr) { - ERROR_MSG("The animation player is null."); - } - auto root = anim_player->get_node_or_null(anim_player->get_root()); - if (root == nullptr) return; + if (anim_player == nullptr) { + ERROR_MSG("The animation player is null."); + } + auto root = anim_player->get_node_or_null(anim_player->get_root()); + if (root == nullptr) return; - auto sprite = get_node_or_null(spine_sprite_path); - if (sprite == nullptr) return; + auto sprite = get_node_or_null(spine_sprite_path); + if (sprite == nullptr) return; - auto item = animate_dialog_tree->get_root()->get_children(); - while (item) { - String animation = item->get_text(0); + auto item = animate_dialog_tree->get_root()->get_children(); + while (item) { + String animation = item->get_text(0); - auto anim = anim_player->get_animation(animation); - if (anim.is_valid() && anim->get_track_count() > 0) { - if (anim->track_get_type(0) == Animation::TYPE_VALUE) { - auto track_path = anim->track_get_path(0); - if (root->get_node_or_null(track_path) == sprite) { - if (anim->track_get_key_count(0) > 0) { - Array key_frame_value = anim->track_get_key_value(0, 0); - if (!key_frame_value.empty()) { - Dictionary _ca = key_frame_value.front(); - if (_ca.has("loop")) item->set_checked(1, _ca["loop"]); - if (_ca.has("track_id")) item->set_range(2, _ca["track_id"]); - } - } - } - } + auto anim = anim_player->get_animation(animation); + if (anim.is_valid() && anim->get_track_count() > 0) { + if (anim->track_get_type(0) == Animation::TYPE_VALUE) { + auto track_path = anim->track_get_path(0); + if (root->get_node_or_null(track_path) == sprite) { + if (anim->track_get_key_count(0) > 0) { + Array key_frame_value = anim->track_get_key_value(0, 0); + if (!key_frame_value.empty()) { + Dictionary _ca = key_frame_value.front(); + if (_ca.has("loop")) item->set_checked(1, _ca["loop"]); + if (_ca.has("track_id")) item->set_range(2, _ca["track_id"]); + } + } + } + } + } - } + item = item->get_next(); + } - item = item->get_next(); - } - - err = false; + err = false; } //----- Signals ----- void SpineSpriteAnimateDialog::_on_scene_tree_selected(NodePath path) { -// print_line(vformat("anime: %s", path)); - auto node = get_node_or_null(path); - if (node == nullptr) { - error("The node you chose is null."); - return; - } - if (!node->is_class("AnimationPlayer")) { - error("The node you chose is not AnimationPlayer."); - return; - } - anim_player_path = path; + // print_line(vformat("anime: %s", path)); + auto node = get_node_or_null(path); + if (node == nullptr) { + error("The node you chose is null."); + return; + } + if (!node->is_class("AnimationPlayer")) { + error("The node you chose is not AnimationPlayer."); + return; + } + anim_player_path = path; } void SpineSpriteAnimateDialog::_on_animate_button_pressed() { - anim_player_path = String(""); - auto node = (Node*)the_plugin->get_editor_interface()->get_selection()->get_selected_nodes().back(); - spine_sprite_path = node->get_path(); + anim_player_path = String(""); + auto node = (Node *) the_plugin->get_editor_interface()->get_selection()->get_selected_nodes().back(); + spine_sprite_path = node->get_path(); -// print_line(vformat("sp: %s", spine_sprite_path)); + // print_line(vformat("sp: %s", spine_sprite_path)); - animate_dialog_override_button->set_visible(false); - scene_tree_dialog->popup_centered_ratio(); + animate_dialog_override_button->set_visible(false); + scene_tree_dialog->popup_centered_ratio(); } void SpineSpriteAnimateDialog::_on_scene_tree_hide() { - animate_dialog->popup_centered(); + animate_dialog->popup_centered(); - bool err = false; - load_data_from_sprite((SpineSprite*)get_node_or_null(spine_sprite_path), err); - - if (err) animate_dialog->hide(); - - err = false; - auto node = get_node_or_null(anim_player_path); - if (node != nullptr) { - load_data_from_anim_player((AnimationPlayer*)node, err); - animate_dialog_override_button->set_visible(!err); - } else { - animate_dialog_override_button->set_visible(false); - } + bool err = false; + load_data_from_sprite((SpineSprite *) get_node_or_null(spine_sprite_path), err); + if (err) animate_dialog->hide(); + err = false; + auto node = get_node_or_null(anim_player_path); + if (node != nullptr) { + load_data_from_anim_player((AnimationPlayer *) node, err); + animate_dialog_override_button->set_visible(!err); + } else { + animate_dialog_override_button->set_visible(false); + } } void SpineSpriteAnimateDialog::_on_animate_dialog_action(const String &act) { - bool err = false; - if (act == "confirmed") { - gen_new_animation_player((SpineSprite*)get_node_or_null(spine_sprite_path), err); - } else if (act == "override") { - gen_animations((SpineSprite*)get_node_or_null(spine_sprite_path), (AnimationPlayer*)get_node_or_null(anim_player_path), get_data_from_tree(), MIN_TRACK_LENGTH, err); - } - if (!err) { - animate_dialog->hide(); - } + bool err = false; + if (act == "confirmed") { + gen_new_animation_player((SpineSprite *) get_node_or_null(spine_sprite_path), err); + } else if (act == "override") { + gen_animations((SpineSprite *) get_node_or_null(spine_sprite_path), (AnimationPlayer *) get_node_or_null(anim_player_path), get_data_from_tree(), MIN_TRACK_LENGTH, err); + } + if (!err) { + animate_dialog->hide(); + } } diff --git a/spine-godot/spine_godot/SpineSpriteAnimateDialog.h b/spine-godot/spine_godot/SpineSpriteAnimateDialog.h index b4446ec78..04f26d619 100644 --- a/spine-godot/spine_godot/SpineSpriteAnimateDialog.h +++ b/spine-godot/spine_godot/SpineSpriteAnimateDialog.h @@ -36,51 +36,52 @@ class SpineSprite; class SpineSpriteAnimateDialog : public Control { - GDCLASS(SpineSpriteAnimateDialog, Control); + GDCLASS(SpineSpriteAnimateDialog, Control); protected: - static void _bind_methods(); + static void _bind_methods(); - AcceptDialog *error_dialog; + AcceptDialog *error_dialog; - ToolButton *animate_button; - EditorPlugin *the_plugin; + ToolButton *animate_button; + EditorPlugin *the_plugin; - ConfirmationDialog *animate_dialog; - Button *animate_dialog_override_button; - Tree *animate_dialog_tree; - SceneTreeDialog *scene_tree_dialog; + ConfirmationDialog *animate_dialog; + Button *animate_dialog_override_button; + Tree *animate_dialog_tree; + SceneTreeDialog *scene_tree_dialog; - NodePath spine_sprite_path; - NodePath anim_player_path; + NodePath spine_sprite_path; + NodePath anim_player_path; - void add_row(const String &animation, bool loop=true, int64_t track_id=0); - void clear_tree(); + void add_row(const String &animation, bool loop = true, int64_t track_id = 0); + void clear_tree(); - void error(const String &text, const String &title="Error"); + void error(const String &text, const String &title = "Error"); - void load_data_from_sprite(SpineSprite *sprite, bool &err); - void load_data_from_anim_player(AnimationPlayer *anim_player, bool &err); + void load_data_from_sprite(SpineSprite *sprite, bool &err); + void load_data_from_anim_player(AnimationPlayer *anim_player, bool &err); - Dictionary get_data_from_tree(); + Dictionary get_data_from_tree(); + + void gen_new_animation_player(SpineSprite *sprite, bool &err); + void gen_animations(SpineSprite *sprite, AnimationPlayer *anim_player, const Dictionary &config, float min_duration, bool &err); + Dictionary gen_current_animation_data(const String &animation, int64_t track_id, bool loop, bool clear, bool empty, bool empty_duration, float delay); - void gen_new_animation_player(SpineSprite *sprite, bool &err); - void gen_animations(SpineSprite *sprite, AnimationPlayer *anim_player, const Dictionary &config, float min_duration, bool &err); - Dictionary gen_current_animation_data(const String &animation, int64_t track_id, bool loop, bool clear, bool empty, bool empty_duration, float delay); public: - SpineSpriteAnimateDialog(); - ~SpineSpriteAnimateDialog(); + SpineSpriteAnimateDialog(); + ~SpineSpriteAnimateDialog(); - void set_animate_button(ToolButton *b); - inline ToolButton *get_animate_button() {return animate_button;} + void set_animate_button(ToolButton *b); + inline ToolButton *get_animate_button() { return animate_button; } - inline void set_plugin(EditorPlugin *p) {the_plugin = p;} + inline void set_plugin(EditorPlugin *p) { the_plugin = p; } - void _on_animate_button_pressed(); - void _on_scene_tree_selected(NodePath path); - void _on_scene_tree_hide(); - void _on_animate_dialog_action(const String &act); + void _on_animate_button_pressed(); + void _on_scene_tree_selected(NodePath path); + void _on_scene_tree_hide(); + void _on_animate_dialog_action(const String &act); }; #endif -#endif //GODOT_SPINESPRITEANIMATEDIALOG_H +#endif//GODOT_SPINESPRITEANIMATEDIALOG_H diff --git a/spine-godot/spine_godot/SpineSpriteMeshInstance2D.cpp b/spine-godot/spine_godot/SpineSpriteMeshInstance2D.cpp index ca0fc5cb2..aba2064f0 100644 --- a/spine-godot/spine_godot/SpineSpriteMeshInstance2D.cpp +++ b/spine-godot/spine_godot/SpineSpriteMeshInstance2D.cpp @@ -43,6 +43,6 @@ Ref SpineSpriteMeshInstance2D::get_slot() { return slot; } -void SpineSpriteMeshInstance2D::apply_transform_2d(Variant o){ +void SpineSpriteMeshInstance2D::apply_transform_2d(Variant o) { slot->get_bone()->apply_world_transform_2d(o); } \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineSpriteMeshInstance2D.h b/spine-godot/spine_godot/SpineSpriteMeshInstance2D.h index 8458d74b2..c748b21cb 100644 --- a/spine-godot/spine_godot/SpineSpriteMeshInstance2D.h +++ b/spine-godot/spine_godot/SpineSpriteMeshInstance2D.h @@ -41,11 +41,12 @@ protected: static void _bind_methods(); Ref slot; + public: SpineSpriteMeshInstance2D(); ~SpineSpriteMeshInstance2D(); - inline void set_slot(Ref s){ + inline void set_slot(Ref s) { slot = s; } Ref get_slot(); @@ -53,4 +54,4 @@ public: void apply_transform_2d(Variant o); }; -#endif //GODOT_SPINESPRITEMESHINSTANCE2D_H +#endif//GODOT_SPINESPRITEMESHINSTANCE2D_H diff --git a/spine-godot/spine_godot/SpineTimeline.cpp b/spine-godot/spine_godot/SpineTimeline.cpp index d4233f1d4..d2de60065 100644 --- a/spine-godot/spine_godot/SpineTimeline.cpp +++ b/spine-godot/spine_godot/SpineTimeline.cpp @@ -36,68 +36,64 @@ #include "core/method_bind_ext.gen.inc" void SpineTimeline::_bind_methods() { - ClassDB::bind_method(D_METHOD("apply", "skeleton", "lastTime", "time", "pEvents", "alpha", "blend", "direction"), &SpineTimeline::apply); - ClassDB::bind_method(D_METHOD("get_frame_entries"), &SpineTimeline::get_frame_entries); - ClassDB::bind_method(D_METHOD("get_frame_count"), &SpineTimeline::get_frame_count); - ClassDB::bind_method(D_METHOD("get_frames"), &SpineTimeline::get_frames); - ClassDB::bind_method(D_METHOD("get_duration"), &SpineTimeline::get_duration); - ClassDB::bind_method(D_METHOD("getPropertyIds"), &SpineTimeline::getPropertyIds); + ClassDB::bind_method(D_METHOD("apply", "skeleton", "lastTime", "time", "pEvents", "alpha", "blend", "direction"), &SpineTimeline::apply); + ClassDB::bind_method(D_METHOD("get_frame_entries"), &SpineTimeline::get_frame_entries); + ClassDB::bind_method(D_METHOD("get_frame_count"), &SpineTimeline::get_frame_count); + ClassDB::bind_method(D_METHOD("get_frames"), &SpineTimeline::get_frames); + ClassDB::bind_method(D_METHOD("get_duration"), &SpineTimeline::get_duration); + ClassDB::bind_method(D_METHOD("getPropertyIds"), &SpineTimeline::getPropertyIds); } -SpineTimeline::SpineTimeline():timeline(nullptr) { - +SpineTimeline::SpineTimeline() : timeline(nullptr) { } SpineTimeline::~SpineTimeline() { - } void SpineTimeline::apply(Ref skeleton, float lastTime, float time, Array pEvents, float alpha, - SpineConstant::MixBlend blend, SpineConstant::MixDirection direction) { - spine::Vector events; - events.setSize(pEvents.size(), nullptr); - for (size_t i=0; i)pEvents[i])->get_spine_object(); - } + SpineConstant::MixBlend blend, SpineConstant::MixDirection direction) { + spine::Vector events; + events.setSize(pEvents.size(), nullptr); + for (size_t i = 0; i < events.size(); ++i) { + events[i] = ((Ref) pEvents[i])->get_spine_object(); + } - timeline->apply(*(skeleton->get_spine_object()), lastTime, time, &events, alpha, (spine::MixBlend) blend, (spine::MixDirection) direction); + timeline->apply(*(skeleton->get_spine_object()), lastTime, time, &events, alpha, (spine::MixBlend) blend, (spine::MixDirection) direction); } int64_t SpineTimeline::get_frame_entries() { - return timeline->getFrameEntries(); + return timeline->getFrameEntries(); } int64_t SpineTimeline::get_frame_count() { - return timeline->getFrameCount(); + return timeline->getFrameCount(); } Array SpineTimeline::get_frames() { - auto &frames = timeline->getFrames(); - Array res; - res.resize(frames.size()); + auto &frames = timeline->getFrames(); + Array res; + res.resize(frames.size()); - for (size_t i=0; igetDuration(); + return timeline->getDuration(); } Array SpineTimeline::getPropertyIds() { - auto &ids = timeline->getPropertyIds(); - Array res; - res.resize(ids.size()); + auto &ids = timeline->getPropertyIds(); + Array res; + res.resize(ids.size()); - for (size_t i=0; i - void apply(Ref skeleton, float lastTime, float time, Array pEvents, float alpha, SpineConstant::MixBlend blend, SpineConstant::MixDirection direction); + // Vector + void apply(Ref skeleton, float lastTime, float time, Array pEvents, float alpha, SpineConstant::MixBlend blend, SpineConstant::MixDirection direction); - int64_t get_frame_entries(); + int64_t get_frame_entries(); - int64_t get_frame_count(); + int64_t get_frame_count(); - // Vector - Array get_frames(); + // Vector + Array get_frames(); - float get_duration(); + float get_duration(); - // Vector - Array getPropertyIds(); + // Vector + Array getPropertyIds(); }; -#endif //GODOT_SPINETIMELINE_H +#endif//GODOT_SPINETIMELINE_H diff --git a/spine-godot/spine_godot/SpineTrackEntry.cpp b/spine-godot/spine_godot/SpineTrackEntry.cpp index 2906e7a52..fe6979af9 100644 --- a/spine-godot/spine_godot/SpineTrackEntry.cpp +++ b/spine-godot/spine_godot/SpineTrackEntry.cpp @@ -40,8 +40,8 @@ void SpineTrackEntry::_bind_methods() { ClassDB::bind_method(D_METHOD("get_hold_previous"), &SpineTrackEntry::get_hold_previous); ClassDB::bind_method(D_METHOD("set_hold_previous", "v"), &SpineTrackEntry::set_hold_previous); - ClassDB::bind_method(D_METHOD("get_reverse"), &SpineTrackEntry::get_reverse); - ClassDB::bind_method(D_METHOD("set_reverse", "v"), &SpineTrackEntry::set_reverse); + ClassDB::bind_method(D_METHOD("get_reverse"), &SpineTrackEntry::get_reverse); + ClassDB::bind_method(D_METHOD("set_reverse", "v"), &SpineTrackEntry::set_reverse); ClassDB::bind_method(D_METHOD("get_delay"), &SpineTrackEntry::get_delay); ClassDB::bind_method(D_METHOD("set_delay", "v"), &SpineTrackEntry::set_delay); @@ -99,167 +99,167 @@ void SpineTrackEntry::_bind_methods() { BIND_ENUM_CONSTANT(MIXBLEND_ADD); } -SpineTrackEntry::SpineTrackEntry():track_entry(NULL) {} +SpineTrackEntry::SpineTrackEntry() : track_entry(NULL) {} SpineTrackEntry::~SpineTrackEntry() {} -int SpineTrackEntry::get_track_index(){ +int SpineTrackEntry::get_track_index() { return track_entry->getTrackIndex(); } -Ref SpineTrackEntry::get_animation(){ +Ref SpineTrackEntry::get_animation() { Ref gd_anim(memnew(SpineAnimation)); auto anim = track_entry->getAnimation(); - if(anim == NULL) return NULL; + if (anim == NULL) return NULL; gd_anim->set_spine_object(anim); return gd_anim; } -bool SpineTrackEntry::get_loop(){ +bool SpineTrackEntry::get_loop() { return track_entry->getLoop(); } -void SpineTrackEntry::set_loop(bool v){ +void SpineTrackEntry::set_loop(bool v) { track_entry->setLoop(v); } -bool SpineTrackEntry::get_hold_previous(){ +bool SpineTrackEntry::get_hold_previous() { return track_entry->getHoldPrevious(); } -void SpineTrackEntry::set_hold_previous(bool v){ +void SpineTrackEntry::set_hold_previous(bool v) { track_entry->setHoldPrevious(v); } -float SpineTrackEntry::get_delay(){ +float SpineTrackEntry::get_delay() { return track_entry->getDelay(); } -void SpineTrackEntry::set_delay(float v){ +void SpineTrackEntry::set_delay(float v) { track_entry->setDelay(v); } -float SpineTrackEntry::get_track_time(){ +float SpineTrackEntry::get_track_time() { return track_entry->getTrackTime(); } -void SpineTrackEntry::set_track_time(float v){ +void SpineTrackEntry::set_track_time(float v) { track_entry->setTrackTime(v); } -float SpineTrackEntry::get_track_end(){ +float SpineTrackEntry::get_track_end() { return track_entry->getTrackEnd(); } -void SpineTrackEntry::set_track_end(float v){ +void SpineTrackEntry::set_track_end(float v) { track_entry->setTrackEnd(v); } -float SpineTrackEntry::get_animation_start(){ +float SpineTrackEntry::get_animation_start() { return track_entry->getAnimationStart(); } -void SpineTrackEntry::set_animation_start(float v){ +void SpineTrackEntry::set_animation_start(float v) { track_entry->setAnimationStart(v); } -float SpineTrackEntry::get_animation_last(){ +float SpineTrackEntry::get_animation_last() { return track_entry->getAnimationLast(); } -void SpineTrackEntry::set_animation_last(float v){ +void SpineTrackEntry::set_animation_last(float v) { track_entry->setAnimationLast(v); } -float SpineTrackEntry::get_animation_time(){ +float SpineTrackEntry::get_animation_time() { return track_entry->getAnimationTime(); } -float SpineTrackEntry::get_time_scale(){ +float SpineTrackEntry::get_time_scale() { return track_entry->getTimeScale(); } -void SpineTrackEntry::set_time_scale(float v){ +void SpineTrackEntry::set_time_scale(float v) { track_entry->setTimeScale(v); } -float SpineTrackEntry::get_alpha(){ +float SpineTrackEntry::get_alpha() { return track_entry->getAlpha(); } -void SpineTrackEntry::set_alpha(float v){ +void SpineTrackEntry::set_alpha(float v) { track_entry->setAlpha(v); } -float SpineTrackEntry::get_event_threshold(){ +float SpineTrackEntry::get_event_threshold() { return track_entry->getEventThreshold(); } -void SpineTrackEntry::set_event_threshold(float v){ +void SpineTrackEntry::set_event_threshold(float v) { track_entry->setEventThreshold(v); } -float SpineTrackEntry::get_attachment_threshold(){ +float SpineTrackEntry::get_attachment_threshold() { return track_entry->getAttachmentThreshold(); } -void SpineTrackEntry::set_attachment_threshold(float v){ +void SpineTrackEntry::set_attachment_threshold(float v) { track_entry->setAttachmentThreshold(v); } -float SpineTrackEntry::get_draw_order_threshold(){ +float SpineTrackEntry::get_draw_order_threshold() { return track_entry->getDrawOrderThreshold(); } -void SpineTrackEntry::set_draw_order_threshold(float v){ +void SpineTrackEntry::set_draw_order_threshold(float v) { track_entry->setDrawOrderThreshold(v); } -Ref SpineTrackEntry::get_next(){ +Ref SpineTrackEntry::get_next() { Ref gd_entry(memnew(SpineTrackEntry)); auto entry = track_entry->getNext(); - if(entry == NULL) return NULL; + if (entry == NULL) return NULL; gd_entry->set_spine_object(entry); return gd_entry; } -bool SpineTrackEntry::is_complete(){ +bool SpineTrackEntry::is_complete() { return track_entry->isComplete(); } -float SpineTrackEntry::get_mix_time(){ +float SpineTrackEntry::get_mix_time() { return track_entry->getMixTime(); } -void SpineTrackEntry::set_mix_time(float v){ +void SpineTrackEntry::set_mix_time(float v) { track_entry->setMixTime(v); } -float SpineTrackEntry::get_mix_duration(){ +float SpineTrackEntry::get_mix_duration() { return track_entry->getMixDuration(); } -void SpineTrackEntry::set_mix_duration(float v){ +void SpineTrackEntry::set_mix_duration(float v) { track_entry->setMixDuration(v); } -SpineTrackEntry::MixBlend SpineTrackEntry::get_mix_blend(){ +SpineTrackEntry::MixBlend SpineTrackEntry::get_mix_blend() { int mb = track_entry->getMixBlend(); return (MixBlend) mb; } -void SpineTrackEntry::set_mix_blend(SpineTrackEntry::MixBlend v){ +void SpineTrackEntry::set_mix_blend(SpineTrackEntry::MixBlend v) { int mb = (int) v; - track_entry->setMixBlend((spine::MixBlend)mb); + track_entry->setMixBlend((spine::MixBlend) mb); } -Ref SpineTrackEntry::get_mixing_from(){ +Ref SpineTrackEntry::get_mixing_from() { Ref gd_entry(memnew(SpineTrackEntry)); auto entry = track_entry->getMixingFrom(); - if(entry == NULL) return NULL; + if (entry == NULL) return NULL; gd_entry->set_spine_object(entry); return gd_entry; } -Ref SpineTrackEntry::get_mixing_to(){ +Ref SpineTrackEntry::get_mixing_to() { Ref gd_entry(memnew(SpineTrackEntry)); auto entry = track_entry->getMixingTo(); - if(entry == NULL) return NULL; + if (entry == NULL) return NULL; gd_entry->set_spine_object(entry); return gd_entry; } -void SpineTrackEntry::reset_rotation_directions(){ +void SpineTrackEntry::reset_rotation_directions() { track_entry->resetRotationDirections(); } bool SpineTrackEntry::get_reverse() { - return track_entry->getReverse(); + return track_entry->getReverse(); } void SpineTrackEntry::set_reverse(bool v) { - track_entry->setReverse(v); + track_entry->setReverse(v); } diff --git a/spine-godot/spine_godot/SpineTrackEntry.h b/spine-godot/spine_godot/SpineTrackEntry.h index aad56ec4a..25c4b785f 100644 --- a/spine-godot/spine_godot/SpineTrackEntry.h +++ b/spine-godot/spine_godot/SpineTrackEntry.h @@ -36,7 +36,7 @@ #include "SpineAnimation.h" -class SpineTrackEntry : public Reference{ +class SpineTrackEntry : public Reference { GDCLASS(SpineTrackEntry, Reference); protected: @@ -49,10 +49,10 @@ public: SpineTrackEntry(); ~SpineTrackEntry(); - inline void set_spine_object(spine::TrackEntry *t){ + inline void set_spine_object(spine::TrackEntry *t) { track_entry = t; } - inline spine::TrackEntry *get_spine_object(){ + inline spine::TrackEntry *get_spine_object() { return track_entry; } @@ -73,8 +73,8 @@ public: bool get_hold_previous(); void set_hold_previous(bool v); - bool get_reverse(); - void set_reverse(bool v); + bool get_reverse(); + void set_reverse(bool v); float get_delay(); void set_delay(float v); @@ -128,4 +128,4 @@ public: }; VARIANT_ENUM_CAST(SpineTrackEntry::MixBlend); -#endif //GODOT_SPINETRACKENTRY_H +#endif//GODOT_SPINETRACKENTRY_H diff --git a/spine-godot/spine_godot/SpineTransformConstraint.cpp b/spine-godot/spine_godot/SpineTransformConstraint.cpp index 15450361e..2166a5917 100644 --- a/spine-godot/spine_godot/SpineTransformConstraint.cpp +++ b/spine-godot/spine_godot/SpineTransformConstraint.cpp @@ -51,31 +51,31 @@ void SpineTransformConstraint::_bind_methods() { ClassDB::bind_method(D_METHOD("set_active", "v"), &SpineTransformConstraint::set_active); } -SpineTransformConstraint::SpineTransformConstraint():transform_constraint(NULL) {} +SpineTransformConstraint::SpineTransformConstraint() : transform_constraint(NULL) {} SpineTransformConstraint::~SpineTransformConstraint() {} -void SpineTransformConstraint::update(){ +void SpineTransformConstraint::update() { transform_constraint->update(); } -int SpineTransformConstraint::get_order(){ +int SpineTransformConstraint::get_order() { return transform_constraint->getOrder(); } -Ref SpineTransformConstraint::get_data(){ +Ref SpineTransformConstraint::get_data() { auto &d = transform_constraint->getData(); Ref gd_d(memnew(SpineTransformConstraintData)); gd_d->set_spine_object(&d); return gd_d; } -Array SpineTransformConstraint::get_bones(){ +Array SpineTransformConstraint::get_bones() { auto &bs = transform_constraint->getBones(); Array gd_bs; gd_bs.resize(bs.size()); - for(size_t i=0; i(NULL); + if (b == NULL) gd_bs[i] = Ref(NULL); Ref gd_b(memnew(SpineBone)); gd_b->set_spine_object(b); gd_bs[i] = gd_b; @@ -83,66 +83,66 @@ Array SpineTransformConstraint::get_bones(){ return gd_bs; } -Ref SpineTransformConstraint::get_target(){ +Ref SpineTransformConstraint::get_target() { auto b = transform_constraint->getTarget(); - if(b == NULL) return NULL; + if (b == NULL) return NULL; Ref gd_b(memnew(SpineBone)); gd_b->set_spine_object(b); return gd_b; } -void SpineTransformConstraint::set_target(Ref v){ - if(v.is_valid()){ +void SpineTransformConstraint::set_target(Ref v) { + if (v.is_valid()) { transform_constraint->setTarget(v->get_spine_object()); - } else{ + } else { transform_constraint->setTarget(NULL); } } -float SpineTransformConstraint::get_mix_rotate(){ +float SpineTransformConstraint::get_mix_rotate() { return transform_constraint->getMixRotate(); } -void SpineTransformConstraint::set_mix_rotate(float v){ +void SpineTransformConstraint::set_mix_rotate(float v) { transform_constraint->setMixRotate(v); } -float SpineTransformConstraint::get_mix_x(){ +float SpineTransformConstraint::get_mix_x() { return transform_constraint->getMixX(); } -void SpineTransformConstraint::set_mix_x(float v){ +void SpineTransformConstraint::set_mix_x(float v) { transform_constraint->setMixX(v); } -float SpineTransformConstraint::get_mix_y(){ +float SpineTransformConstraint::get_mix_y() { return transform_constraint->getMixY(); } -void SpineTransformConstraint::set_mix_y(float v){ +void SpineTransformConstraint::set_mix_y(float v) { transform_constraint->setMixY(v); } -float SpineTransformConstraint::get_mix_scale_x(){ +float SpineTransformConstraint::get_mix_scale_x() { return transform_constraint->getMixScaleX(); } -void SpineTransformConstraint::set_mix_scale_x(float v){ +void SpineTransformConstraint::set_mix_scale_x(float v) { transform_constraint->setMixScaleX(v); } -float SpineTransformConstraint::get_mix_scale_y(){ +float SpineTransformConstraint::get_mix_scale_y() { return transform_constraint->getMixScaleY(); } -void SpineTransformConstraint::set_mix_scale_y(float v){ +void SpineTransformConstraint::set_mix_scale_y(float v) { transform_constraint->setMixScaleY(v); } -float SpineTransformConstraint::get_mix_shear_y(){ +float SpineTransformConstraint::get_mix_shear_y() { return transform_constraint->getMixShearY(); } -void SpineTransformConstraint::set_mix_shear_y(float v){ +void SpineTransformConstraint::set_mix_shear_y(float v) { transform_constraint->setMixShearY(v); } -bool SpineTransformConstraint::is_active(){ +bool SpineTransformConstraint::is_active() { return transform_constraint->isActive(); } -void SpineTransformConstraint::set_active(bool v){ +void SpineTransformConstraint::set_active(bool v) { transform_constraint->setActive(v); } \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineTransformConstraint.h b/spine-godot/spine_godot/SpineTransformConstraint.h index a2b3a2be3..6430f05fb 100644 --- a/spine-godot/spine_godot/SpineTransformConstraint.h +++ b/spine-godot/spine_godot/SpineTransformConstraint.h @@ -37,7 +37,7 @@ #include "SpineTransformConstraintData.h" #include "SpineBone.h" -class SpineTransformConstraint : public Reference{ +class SpineTransformConstraint : public Reference { GDCLASS(SpineTransformConstraint, Reference); protected: @@ -50,10 +50,10 @@ public: SpineTransformConstraint(); ~SpineTransformConstraint(); - inline void set_spine_object(spine::TransformConstraint *tc){ + inline void set_spine_object(spine::TransformConstraint *tc) { transform_constraint = tc; } - inline spine::TransformConstraint *get_spine_object(){ + inline spine::TransformConstraint *get_spine_object() { return transform_constraint; } @@ -90,4 +90,4 @@ public: void set_active(bool v); }; -#endif //GODOT_SPINETRANSFORMCONSTRAINT_H +#endif//GODOT_SPINETRANSFORMCONSTRAINT_H diff --git a/spine-godot/spine_godot/SpineTransformConstraintData.cpp b/spine-godot/spine_godot/SpineTransformConstraintData.cpp index af62fea32..c7534cafb 100644 --- a/spine-godot/spine_godot/SpineTransformConstraintData.cpp +++ b/spine-godot/spine_godot/SpineTransformConstraintData.cpp @@ -51,12 +51,12 @@ void SpineTransformConstraintData::_bind_methods() { SpineTransformConstraintData::SpineTransformConstraintData() {} SpineTransformConstraintData::~SpineTransformConstraintData() {} -Array SpineTransformConstraintData::get_bones(){ +Array SpineTransformConstraintData::get_bones() { auto bs = get_spine_data()->getBones(); Array gd_bs; gd_bs.resize(bs.size()); - for(size_t i=0; i < bs.size(); ++i){ - if(bs[i] == NULL) gd_bs[i] = Ref(NULL); + for (size_t i = 0; i < bs.size(); ++i) { + if (bs[i] == NULL) gd_bs[i] = Ref(NULL); else { Ref gd_b(memnew(SpineBoneData)); gd_b->set_spine_object(bs[i]); @@ -65,54 +65,54 @@ Array SpineTransformConstraintData::get_bones(){ } return gd_bs; } -Ref SpineTransformConstraintData::get_target(){ +Ref SpineTransformConstraintData::get_target() { auto b = get_spine_data()->getTarget(); - if(b == NULL) return NULL; + if (b == NULL) return NULL; Ref gd_b(memnew(SpineBoneData)); gd_b->set_spine_object(b); return gd_b; } -float SpineTransformConstraintData::get_mix_rotate(){ +float SpineTransformConstraintData::get_mix_rotate() { return get_spine_data()->getMixRotate(); } -float SpineTransformConstraintData::get_mix_x(){ +float SpineTransformConstraintData::get_mix_x() { return get_spine_data()->getMixX(); } -float SpineTransformConstraintData::get_mix_y(){ +float SpineTransformConstraintData::get_mix_y() { return get_spine_data()->getMixY(); } -float SpineTransformConstraintData::get_mix_scale_x(){ +float SpineTransformConstraintData::get_mix_scale_x() { return get_spine_data()->getMixScaleX(); } -float SpineTransformConstraintData::get_mix_scale_y(){ +float SpineTransformConstraintData::get_mix_scale_y() { return get_spine_data()->getMixScaleY(); } -float SpineTransformConstraintData::get_mix_shear_y(){ +float SpineTransformConstraintData::get_mix_shear_y() { return get_spine_data()->getMixShearY(); } -float SpineTransformConstraintData::get_offset_rotation(){ +float SpineTransformConstraintData::get_offset_rotation() { return get_spine_data()->getOffsetRotation(); } -float SpineTransformConstraintData::get_offset_x(){ +float SpineTransformConstraintData::get_offset_x() { return get_spine_data()->getOffsetX(); } -float SpineTransformConstraintData::get_offset_y(){ +float SpineTransformConstraintData::get_offset_y() { return get_spine_data()->getOffsetY(); } -float SpineTransformConstraintData::get_offset_scale_x(){ +float SpineTransformConstraintData::get_offset_scale_x() { return get_spine_data()->getOffsetScaleX(); } -float SpineTransformConstraintData::get_offset_scale_y(){ +float SpineTransformConstraintData::get_offset_scale_y() { return get_spine_data()->getOffsetScaleY(); } -float SpineTransformConstraintData::get_offset_shear_y(){ +float SpineTransformConstraintData::get_offset_shear_y() { return get_spine_data()->getOffsetShearY(); } -bool SpineTransformConstraintData::is_relative(){ +bool SpineTransformConstraintData::is_relative() { return get_spine_data()->isRelative(); } -bool SpineTransformConstraintData::is_local(){ +bool SpineTransformConstraintData::is_local() { return get_spine_data()->isLocal(); } \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineTransformConstraintData.h b/spine-godot/spine_godot/SpineTransformConstraintData.h index 5408d0e5b..6c1b21569 100644 --- a/spine-godot/spine_godot/SpineTransformConstraintData.h +++ b/spine-godot/spine_godot/SpineTransformConstraintData.h @@ -47,8 +47,8 @@ public: SpineTransformConstraintData(); ~SpineTransformConstraintData(); - virtual inline spine::TransformConstraintData *get_spine_data(){ - return (spine::TransformConstraintData*) SpineConstraintData::get_spine_object(); + virtual inline spine::TransformConstraintData *get_spine_data() { + return (spine::TransformConstraintData *) SpineConstraintData::get_spine_object(); } Array get_bones(); @@ -71,4 +71,4 @@ public: bool is_local(); }; -#endif //GODOT_SPINETRANSFORMCONSTRAINTDATA_H +#endif//GODOT_SPINETRANSFORMCONSTRAINTDATA_H diff --git a/spine-godot/spine_godot/register_types.cpp b/spine-godot/spine_godot/register_types.cpp index a6039a240..5aa2f7de7 100644 --- a/spine-godot/spine_godot/register_types.cpp +++ b/spine-godot/spine_godot/register_types.cpp @@ -74,22 +74,22 @@ static Ref json_skeleton_saver; #include "SpineRuntimeEditorPlugin.h" static void editor_init_callback() { - EditorNode::get_singleton()->add_editor_plugin(memnew(SpineRuntimeEditorPlugin(EditorNode::get_singleton()))); + EditorNode::get_singleton()->add_editor_plugin(memnew(SpineRuntimeEditorPlugin(EditorNode::get_singleton()))); } #endif -void register_spine_godot_types(){ +void register_spine_godot_types() { #ifdef TOOLS_ENABLED - ClassDB::register_class(); + ClassDB::register_class(); EditorNode::add_init_callback(editor_init_callback); #endif - - ClassDB::register_class(); - ClassDB::register_class(); + + ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); @@ -120,26 +120,25 @@ void register_spine_godot_types(){ ClassDB::register_class(); ClassDB::register_class(); - atlas_loader.instance(); - ResourceLoader::add_resource_format_loader(atlas_loader); + atlas_loader.instance(); + ResourceLoader::add_resource_format_loader(atlas_loader); - atlas_saver.instance(); - ResourceSaver::add_resource_format_saver(atlas_saver); + atlas_saver.instance(); + ResourceSaver::add_resource_format_saver(atlas_saver); json_skeleton_loader.instance(); ResourceLoader::add_resource_format_loader(json_skeleton_loader); json_skeleton_saver.instance(); ResourceSaver::add_resource_format_saver(json_skeleton_saver); - } -void unregister_spine_godot_types(){ - ResourceLoader::remove_resource_format_loader(atlas_loader); - atlas_loader.unref(); +void unregister_spine_godot_types() { + ResourceLoader::remove_resource_format_loader(atlas_loader); + atlas_loader.unref(); - ResourceSaver::remove_resource_format_saver(atlas_saver); - atlas_saver.unref(); + ResourceSaver::remove_resource_format_saver(atlas_saver); + atlas_saver.unref(); ResourceLoader::remove_resource_format_loader(json_skeleton_loader); json_skeleton_loader.unref(); diff --git a/spine-godot/spine_godot/register_types.h b/spine-godot/spine_godot/register_types.h index 694761811..59ef9515f 100644 --- a/spine-godot/spine_godot/register_types.h +++ b/spine-godot/spine_godot/register_types.h @@ -29,4 +29,3 @@ void register_spine_godot_types(); void unregister_spine_godot_types(); - diff --git a/spine-ts/spine-core/src/AnimationState.ts b/spine-ts/spine-core/src/AnimationState.ts index fd0691bf1..4dac3da2d 100644 --- a/spine-ts/spine-core/src/AnimationState.ts +++ b/spine-ts/spine-core/src/AnimationState.ts @@ -1095,24 +1095,24 @@ export enum EventType { * {@link AnimationState#addListener()}. */ export interface AnimationStateListener { /** Invoked when this entry has been set as the current entry. */ - start? (entry: TrackEntry): void; + start?(entry: TrackEntry): void; /** Invoked when another entry has replaced this entry as the current entry. This entry may continue being applied for * mixing. */ - interrupt? (entry: TrackEntry): void; + interrupt?(entry: TrackEntry): void; /** Invoked when this entry is no longer the current entry and will never be applied again. */ - end? (entry: TrackEntry): void; + end?(entry: TrackEntry): void; /** Invoked when this entry will be disposed. This may occur without the entry ever being set as the current entry. * References to the entry should not be kept after dispose is called, as it may be destroyed or reused. */ - dispose? (entry: TrackEntry): void; + dispose?(entry: TrackEntry): void; /** Invoked every time this entry's animation completes a loop. */ - complete? (entry: TrackEntry): void; + complete?(entry: TrackEntry): void; /** Invoked when this entry's animation triggers an event. */ - event? (entry: TrackEntry, event: Event): void; + event?(entry: TrackEntry, event: Event): void; } export abstract class AnimationStateAdapter implements AnimationStateListener { From 48bdebcab4ba820c604242ce9f156f0a0d1af9ec Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Fri, 1 Oct 2021 13:03:37 +0200 Subject: [PATCH 04/18] Clean-up --- spine-godot/example/spineboy-pro.spjson | 8699 ----------------- spine-godot/example/spineboy.atlas.import | 14 - spine-godot/example/spineboy.gd | 17 - spine-godot/example/spineboy.tres | 10 - .../example/{ => spineboy}/spineboy.atlas | 0 .../example/spineboy/spineboy.atlas.import | 14 + .../example/{ => spineboy}/spineboy.png | Bin .../{ => spineboy}/spineboy.png.import | 6 +- spine-godot/example/spineboyanimdata.tres | 7 - spine-godot/example/test.tscn | 11 +- .../spine_godot/SpineAtlasResource.cpp | 110 +- spine-godot/spine_godot/SpineAtlasResource.h | 6 +- spine-godot/spine_godot/SpineRendererObject.h | 5 +- .../spine_godot/SpineSkeletonDataResource.cpp | 1 - spine-godot/spine_godot/SpineSprite.cpp | 8 +- 15 files changed, 68 insertions(+), 8840 deletions(-) delete mode 100644 spine-godot/example/spineboy-pro.spjson delete mode 100644 spine-godot/example/spineboy.atlas.import delete mode 100644 spine-godot/example/spineboy.gd delete mode 100644 spine-godot/example/spineboy.tres rename spine-godot/example/{ => spineboy}/spineboy.atlas (100%) create mode 100644 spine-godot/example/spineboy/spineboy.atlas.import rename spine-godot/example/{ => spineboy}/spineboy.png (100%) rename spine-godot/example/{ => spineboy}/spineboy.png.import (70%) delete mode 100644 spine-godot/example/spineboyanimdata.tres diff --git a/spine-godot/example/spineboy-pro.spjson b/spine-godot/example/spineboy-pro.spjson deleted file mode 100644 index 4d8c7c2cf..000000000 --- a/spine-godot/example/spineboy-pro.spjson +++ /dev/null @@ -1,8699 +0,0 @@ -{ -"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/spine-godot/example/spineboy.atlas.import b/spine-godot/example/spineboy.atlas.import deleted file mode 100644 index f8d1dfe86..000000000 --- a/spine-godot/example/spineboy.atlas.import +++ /dev/null @@ -1,14 +0,0 @@ -[remap] - -importer="spine.atlas" -type="SpineAtlasResource" -path="res://.import/spineboy.atlas-ce2b95e2abaaca5faa7726fe317501ea.spatlas" - -[deps] - -source_file="res://spineboy.atlas" -dest_files=[ "res://.import/spineboy.atlas-ce2b95e2abaaca5faa7726fe317501ea.spatlas" ] - -[params] - -normal_texture_prefix="" diff --git a/spine-godot/example/spineboy.gd b/spine-godot/example/spineboy.gd deleted file mode 100644 index b2047dc82..000000000 --- a/spine-godot/example/spineboy.gd +++ /dev/null @@ -1,17 +0,0 @@ -extends SpineSprite - - -# Declare member variables here. Examples: -# var a = 2 -# var b = "text" - - -# Called when the node enters the scene tree for the first time. -func _ready(): - self.get_animation_state().set_animation("walk", true, 0) - pass # Replace with function body. - - -# Called every frame. 'delta' is the elapsed time since the previous frame. -#func _process(delta): -# pass diff --git a/spine-godot/example/spineboy.tres b/spine-godot/example/spineboy.tres deleted file mode 100644 index 165089c92..000000000 --- a/spine-godot/example/spineboy.tres +++ /dev/null @@ -1,10 +0,0 @@ -[gd_resource type="SpineSkeletonDataResource" load_steps=3 format=2] - -[ext_resource path="res://spineboy.atlas" type="SpineAtlasResource" id=1] -[ext_resource path="res://spineboy-pro.spjson" type="SpineSkeletonJsonDataResource" id=2] - -[resource] -atlas_res = ExtResource( 1 ) -skeleton_json_res = ExtResource( 2 ) -animations = null -skins = null diff --git a/spine-godot/example/spineboy.atlas b/spine-godot/example/spineboy/spineboy.atlas similarity index 100% rename from spine-godot/example/spineboy.atlas rename to spine-godot/example/spineboy/spineboy.atlas diff --git a/spine-godot/example/spineboy/spineboy.atlas.import b/spine-godot/example/spineboy/spineboy.atlas.import new file mode 100644 index 000000000..05918eceb --- /dev/null +++ b/spine-godot/example/spineboy/spineboy.atlas.import @@ -0,0 +1,14 @@ +[remap] + +importer="spine.atlas" +type="SpineAtlasResource" +path="res://.import/spineboy.atlas-0160ebf51649da264b83de15c13561f4.spatlas" + +[deps] + +source_file="res://spineboy/spineboy.atlas" +dest_files=[ "res://.import/spineboy.atlas-0160ebf51649da264b83de15c13561f4.spatlas" ] + +[params] + +normal_texture_prefix="n" diff --git a/spine-godot/example/spineboy.png b/spine-godot/example/spineboy/spineboy.png similarity index 100% rename from spine-godot/example/spineboy.png rename to spine-godot/example/spineboy/spineboy.png diff --git a/spine-godot/example/spineboy.png.import b/spine-godot/example/spineboy/spineboy.png.import similarity index 70% rename from spine-godot/example/spineboy.png.import rename to spine-godot/example/spineboy/spineboy.png.import index 022cf7873..2d273f490 100644 --- a/spine-godot/example/spineboy.png.import +++ b/spine-godot/example/spineboy/spineboy.png.import @@ -2,15 +2,15 @@ importer="texture" type="StreamTexture" -path="res://.import/spineboy.png-846f399ad53ae6f7ed8bbfe03f0b1f88.stex" +path="res://.import/spineboy.png-a63588ec3a5ca6e83ef256edf38d798a.stex" metadata={ "vram_texture": false } [deps] -source_file="res://spineboy.png" -dest_files=[ "res://.import/spineboy.png-846f399ad53ae6f7ed8bbfe03f0b1f88.stex" ] +source_file="res://spineboy/spineboy.png" +dest_files=[ "res://.import/spineboy.png-a63588ec3a5ca6e83ef256edf38d798a.stex" ] [params] diff --git a/spine-godot/example/spineboyanimdata.tres b/spine-godot/example/spineboyanimdata.tres deleted file mode 100644 index f52707c8a..000000000 --- a/spine-godot/example/spineboyanimdata.tres +++ /dev/null @@ -1,7 +0,0 @@ -[gd_resource type="SpineAnimationStateDataResource" load_steps=2 format=2] - -[ext_resource path="res://spineboy.tres" type="SpineSkeletonDataResource" id=1] - -[resource] -skeleton = ExtResource( 1 ) -default_mix = 1.0 diff --git a/spine-godot/example/test.tscn b/spine-godot/example/test.tscn index ae2e48e5b..3e66a33bf 100644 --- a/spine-godot/example/test.tscn +++ b/spine-godot/example/test.tscn @@ -1,13 +1,4 @@ -[gd_scene load_steps=3 format=2] - -[ext_resource path="res://spineboy.gd" type="Script" id=1] -[ext_resource path="res://spineboyanimdata.tres" type="SpineAnimationStateDataResource" id=2] +[gd_scene format=2] [node name="Node2D" type="Node2D"] position = Vector2( 2.12469, 1.06235 ) - -[node name="SpineSprite" type="SpineSprite" parent="."] -position = Vector2( 503.556, 465.311 ) -scale = Vector2( 0.5, 0.5 ) -animation_state_data_res = ExtResource( 2 ) -script = ExtResource( 1 ) diff --git a/spine-godot/spine_godot/SpineAtlasResource.cpp b/spine-godot/spine_godot/SpineAtlasResource.cpp index 91eb5828f..e8e0d3bc0 100644 --- a/spine-godot/spine_godot/SpineAtlasResource.cpp +++ b/spine-godot/spine_godot/SpineAtlasResource.cpp @@ -35,15 +35,15 @@ class GodotSpineTextureLoader : public spine::TextureLoader { private: Array *textures, *normal_maps; - String normal_maps_prefix; + String normal_map_prefix; public: - GodotSpineTextureLoader(Array *t, Array *nt, const String &p) : textures(t), normal_maps(nt), normal_maps_prefix(p) { + GodotSpineTextureLoader(Array *t, Array *nt, const String &p) : textures(t), normal_maps(nt), normal_map_prefix(p) { if (textures) textures->clear(); if (normal_maps) normal_maps->clear(); } - String fixPathIssue(const String &path) { + String fix_path(const String &path) { if (path.size() > 5 && path[4] == '/' && path[5] == '/') return path; const String prefix = "res:/"; auto i = path.find(prefix); @@ -63,52 +63,40 @@ public: virtual void load(spine::AtlasPage &page, const spine::String &path) { Error err = OK; + auto fixed_path = fix_path(String(path.buffer())); - // print_line(String("Spine is loading texture: ") + String(path.buffer())); - auto fixed_path = fixPathIssue(String(path.buffer())); - // print_line("Fixed path: " + fixed_path); - - // Load texture (e.g. tex.png) - Ref tex = ResourceLoader::load(fixed_path, "", false, &err); + Ref texture = ResourceLoader::load(fixed_path, "", false, &err); if (err != OK) { print_error(vformat("Can't load texture: \"%s\"", String(path.buffer()))); page.setRendererObject((void *) memnew(SpineRendererObject{nullptr})); return; } - if (textures) textures->append(tex); - auto p_spine_renderer_object = memnew(SpineRendererObject); - p_spine_renderer_object->tex = tex; + if (textures) textures->append(texture); + auto spine_renderer_object = memnew(SpineRendererObject); + spine_renderer_object->texture = texture; - // Load normal texture (e.g. n_tex.png) - String temppath = fixed_path; - String newpath = vformat("%s/%s_%s", temppath.get_base_dir(), normal_maps_prefix, temppath.get_file()); - // print_line(vformat("try n tex: %s", newpath)); - if (ResourceLoader::exists(newpath)) { - Ref normal_tex = ResourceLoader::load(newpath); - if (normal_maps) normal_maps->append(normal_tex); - p_spine_renderer_object->normal_tex = normal_tex; - - // print_line(String("From atlas resource load: ") + String(" ro ") + String(Variant((long long) p_spine_renderer_object))); - // print_line(String("From atlas resource load: ") + String(Variant(p_spine_renderer_object->tex)) + String(", ") + String(Variant(p_spine_renderer_object->normal_tex))); + String temp_path = fixed_path; + String new_path = vformat("%s/%s_%s", temp_path.get_base_dir(), normal_map_prefix, temp_path.get_file()); + if (ResourceLoader::exists(new_path)) { + Ref normal_map = ResourceLoader::load(new_path); + if (normal_maps) normal_maps->append(normal_map); + spine_renderer_object->normal_map = normal_map; } - page.setRendererObject((void *) p_spine_renderer_object); + page.setRendererObject((void *) spine_renderer_object); - page.width = tex->get_width(); - page.height = tex->get_height(); + page.width = texture->get_width(); + page.height = texture->get_height(); } virtual void unload(void *p) { - // print_line("I'm out."); - auto p_spine_renderer_object = (SpineRendererObject *) p; - Ref &tex = p_spine_renderer_object->tex; - Ref &normal_tex = p_spine_renderer_object->normal_tex; - - if (tex.is_valid()) tex.unref(); - if (normal_tex.is_valid()) normal_tex.unref(); - - memdelete(p_spine_renderer_object); + auto spine_renderer_object = (SpineRendererObject *) p; + Ref &texture = spine_renderer_object->texture; + if (texture.is_valid()) texture.unref(); + Ref &normal_map = spine_renderer_object->normal_map; + if (normal_map.is_valid()) normal_map.unref(); + memdelete(spine_renderer_object); } }; @@ -123,20 +111,20 @@ void SpineAtlasResource::_bind_methods() { ClassDB::bind_method(D_METHOD("get_source_path"), &SpineAtlasResource::get_source_path); ClassDB::bind_method(D_METHOD("get_textures"), &SpineAtlasResource::get_textures); - ClassDB::bind_method(D_METHOD("get_normal_textures"), &SpineAtlasResource::get_normal_textures); + ClassDB::bind_method(D_METHOD("get_normal_maps"), &SpineAtlasResource::get_normal_maps); ADD_PROPERTY(PropertyInfo(Variant::STRING, "source_path"), "", "get_source_path"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "textures"), "", "get_textures"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "normal_textures"), "", "get_normal_textures"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "normal_maps"), "", "get_normal_maps"); } Array SpineAtlasResource::get_textures() { - return tex_list; + return textures; } -Array SpineAtlasResource::get_normal_textures() { - return ntex_list; +Array SpineAtlasResource::get_normal_maps() { + return normal_maps; } String SpineAtlasResource::get_source_path() { @@ -144,33 +132,25 @@ String SpineAtlasResource::get_source_path() { } Error SpineAtlasResource::load_from_atlas_file(const String &p_path) { - // print_line(vformat("Importing atlas file: %s", p_path)); source_path = p_path; - Error err; atlas_data = FileAccess::get_file_as_string(p_path, &err); if (err != OK) return err; if (atlas) delete atlas; - tex_list.clear(); - ntex_list.clear(); - atlas = new spine::Atlas(atlas_data.utf8(), atlas_data.size(), source_path.get_base_dir().utf8(), new GodotSpineTextureLoader(&tex_list, &ntex_list, normal_texture_prefix)); - - // print_line(vformat("atlas loaded!")); - - if (atlas) - return OK; - - tex_list.clear(); - ntex_list.clear(); + textures.clear(); + normal_maps.clear(); + atlas = new spine::Atlas(atlas_data.utf8(), atlas_data.size(), source_path.get_base_dir().utf8(), new GodotSpineTextureLoader(&textures, &normal_maps, normal_texture_prefix)); + if (atlas) return OK; + textures.clear(); + normal_maps.clear(); return ERR_FILE_UNRECOGNIZED; } Error SpineAtlasResource::load_from_file(const String &p_path) { Error err; - String json_string = FileAccess::get_file_as_string(p_path, &err); if (err != OK) return err; @@ -179,26 +159,21 @@ Error SpineAtlasResource::load_from_file(const String &p_path) { JSON json; Variant result; err = json.parse(json_string, result, error_string, error_line); - if (err != OK) { - return err; - } + if (err != OK) return err; Dictionary content = Dictionary(result); - source_path = content["source_path"]; atlas_data = content["atlas_data"]; normal_texture_prefix = content["normal_texture_prefix"]; if (atlas) delete atlas; - tex_list.clear(); - ntex_list.clear(); - atlas = new spine::Atlas(atlas_data.utf8(), atlas_data.size(), source_path.get_base_dir().utf8(), new GodotSpineTextureLoader(&tex_list, &ntex_list, normal_texture_prefix)); + textures.clear(); + normal_maps.clear(); + atlas = new spine::Atlas(atlas_data.utf8(), atlas_data.size(), source_path.get_base_dir().utf8(), new GodotSpineTextureLoader(&textures, &normal_maps, normal_texture_prefix)); + if (atlas) return OK; - if (atlas) - return OK; - - tex_list.clear(); - ntex_list.clear(); + textures.clear(); + normal_maps.clear(); return ERR_FILE_UNRECOGNIZED; } @@ -206,7 +181,6 @@ Error SpineAtlasResource::save_to_file(const String &p_path) { Error err; FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &err); if (err != OK) { - // print_line(vformat("save file err: %d", err)); if (file) file->close(); return err; } @@ -216,8 +190,6 @@ Error SpineAtlasResource::save_to_file(const String &p_path) { content["atlas_data"] = atlas_data; content["normal_texture_prefix"] = normal_texture_prefix; - // print_line(vformat("storing source_path: %s", source_path)); - file->store_string(JSON::print(content)); file->close(); diff --git a/spine-godot/spine_godot/SpineAtlasResource.h b/spine-godot/spine_godot/SpineAtlasResource.h index 881d17664..eea94bbbf 100644 --- a/spine-godot/spine_godot/SpineAtlasResource.h +++ b/spine-godot/spine_godot/SpineAtlasResource.h @@ -52,8 +52,8 @@ protected: String atlas_data; String normal_texture_prefix; - Array tex_list; - Array ntex_list; + Array textures; + Array normal_maps; public: inline String &get_atlas_data() { return atlas_data; } @@ -69,7 +69,7 @@ public: String get_source_path(); Array get_textures(); - Array get_normal_textures(); + Array get_normal_maps(); SpineAtlasResource(); virtual ~SpineAtlasResource(); diff --git a/spine-godot/spine_godot/SpineRendererObject.h b/spine-godot/spine_godot/SpineRendererObject.h index 1076d52bd..11b9370a9 100644 --- a/spine-godot/spine_godot/SpineRendererObject.h +++ b/spine-godot/spine_godot/SpineRendererObject.h @@ -32,10 +32,9 @@ #include - struct SpineRendererObject { - Ref tex; - Ref normal_tex; + Ref texture; + Ref normal_map; }; diff --git a/spine-godot/spine_godot/SpineSkeletonDataResource.cpp b/spine-godot/spine_godot/SpineSkeletonDataResource.cpp index f360433f3..977913c61 100644 --- a/spine-godot/spine_godot/SpineSkeletonDataResource.cpp +++ b/spine-godot/spine_godot/SpineSkeletonDataResource.cpp @@ -119,7 +119,6 @@ void SpineSkeletonDataResource::update_skeleton_data() { void SpineSkeletonDataResource::set_atlas_res(const Ref &a) { atlas_res = a; valid = false; - // print_line("atlas_res_changed emitted"); emit_signal("atlas_res_changed"); update_skeleton_data(); } diff --git a/spine-godot/spine_godot/SpineSprite.cpp b/spine-godot/spine_godot/SpineSprite.cpp index eb8c2c309..d2047853e 100644 --- a/spine-godot/spine_godot/SpineSprite.cpp +++ b/spine-godot/spine_godot/SpineSprite.cpp @@ -386,8 +386,8 @@ void SpineSprite::update_mesh_from_skeleton(Ref s) { spine::RegionAttachment *region_attachment = (spine::RegionAttachment *) attachment; auto p_spine_renderer_object = (SpineRendererObject *) ((spine::AtlasRegion *) region_attachment->getRendererObject())->page->getRendererObject(); - tex = p_spine_renderer_object->tex; - normal_tex = p_spine_renderer_object->normal_tex; + tex = p_spine_renderer_object->texture; + normal_tex = p_spine_renderer_object->normal_map; v_num = 4; vertices.setSize(v_num * VERTEX_STRIDE, 0); @@ -410,8 +410,8 @@ void SpineSprite::update_mesh_from_skeleton(Ref s) { spine::MeshAttachment *mesh = (spine::MeshAttachment *) attachment; auto p_spine_renderer_object = (SpineRendererObject *) ((spine::AtlasRegion *) mesh->getRendererObject())->page->getRendererObject(); - tex = p_spine_renderer_object->tex; - normal_tex = p_spine_renderer_object->normal_tex; + tex = p_spine_renderer_object->texture; + normal_tex = p_spine_renderer_object->normal_map; v_num = mesh->getWorldVerticesLength() / VERTEX_STRIDE; vertices.setSize(mesh->getWorldVerticesLength(), 0); From b22a043ad5d1755e4c004eb93396bf22a623b171 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Fri, 1 Oct 2021 13:44:12 +0200 Subject: [PATCH 05/18] Faster compilation by excluding unnecessary modules. --- spine-godot/custom.py | 34 + .../example/spineboy/spineboy-pro.json | 8699 +++++++++++++++++ .../example/spineboy/spineboy-pro.json.import | 13 + spine-godot/example/test.tscn | 19 +- spine-godot/setup.sh | 5 +- 5 files changed, 8766 insertions(+), 4 deletions(-) create mode 100644 spine-godot/custom.py create mode 100644 spine-godot/example/spineboy/spineboy-pro.json create mode 100644 spine-godot/example/spineboy/spineboy-pro.json.import diff --git a/spine-godot/custom.py b/spine-godot/custom.py new file mode 100644 index 000000000..946f42cf2 --- /dev/null +++ b/spine-godot/custom.py @@ -0,0 +1,34 @@ +# list of disabled modules for faster compilation of the engine +module_arkit_enabled = "no" +module_assimp_enabled = "no" +module_bmp_enabled = "no" +module_denoise_enabled = "no" +module_bullet_enabled = "no" +module_raycast_enabled = "no" +module_camera_enabled = "no" +module_csg_enabled = "no" +module_dds_enabled = "no" +module_enet_enabled = "no" +module_etc_enabled = "no" +module_gdnative_enabled = "no" +module_gridmap_enabled = "no" +module_hdr_enabled = "no" +module_jsonrpc_enabled = "no" +module_mbedtls_enabled = "no" +module_mobile_vr_enabled = "no" +module_opensimplex_enabled = "no" +module_opus_enabled = "no" +module_pvr_enabled = "no" +module_recast_enabled = "no" +module_squish_enabled = "no" +module_tga_enabled = "no" +module_theora_enabled = "no" +module_tinyexr_enabled = "no" +module_upnp_enabled = "no" +module_vhacd_enabled = "no" +module_vorbis_enabled = "no" +module_webm_enabled = "no" +module_webp_enabled = "no" +module_webrtc_enabled = "no" +module_websocket_enabled = "no" +module_xatlas_unwrap_enabled = "no" \ No newline at end of file diff --git a/spine-godot/example/spineboy/spineboy-pro.json b/spine-godot/example/spineboy/spineboy-pro.json new file mode 100644 index 000000000..4d8c7c2cf --- /dev/null +++ b/spine-godot/example/spineboy/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/spine-godot/example/spineboy/spineboy-pro.json.import b/spine-godot/example/spineboy/spineboy-pro.json.import new file mode 100644 index 000000000..22d241514 --- /dev/null +++ b/spine-godot/example/spineboy/spineboy-pro.json.import @@ -0,0 +1,13 @@ +[remap] + +importer="spine.json" +type="SpineSkeletonJsonDataResource" +path="res://.import/spineboy-pro.json-32eeb9972a49130cf636442038541a01.spjson" + +[deps] + +source_file="res://spineboy/spineboy-pro.json" +dest_files=[ "res://.import/spineboy-pro.json-32eeb9972a49130cf636442038541a01.spjson" ] + +[params] + diff --git a/spine-godot/example/test.tscn b/spine-godot/example/test.tscn index 3e66a33bf..edaa0c6e4 100644 --- a/spine-godot/example/test.tscn +++ b/spine-godot/example/test.tscn @@ -1,4 +1,19 @@ -[gd_scene format=2] +[gd_scene load_steps=5 format=2] + +[ext_resource path="res://spineboy/spineboy.atlas" type="SpineAtlasResource" id=1] +[ext_resource path="res://spineboy/spineboy-pro.json" type="SpineSkeletonJsonDataResource" id=2] + +[sub_resource type="SpineSkeletonDataResource" id=1] +atlas_res = ExtResource( 1 ) +skeleton_json_res = ExtResource( 2 ) +animations = null +skins = null + +[sub_resource type="SpineAnimationStateDataResource" id=2] +skeleton = SubResource( 1 ) [node name="Node2D" type="Node2D"] -position = Vector2( 2.12469, 1.06235 ) +position = Vector2( 500.369, 609.791 ) + +[node name="SpineSprite" type="SpineSprite" parent="."] +animation_state_data_res = SubResource( 2 ) diff --git a/spine-godot/setup.sh b/spine-godot/setup.sh index 2c28a4146..28de86933 100755 --- a/spine-godot/setup.sh +++ b/spine-godot/setup.sh @@ -2,8 +2,9 @@ set -e rm -rf godot cp -r ../spine-cpp/spine-cpp spine-godot -git clone --depth 1 https://github.com/godotengine/godot.git -b 3.3.3-stable +git clone --depth 1 https://github.com/godotengine/godot.git -b 3.3.4-stable +cp custom.py godot ln -s $(pwd)/spine_godot godot/modules/spine_godot pushd godot -scons --jobs=$(sysctl -n hw.logicalcpu) +scons target=debug --jobs=$(sysctl -n hw.logicalcpu) popd \ No newline at end of file From 91748c2bbc3c142a511a180dc7446be1a80f56d8 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Fri, 1 Oct 2021 14:21:49 +0200 Subject: [PATCH 06/18] Add CLion macOS project files --- spine-godot/.idea/.gitignore | 8 ++ spine-godot/.idea/codeStyles/Project.xml | 12 ++ .../.idea/codeStyles/codeStyleConfig.xml | 5 + spine-godot/.idea/customTargets.xml | 15 +++ .../inspectionProfiles/Project_Default.xml | 6 + spine-godot/.idea/misc.xml | 17 +++ spine-godot/.idea/tools/External Tools.xml | 16 +++ spine-godot/.idea/vcs.xml | 6 + spine-godot/.idea/workspace.xml | 105 ++++++++++++++++++ spine-godot/setup.sh | 3 +- 10 files changed, 192 insertions(+), 1 deletion(-) create mode 100644 spine-godot/.idea/.gitignore create mode 100644 spine-godot/.idea/codeStyles/Project.xml create mode 100644 spine-godot/.idea/codeStyles/codeStyleConfig.xml create mode 100644 spine-godot/.idea/customTargets.xml create mode 100644 spine-godot/.idea/inspectionProfiles/Project_Default.xml create mode 100644 spine-godot/.idea/misc.xml create mode 100644 spine-godot/.idea/tools/External Tools.xml create mode 100644 spine-godot/.idea/vcs.xml create mode 100644 spine-godot/.idea/workspace.xml diff --git a/spine-godot/.idea/.gitignore b/spine-godot/.idea/.gitignore new file mode 100644 index 000000000..73f69e095 --- /dev/null +++ b/spine-godot/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/spine-godot/.idea/codeStyles/Project.xml b/spine-godot/.idea/codeStyles/Project.xml new file mode 100644 index 000000000..05a8cea49 --- /dev/null +++ b/spine-godot/.idea/codeStyles/Project.xml @@ -0,0 +1,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/spine-godot/.idea/codeStyles/codeStyleConfig.xml b/spine-godot/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 000000000..79ee123c2 --- /dev/null +++ b/spine-godot/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/spine-godot/.idea/customTargets.xml b/spine-godot/.idea/customTargets.xml new file mode 100644 index 000000000..9a3229956 --- /dev/null +++ b/spine-godot/.idea/customTargets.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spine-godot/.idea/inspectionProfiles/Project_Default.xml b/spine-godot/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 000000000..03d9549ea --- /dev/null +++ b/spine-godot/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/spine-godot/.idea/misc.xml b/spine-godot/.idea/misc.xml new file mode 100644 index 000000000..8067168ab --- /dev/null +++ b/spine-godot/.idea/misc.xml @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file diff --git a/spine-godot/.idea/tools/External Tools.xml b/spine-godot/.idea/tools/External Tools.xml new file mode 100644 index 000000000..258fa71c5 --- /dev/null +++ b/spine-godot/.idea/tools/External Tools.xml @@ -0,0 +1,16 @@ + + + + + + + + + + \ No newline at end of file diff --git a/spine-godot/.idea/vcs.xml b/spine-godot/.idea/vcs.xml new file mode 100644 index 000000000..94a25f7f4 --- /dev/null +++ b/spine-godot/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/spine-godot/.idea/workspace.xml b/spine-godot/.idea/workspace.xml new file mode 100644 index 000000000..529c1a0ce --- /dev/null +++ b/spine-godot/.idea/workspace.xml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1633088939732 + + + + + + \ No newline at end of file diff --git a/spine-godot/setup.sh b/spine-godot/setup.sh index 28de86933..f301c35e0 100755 --- a/spine-godot/setup.sh +++ b/spine-godot/setup.sh @@ -1,9 +1,10 @@ #!/bin/bash set -e rm -rf godot -cp -r ../spine-cpp/spine-cpp spine-godot +cp -r ../spine-cpp/spine-cpp spine_godot git clone --depth 1 https://github.com/godotengine/godot.git -b 3.3.4-stable cp custom.py godot +cp -r .idea godot ln -s $(pwd)/spine_godot godot/modules/spine_godot pushd godot scons target=debug --jobs=$(sysctl -n hw.logicalcpu) From aa84a4244fc4e565285e7ecface193961d14f38d Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Fri, 1 Oct 2021 14:47:58 +0200 Subject: [PATCH 07/18] Better SpineExtension:readFile implementation. --- spine-godot/spine_godot/GodotSpineExtension.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/spine-godot/spine_godot/GodotSpineExtension.cpp b/spine-godot/spine_godot/GodotSpineExtension.cpp index 6813a2cc2..cace4e354 100644 --- a/spine-godot/spine_godot/GodotSpineExtension.cpp +++ b/spine-godot/spine_godot/GodotSpineExtension.cpp @@ -62,15 +62,12 @@ void GodotSpineExtension::_free(void *mem, const char *file, int line) { char *GodotSpineExtension::_readFile(const spine::String &path, int *length) { Error error; auto res = FileAccess::get_file_as_array(String(path.buffer()), &error); - if (error != OK) { if (length) *length = 0; return NULL; } - - if (length) *length = res.size(); auto r = alloc(res.size(), __FILE__, __LINE__); - for (size_t i = 0; i < res.size(); ++i) - r[i] = res[i]; + memcpy(r, res.ptr(), res.size()); + if (length) *length = res.size(); return r; } \ No newline at end of file From af08ca6882e013d30cd734761bac6bc469aadfa2 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Fri, 1 Oct 2021 14:55:21 +0200 Subject: [PATCH 08/18] Rename PackedSkinResource -> SpineCustomSkinResource --- ...source.cpp => SpineCustomSkinResource.cpp} | 29 ++++++++++--------- ...inResource.h => SpineCustomSkinResource.h} | 20 ++++++------- spine-godot/spine_godot/SpineSprite.cpp | 11 +++---- spine-godot/spine_godot/SpineSprite.h | 17 ++++++----- spine-godot/spine_godot/register_types.cpp | 5 ++-- 5 files changed, 44 insertions(+), 38 deletions(-) rename spine-godot/spine_godot/{PackedSpineSkinResource.cpp => SpineCustomSkinResource.cpp} (72%) rename spine-godot/spine_godot/{PackedSpineSkinResource.h => SpineCustomSkinResource.h} (85%) diff --git a/spine-godot/spine_godot/PackedSpineSkinResource.cpp b/spine-godot/spine_godot/SpineCustomSkinResource.cpp similarity index 72% rename from spine-godot/spine_godot/PackedSpineSkinResource.cpp rename to spine-godot/spine_godot/SpineCustomSkinResource.cpp index 1521f1770..e15677dba 100644 --- a/spine-godot/spine_godot/PackedSpineSkinResource.cpp +++ b/spine-godot/spine_godot/SpineCustomSkinResource.cpp @@ -27,13 +27,13 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -#include "PackedSpineSkinResource.h" +#include "SpineCustomSkinResource.h" -void PackedSpineSkinResource::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_skin_name", "v"), &PackedSpineSkinResource::set_skin_name); - ClassDB::bind_method(D_METHOD("get_skin_name"), &PackedSpineSkinResource::get_skin_name); - ClassDB::bind_method(D_METHOD("set_sub_skin_names", "v"), &PackedSpineSkinResource::set_sub_skin_names); - ClassDB::bind_method(D_METHOD("get_sub_skin_names"), &PackedSpineSkinResource::get_sub_skin_names); +void SpineCustomSkinResource::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_skin_name", "v"), &SpineCustomSkinResource::set_skin_name); + ClassDB::bind_method(D_METHOD("get_skin_name"), &SpineCustomSkinResource::get_skin_name); + ClassDB::bind_method(D_METHOD("set_sub_skin_names", "v"), &SpineCustomSkinResource::set_sub_skin_names); + ClassDB::bind_method(D_METHOD("get_sub_skin_names"), &SpineCustomSkinResource::get_sub_skin_names); ADD_SIGNAL(MethodInfo("property_changed")); @@ -41,21 +41,24 @@ void PackedSpineSkinResource::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "sub_skin_names"), "set_sub_skin_names", "get_sub_skin_names"); } -PackedSpineSkinResource::PackedSpineSkinResource() : skin_name("custom_skin_name") {} -PackedSpineSkinResource::~PackedSpineSkinResource() {} +SpineCustomSkinResource::SpineCustomSkinResource() : skin_name("custom_skin_name") {} -void PackedSpineSkinResource::set_skin_name(const String &v) { +SpineCustomSkinResource::~SpineCustomSkinResource() {} + +void SpineCustomSkinResource::set_skin_name(const String &v) { skin_name = v; emit_signal("property_changed"); } -String PackedSpineSkinResource::get_skin_name() { + +String SpineCustomSkinResource::get_skin_name() { return skin_name; } -void PackedSpineSkinResource::set_sub_skin_names(Array v) { +void SpineCustomSkinResource::set_sub_skin_names(Array v) { sub_skin_names = v; emit_signal("property_changed"); } -Array PackedSpineSkinResource::get_sub_skin_names() { + +Array SpineCustomSkinResource::get_sub_skin_names() { return sub_skin_names; -} +} \ No newline at end of file diff --git a/spine-godot/spine_godot/PackedSpineSkinResource.h b/spine-godot/spine_godot/SpineCustomSkinResource.h similarity index 85% rename from spine-godot/spine_godot/PackedSpineSkinResource.h rename to spine-godot/spine_godot/SpineCustomSkinResource.h index f3e979c2b..dd01514cd 100644 --- a/spine-godot/spine_godot/PackedSpineSkinResource.h +++ b/spine-godot/spine_godot/SpineCustomSkinResource.h @@ -27,15 +27,14 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -#ifndef GODOT_PACKEDSPINESKINRESOURCE_H -#define GODOT_PACKEDSPINESKINRESOURCE_H +#ifndef GODOT_SPINECUSTOMSKINRESOURCE_H +#define GODOT_SPINECUSTOMSKINRESOURCE_H #include "core/variant_parser.h" +#include "SpineSKin.h" -#include "SpineSkin.h" - -class PackedSpineSkinResource : public Resource { - GDCLASS(PackedSpineSkinResource, Resource); +class SpineCustomSkinResource : public Resource { + GDCLASS(SpineCustomSkinResource, Resource); protected: static void _bind_methods(); @@ -45,8 +44,8 @@ private: Array sub_skin_names; public: - PackedSpineSkinResource(); - virtual ~PackedSpineSkinResource(); + SpineCustomSkinResource(); + virtual ~SpineCustomSkinResource(); void set_skin_name(const String &v); String get_skin_name(); @@ -54,5 +53,6 @@ public: void set_sub_skin_names(Array v); Array get_sub_skin_names(); }; - -#endif//GODOT_PACKEDSPINESKINRESOURCE_H +#include "SpineSkin.h" +#include "core/variant_parser.h" +#endif //GODOT_SPINECUSTOMSKINRESOURCE_H diff --git a/spine-godot/spine_godot/SpineSprite.cpp b/spine-godot/spine_godot/SpineSprite.cpp index d2047853e..7de4bd19f 100644 --- a/spine-godot/spine_godot/SpineSprite.cpp +++ b/spine-godot/spine_godot/SpineSprite.cpp @@ -29,8 +29,9 @@ #include "SpineSprite.h" -#include "SpineTrackEntry.h" +#include "SpineCustomSkinResource.h" #include "SpineEvent.h" +#include "SpineTrackEntry.h" void SpineSprite::_bind_methods() { ClassDB::bind_method(D_METHOD("set_animation_state_data_res", "animation_state_data_res"), &SpineSprite::set_animation_state_data_res); @@ -86,7 +87,7 @@ void SpineSprite::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "overlap"), "set_overlap", "get_overlap"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "bind_slot_nodes"), "set_bind_slot_nodes", "get_bind_slot_nodes"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "packed_skin_resource", PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "PackedSpineSkinResource"), "set_skin", "get_skin"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "packed_skin_resource", PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "SpineCustomSkinResource"), "set_skin", "get_skin"); ADD_GROUP("animation", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Process,Physics,Manually"), "set_process_mode", "get_process_mode"); @@ -646,7 +647,7 @@ void SpineSprite::set_overlap(bool v) { overlap = v; } -void SpineSprite::set_skin(Ref v) { +void SpineSprite::set_skin(Ref v) { if (v != skin && skin.is_valid()) { if (skin->is_connected("property_changed", this, "_on_skin_property_changed")) skin->disconnect("property_changed", this, "_on_skin_property_changed"); @@ -660,7 +661,7 @@ void SpineSprite::set_skin(Ref v) { update_runtime_skin(); } } -Ref SpineSprite::get_skin() { +Ref SpineSprite::get_skin() { return skin; } void SpineSprite::update_runtime_skin() { @@ -675,7 +676,7 @@ void SpineSprite::_on_skin_property_changed() { update_runtime_skin(); } -Ref SpineSprite::gen_spine_skin_from_packed_resource(Ref res) { +Ref SpineSprite::gen_spine_skin_from_packed_resource(Ref res) { if (!(animation_state.is_valid() && skeleton.is_valid())) return NULL; if (!res.is_valid()) diff --git a/spine-godot/spine_godot/SpineSprite.h b/spine-godot/spine_godot/SpineSprite.h index 0bf686584..91a5f2aa6 100644 --- a/spine-godot/spine_godot/SpineSprite.h +++ b/spine-godot/spine_godot/SpineSprite.h @@ -34,11 +34,12 @@ #include -#include "SpineAnimationStateDataResource.h" -#include "SpineSkeleton.h" -#include "SpineAnimationState.h" -#include "SpineSpriteMeshInstance2D.h" #include "PackedSpineSkinResource.h" +#include "SpineAnimationState.h" +#include "SpineAnimationStateDataResource.h" +#include "SpineCustomSkinResource.h" +#include "SpineSkeleton.h" +#include "SpineSpriteMeshInstance2D.h" class SpineSprite : public Node2D, public spine::AnimationStateListenerObject { GDCLASS(SpineSprite, Node2D); @@ -75,7 +76,7 @@ private: Array bind_slot_nodes; bool overlap; - Ref skin; + Ref skin; ProcessMode process_mode; @@ -145,12 +146,12 @@ public: bool get_overlap(); void set_overlap(bool v); - void set_skin(Ref v); - Ref get_skin(); + void set_skin(Ref v); + Ref get_skin(); void _on_skin_property_changed(); void update_runtime_skin(); - Ref gen_spine_skin_from_packed_resource(Ref res); + Ref gen_spine_skin_from_packed_resource(Ref res); // current animation count int64_t get_current_animation_count() const; diff --git a/spine-godot/spine_godot/register_types.cpp b/spine-godot/spine_godot/register_types.cpp index 5aa2f7de7..429ff926b 100644 --- a/spine-godot/spine_godot/register_types.cpp +++ b/spine-godot/spine_godot/register_types.cpp @@ -54,7 +54,7 @@ #include "SpineTransformConstraintData.h" #include "SpinePathConstraintData.h" #include "SpineSpriteMeshInstance2D.h" -#include "PackedSpineSkinResource.h" +#include "SpineCustomSkinResource.h" #include "SpineTimeline.h" #include "SpineConstant.h" #include "SpineCollisionShapeProxy.h" @@ -71,6 +71,7 @@ static Ref json_skeleton_saver; #include "editor/editor_export.h" #include "editor/editor_node.h" +#include "SpineCustomSkinResource.h" #include "SpineRuntimeEditorPlugin.h" static void editor_init_callback() { @@ -115,7 +116,7 @@ void register_spine_godot_types() { ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); - ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); From 51a236c60f0ee85962758179dd4b31102492911d Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Fri, 1 Oct 2021 14:57:52 +0200 Subject: [PATCH 09/18] Fix compilation errors. --- spine-godot/spine_godot/SpineCustomSkinResource.h | 2 +- spine-godot/spine_godot/SpineSprite.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spine-godot/spine_godot/SpineCustomSkinResource.h b/spine-godot/spine_godot/SpineCustomSkinResource.h index dd01514cd..ebcd5dd7f 100644 --- a/spine-godot/spine_godot/SpineCustomSkinResource.h +++ b/spine-godot/spine_godot/SpineCustomSkinResource.h @@ -31,7 +31,7 @@ #define GODOT_SPINECUSTOMSKINRESOURCE_H #include "core/variant_parser.h" -#include "SpineSKin.h" +#include "SpineSkin.h" class SpineCustomSkinResource : public Resource { GDCLASS(SpineCustomSkinResource, Resource); diff --git a/spine-godot/spine_godot/SpineSprite.h b/spine-godot/spine_godot/SpineSprite.h index 91a5f2aa6..79d24b6ed 100644 --- a/spine-godot/spine_godot/SpineSprite.h +++ b/spine-godot/spine_godot/SpineSprite.h @@ -34,7 +34,7 @@ #include -#include "PackedSpineSkinResource.h" +#include "SpineCustomSkinResource.h" #include "SpineAnimationState.h" #include "SpineAnimationStateDataResource.h" #include "SpineCustomSkinResource.h" From 9ad9fff97eac580a7cd9e95608eb1d89f1daa9a8 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Fri, 1 Oct 2021 15:40:53 +0200 Subject: [PATCH 10/18] Move atlas format loader/saver to spineatlas.h, remove custom skin resource. --- spine-godot/example/project.godot | 2 +- .../example/{test.tscn => spineboy.tscn} | 11 ++-- .../ResourceFormatLoaderSpineAtlas.cpp | 56 ---------------- .../ResourceFormatLoaderSpineAtlas.h | 46 ------------- .../ResourceFormatSaverSpineAtlas.cpp | 48 -------------- .../ResourceFormatSaverSpineAtlas.h | 45 ------------- .../spine_godot/SpineAtlasResource.cpp | 42 ++++++++++++ spine-godot/spine_godot/SpineAtlasResource.h | 25 +++++++- .../spine_godot/SpineCustomSkinResource.cpp | 64 ------------------- .../spine_godot/SpineCustomSkinResource.h | 58 ----------------- spine-godot/spine_godot/SpineSprite.cpp | 61 +----------------- spine-godot/spine_godot/SpineSprite.h | 11 ---- spine-godot/spine_godot/register_types.cpp | 9 +-- 13 files changed, 77 insertions(+), 401 deletions(-) rename spine-godot/example/{test.tscn => spineboy.tscn} (72%) delete mode 100644 spine-godot/spine_godot/ResourceFormatLoaderSpineAtlas.cpp delete mode 100644 spine-godot/spine_godot/ResourceFormatLoaderSpineAtlas.h delete mode 100644 spine-godot/spine_godot/ResourceFormatSaverSpineAtlas.cpp delete mode 100644 spine-godot/spine_godot/ResourceFormatSaverSpineAtlas.h delete mode 100644 spine-godot/spine_godot/SpineCustomSkinResource.cpp delete mode 100644 spine-godot/spine_godot/SpineCustomSkinResource.h diff --git a/spine-godot/example/project.godot b/spine-godot/example/project.godot index 1f28721fa..c7fc9bd26 100644 --- a/spine-godot/example/project.godot +++ b/spine-godot/example/project.godot @@ -11,7 +11,7 @@ config_version=4 [application] config/name="spine-godot-examples" -run/main_scene="res://test.tscn" +run/main_scene="res://spineboy.tscn" config/icon="res://icon.png" [physics] diff --git a/spine-godot/example/test.tscn b/spine-godot/example/spineboy.tscn similarity index 72% rename from spine-godot/example/test.tscn rename to spine-godot/example/spineboy.tscn index edaa0c6e4..8a99d91f3 100644 --- a/spine-godot/example/test.tscn +++ b/spine-godot/example/spineboy.tscn @@ -1,11 +1,11 @@ [gd_scene load_steps=5 format=2] -[ext_resource path="res://spineboy/spineboy.atlas" type="SpineAtlasResource" id=1] -[ext_resource path="res://spineboy/spineboy-pro.json" type="SpineSkeletonJsonDataResource" id=2] +[ext_resource path="res://spineboy/spineboy-pro.json" type="SpineSkeletonJsonDataResource" id=1] +[ext_resource path="res://spineboy/spineboy.atlas" type="SpineAtlasResource" id=2] [sub_resource type="SpineSkeletonDataResource" id=1] -atlas_res = ExtResource( 1 ) -skeleton_json_res = ExtResource( 2 ) +atlas_res = ExtResource( 2 ) +skeleton_json_res = ExtResource( 1 ) animations = null skins = null @@ -13,7 +13,8 @@ skins = null skeleton = SubResource( 1 ) [node name="Node2D" type="Node2D"] -position = Vector2( 500.369, 609.791 ) [node name="SpineSprite" type="SpineSprite" parent="."] +position = Vector2( 504, 622 ) animation_state_data_res = SubResource( 2 ) +current_animations = [ "walk" ] diff --git a/spine-godot/spine_godot/ResourceFormatLoaderSpineAtlas.cpp b/spine-godot/spine_godot/ResourceFormatLoaderSpineAtlas.cpp deleted file mode 100644 index f3c5c8ada..000000000 --- a/spine-godot/spine_godot/ResourceFormatLoaderSpineAtlas.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "ResourceFormatLoaderSpineAtlas.h" -#include "SpineAtlasResource.h" - -RES ResourceFormatLoaderSpineAtlas::load(const String &p_path, const String &p_original_path, Error *r_error) { - Ref atlas = memnew(SpineAtlasResource); - atlas->load_from_file(p_path); - - if (r_error) { - *r_error = OK; - } - return atlas; -} - -void ResourceFormatLoaderSpineAtlas::get_recognized_extensions(List *r_extensions) const { - const char atlas_ext[] = "spatlas"; - if (!r_extensions->find(atlas_ext)) { - r_extensions->push_back(atlas_ext); - } -} - -String ResourceFormatLoaderSpineAtlas::get_resource_type(const String &p_path) const { - return "SpineAtlasResource"; -} - -bool ResourceFormatLoaderSpineAtlas::handles_type(const String &p_type) const { - return p_type == "SpineAtlasResource" || ClassDB::is_parent_class(p_type, "SpineAtlasResource"); -} \ No newline at end of file diff --git a/spine-godot/spine_godot/ResourceFormatLoaderSpineAtlas.h b/spine-godot/spine_godot/ResourceFormatLoaderSpineAtlas.h deleted file mode 100644 index 27133afca..000000000 --- a/spine-godot/spine_godot/ResourceFormatLoaderSpineAtlas.h +++ /dev/null @@ -1,46 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_RESOURCEFORMATLOADERSPINEATLAS_H -#define GODOT_RESOURCEFORMATLOADERSPINEATLAS_H - -#include "core/io/resource_loader.h" - -class ResourceFormatLoaderSpineAtlas : public ResourceFormatLoader { - GDCLASS(ResourceFormatLoaderSpineAtlas, ResourceFormatLoader); - -public: - virtual RES load(const String &p_path, const String &p_original_path, Error *r_error = NULL); - virtual void get_recognized_extensions(List *r_extensions) const; - virtual bool handles_type(const String &p_type) const; - virtual String get_resource_type(const String &p_path) const; -}; - - -#endif//GODOT_RESOURCEFORMATLOADERSPINEATLAS_H diff --git a/spine-godot/spine_godot/ResourceFormatSaverSpineAtlas.cpp b/spine-godot/spine_godot/ResourceFormatSaverSpineAtlas.cpp deleted file mode 100644 index ef051f31c..000000000 --- a/spine-godot/spine_godot/ResourceFormatSaverSpineAtlas.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "ResourceFormatSaverSpineAtlas.h" - -#include "SpineAtlasResource.h" - -Error ResourceFormatSaverSpineAtlas::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { - Ref res = p_resource.get_ref_ptr(); - Error error = res->save_to_file(p_path); - return error; -} - -void ResourceFormatSaverSpineAtlas::get_recognized_extensions(const RES &p_resource, List *p_extensions) const { - if (Object::cast_to(*p_resource)) { - p_extensions->push_back("spatlas"); - } -} - -bool ResourceFormatSaverSpineAtlas::recognize(const RES &p_resource) const { - return Object::cast_to(*p_resource) != nullptr; -} diff --git a/spine-godot/spine_godot/ResourceFormatSaverSpineAtlas.h b/spine-godot/spine_godot/ResourceFormatSaverSpineAtlas.h deleted file mode 100644 index b20420772..000000000 --- a/spine-godot/spine_godot/ResourceFormatSaverSpineAtlas.h +++ /dev/null @@ -1,45 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_RESOURCEFORMATSAVERSPINEATLAS_H -#define GODOT_RESOURCEFORMATSAVERSPINEATLAS_H - -#include "core/io/resource_saver.h" - -class ResourceFormatSaverSpineAtlas : public ResourceFormatSaver { - GDCLASS(ResourceFormatSaverSpineAtlas, ResourceFormatSaver); - -public: - Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0) override; - void get_recognized_extensions(const RES &p_resource, List *p_extensions) const override; - bool recognize(const RES &p_resource) const override; -}; - - -#endif//GODOT_RESOURCEFORMATSAVERSPINEATLAS_H diff --git a/spine-godot/spine_godot/SpineAtlasResource.cpp b/spine-godot/spine_godot/SpineAtlasResource.cpp index e8e0d3bc0..088426621 100644 --- a/spine-godot/spine_godot/SpineAtlasResource.cpp +++ b/spine-godot/spine_godot/SpineAtlasResource.cpp @@ -101,6 +101,7 @@ public: }; SpineAtlasResource::SpineAtlasResource() : atlas(nullptr), normal_texture_prefix("n") {} + SpineAtlasResource::~SpineAtlasResource() { if (atlas) delete atlas; } @@ -195,3 +196,44 @@ Error SpineAtlasResource::save_to_file(const String &p_path) { return OK; } + +RES SpineAtlasResourceFormatLoader::load(const String &p_path, const String &p_original_path, Error *r_error) { + Ref atlas = memnew(SpineAtlasResource); + atlas->load_from_file(p_path); + + if (r_error) { + *r_error = OK; + } + return atlas; +} + +void SpineAtlasResourceFormatLoader::get_recognized_extensions(List *r_extensions) const { + const char atlas_ext[] = "spatlas"; + if (!r_extensions->find(atlas_ext)) { + r_extensions->push_back(atlas_ext); + } +} + +String SpineAtlasResourceFormatLoader::get_resource_type(const String &p_path) const { + return "SpineAtlasResource"; +} + +bool SpineAtlasResourceFormatLoader::handles_type(const String &p_type) const { + return p_type == "SpineAtlasResource" || ClassDB::is_parent_class(p_type, "SpineAtlasResource"); +} + +Error SpineAtlasResourceFormatSaver::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { + Ref res = p_resource.get_ref_ptr(); + Error error = res->save_to_file(p_path); + return error; +} + +void SpineAtlasResourceFormatSaver::get_recognized_extensions(const RES &p_resource, List *p_extensions) const { + if (Object::cast_to(*p_resource)) { + p_extensions->push_back("spatlas"); + } +} + +bool SpineAtlasResourceFormatSaver::recognize(const RES &p_resource) const { + return Object::cast_to(*p_resource) != nullptr; +} diff --git a/spine-godot/spine_godot/SpineAtlasResource.h b/spine-godot/spine_godot/SpineAtlasResource.h index eea94bbbf..84c7cc9ca 100644 --- a/spine-godot/spine_godot/SpineAtlasResource.h +++ b/spine-godot/spine_godot/SpineAtlasResource.h @@ -32,12 +32,14 @@ #include "core/variant_parser.h" +#include "core/io/resource_loader.h" +#include "core/io/resource_saver.h" +#include "core/io/image_loader.h" +#include "scene/resources/texture.h" #include #include #include -#include -#include #include "SpineRendererObject.h" class SpineAtlasResource : public Resource { @@ -75,5 +77,24 @@ public: virtual ~SpineAtlasResource(); }; +class SpineAtlasResourceFormatLoader : public ResourceFormatLoader { +GDCLASS(SpineAtlasResourceFormatLoader, ResourceFormatLoader); + +public: + virtual RES load(const String &p_path, const String &p_original_path, Error *r_error = NULL); + virtual void get_recognized_extensions(List *r_extensions) const; + virtual bool handles_type(const String &p_type) const; + virtual String get_resource_type(const String &p_path) const; +}; + +class SpineAtlasResourceFormatSaver : public ResourceFormatSaver { +GDCLASS(SpineAtlasResourceFormatSaver, ResourceFormatSaver); + +public: + Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0) override; + void get_recognized_extensions(const RES &p_resource, List *p_extensions) const override; + bool recognize(const RES &p_resource) const override; +}; + #endif//GODOT_SPINEATLASRESOURCE_H diff --git a/spine-godot/spine_godot/SpineCustomSkinResource.cpp b/spine-godot/spine_godot/SpineCustomSkinResource.cpp deleted file mode 100644 index e15677dba..000000000 --- a/spine-godot/spine_godot/SpineCustomSkinResource.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpineCustomSkinResource.h" - -void SpineCustomSkinResource::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_skin_name", "v"), &SpineCustomSkinResource::set_skin_name); - ClassDB::bind_method(D_METHOD("get_skin_name"), &SpineCustomSkinResource::get_skin_name); - ClassDB::bind_method(D_METHOD("set_sub_skin_names", "v"), &SpineCustomSkinResource::set_sub_skin_names); - ClassDB::bind_method(D_METHOD("get_sub_skin_names"), &SpineCustomSkinResource::get_sub_skin_names); - - ADD_SIGNAL(MethodInfo("property_changed")); - - ADD_PROPERTY(PropertyInfo(Variant::STRING, "skin_name"), "set_skin_name", "get_skin_name"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "sub_skin_names"), "set_sub_skin_names", "get_sub_skin_names"); -} - -SpineCustomSkinResource::SpineCustomSkinResource() : skin_name("custom_skin_name") {} - -SpineCustomSkinResource::~SpineCustomSkinResource() {} - -void SpineCustomSkinResource::set_skin_name(const String &v) { - skin_name = v; - emit_signal("property_changed"); -} - -String SpineCustomSkinResource::get_skin_name() { - return skin_name; -} - -void SpineCustomSkinResource::set_sub_skin_names(Array v) { - sub_skin_names = v; - emit_signal("property_changed"); -} - -Array SpineCustomSkinResource::get_sub_skin_names() { - return sub_skin_names; -} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineCustomSkinResource.h b/spine-godot/spine_godot/SpineCustomSkinResource.h deleted file mode 100644 index ebcd5dd7f..000000000 --- a/spine-godot/spine_godot/SpineCustomSkinResource.h +++ /dev/null @@ -1,58 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINECUSTOMSKINRESOURCE_H -#define GODOT_SPINECUSTOMSKINRESOURCE_H - -#include "core/variant_parser.h" -#include "SpineSkin.h" - -class SpineCustomSkinResource : public Resource { - GDCLASS(SpineCustomSkinResource, Resource); - -protected: - static void _bind_methods(); - -private: - String skin_name; - Array sub_skin_names; - -public: - SpineCustomSkinResource(); - virtual ~SpineCustomSkinResource(); - - void set_skin_name(const String &v); - String get_skin_name(); - - void set_sub_skin_names(Array v); - Array get_sub_skin_names(); -}; -#include "SpineSkin.h" -#include "core/variant_parser.h" -#endif //GODOT_SPINECUSTOMSKINRESOURCE_H diff --git a/spine-godot/spine_godot/SpineSprite.cpp b/spine-godot/spine_godot/SpineSprite.cpp index 7de4bd19f..1da9c898d 100644 --- a/spine-godot/spine_godot/SpineSprite.cpp +++ b/spine-godot/spine_godot/SpineSprite.cpp @@ -29,7 +29,6 @@ #include "SpineSprite.h" -#include "SpineCustomSkinResource.h" #include "SpineEvent.h" #include "SpineTrackEntry.h" @@ -62,10 +61,6 @@ void SpineSprite::_bind_methods() { ClassDB::bind_method(D_METHOD("set_bind_slot_nodes", "v"), &SpineSprite::set_bind_slot_nodes); ClassDB::bind_method(D_METHOD("get_overlap"), &SpineSprite::get_overlap); ClassDB::bind_method(D_METHOD("set_overlap", "v"), &SpineSprite::set_overlap); - ClassDB::bind_method(D_METHOD("set_skin", "v"), &SpineSprite::set_skin); - ClassDB::bind_method(D_METHOD("get_skin"), &SpineSprite::get_skin); - ClassDB::bind_method(D_METHOD("_on_skin_property_changed"), &SpineSprite::_on_skin_property_changed); - ClassDB::bind_method(D_METHOD("gen_spine_skin_from_packed_resource", "res"), &SpineSprite::gen_spine_skin_from_packed_resource); ClassDB::bind_method(D_METHOD("bone_get_global_transform", "bone_name"), &SpineSprite::bone_get_global_transform); ClassDB::bind_method(D_METHOD("bone_set_global_transform", "bone_name", "global_transform"), &SpineSprite::bone_set_global_transform); @@ -87,7 +82,7 @@ void SpineSprite::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "overlap"), "set_overlap", "get_overlap"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "bind_slot_nodes"), "set_bind_slot_nodes", "get_bind_slot_nodes"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "packed_skin_resource", PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "SpineCustomSkinResource"), "set_skin", "get_skin"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "custom_skin_resource", PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "SpineCustomSkinResource"), "set_skin", "get_skin"); ADD_GROUP("animation", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Process,Physics,Manually"), "set_process_mode", "get_process_mode"); @@ -636,6 +631,7 @@ void SpineSprite::set_set_empty_animations(bool v) { Array SpineSprite::get_bind_slot_nodes() { return bind_slot_nodes; } + void SpineSprite::set_bind_slot_nodes(Array v) { bind_slot_nodes = v; } @@ -643,62 +639,11 @@ void SpineSprite::set_bind_slot_nodes(Array v) { bool SpineSprite::get_overlap() { return overlap; } + void SpineSprite::set_overlap(bool v) { overlap = v; } -void SpineSprite::set_skin(Ref v) { - if (v != skin && skin.is_valid()) { - if (skin->is_connected("property_changed", this, "_on_skin_property_changed")) - skin->disconnect("property_changed", this, "_on_skin_property_changed"); - } - - skin = v; - - if (skin.is_valid()) { - if (!skin->is_connected("property_changed", this, "_on_skin_property_changed")) - skin->connect("property_changed", this, "_on_skin_property_changed"); - update_runtime_skin(); - } -} -Ref SpineSprite::get_skin() { - return skin; -} -void SpineSprite::update_runtime_skin() { - auto new_skin = gen_spine_skin_from_packed_resource(skin); - - if (new_skin.is_valid()) { - skeleton->set_skin(new_skin); - skeleton->set_to_setup_pose(); - } -} -void SpineSprite::_on_skin_property_changed() { - update_runtime_skin(); -} - -Ref SpineSprite::gen_spine_skin_from_packed_resource(Ref res) { - if (!(animation_state.is_valid() && skeleton.is_valid())) - return NULL; - if (!res.is_valid()) - return NULL; - if (res->get_skin_name().empty()) - return NULL; - auto exist_skin = animation_state_data_res->get_skeleton()->find_skin(res->get_skin_name()); - if (exist_skin.is_valid()) { - return exist_skin; - } - - auto new_skin = Ref(memnew(SpineSkin))->init(res->get_skin_name()); - auto sub_skin_names = res->get_sub_skin_names(); - for (size_t i = 0; i < sub_skin_names.size(); ++i) { - auto skin_name = (String) sub_skin_names[i]; - auto sub_skin = animation_state_data_res->get_skeleton()->find_skin(skin_name); - if (sub_skin.is_valid()) - new_skin->add_skin(sub_skin); - } - return new_skin; -} - void SpineSprite::bind_slot_with_node_2d(const String &slot_name, Node2D *n) { auto node_path = n->get_path_to(this); diff --git a/spine-godot/spine_godot/SpineSprite.h b/spine-godot/spine_godot/SpineSprite.h index 79d24b6ed..fc7276091 100644 --- a/spine-godot/spine_godot/SpineSprite.h +++ b/spine-godot/spine_godot/SpineSprite.h @@ -31,13 +31,10 @@ #define GODOT_SPINESPRITE_H #include - #include -#include "SpineCustomSkinResource.h" #include "SpineAnimationState.h" #include "SpineAnimationStateDataResource.h" -#include "SpineCustomSkinResource.h" #include "SpineSkeleton.h" #include "SpineSpriteMeshInstance2D.h" @@ -76,7 +73,6 @@ private: Array bind_slot_nodes; bool overlap; - Ref skin; ProcessMode process_mode; @@ -146,13 +142,6 @@ public: bool get_overlap(); void set_overlap(bool v); - void set_skin(Ref v); - Ref get_skin(); - void _on_skin_property_changed(); - void update_runtime_skin(); - - Ref gen_spine_skin_from_packed_resource(Ref res); - // current animation count int64_t get_current_animation_count() const; void set_current_animation_count(int64_t v); diff --git a/spine-godot/spine_godot/register_types.cpp b/spine-godot/spine_godot/register_types.cpp index 429ff926b..1fd9ad626 100644 --- a/spine-godot/spine_godot/register_types.cpp +++ b/spine-godot/spine_godot/register_types.cpp @@ -32,8 +32,6 @@ #include "core/class_db.h" #include "SpineAtlasResource.h" -#include "ResourceFormatLoaderSpineAtlas.h" -#include "ResourceFormatSaverSpineAtlas.h" #include "SpineSkeletonDataResource.h" #include "ResourceFormatLoaderSpineSkeletonJsonData.h" #include "ResourceFormatSaverSpineSkeletonJsonData.h" @@ -54,15 +52,14 @@ #include "SpineTransformConstraintData.h" #include "SpinePathConstraintData.h" #include "SpineSpriteMeshInstance2D.h" -#include "SpineCustomSkinResource.h" #include "SpineTimeline.h" #include "SpineConstant.h" #include "SpineCollisionShapeProxy.h" #include "SpineSpriteAnimateDialog.h" -static Ref atlas_loader; -static Ref atlas_saver; +static Ref atlas_loader; +static Ref atlas_saver; static Ref json_skeleton_loader; static Ref json_skeleton_saver; @@ -71,7 +68,6 @@ static Ref json_skeleton_saver; #include "editor/editor_export.h" #include "editor/editor_node.h" -#include "SpineCustomSkinResource.h" #include "SpineRuntimeEditorPlugin.h" static void editor_init_callback() { @@ -116,7 +112,6 @@ void register_spine_godot_types() { ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); - ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); From d51bbb9493a5bda761d858138301dc56387923c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Izurieta?= Date: Fri, 3 Dec 2021 07:44:13 -0500 Subject: [PATCH 11/18] Some compilation fixes for Godot 3.4 (#1979) * Fix spine-godot README folder paths * Fix spine-godot compilation issues for godot-3.4 --- spine-godot/README.md | 4 ++-- spine-godot/spine_godot/SpineAnimation.cpp | 2 +- spine-godot/spine_godot/SpineAnimationState.cpp | 4 ++-- spine-godot/spine_godot/SpineTimeline.cpp | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/spine-godot/README.md b/spine-godot/README.md index d01a47d9d..ee9038925 100644 --- a/spine-godot/README.md +++ b/spine-godot/README.md @@ -25,8 +25,8 @@ spine-godot works with the latest stable Godot 3.3 release. It requires compilat To integrate spine-godot into your project: 1. Follow the [instructions on how to compilation of Godot](https://docs.godotengine.org/en/stable/development/compiling/index.html) -2. Copy the `spine-runtimes/spine-godot` folder into the folder `modules/spine-godot` in your Godot source tree. -3. Copy the `spine-cpp/spine-cpp`folder into the folder `modules/spine-godot/spine-cpp` in your Godot source tree. +2. Copy the `spine-runtimes/spine-godot/spine_godot` folder into the folder `modules/spine_godot` in your Godot source tree. +3. Copy the `spine-cpp/spine-cpp`folder into the folder `modules/spine_godot/spine-cpp` in your Godot source tree. 4. Compile Godot via scons for your platform as per the Godot documentation. The resulting Godot engine binary will include the spine-godot runtime. diff --git a/spine-godot/spine_godot/SpineAnimation.cpp b/spine-godot/spine_godot/SpineAnimation.cpp index a646460f1..7f0772f24 100644 --- a/spine-godot/spine_godot/SpineAnimation.cpp +++ b/spine-godot/spine_godot/SpineAnimation.cpp @@ -90,7 +90,7 @@ bool SpineAnimation::has_timeline(Array ids) { list.setSize(ids.size(), 0); for (size_t i = 0; i < list.size(); ++i) { - list[i] = ids[i]; + list[i] = (int64_t) ids[i]; } return animation->hasTimeline(list); } diff --git a/spine-godot/spine_godot/SpineAnimationState.cpp b/spine-godot/spine_godot/SpineAnimationState.cpp index 2d9f6c8f6..155a1d6d3 100644 --- a/spine-godot/spine_godot/SpineAnimationState.cpp +++ b/spine-godot/spine_godot/SpineAnimationState.cpp @@ -95,7 +95,7 @@ Ref SpineAnimationState::set_animation(const String &anim_name, auto skeleton_data = anim_state_data_res->get_skeleton(); auto anim = skeleton_data->find_animation(anim_name); if (!anim.is_valid() || anim->get_spine_object() == NULL) { - ERR_PRINT(String("Can not find animation: ") + anim_name) + ERR_PRINT(String("Can not find animation: ") + anim_name); return NULL; } auto entry = animation_state->setAnimation(track, anim->get_spine_object(), loop); @@ -108,7 +108,7 @@ Ref SpineAnimationState::add_animation(const String &anim_name, auto skeleton_data = anim_state_data_res->get_skeleton(); auto anim = skeleton_data->find_animation(anim_name); if (!anim.is_valid() || anim->get_spine_object() == NULL) { - ERR_PRINT(String("Can not find animation: ") + anim_name) + ERR_PRINT(String("Can not find animation: ") + anim_name); return NULL; } auto entry = animation_state->addAnimation(track, anim->get_spine_object(), loop, delay); diff --git a/spine-godot/spine_godot/SpineTimeline.cpp b/spine-godot/spine_godot/SpineTimeline.cpp index d2de60065..29561c595 100644 --- a/spine-godot/spine_godot/SpineTimeline.cpp +++ b/spine-godot/spine_godot/SpineTimeline.cpp @@ -92,7 +92,7 @@ Array SpineTimeline::getPropertyIds() { res.resize(ids.size()); for (size_t i = 0; i < res.size(); ++i) { - res[i] = ids[i]; + res[i] = (int64_t) ids[i]; } return res; From c276b4dfdd65cb8d0bf77745562a946450801ebc Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Mon, 4 Apr 2022 11:53:49 +0200 Subject: [PATCH 12/18] [godot] Git ignore spine_godot and godot checkout, update to Godot 3.4.4 --- .gitignore | 2 + spine-godot/setup.sh | 2 +- .../spine_godot/GodotSpineExtension.cpp | 73 -- spine-godot/spine_godot/GodotSpineExtension.h | 54 - ...ourceFormatLoaderSpineSkeletonJsonData.cpp | 56 - ...esourceFormatLoaderSpineSkeletonJsonData.h | 45 - ...sourceFormatSaverSpineSkeletonJsonData.cpp | 48 - ...ResourceFormatSaverSpineSkeletonJsonData.h | 45 - spine-godot/spine_godot/SCsub | 9 - spine-godot/spine_godot/SpineAnimation.cpp | 96 -- spine-godot/spine_godot/SpineAnimation.h | 74 -- .../spine_godot/SpineAnimationState.cpp | 191 ---- spine-godot/spine_godot/SpineAnimationState.h | 94 -- .../SpineAnimationStateDataResource.cpp | 163 --- .../SpineAnimationStateDataResource.h | 76 -- .../spine_godot/SpineAtlasResource.cpp | 239 ----- spine-godot/spine_godot/SpineAtlasResource.h | 100 -- spine-godot/spine_godot/SpineAttachment.cpp | 55 - spine-godot/spine_godot/SpineAttachment.h | 64 -- spine-godot/spine_godot/SpineBone.cpp | 536 ---------- spine-godot/spine_godot/SpineBone.h | 175 ---- spine-godot/spine_godot/SpineBoneData.cpp | 163 --- spine-godot/spine_godot/SpineBoneData.h | 103 -- .../spine_godot/SpineCollisionShapeProxy.cpp | 196 ---- .../spine_godot/SpineCollisionShapeProxy.h | 80 -- spine-godot/spine_godot/SpineConstant.cpp | 60 -- spine-godot/spine_godot/SpineConstant.h | 81 -- .../spine_godot/SpineConstraintData.cpp | 59 -- spine-godot/spine_godot/SpineConstraintData.h | 66 -- spine-godot/spine_godot/SpineEvent.cpp | 110 -- spine-godot/spine_godot/SpineEvent.h | 91 -- spine-godot/spine_godot/SpineEventData.cpp | 36 - spine-godot/spine_godot/SpineEventData.h | 58 -- spine-godot/spine_godot/SpineIkConstraint.cpp | 146 --- spine-godot/spine_godot/SpineIkConstraint.h | 94 -- .../spine_godot/SpineIkConstraintData.cpp | 123 --- .../spine_godot/SpineIkConstraintData.h | 78 -- .../spine_godot/SpinePathConstraint.cpp | 145 --- spine-godot/spine_godot/SpinePathConstraint.h | 94 -- .../spine_godot/SpinePathConstraintData.cpp | 168 --- .../spine_godot/SpinePathConstraintData.h | 108 -- spine-godot/spine_godot/SpineRendererObject.h | 41 - .../spine_godot/SpineRuntimeEditorPlugin.cpp | 99 -- .../spine_godot/SpineRuntimeEditorPlugin.h | 98 -- spine-godot/spine_godot/SpineSkeleton.cpp | 427 -------- spine-godot/spine_godot/SpineSkeleton.h | 134 --- .../spine_godot/SpineSkeletonDataResource.cpp | 455 --------- .../spine_godot/SpineSkeletonDataResource.h | 140 --- .../SpineSkeletonJsonDataResource.cpp | 55 - .../SpineSkeletonJsonDataResource.h | 50 - spine-godot/spine_godot/SpineSkin.cpp | 161 --- spine-godot/spine_godot/SpineSkin.h | 85 -- .../SpineSkinAttachmentMapEntries.cpp | 93 -- .../SpineSkinAttachmentMapEntries.h | 93 -- spine-godot/spine_godot/SpineSlot.cpp | 148 --- spine-godot/spine_godot/SpineSlot.h | 93 -- spine-godot/spine_godot/SpineSlotData.cpp | 114 --- spine-godot/spine_godot/SpineSlotData.h | 88 -- spine-godot/spine_godot/SpineSprite.cpp | 966 ------------------ spine-godot/spine_godot/SpineSprite.h | 154 --- .../spine_godot/SpineSpriteAnimateDialog.cpp | 351 ------- .../spine_godot/SpineSpriteAnimateDialog.h | 87 -- .../spine_godot/SpineSpriteMeshInstance2D.cpp | 48 - .../spine_godot/SpineSpriteMeshInstance2D.h | 57 -- spine-godot/spine_godot/SpineTimeline.cpp | 99 -- spine-godot/spine_godot/SpineTimeline.h | 75 -- spine-godot/spine_godot/SpineTrackEntry.cpp | 265 ----- spine-godot/spine_godot/SpineTrackEntry.h | 131 --- .../spine_godot/SpineTransformConstraint.cpp | 148 --- .../spine_godot/SpineTransformConstraint.h | 93 -- .../SpineTransformConstraintData.cpp | 118 --- .../SpineTransformConstraintData.h | 74 -- spine-godot/spine_godot/config.py | 5 - spine-godot/spine_godot/register_types.cpp | 144 --- spine-godot/spine_godot/register_types.h | 31 - 75 files changed, 3 insertions(+), 9473 deletions(-) delete mode 100644 spine-godot/spine_godot/GodotSpineExtension.cpp delete mode 100644 spine-godot/spine_godot/GodotSpineExtension.h delete mode 100644 spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.cpp delete mode 100644 spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.h delete mode 100644 spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.cpp delete mode 100644 spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.h delete mode 100644 spine-godot/spine_godot/SCsub delete mode 100644 spine-godot/spine_godot/SpineAnimation.cpp delete mode 100644 spine-godot/spine_godot/SpineAnimation.h delete mode 100644 spine-godot/spine_godot/SpineAnimationState.cpp delete mode 100644 spine-godot/spine_godot/SpineAnimationState.h delete mode 100644 spine-godot/spine_godot/SpineAnimationStateDataResource.cpp delete mode 100644 spine-godot/spine_godot/SpineAnimationStateDataResource.h delete mode 100644 spine-godot/spine_godot/SpineAtlasResource.cpp delete mode 100644 spine-godot/spine_godot/SpineAtlasResource.h delete mode 100644 spine-godot/spine_godot/SpineAttachment.cpp delete mode 100644 spine-godot/spine_godot/SpineAttachment.h delete mode 100644 spine-godot/spine_godot/SpineBone.cpp delete mode 100644 spine-godot/spine_godot/SpineBone.h delete mode 100644 spine-godot/spine_godot/SpineBoneData.cpp delete mode 100644 spine-godot/spine_godot/SpineBoneData.h delete mode 100644 spine-godot/spine_godot/SpineCollisionShapeProxy.cpp delete mode 100644 spine-godot/spine_godot/SpineCollisionShapeProxy.h delete mode 100644 spine-godot/spine_godot/SpineConstant.cpp delete mode 100644 spine-godot/spine_godot/SpineConstant.h delete mode 100644 spine-godot/spine_godot/SpineConstraintData.cpp delete mode 100644 spine-godot/spine_godot/SpineConstraintData.h delete mode 100644 spine-godot/spine_godot/SpineEvent.cpp delete mode 100644 spine-godot/spine_godot/SpineEvent.h delete mode 100644 spine-godot/spine_godot/SpineEventData.cpp delete mode 100644 spine-godot/spine_godot/SpineEventData.h delete mode 100644 spine-godot/spine_godot/SpineIkConstraint.cpp delete mode 100644 spine-godot/spine_godot/SpineIkConstraint.h delete mode 100644 spine-godot/spine_godot/SpineIkConstraintData.cpp delete mode 100644 spine-godot/spine_godot/SpineIkConstraintData.h delete mode 100644 spine-godot/spine_godot/SpinePathConstraint.cpp delete mode 100644 spine-godot/spine_godot/SpinePathConstraint.h delete mode 100644 spine-godot/spine_godot/SpinePathConstraintData.cpp delete mode 100644 spine-godot/spine_godot/SpinePathConstraintData.h delete mode 100644 spine-godot/spine_godot/SpineRendererObject.h delete mode 100644 spine-godot/spine_godot/SpineRuntimeEditorPlugin.cpp delete mode 100644 spine-godot/spine_godot/SpineRuntimeEditorPlugin.h delete mode 100644 spine-godot/spine_godot/SpineSkeleton.cpp delete mode 100644 spine-godot/spine_godot/SpineSkeleton.h delete mode 100644 spine-godot/spine_godot/SpineSkeletonDataResource.cpp delete mode 100644 spine-godot/spine_godot/SpineSkeletonDataResource.h delete mode 100644 spine-godot/spine_godot/SpineSkeletonJsonDataResource.cpp delete mode 100644 spine-godot/spine_godot/SpineSkeletonJsonDataResource.h delete mode 100644 spine-godot/spine_godot/SpineSkin.cpp delete mode 100644 spine-godot/spine_godot/SpineSkin.h delete mode 100644 spine-godot/spine_godot/SpineSkinAttachmentMapEntries.cpp delete mode 100644 spine-godot/spine_godot/SpineSkinAttachmentMapEntries.h delete mode 100644 spine-godot/spine_godot/SpineSlot.cpp delete mode 100644 spine-godot/spine_godot/SpineSlot.h delete mode 100644 spine-godot/spine_godot/SpineSlotData.cpp delete mode 100644 spine-godot/spine_godot/SpineSlotData.h delete mode 100644 spine-godot/spine_godot/SpineSprite.cpp delete mode 100644 spine-godot/spine_godot/SpineSprite.h delete mode 100644 spine-godot/spine_godot/SpineSpriteAnimateDialog.cpp delete mode 100644 spine-godot/spine_godot/SpineSpriteAnimateDialog.h delete mode 100644 spine-godot/spine_godot/SpineSpriteMeshInstance2D.cpp delete mode 100644 spine-godot/spine_godot/SpineSpriteMeshInstance2D.h delete mode 100644 spine-godot/spine_godot/SpineTimeline.cpp delete mode 100644 spine-godot/spine_godot/SpineTimeline.h delete mode 100644 spine-godot/spine_godot/SpineTrackEntry.cpp delete mode 100644 spine-godot/spine_godot/SpineTrackEntry.h delete mode 100644 spine-godot/spine_godot/SpineTransformConstraint.cpp delete mode 100644 spine-godot/spine_godot/SpineTransformConstraint.h delete mode 100644 spine-godot/spine_godot/SpineTransformConstraintData.cpp delete mode 100644 spine-godot/spine_godot/SpineTransformConstraintData.h delete mode 100644 spine-godot/spine_godot/config.py delete mode 100644 spine-godot/spine_godot/register_types.cpp delete mode 100644 spine-godot/spine_godot/register_types.h diff --git a/.gitignore b/.gitignore index 81d8a4436..dc09502da 100644 --- a/.gitignore +++ b/.gitignore @@ -164,3 +164,5 @@ spine-cocos2dx/example-v4/build-macos spine-cocos2dx/example/build-ios spine-cocos2dx/example/proj.android/app/.cxx spine-cocos2dx/example/build-win +spine-godot/godot +spine-godot/spine_godot diff --git a/spine-godot/setup.sh b/spine-godot/setup.sh index f301c35e0..e78c64151 100755 --- a/spine-godot/setup.sh +++ b/spine-godot/setup.sh @@ -2,7 +2,7 @@ set -e rm -rf godot cp -r ../spine-cpp/spine-cpp spine_godot -git clone --depth 1 https://github.com/godotengine/godot.git -b 3.3.4-stable +git clone --depth 1 https://github.com/godotengine/godot.git -b 3.4.4-stable cp custom.py godot cp -r .idea godot ln -s $(pwd)/spine_godot godot/modules/spine_godot diff --git a/spine-godot/spine_godot/GodotSpineExtension.cpp b/spine-godot/spine_godot/GodotSpineExtension.cpp deleted file mode 100644 index cace4e354..000000000 --- a/spine-godot/spine_godot/GodotSpineExtension.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "GodotSpineExtension.h" - -#include "core/variant_parser.h" -#include - -#include - -spine::SpineExtension *spine::getDefaultExtension() { - return new GodotSpineExtension(); -} - -GodotSpineExtension::GodotSpineExtension() {} -GodotSpineExtension::~GodotSpineExtension() {} - -void *GodotSpineExtension::_alloc(size_t size, const char *file, int line) { - return memalloc(size); -} - -void *GodotSpineExtension::_calloc(size_t size, const char *file, int line) { - auto p = memalloc(size); - memset(p, 0, size); - return p; -} - -void *GodotSpineExtension::_realloc(void *ptr, size_t size, const char *file, int line) { - return memrealloc(ptr, size); -} - -void GodotSpineExtension::_free(void *mem, const char *file, int line) { - memfree(mem); -} - -char *GodotSpineExtension::_readFile(const spine::String &path, int *length) { - Error error; - auto res = FileAccess::get_file_as_array(String(path.buffer()), &error); - if (error != OK) { - if (length) *length = 0; - return NULL; - } - auto r = alloc(res.size(), __FILE__, __LINE__); - memcpy(r, res.ptr(), res.size()); - if (length) *length = res.size(); - return r; -} \ No newline at end of file diff --git a/spine-godot/spine_godot/GodotSpineExtension.h b/spine-godot/spine_godot/GodotSpineExtension.h deleted file mode 100644 index e00726051..000000000 --- a/spine-godot/spine_godot/GodotSpineExtension.h +++ /dev/null @@ -1,54 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINEEXTENSION_H -#define GODOT_SPINEEXTENSION_H - - -#include -class GodotSpineExtension : public spine::SpineExtension { -public: - GodotSpineExtension(); - - virtual ~GodotSpineExtension(); - -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 spine::String &path, int *length); -}; - - -#endif//GODOT_SPINEEXTENSION_H diff --git a/spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.cpp b/spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.cpp deleted file mode 100644 index 9c1cc80e5..000000000 --- a/spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "ResourceFormatLoaderSpineSkeletonJsonData.h" -#include "SpineSkeletonJsonDataResource.h" - -RES ResourceFormatLoaderSpineSkeletonJsonData::load(const String &p_path, const String &p_original_path, Error *r_error) { - Ref skeleton = memnew(SpineSkeletonJsonDataResource); - skeleton->load_from_file(p_path); - - if (r_error) { - *r_error = OK; - } - return skeleton; -} - -void ResourceFormatLoaderSpineSkeletonJsonData::get_recognized_extensions(List *r_extensions) const { - const char json_ext[] = "spjson"; - if (!r_extensions->find(json_ext)) { - r_extensions->push_back(json_ext); - } -} - -String ResourceFormatLoaderSpineSkeletonJsonData::get_resource_type(const String &p_path) const { - return "SpineSkeletonJsonDataResource"; -} - -bool ResourceFormatLoaderSpineSkeletonJsonData::handles_type(const String &p_type) const { - return p_type == "SpineSkeletonJsonDataResource" || ClassDB::is_parent_class(p_type, "SpineSkeletonJsonDataResource"); -} \ No newline at end of file diff --git a/spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.h b/spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.h deleted file mode 100644 index 9736655f6..000000000 --- a/spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.h +++ /dev/null @@ -1,45 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_RESOURCEFORMATLOADERSPINESKELETONJSONDATA_H -#define GODOT_RESOURCEFORMATLOADERSPINESKELETONJSONDATA_H - -#include "core/io/resource_loader.h" - -class ResourceFormatLoaderSpineSkeletonJsonData : public ResourceFormatLoader { - GDCLASS(ResourceFormatLoaderSpineSkeletonJsonData, ResourceFormatLoader); - -public: - virtual RES load(const String &p_path, const String &p_original_path, Error *r_error = NULL); - virtual void get_recognized_extensions(List *r_extensions) const; - virtual bool handles_type(const String &p_type) const; - virtual String get_resource_type(const String &p_path) const; -}; - -#endif//GODOT_RESOURCEFORMATLOADERSPINESKELETONJSONDATA_H diff --git a/spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.cpp b/spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.cpp deleted file mode 100644 index 5fa669c04..000000000 --- a/spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "ResourceFormatSaverSpineSkeletonJsonData.h" - -#include "SpineSkeletonJsonDataResource.h" - -Error ResourceFormatSaverSpineSkeletonJsonData::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { - Ref res = p_resource.get_ref_ptr(); - Error error = res->save_to_file(p_path); - return error; -} - -void ResourceFormatSaverSpineSkeletonJsonData::get_recognized_extensions(const RES &p_resource, List *p_extensions) const { - if (Object::cast_to(*p_resource)) { - p_extensions->push_back("spjson"); - } -} - -bool ResourceFormatSaverSpineSkeletonJsonData::recognize(const RES &p_resource) const { - return Object::cast_to(*p_resource) != nullptr; -} diff --git a/spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.h b/spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.h deleted file mode 100644 index 2c42ee5d0..000000000 --- a/spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.h +++ /dev/null @@ -1,45 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_RESOURCEFORMATSAVERSPINESKELETONJSONDATA_H -#define GODOT_RESOURCEFORMATSAVERSPINESKELETONJSONDATA_H - -#include "core/io/resource_saver.h" - -class ResourceFormatSaverSpineSkeletonJsonData : public ResourceFormatSaver { - GDCLASS(ResourceFormatSaverSpineSkeletonJsonData, ResourceFormatSaver); - -public: - Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0) override; - void get_recognized_extensions(const RES &p_resource, List *p_extensions) const override; - bool recognize(const RES &p_resource) const override; -}; - - -#endif//GODOT_RESOURCEFORMATSAVERSPINESKELETONJSONDATA_H diff --git a/spine-godot/spine_godot/SCsub b/spine-godot/spine_godot/SCsub deleted file mode 100644 index 0d5573c77..000000000 --- a/spine-godot/spine_godot/SCsub +++ /dev/null @@ -1,9 +0,0 @@ -Import('env') - -env_spine_runtime = env.Clone() - -env_spine_runtime.Append(CPPPATH=["spine-cpp/include"]) -env_spine_runtime.Append(CCFLAGS=['-O2']) - -env_spine_runtime.add_source_files(env.modules_sources, "spine-cpp/src/spine/*.cpp") -env_spine_runtime.add_source_files(env.modules_sources, "*.cpp") diff --git a/spine-godot/spine_godot/SpineAnimation.cpp b/spine-godot/spine_godot/SpineAnimation.cpp deleted file mode 100644 index 7f0772f24..000000000 --- a/spine-godot/spine_godot/SpineAnimation.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpineAnimation.h" - -#include "SpineSkeleton.h" -#include "SpineEvent.h" -#include "SpineTimeline.h" - -// enable more than 5 arguments of a method bind function -#include "core/method_bind_ext.gen.inc" - -void SpineAnimation::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_anim_name"), &SpineAnimation::get_anim_name); - ClassDB::bind_method(D_METHOD("get_duration"), &SpineAnimation::get_duration); - ClassDB::bind_method(D_METHOD("set_duration", "v"), &SpineAnimation::set_duration); - - ClassDB::bind_method(D_METHOD("apply", "skeleton", "last_time", "time", "loop", "events", "alpha", "blend", "direction"), &SpineAnimation::apply); - ClassDB::bind_method(D_METHOD("get_timelines"), &SpineAnimation::get_timelines); - ClassDB::bind_method(D_METHOD("has_timeline", "ids"), &SpineAnimation::has_timeline); -} - -SpineAnimation::SpineAnimation() : animation(NULL) {} -SpineAnimation::~SpineAnimation() {} - -String SpineAnimation::get_anim_name() { - return animation->getName().buffer(); -} - -float SpineAnimation::get_duration() { - return animation->getDuration(); -} -void SpineAnimation::set_duration(float v) { - animation->setDuration(v); -} - -void SpineAnimation::apply(Ref skeleton, float lastTime, float time, bool loop, - Array pEvents, float alpha, SpineConstant::MixBlend blend, - SpineConstant::MixDirection direction) { - spine::Vector events; - events.setSize(pEvents.size(), nullptr); - for (size_t i = 0; i < events.size(); ++i) { - events[i] = ((Ref) (pEvents[i]))->get_spine_object(); - } - animation->apply(*(skeleton->get_spine_object()), lastTime, time, loop, &events, alpha, (spine::MixBlend) blend, (spine::MixDirection) direction); -} - -Array SpineAnimation::get_timelines() { - auto &timelines = animation->getTimelines(); - Array res; - res.resize(timelines.size()); - - for (size_t i = 0; i < res.size(); ++i) { - auto a = Ref(memnew(SpineTimeline)); - a->set_spine_object(timelines[i]); - res.set(i, a); - } - - return res; -} - -bool SpineAnimation::has_timeline(Array ids) { - spine::Vector list; - list.setSize(ids.size(), 0); - - for (size_t i = 0; i < list.size(); ++i) { - list[i] = (int64_t) ids[i]; - } - return animation->hasTimeline(list); -} diff --git a/spine-godot/spine_godot/SpineAnimation.h b/spine-godot/spine_godot/SpineAnimation.h deleted file mode 100644 index 98dbed587..000000000 --- a/spine-godot/spine_godot/SpineAnimation.h +++ /dev/null @@ -1,74 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINEANIMATION_H -#define GODOT_SPINEANIMATION_H - -#include "core/variant_parser.h" - -#include "SpineConstant.h" - -#include - -class SpineEvent; -class SpineSkeleton; -class SpineTimeline; - -class SpineAnimation : public Reference { - GDCLASS(SpineAnimation, Reference); - -private: - spine::Animation *animation; - -protected: - static void _bind_methods(); - -public: - SpineAnimation(); - ~SpineAnimation(); - - inline void set_spine_object(spine::Animation *a) { - animation = a; - } - inline spine::Animation *get_spine_object() { - return animation; - } - - // Vector> pEvents - void apply(Ref skeleton, float lastTime, float time, bool loop, Array pEvents, float alpha, SpineConstant::MixBlend blend, SpineConstant::MixDirection direction); - - Array get_timelines(); // Vector> - bool has_timeline(Array ids);// Vector - - String get_anim_name(); - float get_duration(); - void set_duration(float v); -}; - -#endif//GODOT_SPINEANIMATION_H diff --git a/spine-godot/spine_godot/SpineAnimationState.cpp b/spine-godot/spine_godot/SpineAnimationState.cpp deleted file mode 100644 index 155a1d6d3..000000000 --- a/spine-godot/spine_godot/SpineAnimationState.cpp +++ /dev/null @@ -1,191 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpineAnimationState.h" - -void SpineAnimationState::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_animation", "anim_name", "loop", "track_id"), &SpineAnimationState::set_animation, DEFVAL(true), DEFVAL(0)); - ClassDB::bind_method(D_METHOD("update", "delta"), &SpineAnimationState::update, DEFVAL(0)); - ClassDB::bind_method(D_METHOD("apply", "skeleton"), &SpineAnimationState::apply); - ClassDB::bind_method(D_METHOD("clear_tracks"), &SpineAnimationState::clear_tracks); - ClassDB::bind_method(D_METHOD("clear_track"), &SpineAnimationState::clear_track); - ClassDB::bind_method(D_METHOD("add_animation", "anim_name", "delay", "loop", "track_id"), &SpineAnimationState::add_animation, DEFVAL(0), DEFVAL(true), DEFVAL(0)); - ClassDB::bind_method(D_METHOD("set_empty_animation", "track_id", "mix_duration"), &SpineAnimationState::set_empty_animation); - ClassDB::bind_method(D_METHOD("add_empty_animation", "track_id", "mix_duration", "delay"), &SpineAnimationState::add_empty_animation); - ClassDB::bind_method(D_METHOD("set_empty_animations", "mix_duration"), &SpineAnimationState::set_empty_animations); - ClassDB::bind_method(D_METHOD("get_data"), &SpineAnimationState::get_data); - ClassDB::bind_method(D_METHOD("get_time_scale"), &SpineAnimationState::get_time_scale); - ClassDB::bind_method(D_METHOD("set_time_scale", "time_scale"), &SpineAnimationState::set_time_scale); - ClassDB::bind_method(D_METHOD("disable_queue"), &SpineAnimationState::disable_queue); - ClassDB::bind_method(D_METHOD("enable_queue"), &SpineAnimationState::enable_queue); - // ClassDB::bind_method(D_METHOD("reload"), &SpineAnimationState::reload_animation_state); - ClassDB::bind_method(D_METHOD("get_current", "track_id"), &SpineAnimationState::get_current); -} - -SpineAnimationState::SpineAnimationState() : animation_state(NULL) { -} - -SpineAnimationState::~SpineAnimationState() { - if (animation_state) { - delete animation_state; - animation_state = NULL; - } -} - -void SpineAnimationState::load_animation_state(Ref ad) { - if (animation_state) { - delete animation_state; - animation_state = NULL; - } - animation_state = new spine::AnimationState(ad->get_animation_state_data()); - anim_state_data_res = ad; -} - -void SpineAnimationState::reload_animation_state() { - if (!anim_state_data_res.is_valid()) { - ERR_PRINT(" Reload animation state fail, because anim_state_data_res not set!"); - return; - } - if (animation_state) { - delete animation_state; - animation_state = NULL; - } - animation_state = new spine::AnimationState(anim_state_data_res->get_animation_state_data()); -} - -#define CHECK_V \ - if (!animation_state) { \ - ERR_PRINT("The animation state is not loaded yet!"); \ - return; \ - } -#define CHECK_X(x) \ - if (!animation_state) { \ - ERR_PRINT("The animation state is not loaded yet!"); \ - return x; \ - } -#define S_T(x) (spine::String(x.utf8())) -Ref SpineAnimationState::set_animation(const String &anim_name, bool loop, uint64_t track) { - CHECK_X(NULL); - auto skeleton_data = anim_state_data_res->get_skeleton(); - auto anim = skeleton_data->find_animation(anim_name); - if (!anim.is_valid() || anim->get_spine_object() == NULL) { - ERR_PRINT(String("Can not find animation: ") + anim_name); - return NULL; - } - auto entry = animation_state->setAnimation(track, anim->get_spine_object(), loop); - Ref gd_entry(memnew(SpineTrackEntry)); - gd_entry->set_spine_object(entry); - return gd_entry; -} -Ref SpineAnimationState::add_animation(const String &anim_name, float delay, bool loop, uint64_t track) { - CHECK_X(NULL); - auto skeleton_data = anim_state_data_res->get_skeleton(); - auto anim = skeleton_data->find_animation(anim_name); - if (!anim.is_valid() || anim->get_spine_object() == NULL) { - ERR_PRINT(String("Can not find animation: ") + anim_name); - return NULL; - } - auto entry = animation_state->addAnimation(track, anim->get_spine_object(), loop, delay); - Ref gd_entry(memnew(SpineTrackEntry)); - gd_entry->set_spine_object(entry); - return gd_entry; -} - -Ref SpineAnimationState::set_empty_animation(uint64_t track_id, float mix_duration) { - CHECK_X(NULL); - auto entry = animation_state->setEmptyAnimation(track_id, mix_duration); - Ref gd_entry(memnew(SpineTrackEntry)); - gd_entry->set_spine_object(entry); - return gd_entry; -} -Ref SpineAnimationState::add_empty_animation(uint64_t track_id, float mix_duration, float delay) { - CHECK_X(NULL); - auto entry = animation_state->addEmptyAnimation(track_id, mix_duration, delay); - Ref gd_entry(memnew(SpineTrackEntry)); - gd_entry->set_spine_object(entry); - return gd_entry; -} -void SpineAnimationState::set_empty_animations(float mix_duration) { - CHECK_V; - animation_state->setEmptyAnimations(mix_duration); -} - -void SpineAnimationState::update(float delta) { - CHECK_V; - animation_state->update(delta); -} -bool SpineAnimationState::apply(Ref skeleton) { - CHECK_X(false); - return animation_state->apply(*(skeleton->get_spine_object())); -} - - -void SpineAnimationState::clear_tracks() { - CHECK_V; - animation_state->clearTracks(); -} -void SpineAnimationState::clear_track(uint64_t track_id) { - CHECK_V; - animation_state->clearTrack(track_id); -} - -Ref SpineAnimationState::get_data() { - CHECK_X(NULL); - return anim_state_data_res; -} - -float SpineAnimationState::get_time_scale() { - CHECK_X(0); - return animation_state->getTimeScale(); -} -void SpineAnimationState::set_time_scale(float v) { - CHECK_V; - animation_state->setTimeScale(v); -} - -void SpineAnimationState::disable_queue() { - CHECK_V; - animation_state->disableQueue(); -} -void SpineAnimationState::enable_queue() { - CHECK_V; - animation_state->enableQueue(); -} - -Ref SpineAnimationState::get_current(uint64_t track_index) { - CHECK_X(NULL); - Ref gd_entry(memnew(SpineTrackEntry)); - auto entry = animation_state->getCurrent(track_index); - if (entry == NULL) return NULL; - gd_entry->set_spine_object(entry); - return gd_entry; -} - -#undef CHECK_V -#undef CHECK_X diff --git a/spine-godot/spine_godot/SpineAnimationState.h b/spine-godot/spine_godot/SpineAnimationState.h deleted file mode 100644 index 097be72ac..000000000 --- a/spine-godot/spine_godot/SpineAnimationState.h +++ /dev/null @@ -1,94 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINEANIMATIONSTATE_H -#define GODOT_SPINEANIMATIONSTATE_H - -#include "core/variant_parser.h" - -#include "SpineAnimationStateDataResource.h" -#include "SpineSkeleton.h" -#include "SpineTrackEntry.h" - -class SpineAnimationState : public Reference { - GDCLASS(SpineAnimationState, Reference); - -protected: - static void _bind_methods(); - -private: - spine::AnimationState *animation_state; - - Ref anim_state_data_res; - -public: - void load_animation_state(Ref ad); - - inline void set_animation_state(spine::AnimationState *a) { - animation_state = a; - } - inline spine::AnimationState *get_animation_state() { - return animation_state; - } - - void reload_animation_state(); - - Ref set_animation(const String &anim_name, bool loop, uint64_t track_id); - inline void set_animation_by_ref(Ref anim, bool loop, uint64_t track_id) { - if (anim.is_valid()) { - animation_state->setAnimation(track_id, anim->get_spine_object(), loop); - } - } - Ref add_animation(const String &anim_name, float delay, bool loop, uint64_t track_id); - - Ref set_empty_animation(uint64_t track_id, float mix_duration); - Ref add_empty_animation(uint64_t track_id, float mix_duration, float delay); - void set_empty_animations(float mix_duration); - - Ref get_data(); - - float get_time_scale(); - void set_time_scale(float v); - - void disable_queue(); - void enable_queue(); - - void update(float delta); - bool apply(Ref skeleton); - - void clear_tracks(); - void clear_track(uint64_t track_id); - - Ref get_current(uint64_t track_index); - - SpineAnimationState(); - ~SpineAnimationState(); -}; - -#endif//GODOT_SPINEANIMATIONSTATE_H diff --git a/spine-godot/spine_godot/SpineAnimationStateDataResource.cpp b/spine-godot/spine_godot/SpineAnimationStateDataResource.cpp deleted file mode 100644 index de4041ec2..000000000 --- a/spine-godot/spine_godot/SpineAnimationStateDataResource.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpineAnimationStateDataResource.h" - -SpineAnimationStateDataResource::SpineAnimationStateDataResource() : animation_state_data(NULL), animation_state_data_created(false), default_mix(0.5f) { -} -SpineAnimationStateDataResource::~SpineAnimationStateDataResource() { - if (animation_state_data) { - delete animation_state_data; - animation_state_data = NULL; - } -} - -void SpineAnimationStateDataResource::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_skeleton", "skeleton"), &SpineAnimationStateDataResource::set_skeleton); - ClassDB::bind_method(D_METHOD("get_spine_object"), &SpineAnimationStateDataResource::get_skeleton); - ClassDB::bind_method(D_METHOD("_on_skeleton_data_loaded"), &SpineAnimationStateDataResource::_on_skeleton_data_loaded); - ClassDB::bind_method(D_METHOD("is_animation_state_data_created"), &SpineAnimationStateDataResource::is_animation_state_data_created); - ClassDB::bind_method(D_METHOD("_on_skeleton_data_changed"), &SpineAnimationStateDataResource::_on_skeleton_data_changed); - ClassDB::bind_method(D_METHOD("set_default_mix", "mix"), &SpineAnimationStateDataResource::set_default_mix); - ClassDB::bind_method(D_METHOD("get_default_mix"), &SpineAnimationStateDataResource::get_default_mix); - ClassDB::bind_method(D_METHOD("get_mix", "from", "to"), &SpineAnimationStateDataResource::get_mix); - ClassDB::bind_method(D_METHOD("set_mix", "from", "to", "mix"), &SpineAnimationStateDataResource::set_mix); - - ADD_SIGNAL(MethodInfo("animation_state_data_created")); - ADD_SIGNAL(MethodInfo("skeleton_data_res_changed")); - ADD_SIGNAL(MethodInfo("animation_state_data_changed")); - - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "skeleton", PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "SpineSkeletonDataResource"), "set_skeleton", "get_spine_object"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "default_mix", PropertyHint::PROPERTY_HINT_EXP_RANGE, "0,1,0.01"), "set_default_mix", "get_default_mix"); -} - -void SpineAnimationStateDataResource::set_skeleton(const Ref &s) { - skeleton = s; - - _on_skeleton_data_changed(); - if (skeleton.is_valid()) { - skeleton->connect("skeleton_data_loaded", this, "_on_skeleton_data_loaded"); - skeleton->connect("atlas_res_changed", this, "_on_skeleton_data_changed"); - skeleton->connect("skeleton_json_res_changed", this, "_on_skeleton_data_changed"); - - if (skeleton->is_skeleton_data_loaded()) { - _on_skeleton_data_loaded(); - } - } else { - if (animation_state_data) { - delete animation_state_data; - animation_state_data = NULL; - animation_state_data_created = false; - // print_line("Animation state data deleted."); - } - } -} -Ref SpineAnimationStateDataResource::get_skeleton() { - return skeleton; -} - -void SpineAnimationStateDataResource::set_default_mix(float m) { - default_mix = m; - if (!is_animation_state_data_created()) { - // ERR_PRINT("'set_default_mix' fail. Animation state data is not created!"); - return; - } - animation_state_data->setDefaultMix(((m >= 0 && m <= 1) ? m : m <= 0 ? 0 - : 1)); - // emit_signal("animation_state_data_changed"); -} -float SpineAnimationStateDataResource::get_default_mix() { - if (!is_animation_state_data_created()) { - // ERR_PRINT("'get_default_mix' fail. Animation state data is not created!"); - return default_mix; - } - default_mix = animation_state_data->getDefaultMix(); - return default_mix; -} - -void SpineAnimationStateDataResource::set_mix(const String &from, const String &to, float mix_duration) { - if (!is_animation_state_data_created()) { - ERR_PRINT("'set_mix' fail. Animation state data is not created!"); - return; - } - auto anim_from = get_skeleton()->find_animation(from); - auto anim_to = get_skeleton()->find_animation(to); - if (!anim_from.is_valid()) { - ERR_PRINT("'set_mix' fail. From animation animation not found!"); - return; - } - if (!anim_to.is_valid()) { - ERR_PRINT("'set_mix' fail. To animation animation not found!"); - return; - } - animation_state_data->setMix(anim_from->get_spine_object(), anim_to->get_spine_object(), mix_duration); -} -float SpineAnimationStateDataResource::get_mix(const String &from, const String &to) { - if (!is_animation_state_data_created()) { - ERR_PRINT("'set_mix' fail. Animation state data is not created!"); - return 0; - } - auto anim_from = get_skeleton()->find_animation(from); - auto anim_to = get_skeleton()->find_animation(to); - if (!anim_from.is_valid()) { - ERR_PRINT("'set_mix' fail. From animation animation not found!"); - return 0; - } - if (!anim_to.is_valid()) { - ERR_PRINT("'set_mix' fail. To animation animation not found!"); - return 0; - } - return animation_state_data->getMix(anim_from->get_spine_object(), anim_to->get_spine_object()); -} - -void SpineAnimationStateDataResource::_on_skeleton_data_loaded() { - animation_state_data = new spine::AnimationStateData(skeleton->get_skeleton_data()); - // print_line("Animation state data created."); - - - emit_signal("animation_state_data_created"); - animation_state_data->setDefaultMix(default_mix); - animation_state_data_created = true; -} - -void SpineAnimationStateDataResource::_on_skeleton_data_changed() { - animation_state_data_created = false; - if (animation_state_data) { - delete animation_state_data; - animation_state_data = NULL; - // print_line("Animation state data deleted."); - } - - // print_line("skeleton_data_res_changed emitted"); - emit_signal("skeleton_data_res_changed"); -} - -bool SpineAnimationStateDataResource::is_animation_state_data_created() { - return animation_state_data_created; -} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineAnimationStateDataResource.h b/spine-godot/spine_godot/SpineAnimationStateDataResource.h deleted file mode 100644 index 58f0cd536..000000000 --- a/spine-godot/spine_godot/SpineAnimationStateDataResource.h +++ /dev/null @@ -1,76 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINEANIMATIONSTATEDATARESOURCE_H -#define GODOT_SPINEANIMATIONSTATEDATARESOURCE_H - -#include "core/variant_parser.h" - -#include "SpineSkeletonDataResource.h" - -class SpineAnimationStateDataResource : public Resource { - GDCLASS(SpineAnimationStateDataResource, Resource); - -protected: - static void _bind_methods(); - -private: - Ref skeleton; - - spine::AnimationStateData *animation_state_data; - - bool animation_state_data_created; - - float default_mix; - -public: - void set_skeleton(const Ref &s); - Ref get_skeleton(); - - inline spine::AnimationStateData *get_animation_state_data() { - return animation_state_data; - } - - void set_default_mix(float m); - float get_default_mix(); - - void set_mix(const String &from, const String &to, float mix_duration); - float get_mix(const String &from, const String &to); - - - void _on_skeleton_data_loaded(); - void _on_skeleton_data_changed(); - - bool is_animation_state_data_created(); - - SpineAnimationStateDataResource(); - ~SpineAnimationStateDataResource(); -}; - -#endif//GODOT_SPINEANIMATIONSTATEDATARESOURCE_H diff --git a/spine-godot/spine_godot/SpineAtlasResource.cpp b/spine-godot/spine_godot/SpineAtlasResource.cpp deleted file mode 100644 index 088426621..000000000 --- a/spine-godot/spine_godot/SpineAtlasResource.cpp +++ /dev/null @@ -1,239 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpineAtlasResource.h" -#include "core/io/json.h" - -#include - -class GodotSpineTextureLoader : public spine::TextureLoader { -private: - Array *textures, *normal_maps; - String normal_map_prefix; - -public: - GodotSpineTextureLoader(Array *t, Array *nt, const String &p) : textures(t), normal_maps(nt), normal_map_prefix(p) { - if (textures) textures->clear(); - if (normal_maps) normal_maps->clear(); - } - - String fix_path(const String &path) { - if (path.size() > 5 && path[4] == '/' && path[5] == '/') return path; - const String prefix = "res:/"; - auto i = path.find(prefix); - auto sub_str_pos = i + prefix.size() - 1; - if (sub_str_pos < 0) return path; - auto res = path.substr(sub_str_pos); - - if (res.size() > 0) { - if (res[0] != '/') { - return prefix + "/" + res; - } else { - return prefix + res; - } - } - return path; - } - - virtual void load(spine::AtlasPage &page, const spine::String &path) { - Error err = OK; - auto fixed_path = fix_path(String(path.buffer())); - - Ref texture = ResourceLoader::load(fixed_path, "", false, &err); - if (err != OK) { - print_error(vformat("Can't load texture: \"%s\"", String(path.buffer()))); - page.setRendererObject((void *) memnew(SpineRendererObject{nullptr})); - return; - } - - if (textures) textures->append(texture); - auto spine_renderer_object = memnew(SpineRendererObject); - spine_renderer_object->texture = texture; - - String temp_path = fixed_path; - String new_path = vformat("%s/%s_%s", temp_path.get_base_dir(), normal_map_prefix, temp_path.get_file()); - if (ResourceLoader::exists(new_path)) { - Ref normal_map = ResourceLoader::load(new_path); - if (normal_maps) normal_maps->append(normal_map); - spine_renderer_object->normal_map = normal_map; - } - - page.setRendererObject((void *) spine_renderer_object); - - page.width = texture->get_width(); - page.height = texture->get_height(); - } - - virtual void unload(void *p) { - auto spine_renderer_object = (SpineRendererObject *) p; - Ref &texture = spine_renderer_object->texture; - if (texture.is_valid()) texture.unref(); - Ref &normal_map = spine_renderer_object->normal_map; - if (normal_map.is_valid()) normal_map.unref(); - memdelete(spine_renderer_object); - } -}; - -SpineAtlasResource::SpineAtlasResource() : atlas(nullptr), normal_texture_prefix("n") {} - -SpineAtlasResource::~SpineAtlasResource() { - if (atlas) delete atlas; -} - -void SpineAtlasResource::_bind_methods() { - ClassDB::bind_method(D_METHOD("load_from_atlas_file", "path"), &SpineAtlasResource::load_from_atlas_file); - - ClassDB::bind_method(D_METHOD("get_source_path"), &SpineAtlasResource::get_source_path); - - ClassDB::bind_method(D_METHOD("get_textures"), &SpineAtlasResource::get_textures); - ClassDB::bind_method(D_METHOD("get_normal_maps"), &SpineAtlasResource::get_normal_maps); - - ADD_PROPERTY(PropertyInfo(Variant::STRING, "source_path"), "", "get_source_path"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "textures"), "", "get_textures"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "normal_maps"), "", "get_normal_maps"); -} - - -Array SpineAtlasResource::get_textures() { - return textures; -} - -Array SpineAtlasResource::get_normal_maps() { - return normal_maps; -} - -String SpineAtlasResource::get_source_path() { - return source_path; -} - -Error SpineAtlasResource::load_from_atlas_file(const String &p_path) { - source_path = p_path; - Error err; - - atlas_data = FileAccess::get_file_as_string(p_path, &err); - if (err != OK) return err; - - if (atlas) delete atlas; - textures.clear(); - normal_maps.clear(); - atlas = new spine::Atlas(atlas_data.utf8(), atlas_data.size(), source_path.get_base_dir().utf8(), new GodotSpineTextureLoader(&textures, &normal_maps, normal_texture_prefix)); - if (atlas) return OK; - - textures.clear(); - normal_maps.clear(); - return ERR_FILE_UNRECOGNIZED; -} - -Error SpineAtlasResource::load_from_file(const String &p_path) { - Error err; - String json_string = FileAccess::get_file_as_string(p_path, &err); - if (err != OK) return err; - - String error_string; - int error_line; - JSON json; - Variant result; - err = json.parse(json_string, result, error_string, error_line); - if (err != OK) return err; - - Dictionary content = Dictionary(result); - source_path = content["source_path"]; - atlas_data = content["atlas_data"]; - normal_texture_prefix = content["normal_texture_prefix"]; - - if (atlas) delete atlas; - textures.clear(); - normal_maps.clear(); - atlas = new spine::Atlas(atlas_data.utf8(), atlas_data.size(), source_path.get_base_dir().utf8(), new GodotSpineTextureLoader(&textures, &normal_maps, normal_texture_prefix)); - if (atlas) return OK; - - textures.clear(); - normal_maps.clear(); - return ERR_FILE_UNRECOGNIZED; -} - -Error SpineAtlasResource::save_to_file(const String &p_path) { - Error err; - FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &err); - if (err != OK) { - if (file) file->close(); - return err; - } - - Dictionary content; - content["source_path"] = source_path; - content["atlas_data"] = atlas_data; - content["normal_texture_prefix"] = normal_texture_prefix; - - file->store_string(JSON::print(content)); - file->close(); - - return OK; -} - -RES SpineAtlasResourceFormatLoader::load(const String &p_path, const String &p_original_path, Error *r_error) { - Ref atlas = memnew(SpineAtlasResource); - atlas->load_from_file(p_path); - - if (r_error) { - *r_error = OK; - } - return atlas; -} - -void SpineAtlasResourceFormatLoader::get_recognized_extensions(List *r_extensions) const { - const char atlas_ext[] = "spatlas"; - if (!r_extensions->find(atlas_ext)) { - r_extensions->push_back(atlas_ext); - } -} - -String SpineAtlasResourceFormatLoader::get_resource_type(const String &p_path) const { - return "SpineAtlasResource"; -} - -bool SpineAtlasResourceFormatLoader::handles_type(const String &p_type) const { - return p_type == "SpineAtlasResource" || ClassDB::is_parent_class(p_type, "SpineAtlasResource"); -} - -Error SpineAtlasResourceFormatSaver::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { - Ref res = p_resource.get_ref_ptr(); - Error error = res->save_to_file(p_path); - return error; -} - -void SpineAtlasResourceFormatSaver::get_recognized_extensions(const RES &p_resource, List *p_extensions) const { - if (Object::cast_to(*p_resource)) { - p_extensions->push_back("spatlas"); - } -} - -bool SpineAtlasResourceFormatSaver::recognize(const RES &p_resource) const { - return Object::cast_to(*p_resource) != nullptr; -} diff --git a/spine-godot/spine_godot/SpineAtlasResource.h b/spine-godot/spine_godot/SpineAtlasResource.h deleted file mode 100644 index 84c7cc9ca..000000000 --- a/spine-godot/spine_godot/SpineAtlasResource.h +++ /dev/null @@ -1,100 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINEATLASRESOURCE_H -#define GODOT_SPINEATLASRESOURCE_H - - -#include "core/variant_parser.h" -#include "core/io/resource_loader.h" -#include "core/io/resource_saver.h" -#include "core/io/image_loader.h" -#include "scene/resources/texture.h" - -#include -#include -#include -#include "SpineRendererObject.h" - -class SpineAtlasResource : public Resource { - GDCLASS(SpineAtlasResource, Resource); - -protected: - static void _bind_methods(); - - spine::Atlas *atlas; - - String source_path; - String atlas_data; - String normal_texture_prefix; - - Array textures; - Array normal_maps; - -public: - inline String &get_atlas_data() { return atlas_data; } - - inline spine::Atlas *get_spine_atlas() { return atlas; } - - inline void set_normal_texture_prefix(const String &p) { normal_texture_prefix = p; } - - Error load_from_atlas_file(const String &p_path);// .atlas - - Error load_from_file(const String &p_path);// .spatlas - Error save_to_file(const String &p_path); // .spatlas - - String get_source_path(); - Array get_textures(); - Array get_normal_maps(); - - SpineAtlasResource(); - virtual ~SpineAtlasResource(); -}; - -class SpineAtlasResourceFormatLoader : public ResourceFormatLoader { -GDCLASS(SpineAtlasResourceFormatLoader, ResourceFormatLoader); - -public: - virtual RES load(const String &p_path, const String &p_original_path, Error *r_error = NULL); - virtual void get_recognized_extensions(List *r_extensions) const; - virtual bool handles_type(const String &p_type) const; - virtual String get_resource_type(const String &p_path) const; -}; - -class SpineAtlasResourceFormatSaver : public ResourceFormatSaver { -GDCLASS(SpineAtlasResourceFormatSaver, ResourceFormatSaver); - -public: - Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0) override; - void get_recognized_extensions(const RES &p_resource, List *p_extensions) const override; - bool recognize(const RES &p_resource) const override; -}; - - -#endif//GODOT_SPINEATLASRESOURCE_H diff --git a/spine-godot/spine_godot/SpineAttachment.cpp b/spine-godot/spine_godot/SpineAttachment.cpp deleted file mode 100644 index e25f54c5e..000000000 --- a/spine-godot/spine_godot/SpineAttachment.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpineAttachment.h" - -void SpineAttachment::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_attachment_name"), &SpineAttachment::get_attachment_name); - ClassDB::bind_method(D_METHOD("copy"), &SpineAttachment::copy); -} - -SpineAttachment::SpineAttachment() : attachment(NULL) {} -SpineAttachment::~SpineAttachment() { - if (attachment) { - attachment->dereference(); - attachment = NULL; - } -} - -String SpineAttachment::get_attachment_name() { - return attachment->getName().buffer(); -} - -Ref SpineAttachment::copy() { - auto a = attachment->copy(); - if (a == NULL) return NULL; - Ref gd_attachment(memnew(SpineAttachment)); - gd_attachment->set_spine_object(a); - return gd_attachment; -} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineAttachment.h b/spine-godot/spine_godot/SpineAttachment.h deleted file mode 100644 index 81ec52c9d..000000000 --- a/spine-godot/spine_godot/SpineAttachment.h +++ /dev/null @@ -1,64 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINEATTACHMENT_H -#define GODOT_SPINEATTACHMENT_H - -#include "core/variant_parser.h" - -#include - -class SpineAttachment : public Reference { - GDCLASS(SpineAttachment, Reference); - -protected: - static void _bind_methods(); - -private: - spine::Attachment *attachment; - -public: - SpineAttachment(); - ~SpineAttachment(); - - inline void set_spine_object(spine::Attachment *a) { - attachment = a; - if (attachment) - attachment->reference(); - } - inline spine::Attachment *get_spine_object() { - return attachment; - } - - String get_attachment_name(); - - Ref copy(); -}; - -#endif//GODOT_SPINEATTACHMENT_H diff --git a/spine-godot/spine_godot/SpineBone.cpp b/spine-godot/spine_godot/SpineBone.cpp deleted file mode 100644 index afde7a781..000000000 --- a/spine-godot/spine_godot/SpineBone.cpp +++ /dev/null @@ -1,536 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpineBone.h" - -#include "SpineSprite.h" -#include "SpineSkeleton.h" - -void SpineBone::_bind_methods() { - ClassDB::bind_method(D_METHOD("update_world_transform"), &SpineBone::update_world_transform); - // void set_to_setup_pose(); - // - // Vector2 world_to_local(Vector2 world_position); - // - // Vector2 local_to_world(Vector2 local_position); - // - // float world_to_local_rotation(float world_rotation); - // - // float local_to_world_rotation(float local_rotation); - // - // void rotate_world(float degrees); - ClassDB::bind_method(D_METHOD("set_to_setup_pose"), &SpineBone::set_to_setup_pose); - ClassDB::bind_method(D_METHOD("world_to_local", "world_position"), &SpineBone::world_to_local); - ClassDB::bind_method(D_METHOD("local_to_world", "local_position"), &SpineBone::local_to_world); - ClassDB::bind_method(D_METHOD("world_to_local_rotation", "world_rotation"), &SpineBone::world_to_local_rotation); - ClassDB::bind_method(D_METHOD("local_to_world_rotation", "local_rotation"), &SpineBone::local_to_world_rotation); - ClassDB::bind_method(D_METHOD("rotate_world"), &SpineBone::rotate_world); - // - // float get_world_to_local_rotation_x(); - // float get_world_to_local_rotation_y(); - // - // Ref get_data(); - // - // Ref get_skeleton(); - // - // Ref get_parent(); - // - // Array get_children(); - ClassDB::bind_method(D_METHOD("get_world_to_local_rotation_x"), &SpineBone::get_world_to_local_rotation_x); - ClassDB::bind_method(D_METHOD("get_world_to_local_rotation_y"), &SpineBone::get_world_to_local_rotation_y); - ClassDB::bind_method(D_METHOD("get_data"), &SpineBone::get_data); - ClassDB::bind_method(D_METHOD("get_skeleton"), &SpineBone::get_skeleton); - ClassDB::bind_method(D_METHOD("get_parent"), &SpineBone::get_parent); - ClassDB::bind_method(D_METHOD("get_children"), &SpineBone::get_children); - // - // float get_x(); - // void set_x(float v); - // - // float get_y(); - // void set_y(float v); - // - // float get_rotation(); - // void set_rotation(float v); - // - // float get_scale_x(); - // void set_scale_x(float v); - ClassDB::bind_method(D_METHOD("get_x"), &SpineBone::get_x); - ClassDB::bind_method(D_METHOD("set_x", "v"), &SpineBone::set_x); - ClassDB::bind_method(D_METHOD("get_y"), &SpineBone::get_y); - ClassDB::bind_method(D_METHOD("set_y", "v"), &SpineBone::set_y); - ClassDB::bind_method(D_METHOD("get_rotation"), &SpineBone::get_rotation); - ClassDB::bind_method(D_METHOD("set_rotation", "v"), &SpineBone::set_rotation); - ClassDB::bind_method(D_METHOD("get_scale_x"), &SpineBone::get_scale_x); - ClassDB::bind_method(D_METHOD("set_scale_x", "v"), &SpineBone::set_scale_x); - // - // float get_scale_y(); - // void set_scale_y(float v); - // - // float get_shear_x(); - // void set_shear_x(float v); - // - // float get_shear_y(); - // void set_shear_y(float v); - // - // float get_applied_rotation(); - // void set_applied_rotation(float v); - ClassDB::bind_method(D_METHOD("get_scale_y"), &SpineBone::get_scale_y); - ClassDB::bind_method(D_METHOD("set_scale_y", "v"), &SpineBone::set_scale_y); - ClassDB::bind_method(D_METHOD("get_shear_x"), &SpineBone::get_shear_x); - ClassDB::bind_method(D_METHOD("set_shear_x", "v"), &SpineBone::set_shear_x); - ClassDB::bind_method(D_METHOD("get_shear_y"), &SpineBone::get_shear_y); - ClassDB::bind_method(D_METHOD("set_shear_y", "v"), &SpineBone::set_shear_y); - ClassDB::bind_method(D_METHOD("get_applied_rotation"), &SpineBone::get_applied_rotation); - ClassDB::bind_method(D_METHOD("set_applied_rotation", "v"), &SpineBone::set_applied_rotation); - // - // float get_a_x(); - // void set_a_x(float v); - // - // float get_a_y(); - // void set_a_y(float v); - // - // float get_a_scale_x(); - // void set_a_scale_x(float v); - // - // float get_a_scale_y(); - // void set_a_scale_y(float v); - ClassDB::bind_method(D_METHOD("get_a_x"), &SpineBone::get_a_x); - ClassDB::bind_method(D_METHOD("set_a_x", "v"), &SpineBone::set_a_x); - ClassDB::bind_method(D_METHOD("get_a_y"), &SpineBone::get_a_y); - ClassDB::bind_method(D_METHOD("set_a_y", "v"), &SpineBone::set_a_y); - ClassDB::bind_method(D_METHOD("get_a_scale_x"), &SpineBone::get_a_scale_x); - ClassDB::bind_method(D_METHOD("set_a_scale_x", "v"), &SpineBone::set_a_scale_x); - ClassDB::bind_method(D_METHOD("get_a_scale_y"), &SpineBone::get_a_scale_y); - ClassDB::bind_method(D_METHOD("set_a_scale_y", "v"), &SpineBone::set_a_scale_y); - // - // float get_a_shear_x(); - // void set_a_shear_x(float v); - // - // float get_a_shear_y(); - // void set_a_shear_y(float v); - // - // float get_a(); - // void set_a(float v); - // - // float get_b(); - // void set_b(float v); - ClassDB::bind_method(D_METHOD("get_a_shear_x"), &SpineBone::get_a_shear_x); - ClassDB::bind_method(D_METHOD("set_a_shear_x", "v"), &SpineBone::set_a_shear_x); - ClassDB::bind_method(D_METHOD("get_a_shear_y"), &SpineBone::get_a_shear_y); - ClassDB::bind_method(D_METHOD("set_a_shear_y", "v"), &SpineBone::set_a_shear_y); - ClassDB::bind_method(D_METHOD("get_a"), &SpineBone::get_a); - ClassDB::bind_method(D_METHOD("set_a", "v"), &SpineBone::set_a); - ClassDB::bind_method(D_METHOD("get_b"), &SpineBone::get_b); - ClassDB::bind_method(D_METHOD("set_b", "v"), &SpineBone::set_b); - // - // float get_c(); - // void set_c(float v); - // - // float get_d(); - // void set_d(float v); - // - // float get_world_x(); - // void set_world_x(float v); - // - // float get_world_y(); - // void set_world_y(float v); - ClassDB::bind_method(D_METHOD("get_c"), &SpineBone::get_c); - ClassDB::bind_method(D_METHOD("set_c", "v"), &SpineBone::set_c); - ClassDB::bind_method(D_METHOD("get_d"), &SpineBone::get_d); - ClassDB::bind_method(D_METHOD("set_d", "v"), &SpineBone::set_d); - ClassDB::bind_method(D_METHOD("get_world_x"), &SpineBone::get_world_x); - ClassDB::bind_method(D_METHOD("set_world_x", "v"), &SpineBone::set_world_x); - ClassDB::bind_method(D_METHOD("get_world_y"), &SpineBone::get_world_y); - ClassDB::bind_method(D_METHOD("set_world_y", "v"), &SpineBone::set_world_y); - // - // float get_world_rotation_x(); - // float get_world_rotation_y(); - // - // float get_world_scale_x(); - // float get_world_scale_y(); - // - // bool is_applied_valid(); - // void set_applied_valid(bool v); - // - // bool is_active(); - // void set_active(bool v); - ClassDB::bind_method(D_METHOD("get_world_rotation_x"), &SpineBone::get_world_rotation_x); - ClassDB::bind_method(D_METHOD("get_world_rotation_y"), &SpineBone::get_world_rotation_y); - ClassDB::bind_method(D_METHOD("get_world_scale_x"), &SpineBone::get_world_scale_x); - ClassDB::bind_method(D_METHOD("get_world_scale_y"), &SpineBone::get_world_scale_y); - ClassDB::bind_method(D_METHOD("is_active"), &SpineBone::is_active); - ClassDB::bind_method(D_METHOD("set_active", "v"), &SpineBone::set_active); - - ClassDB::bind_method(D_METHOD("get_godot_transform"), &SpineBone::get_godot_transform); - ClassDB::bind_method(D_METHOD("set_godot_transform", "local_transform"), &SpineBone::set_godot_transform); - ClassDB::bind_method(D_METHOD("get_godot_global_transform"), &SpineBone::get_godot_global_transform); - ClassDB::bind_method(D_METHOD("set_godot_global_transform", "global_transform"), &SpineBone::set_godot_global_transform); - - ClassDB::bind_method(D_METHOD("apply_world_transform_2d", "node2d"), &SpineBone::apply_world_transform_2d); -} - -SpineBone::SpineBone() : bone(NULL), the_sprite(nullptr) {} -SpineBone::~SpineBone() {} - -void SpineBone::update_world_transform() { - bone->updateWorldTransform(); -} - -void SpineBone::set_to_setup_pose() { - bone->setToSetupPose(); -} - -Vector2 SpineBone::world_to_local(Vector2 world_position) { - float x, y; - bone->worldToLocal(world_position.x, world_position.y, x, y); - return Vector2(x, y); -} - -Vector2 SpineBone::local_to_world(Vector2 local_position) { - float x, y; - bone->localToWorld(local_position.x, local_position.y, x, y); - return Vector2(x, y); -} - -float SpineBone::world_to_local_rotation(float world_rotation) { - return bone->worldToLocalRotation(world_rotation); -} - -float SpineBone::local_to_world_rotation(float local_rotation) { - return bone->localToWorldRotation(local_rotation); -} - -void SpineBone::rotate_world(float degrees) { - bone->rotateWorld(degrees); -} - -float SpineBone::get_world_to_local_rotation_x() { - return bone->getWorldToLocalRotationX(); -} -float SpineBone::get_world_to_local_rotation_y() { - return bone->getWorldToLocalRotationY(); -} - -Ref SpineBone::get_data() { - auto &bd = bone->getData(); - Ref gd_bd(memnew(SpineBoneData)); - gd_bd->set_spine_object(&bd); - return gd_bd; -} - -Ref SpineBone::get_skeleton() { - auto &s = bone->getSkeleton(); - Ref gd_s(memnew(SpineSkeleton)); - gd_s->set_spine_object(&s); - gd_s->set_spine_sprite(the_sprite); - return gd_s; -} - -Ref SpineBone::get_parent() { - auto b = bone->getParent(); - if (b == NULL) return NULL; - Ref gd_b(memnew(SpineBone)); - gd_b->set_spine_object(b); - gd_b->set_spine_sprite(the_sprite); - return gd_b; -} - -Array SpineBone::get_children() { - auto bs = bone->getChildren(); - Array gd_bs; - gd_bs.resize(bs.size()); - for (size_t i = 0; i < bs.size(); ++i) { - auto b = bs[i]; - if (b == NULL) gd_bs[i] = Ref(NULL); - Ref gd_b(memnew(SpineBone)); - gd_b->set_spine_object(b); - gd_b->set_spine_sprite(the_sprite); - gd_bs[i] = gd_b; - } - return gd_bs; -} - -float SpineBone::get_x() { - return bone->getX(); -} -void SpineBone::set_x(float v) { - bone->setX(v); -} - -float SpineBone::get_y() { - return bone->getY(); -} -void SpineBone::set_y(float v) { - bone->setY(v); -} - -float SpineBone::get_rotation() { - return bone->getRotation(); -} -void SpineBone::set_rotation(float v) { - bone->setRotation(v); -} - -float SpineBone::get_scale_x() { - return bone->getScaleX(); -} -void SpineBone::set_scale_x(float v) { - bone->setScaleX(v); -} - -float SpineBone::get_scale_y() { - return bone->getScaleY(); -} -void SpineBone::set_scale_y(float v) { - bone->setScaleY(v); -} - -float SpineBone::get_shear_x() { - return bone->getShearX(); -} -void SpineBone::set_shear_x(float v) { - bone->setShearX(v); -} - -float SpineBone::get_shear_y() { - return bone->getShearY(); -} -void SpineBone::set_shear_y(float v) { - bone->setShearY(v); -} - -float SpineBone::get_applied_rotation() { - return bone->getAppliedRotation(); -} -void SpineBone::set_applied_rotation(float v) { - bone->setAppliedRotation(v); -} - -float SpineBone::get_a_x() { - return bone->getAX(); -} -void SpineBone::set_a_x(float v) { - bone->setAX(v); -} - -float SpineBone::get_a_y() { - return bone->getAY(); -} -void SpineBone::set_a_y(float v) { - bone->setAY(v); -} - -float SpineBone::get_a_scale_x() { - return bone->getAScaleX(); -} -void SpineBone::set_a_scale_x(float v) { - bone->setAScaleX(v); -} - -float SpineBone::get_a_scale_y() { - return bone->getAScaleY(); -} -void SpineBone::set_a_scale_y(float v) { - bone->setAScaleY(v); -} - -float SpineBone::get_a_shear_x() { - return bone->getAShearX(); -} -void SpineBone::set_a_shear_x(float v) { - bone->setAShearX(v); -} - -float SpineBone::get_a_shear_y() { - return bone->getAShearY(); -} -void SpineBone::set_a_shear_y(float v) { - bone->setAShearY(v); -} - -float SpineBone::get_a() { - return bone->getA(); -} -void SpineBone::set_a(float v) { - bone->setA(v); -} - -float SpineBone::get_b() { - return bone->getB(); -} -void SpineBone::set_b(float v) { - bone->setB(v); -} - -float SpineBone::get_c() { - return bone->getC(); -} -void SpineBone::set_c(float v) { - bone->setC(v); -} - -float SpineBone::get_d() { - return bone->getD(); -} -void SpineBone::set_d(float v) { - bone->setD(v); -} - -float SpineBone::get_world_x() { - return bone->getWorldX(); -} -void SpineBone::set_world_x(float v) { - bone->setWorldX(v); -} - -float SpineBone::get_world_y() { - return bone->getWorldY(); -} -void SpineBone::set_world_y(float v) { - bone->setWorldY(v); -} - -float SpineBone::get_world_rotation_x() { - return bone->getWorldRotationX(); -} -float SpineBone::get_world_rotation_y() { - return bone->getWorldRotationY(); -} - -float SpineBone::get_world_scale_x() { - return bone->getWorldScaleX(); -} -float SpineBone::get_world_scale_y() { - return bone->getWorldScaleY(); -} - -bool SpineBone::is_active() { - return bone->isActive(); -} -void SpineBone::set_active(bool v) { - bone->setActive(v); -} - -// External feature functions -void SpineBone::apply_world_transform_2d(Variant o) { - if (o.get_type() == Variant::OBJECT) { - auto node = (Node *) o; - if (node->is_class("Node2D")) { - auto node2d = (Node2D *) node; - // In godot the y-axis is nag to spine - node2d->set_transform(Transform2D( - get_a(), get_c(), - get_b(), get_d(), - get_world_x(), -get_world_y())); - // Fix the rotation - auto pos = node2d->get_position(); - node2d->translate(-pos); - node2d->set_rotation(-node2d->get_rotation()); - node2d->translate(pos); - } - } -} - -Transform2D SpineBone::get_godot_transform() { - if (get_spine_object() == nullptr) - return Transform2D(); - Transform2D trans; - trans.translate(get_x(), -get_y()); - // It seems that spine uses degree for rotation - trans.rotate(Math::deg2rad(-get_rotation())); - trans.scale(Size2(get_scale_x(), get_scale_y())); - return trans; -} - -void SpineBone::set_godot_transform(Transform2D trans) { - if (get_spine_object() == nullptr) - return; - Vector2 position = trans.get_origin(); - position.y *= -1; - real_t rotation = trans.get_rotation(); - rotation = Math::rad2deg(-rotation); - Vector2 scale = trans.get_scale(); - - set_x(position.x); - set_y(position.y); - set_rotation(rotation); - set_scale_x(scale.x); - set_scale_y(scale.y); -} - -Transform2D SpineBone::get_godot_global_transform() { - if (get_spine_object() == nullptr) - return Transform2D(); - if (the_sprite == nullptr) - return get_godot_transform(); - Transform2D res = the_sprite->get_transform(); - res.translate(get_world_x(), -get_world_y()); - res.rotate(Math::deg2rad(-get_world_rotation_x())); - res.scale(Vector2(get_world_scale_x(), get_world_scale_y())); - auto p = the_sprite->get_parent() ? Object::cast_to(the_sprite->get_parent()) : nullptr; - if (p) { - return p->get_global_transform() * res; - } - return res; -} - -void SpineBone::set_godot_global_transform(Transform2D transform) { - if (get_spine_object() == nullptr) - return; - if (the_sprite == nullptr) - set_godot_transform(transform); - transform = the_sprite->get_global_transform().affine_inverse() * transform; - Vector2 position = transform.get_origin(); - real_t rotation = transform.get_rotation(); - Vector2 scale = transform.get_scale(); - position.y *= -1; - auto parent = get_parent(); - if (parent.is_valid()) { - position = parent->world_to_local(position); - if (parent->get_world_scale_x() != 0) - scale.x /= parent->get_world_scale_x(); - else - print_error("The parent scale.x is zero."); - if (parent->get_world_scale_y() != 0) - scale.y /= parent->get_world_scale_y(); - else - print_error("The parent scale.y is zero."); - } - rotation = world_to_local_rotation(Math::rad2deg(-rotation)); - - set_x(position.x); - set_y(position.y); - set_rotation(rotation); - set_scale_x(scale.x); - set_scale_y(scale.y); -} - -void SpineBone::set_spine_sprite(SpineSprite *s) { - the_sprite = s; -} diff --git a/spine-godot/spine_godot/SpineBone.h b/spine-godot/spine_godot/SpineBone.h deleted file mode 100644 index b7efd1381..000000000 --- a/spine-godot/spine_godot/SpineBone.h +++ /dev/null @@ -1,175 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINEBONE_H -#define GODOT_SPINEBONE_H - -#include "core/variant_parser.h" -#include - -#include -#include - -#include "SpineBoneData.h" -#include "SpineIkConstraint.h" -#include "SpinePathConstraint.h" -#include "SpineTransformConstraint.h" - -class SpineSkeleton; -class SpineSprite; - -class SpineBone : public Reference { - GDCLASS(SpineBone, Reference); - -protected: - static void _bind_methods(); - -private: - spine::Bone *bone; - - SpineSprite *the_sprite; - -public: - SpineBone(); - ~SpineBone(); - - inline void set_spine_object(spine::Bone *b) { - bone = b; - } - inline spine::Bone *get_spine_object() { - return bone; - } - - void set_spine_sprite(SpineSprite *s); - - void update_world_transform(); - - void set_to_setup_pose(); - - Vector2 world_to_local(Vector2 world_position); - - Vector2 local_to_world(Vector2 local_position); - - float world_to_local_rotation(float world_rotation); - - float local_to_world_rotation(float local_rotation); - - void rotate_world(float degrees); - - float get_world_to_local_rotation_x(); - float get_world_to_local_rotation_y(); - - Ref get_data(); - - Ref get_skeleton(); - - Ref get_parent(); - - Array get_children(); - - float get_x(); - void set_x(float v); - - float get_y(); - void set_y(float v); - - float get_rotation(); - void set_rotation(float v); - - float get_scale_x(); - void set_scale_x(float v); - - float get_scale_y(); - void set_scale_y(float v); - - float get_shear_x(); - void set_shear_x(float v); - - float get_shear_y(); - void set_shear_y(float v); - - float get_applied_rotation(); - void set_applied_rotation(float v); - - float get_a_x(); - void set_a_x(float v); - - float get_a_y(); - void set_a_y(float v); - - float get_a_scale_x(); - void set_a_scale_x(float v); - - float get_a_scale_y(); - void set_a_scale_y(float v); - - float get_a_shear_x(); - void set_a_shear_x(float v); - - float get_a_shear_y(); - void set_a_shear_y(float v); - - float get_a(); - void set_a(float v); - - float get_b(); - void set_b(float v); - - float get_c(); - void set_c(float v); - - float get_d(); - void set_d(float v); - - float get_world_x(); - void set_world_x(float v); - - float get_world_y(); - void set_world_y(float v); - - float get_world_rotation_x(); - float get_world_rotation_y(); - - float get_world_scale_x(); - float get_world_scale_y(); - - bool is_active(); - void set_active(bool v); - - // External feature functions - void apply_world_transform_2d(Variant o); - - Transform2D get_godot_transform(); - void set_godot_transform(Transform2D trans); - - Transform2D get_godot_global_transform(); - void set_godot_global_transform(Transform2D trans); -}; - -#endif//GODOT_SPINEBONE_H diff --git a/spine-godot/spine_godot/SpineBoneData.cpp b/spine-godot/spine_godot/SpineBoneData.cpp deleted file mode 100644 index b870527dc..000000000 --- a/spine-godot/spine_godot/SpineBoneData.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpineBoneData.h" - -void SpineBoneData::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_index"), &SpineBoneData::get_index); - ClassDB::bind_method(D_METHOD("get_bone_name"), &SpineBoneData::get_bone_name); - ClassDB::bind_method(D_METHOD("get_parent"), &SpineBoneData::get_parent); - - ClassDB::bind_method(D_METHOD("get_length"), &SpineBoneData::get_length); - ClassDB::bind_method(D_METHOD("set_length", "v"), &SpineBoneData::set_length); - - ClassDB::bind_method(D_METHOD("get_x"), &SpineBoneData::get_x); - ClassDB::bind_method(D_METHOD("set_x", "v"), &SpineBoneData::set_x); - - ClassDB::bind_method(D_METHOD("get_y"), &SpineBoneData::get_y); - ClassDB::bind_method(D_METHOD("set_y", "v"), &SpineBoneData::set_y); - - ClassDB::bind_method(D_METHOD("get_rotation"), &SpineBoneData::get_rotation); - ClassDB::bind_method(D_METHOD("set_rotation", "v"), &SpineBoneData::set_rotation); - - ClassDB::bind_method(D_METHOD("get_scale_x"), &SpineBoneData::get_scale_x); - ClassDB::bind_method(D_METHOD("set_scale_x", "v"), &SpineBoneData::set_scale_x); - - ClassDB::bind_method(D_METHOD("get_scale_y"), &SpineBoneData::get_scale_y); - ClassDB::bind_method(D_METHOD("set_scale_y", "v"), &SpineBoneData::set_scale_y); - - ClassDB::bind_method(D_METHOD("get_shear_x"), &SpineBoneData::get_shear_x); - ClassDB::bind_method(D_METHOD("set_shear_x", "v"), &SpineBoneData::set_shear_x); - - ClassDB::bind_method(D_METHOD("get_shear_y"), &SpineBoneData::get_shear_y); - ClassDB::bind_method(D_METHOD("set_shear_y", "v"), &SpineBoneData::set_shear_y); - - ClassDB::bind_method(D_METHOD("get_transform_mode"), &SpineBoneData::get_transform_mode); - ClassDB::bind_method(D_METHOD("set_transform_mode", "v"), &SpineBoneData::set_transform_mode); - - ClassDB::bind_method(D_METHOD("is_skin_required"), &SpineBoneData::is_skin_required); - ClassDB::bind_method(D_METHOD("set_skin_required", "v"), &SpineBoneData::set_skin_required); - - BIND_ENUM_CONSTANT(TRANSFORMMODE_NORMAL); - BIND_ENUM_CONSTANT(TRANSFORMMODE_ONLYTRANSLATION); - BIND_ENUM_CONSTANT(TRANSFORMMODE_NOROTATIONORREFLECTION); - BIND_ENUM_CONSTANT(TRANSFORMMODE_NOSCALE); - BIND_ENUM_CONSTANT(TRANSFORMMODE_NOSCALEORREFLECTION); -} - -SpineBoneData::SpineBoneData() : bone_data(NULL) {} -SpineBoneData::~SpineBoneData() {} - -int SpineBoneData::get_index() { - return bone_data->getIndex(); -} - -String SpineBoneData::get_bone_name() { - return bone_data->getName().buffer(); -} - -Ref SpineBoneData::get_parent() { - auto p = bone_data->getParent(); - if (p == NULL) return NULL; - Ref gd_bone_data(memnew(SpineBoneData)); - gd_bone_data->set_spine_object(p); - return gd_bone_data; -} - -float SpineBoneData::get_length() { - return bone_data->getLength(); -} -void SpineBoneData::set_length(float v) { - bone_data->setLength(v); -} - -float SpineBoneData::get_x() { - return bone_data->getX(); -} -void SpineBoneData::set_x(float v) { - bone_data->setX(v); -} - -float SpineBoneData::get_y() { - return bone_data->getY(); -} -void SpineBoneData::set_y(float v) { - bone_data->setY(v); -} - -float SpineBoneData::get_rotation() { - return bone_data->getRotation(); -} -void SpineBoneData::set_rotation(float v) { - bone_data->setRotation(v); -} - -float SpineBoneData::get_scale_x() { - return bone_data->getScaleX(); -} -void SpineBoneData::set_scale_x(float v) { - bone_data->setScaleX(v); -} - -float SpineBoneData::get_scale_y() { - return bone_data->getScaleY(); -} -void SpineBoneData::set_scale_y(float v) { - bone_data->setScaleY(v); -} - -float SpineBoneData::get_shear_x() { - return bone_data->getShearX(); -} -void SpineBoneData::set_shear_x(float v) { - bone_data->setShearX(v); -} - -float SpineBoneData::get_shear_y() { - return bone_data->getShearY(); -} -void SpineBoneData::set_shear_y(float v) { - bone_data->setShearY(v); -} - -SpineBoneData::TransformMode SpineBoneData::get_transform_mode() { - auto tm = (int) bone_data->getTransformMode(); - return (TransformMode) tm; -} -void SpineBoneData::set_transform_mode(TransformMode v) { - auto tm = (int) v; - bone_data->setTransformMode((spine::TransformMode) tm); -} - -bool SpineBoneData::is_skin_required() { - return bone_data->isSkinRequired(); -} -void SpineBoneData::set_skin_required(bool v) { - bone_data->setSkinRequired(v); -} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineBoneData.h b/spine-godot/spine_godot/SpineBoneData.h deleted file mode 100644 index dc3e3feb6..000000000 --- a/spine-godot/spine_godot/SpineBoneData.h +++ /dev/null @@ -1,103 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINEBONEDATA_H -#define GODOT_SPINEBONEDATA_H - -#include "core/variant_parser.h" - -#include - -class SpineBoneData : public Reference { - GDCLASS(SpineBoneData, Reference); - -protected: - static void _bind_methods(); - -private: - spine::BoneData *bone_data; - -public: - SpineBoneData(); - ~SpineBoneData(); - - inline void set_spine_object(spine::BoneData *b) { - bone_data = b; - } - inline spine::BoneData *get_spine_object() { - return bone_data; - } - - enum TransformMode { - TRANSFORMMODE_NORMAL = 0, - TRANSFORMMODE_ONLYTRANSLATION, - TRANSFORMMODE_NOROTATIONORREFLECTION, - TRANSFORMMODE_NOSCALE, - TRANSFORMMODE_NOSCALEORREFLECTION - }; - - int get_index(); - - String get_bone_name(); - - Ref get_parent(); - - float get_length(); - void set_length(float v); - - float get_x(); - void set_x(float v); - - float get_y(); - void set_y(float v); - - float get_rotation(); - void set_rotation(float v); - - float get_scale_x(); - void set_scale_x(float v); - - float get_scale_y(); - void set_scale_y(float v); - - float get_shear_x(); - void set_shear_x(float v); - - float get_shear_y(); - void set_shear_y(float v); - - TransformMode get_transform_mode(); - void set_transform_mode(TransformMode v); - - bool is_skin_required(); - void set_skin_required(bool v); -}; - -VARIANT_ENUM_CAST(SpineBoneData::TransformMode); -#endif//GODOT_SPINEBONEDATA_H diff --git a/spine-godot/spine_godot/SpineCollisionShapeProxy.cpp b/spine-godot/spine_godot/SpineCollisionShapeProxy.cpp deleted file mode 100644 index 9015db60d..000000000 --- a/spine-godot/spine_godot/SpineCollisionShapeProxy.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpineCollisionShapeProxy.h" - -#include "SpineSprite.h" - -void SpineCollisionShapeProxy::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_spine_sprite_path"), &SpineCollisionShapeProxy::get_spine_sprite_path); - ClassDB::bind_method(D_METHOD("set_spine_sprite_path", "v"), &SpineCollisionShapeProxy::set_spine_sprite_path); - - ClassDB::bind_method(D_METHOD("get_slot"), &SpineCollisionShapeProxy::get_slot); - ClassDB::bind_method(D_METHOD("set_slot", "v"), &SpineCollisionShapeProxy::set_slot); - - ClassDB::bind_method(D_METHOD("get_sync_transform"), &SpineCollisionShapeProxy::get_sync_transform); - ClassDB::bind_method(D_METHOD("set_sync_transform", "v"), &SpineCollisionShapeProxy::set_sync_transform); - - ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "spine_sprite_path"), "set_spine_sprite_path", "get_spine_sprite_path"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync_transform"), "set_sync_transform", "get_sync_transform"); -} - -SpineCollisionShapeProxy::SpineCollisionShapeProxy() : sync_transform(true) { -} - -SpineCollisionShapeProxy::~SpineCollisionShapeProxy() { -} - -void SpineCollisionShapeProxy::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_READY: { - set_process_internal(true); - } break; - case NOTIFICATION_INTERNAL_PROCESS: { - if (!disabled) { - if (sync_transform) _sync_transform(get_spine_sprite()); - _update_polygon_from_spine_sprite(get_spine_sprite()); - if (is_visible()) update(); - } - } break; - } -} - -SpineSprite *SpineCollisionShapeProxy::get_spine_sprite() const { - return (SpineSprite *) get_node_or_null(spine_sprite_path); -} - -NodePath SpineCollisionShapeProxy::get_spine_sprite_path() { - return spine_sprite_path; -} - -void SpineCollisionShapeProxy::set_spine_sprite_path(NodePath v) { - spine_sprite_path = v; - - _update_polygon_from_spine_sprite(get_spine_sprite()); -} - -String SpineCollisionShapeProxy::get_slot() const { - return slot; -} - -void SpineCollisionShapeProxy::set_slot(const String &v) { - slot = v; - _update_polygon_from_spine_sprite(get_spine_sprite()); -} - -void SpineCollisionShapeProxy::_update_polygon_from_spine_sprite(SpineSprite *sprite) { - _clear_polygon(); - if (sprite == nullptr || slot.empty()) { - return; - } - - if (!sprite->get_skeleton().is_valid()) { - return; - } - - auto sk = sprite->get_skeleton()->get_spine_object(); - - spine::Vector vertices; - - spine::Slot *s = sk->findSlot(spine::String(slot.utf8())); - if (!s) { - return; - } - spine::Attachment *attachment = s->getAttachment(); - if (!attachment) { - return; - } - - if (attachment->getRTTI().isExactly(spine::BoundingBoxAttachment::rtti)) { - auto *box = (spine::BoundingBoxAttachment *) attachment; - - vertices.setSize(box->getWorldVerticesLength(), 0); - box->computeWorldVertices(*s, vertices); - } else { - return; - } - - polygon.resize(vertices.size() / 2); - for (size_t j = 0; j < vertices.size(); j += 2) { - polygon.set(j / 2, Vector2(vertices[j], -vertices[j + 1])); - } - - set_polygon(polygon); -} - -void SpineCollisionShapeProxy::_clear_polygon() { - polygon.clear(); - set_polygon(polygon); -} - -void SpineCollisionShapeProxy::_sync_transform(SpineSprite *sprite) { - if (sprite == nullptr) return; - set_global_transform(sprite->get_global_transform()); -} - -bool SpineCollisionShapeProxy::get_sync_transform() { - return sync_transform; -} - -void SpineCollisionShapeProxy::set_sync_transform(bool v) { - sync_transform = v; -} - -void SpineCollisionShapeProxy::_get_property_list(List *p_list) const { - PropertyInfo p; - Vector res; - - p.name = "slot"; - p.type = Variant::STRING; - _get_slot_list(res); - if (res.empty()) res.push_back("No Slot"); - p.hint_string = String(",").join(res); - p.hint = PROPERTY_HINT_ENUM; - p_list->push_back(p); -} - -bool SpineCollisionShapeProxy::_get(const StringName &p_property, Variant &r_value) const { - if (p_property == "slot") { - r_value = get_slot(); - return true; - } - return false; -} - -bool SpineCollisionShapeProxy::_set(const StringName &p_property, const Variant &p_value) { - if (p_property == "slot") { - set_slot(p_value); - return true; - } - return false; -} - -void SpineCollisionShapeProxy::_get_slot_list(Vector &res) const { - if (get_spine_sprite() == nullptr) { - return; - } - - auto sprite = get_spine_sprite(); - if (!sprite->get_skeleton().is_valid()) { - return; - } - - auto slots = sprite->get_skeleton()->get_slots(); - res.resize(slots.size()); - for (size_t i = 0; i < res.size(); ++i) { - auto slot = (Ref) slots[i]; - if (slot.is_valid()) - res.set(i, slot->get_data()->get_slot_name()); - } -} diff --git a/spine-godot/spine_godot/SpineCollisionShapeProxy.h b/spine-godot/spine_godot/SpineCollisionShapeProxy.h deleted file mode 100644 index c29eaa591..000000000 --- a/spine-godot/spine_godot/SpineCollisionShapeProxy.h +++ /dev/null @@ -1,80 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINECOLLISIONSHAPEPROXY_H -#define GODOT_SPINECOLLISIONSHAPEPROXY_H - -#include "scene/2d/collision_polygon_2d.h" - -class SpineSprite; -class SpineAnimationState; -class SpineSkeleton; - -class SpineCollisionShapeProxy : public CollisionPolygon2D { - GDCLASS(SpineCollisionShapeProxy, CollisionPolygon2D) -protected: - static void _bind_methods(); - - NodePath spine_sprite_path; - - String slot; - - bool sync_transform; - -protected: - void _notification(int p_what); - void _get_property_list(List *p_list) const; - bool _get(const StringName &p_property, Variant &r_value) const; - bool _set(const StringName &p_property, const Variant &p_value); - - - SpineSprite *get_spine_sprite() const; - - void _update_polygon_from_spine_sprite(SpineSprite *sprite); - void _clear_polygon(); - void _sync_transform(SpineSprite *sprite); - - void _get_slot_list(Vector &res) const; - -public: - SpineCollisionShapeProxy(); - ~SpineCollisionShapeProxy(); - - NodePath get_spine_sprite_path(); - void set_spine_sprite_path(NodePath v); - - String get_slot() const; - void set_slot(const String &v); - - bool get_sync_transform(); - void set_sync_transform(bool v); -}; - - -#endif//GODOT_SPINECOLLISIONSHAPEPROXY_H diff --git a/spine-godot/spine_godot/SpineConstant.cpp b/spine-godot/spine_godot/SpineConstant.cpp deleted file mode 100644 index 760ff668a..000000000 --- a/spine-godot/spine_godot/SpineConstant.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpineConstant.h" - -void SpineConstant::_bind_methods() { - BIND_ENUM_CONSTANT(MixBlend_Setup); - BIND_ENUM_CONSTANT(MixBlend_First); - BIND_ENUM_CONSTANT(MixBlend_Replace); - BIND_ENUM_CONSTANT(MixBlend_Add); - - BIND_ENUM_CONSTANT(MixDirection_In); - BIND_ENUM_CONSTANT(MixDirection_Out); - - BIND_ENUM_CONSTANT(Property_Rotate); - BIND_ENUM_CONSTANT(Property_X); - BIND_ENUM_CONSTANT(Property_Y); - BIND_ENUM_CONSTANT(Property_ScaleX); - BIND_ENUM_CONSTANT(Property_ScaleY); - BIND_ENUM_CONSTANT(Property_ShearX); - BIND_ENUM_CONSTANT(Property_ShearY); - BIND_ENUM_CONSTANT(Property_Rgb); - BIND_ENUM_CONSTANT(Property_Alpha); - BIND_ENUM_CONSTANT(Property_Rgb2); - BIND_ENUM_CONSTANT(Property_Attachment); - BIND_ENUM_CONSTANT(Property_Deform); - BIND_ENUM_CONSTANT(Property_Event); - BIND_ENUM_CONSTANT(Property_DrawOrder); - BIND_ENUM_CONSTANT(Property_IkConstraint); - BIND_ENUM_CONSTANT(Property_TransformConstraint); - BIND_ENUM_CONSTANT(Property_PathConstraintPosition); - BIND_ENUM_CONSTANT(Property_PathConstraintSpacing); - BIND_ENUM_CONSTANT(Property_PathConstraintMix); -} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineConstant.h b/spine-godot/spine_godot/SpineConstant.h deleted file mode 100644 index c7f86d8b9..000000000 --- a/spine-godot/spine_godot/SpineConstant.h +++ /dev/null @@ -1,81 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINECONSTANT_H -#define GODOT_SPINECONSTANT_H - -#include "core/variant_parser.h" - -class SpineConstant : public Object { - GDCLASS(SpineConstant, Object); - -protected: - static void _bind_methods(); - -public: - enum MixBlend { - MixBlend_Setup = 0, - MixBlend_First, - MixBlend_Replace, - MixBlend_Add - }; - - enum MixDirection { - MixDirection_In = 0, - MixDirection_Out - }; - - enum PropertyId { - 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 - }; -}; - -VARIANT_ENUM_CAST(SpineConstant::MixBlend); -VARIANT_ENUM_CAST(SpineConstant::MixDirection); -VARIANT_ENUM_CAST(SpineConstant::PropertyId); - -#endif//GODOT_SPINECONSTANT_H diff --git a/spine-godot/spine_godot/SpineConstraintData.cpp b/spine-godot/spine_godot/SpineConstraintData.cpp deleted file mode 100644 index 16bbac435..000000000 --- a/spine-godot/spine_godot/SpineConstraintData.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpineConstraintData.h" - -void SpineConstraintData::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_constraint_data_name"), &SpineConstraintData::get_constraint_data_name); - ClassDB::bind_method(D_METHOD("get_order"), &SpineConstraintData::get_order); - ClassDB::bind_method(D_METHOD("set_order", "v"), &SpineConstraintData::set_order); - ClassDB::bind_method(D_METHOD("is_skin_required"), &SpineConstraintData::is_skin_required); - ClassDB::bind_method(D_METHOD("set_skin_required", "v"), &SpineConstraintData::set_skin_required); -} - -SpineConstraintData::SpineConstraintData() : constraint_data(NULL) {} -SpineConstraintData::~SpineConstraintData() {} - -String SpineConstraintData::get_constraint_data_name() { - return constraint_data->getName().buffer(); -} - -uint64_t SpineConstraintData::get_order() { - return constraint_data->getOrder(); -} -void SpineConstraintData::set_order(uint64_t v) { - constraint_data->setOrder(v); -} - -bool SpineConstraintData::is_skin_required() { - return constraint_data->isSkinRequired(); -} -void SpineConstraintData::set_skin_required(bool v) { - constraint_data->setSkinRequired(v); -} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineConstraintData.h b/spine-godot/spine_godot/SpineConstraintData.h deleted file mode 100644 index 35b9dd52a..000000000 --- a/spine-godot/spine_godot/SpineConstraintData.h +++ /dev/null @@ -1,66 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINECONSTRAINTDATA_H -#define GODOT_SPINECONSTRAINTDATA_H - -#include "core/variant_parser.h" - -#include - -class SpineConstraintData : public Reference { - GDCLASS(SpineConstraintData, Reference); - -protected: - static void _bind_methods(); - -private: - spine::ConstraintData *constraint_data; - -public: - SpineConstraintData(); - ~SpineConstraintData(); - - inline void set_spine_object(spine::ConstraintData *c) { - constraint_data = c; - } - virtual inline spine::ConstraintData *get_spine_object() { - return constraint_data; - } - - String get_constraint_data_name(); - - uint64_t get_order(); - void set_order(uint64_t v); - - bool is_skin_required(); - void set_skin_required(bool v); -}; - -#endif//GODOT_SPINECONSTRAINTDATA_H diff --git a/spine-godot/spine_godot/SpineEvent.cpp b/spine-godot/spine_godot/SpineEvent.cpp deleted file mode 100644 index 9d753db33..000000000 --- a/spine-godot/spine_godot/SpineEvent.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpineEvent.h" - -void SpineEvent::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_data"), &SpineEvent::get_data); - ClassDB::bind_method(D_METHOD("get_event_name"), &SpineEvent::get_event_name); - ClassDB::bind_method(D_METHOD("get_time"), &SpineEvent::get_time); - ClassDB::bind_method(D_METHOD("get_int_value"), &SpineEvent::get_int_value); - ClassDB::bind_method(D_METHOD("set_int_value", "v"), &SpineEvent::set_int_value); - ClassDB::bind_method(D_METHOD("get_float_value"), &SpineEvent::get_float_value); - ClassDB::bind_method(D_METHOD("set_float_value", "v"), &SpineEvent::set_float_value); - ClassDB::bind_method(D_METHOD("get_string_value"), &SpineEvent::get_string_value); - ClassDB::bind_method(D_METHOD("set_string_value", "v"), &SpineEvent::set_string_value); - ClassDB::bind_method(D_METHOD("get_volume"), &SpineEvent::get_volume); - ClassDB::bind_method(D_METHOD("set_volume", "v"), &SpineEvent::set_volume); - ClassDB::bind_method(D_METHOD("get_balance"), &SpineEvent::get_balance); - ClassDB::bind_method(D_METHOD("set_balance", "v"), &SpineEvent::set_balance); - // - // BIND_ENUM_CONSTANT(EVENTTYPE_START); - // BIND_ENUM_CONSTANT(EVENTTYPE_INTERRUPT); - // BIND_ENUM_CONSTANT(EVENTTYPE_END); - // BIND_ENUM_CONSTANT(EVENTTYPE_COMPLETE); - // BIND_ENUM_CONSTANT(EVENTTYPE_DISPOSE); - // BIND_ENUM_CONSTANT(EVENTTYPE_EVENT); -} - -SpineEvent::SpineEvent() : event(NULL) {} -SpineEvent::~SpineEvent() {} - -Ref SpineEvent::get_data() { - Ref event_data(memnew(SpineEventData)); - event_data->set_spine_object(&(event->getData())); - return event_data; -} - -String SpineEvent::get_event_name() { - return event->getData().getName().buffer(); -} - -float SpineEvent::get_time() { - return event->getTime(); -} - -int SpineEvent::get_int_value() { - return event->getIntValue(); -} - -void SpineEvent::set_int_value(int v) { - event->setIntValue(v); -} - -float SpineEvent::get_float_value() { - return event->getFloatValue(); -} - -void SpineEvent::set_float_value(float v) { - event->setFloatValue(v); -} - -String SpineEvent::get_string_value() { - return event->getStringValue().buffer(); -} - -void SpineEvent::set_string_value(const String &v) { - event->setStringValue(spine::String(v.utf8())); -} - -float SpineEvent::get_volume() { - return event->getVolume(); -} - -void SpineEvent::set_volume(float v) { - event->setVolume(v); -} - -float SpineEvent::get_balance() { - return event->getBalance(); -} - -void SpineEvent::set_balance(float v) { - event->setBalance(v); -} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineEvent.h b/spine-godot/spine_godot/SpineEvent.h deleted file mode 100644 index bbbf0b986..000000000 --- a/spine-godot/spine_godot/SpineEvent.h +++ /dev/null @@ -1,91 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINEEVENT_H -#define GODOT_SPINEEVENT_H - -#include "core/variant_parser.h" - -#include - -#include "SpineEventData.h" - -class SpineEvent : public Reference { - GDCLASS(SpineEvent, Reference); - -protected: - static void _bind_methods(); - -private: - spine::Event *event; - -public: - SpineEvent(); - ~SpineEvent(); - - inline void set_spine_object(spine::Event *e) { - event = e; - } - inline spine::Event *get_spine_object() const { - return event; - } - - enum EventType { - EVENTTYPE_START = spine::EventType_Start, - EVENTTYPE_INTERRUPT = spine::EventType_Interrupt, - EVENTTYPE_END = spine::EventType_End, - EVENTTYPE_COMPLETE = spine::EventType_Complete, - EVENTTYPE_DISPOSE = spine::EventType_Dispose, - EVENTTYPE_EVENT = spine::EventType_Event - }; - - - Ref get_data(); - - String get_event_name(); - - float get_time(); - - int get_int_value(); - void set_int_value(int inValue); - - float get_float_value(); - void set_float_value(float inValue); - - String get_string_value(); - void set_string_value(const String &inValue); - - float get_volume(); - void set_volume(float inValue); - - float get_balance(); - void set_balance(float inValue); -}; - -#endif//GODOT_SPINEEVENT_H diff --git a/spine-godot/spine_godot/SpineEventData.cpp b/spine-godot/spine_godot/SpineEventData.cpp deleted file mode 100644 index bca195e79..000000000 --- a/spine-godot/spine_godot/SpineEventData.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpineEventData.h" - -void SpineEventData::_bind_methods() { -} - -SpineEventData::SpineEventData() : event_data(NULL) {} -SpineEventData::~SpineEventData() {} diff --git a/spine-godot/spine_godot/SpineEventData.h b/spine-godot/spine_godot/SpineEventData.h deleted file mode 100644 index 1cf669f26..000000000 --- a/spine-godot/spine_godot/SpineEventData.h +++ /dev/null @@ -1,58 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINEEVENTDATA_H -#define GODOT_SPINEEVENTDATA_H - -#include "core/variant_parser.h" - -#include - -class SpineEventData : public Reference { - GDCLASS(SpineEventData, Reference); - -protected: - static void _bind_methods(); - -private: - const spine::EventData *event_data; - -public: - SpineEventData(); - ~SpineEventData(); - - inline void set_spine_object(const spine::EventData *e) { - event_data = e; - } - inline const spine::EventData *get_spine_object() { - return event_data; - } -}; - -#endif//GODOT_SPINEEVENTDATA_H diff --git a/spine-godot/spine_godot/SpineIkConstraint.cpp b/spine-godot/spine_godot/SpineIkConstraint.cpp deleted file mode 100644 index d88492b48..000000000 --- a/spine-godot/spine_godot/SpineIkConstraint.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpineIkConstraint.h" -#include "SpineBone.h" - -void SpineIkConstraint::_bind_methods() { - // ClassDB::bind_method(D_METHOD("apply"), &SpineIkConstraint::apply); - ClassDB::bind_method(D_METHOD("update"), &SpineIkConstraint::update); - ClassDB::bind_method(D_METHOD("get_order"), &SpineIkConstraint::get_order); - ClassDB::bind_method(D_METHOD("get_data"), &SpineIkConstraint::get_data); - ClassDB::bind_method(D_METHOD("get_bones"), &SpineIkConstraint::get_bones); - ClassDB::bind_method(D_METHOD("get_target"), &SpineIkConstraint::get_target); - ClassDB::bind_method(D_METHOD("set_target", "v"), &SpineIkConstraint::set_target); - ClassDB::bind_method(D_METHOD("get_bend_direction"), &SpineIkConstraint::get_bend_direction); - ClassDB::bind_method(D_METHOD("set_bend_direction", "v"), &SpineIkConstraint::set_bend_direction); - ClassDB::bind_method(D_METHOD("get_compress"), &SpineIkConstraint::get_compress); - ClassDB::bind_method(D_METHOD("set_compress", "v"), &SpineIkConstraint::set_compress); - ClassDB::bind_method(D_METHOD("get_stretch"), &SpineIkConstraint::get_stretch); - ClassDB::bind_method(D_METHOD("set_stretch", "v"), &SpineIkConstraint::set_stretch); - ClassDB::bind_method(D_METHOD("get_mix"), &SpineIkConstraint::get_mix); - ClassDB::bind_method(D_METHOD("set_mix", "v"), &SpineIkConstraint::set_mix); - ClassDB::bind_method(D_METHOD("get_softness"), &SpineIkConstraint::get_softness); - ClassDB::bind_method(D_METHOD("set_softness", "v"), &SpineIkConstraint::set_softness); - ClassDB::bind_method(D_METHOD("is_active"), &SpineIkConstraint::is_active); - ClassDB::bind_method(D_METHOD("set_active", "v"), &SpineIkConstraint::set_active); -} - -SpineIkConstraint::SpineIkConstraint() : ik_constraint(NULL) {} -SpineIkConstraint::~SpineIkConstraint() {} - -// void SpineIkConstraint::apply(){ -// ik_constraint->apply(); -// } - -void SpineIkConstraint::update() { - ik_constraint->update(); -} - -int SpineIkConstraint::get_order() { - return ik_constraint->getOrder(); -} - -Ref SpineIkConstraint::get_data() { - auto &ikc = ik_constraint->getData(); - Ref gd_ikc(memnew(SpineIkConstraintData)); - gd_ikc->set_spine_object(&ikc); - return gd_ikc; -} - -Array SpineIkConstraint::get_bones() { - auto &bs = ik_constraint->getBones(); - Array gd_bs; - gd_bs.resize(bs.size()); - for (size_t i = 0; i < bs.size(); ++i) { - auto b = bs[i]; - if (b == NULL) gd_bs[i] = Ref(NULL); - Ref gd_b(memnew(SpineBone)); - gd_b->set_spine_object(b); - gd_bs[i] = gd_b; - } - return gd_bs; -} - -Ref SpineIkConstraint::get_target() { - auto b = ik_constraint->getTarget(); - if (b == NULL) return NULL; - Ref gd_b(memnew(SpineBone)); - gd_b->set_spine_object(b); - return gd_b; -} -void SpineIkConstraint::set_target(Ref v) { - if (v.is_valid()) { - ik_constraint->setTarget(v->get_spine_object()); - } else { - ik_constraint->setTarget(NULL); - } -} - -int SpineIkConstraint::get_bend_direction() { - return ik_constraint->getBendDirection(); -} -void SpineIkConstraint::set_bend_direction(int v) { - ik_constraint->setBendDirection(v); -} - -bool SpineIkConstraint::get_compress() { - return ik_constraint->getCompress(); -} -void SpineIkConstraint::set_compress(bool v) { - ik_constraint->setCompress(v); -} - -bool SpineIkConstraint::get_stretch() { - return ik_constraint->getStretch(); -} -void SpineIkConstraint::set_stretch(bool v) { - ik_constraint->setStretch(v); -} - -float SpineIkConstraint::get_mix() { - return ik_constraint->getMix(); -} -void SpineIkConstraint::set_mix(float v) { - ik_constraint->setMix(v); -} - -float SpineIkConstraint::get_softness() { - return ik_constraint->getSoftness(); -} -void SpineIkConstraint::set_softness(float v) { - ik_constraint->setSoftness(v); -} - -bool SpineIkConstraint::is_active() { - return ik_constraint->isActive(); -} -void SpineIkConstraint::set_active(bool v) { - ik_constraint->setActive(v); -} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineIkConstraint.h b/spine-godot/spine_godot/SpineIkConstraint.h deleted file mode 100644 index c7c4aeefe..000000000 --- a/spine-godot/spine_godot/SpineIkConstraint.h +++ /dev/null @@ -1,94 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINEIKCONSTRAINT_H -#define GODOT_SPINEIKCONSTRAINT_H - -#include "core/variant_parser.h" - -#include - -#include "SpineIkConstraintData.h" - -class SpineBone; - -class SpineIkConstraint : public Reference { - GDCLASS(SpineIkConstraint, Reference); - -protected: - static void _bind_methods(); - -private: - spine::IkConstraint *ik_constraint; - -public: - SpineIkConstraint(); - ~SpineIkConstraint(); - - inline void set_spine_object(spine::IkConstraint *ic) { - ik_constraint = ic; - } - inline spine::IkConstraint *get_spine_object() { - return ik_constraint; - } - - // The spine-runtime-cpp 4.0 seems to not have a apply function implementation. - // void apply(); - - void update(); - - int get_order(); - - Ref get_data(); - - Array get_bones(); - - Ref get_target(); - void set_target(Ref v); - - int get_bend_direction(); - void set_bend_direction(int v); - - bool get_compress(); - void set_compress(bool v); - - bool get_stretch(); - void set_stretch(bool v); - - float get_mix(); - void set_mix(float v); - - float get_softness(); - void set_softness(float v); - - bool is_active(); - void set_active(bool v); -}; - -#endif//GODOT_SPINEIKCONSTRAINT_H diff --git a/spine-godot/spine_godot/SpineIkConstraintData.cpp b/spine-godot/spine_godot/SpineIkConstraintData.cpp deleted file mode 100644 index 62731aecf..000000000 --- a/spine-godot/spine_godot/SpineIkConstraintData.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpineIkConstraintData.h" - -void SpineIkConstraintData::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_all_bone_data"), &SpineIkConstraintData::get_bones); - ClassDB::bind_method(D_METHOD("get_target"), &SpineIkConstraintData::get_target); - ClassDB::bind_method(D_METHOD("set_target", "v"), &SpineIkConstraintData::set_target); - ClassDB::bind_method(D_METHOD("get_bend_direction"), &SpineIkConstraintData::get_bend_direction); - ClassDB::bind_method(D_METHOD("set_bend_direction", "v"), &SpineIkConstraintData::set_bend_direction); - ClassDB::bind_method(D_METHOD("get_compress"), &SpineIkConstraintData::get_compress); - ClassDB::bind_method(D_METHOD("set_compress", "v"), &SpineIkConstraintData::set_compress); - ClassDB::bind_method(D_METHOD("get_stretch"), &SpineIkConstraintData::get_stretch); - ClassDB::bind_method(D_METHOD("set_stretch", "v"), &SpineIkConstraintData::set_stretch); - ClassDB::bind_method(D_METHOD("get_uniform"), &SpineIkConstraintData::get_uniform); - ClassDB::bind_method(D_METHOD("set_uniform", "v"), &SpineIkConstraintData::set_uniform); - ClassDB::bind_method(D_METHOD("get_mix"), &SpineIkConstraintData::get_mix); - ClassDB::bind_method(D_METHOD("set_mix", "v"), &SpineIkConstraintData::set_mix); - ClassDB::bind_method(D_METHOD("get_softness"), &SpineIkConstraintData::get_softness); - ClassDB::bind_method(D_METHOD("set_softness", "v"), &SpineIkConstraintData::set_softness); -} - -SpineIkConstraintData::SpineIkConstraintData() {} -SpineIkConstraintData::~SpineIkConstraintData() {} - -Array SpineIkConstraintData::get_bones() { - auto bs = get_spine_data()->getBones(); - Array gd_bs; - gd_bs.resize(bs.size()); - for (size_t i = 0; i < bs.size(); ++i) { - if (bs[i] == NULL) gd_bs[i] = Ref(NULL); - else { - Ref gd_b(memnew(SpineBoneData)); - gd_b->set_spine_object(bs[i]); - gd_bs[i] = gd_b; - } - } - return gd_bs; -} - -Ref SpineIkConstraintData::get_target() { - auto b = get_spine_data()->getTarget(); - if (b == NULL) return NULL; - Ref gd_b(memnew(SpineBoneData)); - gd_b->set_spine_object(b); - return gd_b; -} -void SpineIkConstraintData::set_target(Ref v) { - if (v.is_valid()) { - get_spine_data()->setTarget(v->get_spine_object()); - } else { - get_spine_data()->setTarget(NULL); - } -} - -int SpineIkConstraintData::get_bend_direction() { - return get_spine_data()->getBendDirection(); -} -void SpineIkConstraintData::set_bend_direction(int v) { - get_spine_data()->setBendDirection(v); -} - -bool SpineIkConstraintData::get_compress() { - return get_spine_data()->getCompress(); -} -void SpineIkConstraintData::set_compress(bool v) { - get_spine_data()->setCompress(v); -} - -bool SpineIkConstraintData::get_stretch() { - return get_spine_data()->getStretch(); -} -void SpineIkConstraintData::set_stretch(bool v) { - get_spine_data()->setStretch(v); -} - -bool SpineIkConstraintData::get_uniform() { - return get_spine_data()->getUniform(); -} -void SpineIkConstraintData::set_uniform(bool v) { - get_spine_data()->setUniform(v); -} - -float SpineIkConstraintData::get_mix() { - return get_spine_data()->getMix(); -} -void SpineIkConstraintData::set_mix(float v) { - get_spine_data()->setMix(v); -} - -float SpineIkConstraintData::get_softness() { - return get_spine_data()->getSoftness(); -} -void SpineIkConstraintData::set_softness(float v) { - get_spine_data()->setSoftness(v); -} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineIkConstraintData.h b/spine-godot/spine_godot/SpineIkConstraintData.h deleted file mode 100644 index da0434d0b..000000000 --- a/spine-godot/spine_godot/SpineIkConstraintData.h +++ /dev/null @@ -1,78 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINEIKCONSTRAINTDATA_H -#define GODOT_SPINEIKCONSTRAINTDATA_H - -#include "core/variant_parser.h" - -#include - -#include "SpineConstraintData.h" -#include "SpineBoneData.h" - -class SpineIkConstraintData : public SpineConstraintData { - GDCLASS(SpineIkConstraintData, SpineConstraintData); - -protected: - static void _bind_methods(); - -public: - SpineIkConstraintData(); - ~SpineIkConstraintData(); - - virtual inline spine::IkConstraintData *get_spine_data() { - return (spine::IkConstraintData *) SpineConstraintData::get_spine_object(); - } - - Array get_bones(); - - Ref get_target(); - void set_target(Ref v); - - int get_bend_direction(); - void set_bend_direction(int v); - - bool get_compress(); - void set_compress(bool v); - - bool get_stretch(); - void set_stretch(bool v); - - bool get_uniform(); - void set_uniform(bool v); - - float get_mix(); - void set_mix(float v); - - float get_softness(); - void set_softness(float v); -}; - -#endif//GODOT_SPINEIKCONSTRAINTDATA_H diff --git a/spine-godot/spine_godot/SpinePathConstraint.cpp b/spine-godot/spine_godot/SpinePathConstraint.cpp deleted file mode 100644 index 3df032a22..000000000 --- a/spine-godot/spine_godot/SpinePathConstraint.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpinePathConstraint.h" - -void SpinePathConstraint::_bind_methods() { - // ClassDB::bind_method(D_METHOD("apply"), &SpinePathConstraint::apply); - ClassDB::bind_method(D_METHOD("update"), &SpinePathConstraint::update); - ClassDB::bind_method(D_METHOD("get_order"), &SpinePathConstraint::get_order); - ClassDB::bind_method(D_METHOD("get_position"), &SpinePathConstraint::get_position); - ClassDB::bind_method(D_METHOD("set_position", "v"), &SpinePathConstraint::set_position); - ClassDB::bind_method(D_METHOD("get_spacing"), &SpinePathConstraint::get_spacing); - ClassDB::bind_method(D_METHOD("set_spacing", "v"), &SpinePathConstraint::set_spacing); - ClassDB::bind_method(D_METHOD("get_mix_rotate"), &SpinePathConstraint::get_mix_rotate); - ClassDB::bind_method(D_METHOD("set_mix_rotate", "v"), &SpinePathConstraint::set_mix_rotate); - ClassDB::bind_method(D_METHOD("get_mix_x"), &SpinePathConstraint::get_mix_x); - ClassDB::bind_method(D_METHOD("set_mix_x", "v"), &SpinePathConstraint::set_mix_x); - ClassDB::bind_method(D_METHOD("get_mix_y"), &SpinePathConstraint::get_mix_y); - ClassDB::bind_method(D_METHOD("set_mix_y", "v"), &SpinePathConstraint::set_mix_y); - ClassDB::bind_method(D_METHOD("get_bones"), &SpinePathConstraint::get_bones); - ClassDB::bind_method(D_METHOD("get_target"), &SpinePathConstraint::get_target); - ClassDB::bind_method(D_METHOD("set_target", "v"), &SpinePathConstraint::set_target); - ClassDB::bind_method(D_METHOD("get_data"), &SpinePathConstraint::get_data); - ClassDB::bind_method(D_METHOD("is_active"), &SpinePathConstraint::is_active); - ClassDB::bind_method(D_METHOD("set_active", "v"), &SpinePathConstraint::set_active); -} - -SpinePathConstraint::SpinePathConstraint() : path_constraint(NULL) {} -SpinePathConstraint::~SpinePathConstraint() {} - -// void SpinePathConstraint::apply(){ -// path_constraint->apply(); -// } - -void SpinePathConstraint::update() { - path_constraint->update(); -} - -int SpinePathConstraint::get_order() { - return path_constraint->getOrder(); -} - -float SpinePathConstraint::get_position() { - return path_constraint->getPosition(); -} -void SpinePathConstraint::set_position(float v) { - path_constraint->setPosition(v); -} - -float SpinePathConstraint::get_spacing() { - return path_constraint->getSpacing(); -} -void SpinePathConstraint::set_spacing(float v) { - path_constraint->setSpacing(v); -} - -float SpinePathConstraint::get_mix_rotate() { - return path_constraint->getMixRotate(); -} -void SpinePathConstraint::set_mix_rotate(float v) { - path_constraint->setMixRotate(v); -} - -float SpinePathConstraint::get_mix_x() { - return path_constraint->getMixX(); -} -void SpinePathConstraint::set_mix_x(float v) { - path_constraint->setMixX(v); -} - -float SpinePathConstraint::get_mix_y() { - return path_constraint->getMixY(); -} -void SpinePathConstraint::set_mix_y(float v) { - path_constraint->setMixY(v); -} - -Array SpinePathConstraint::get_bones() { - auto &bs = path_constraint->getBones(); - Array gd_bs; - gd_bs.resize(bs.size()); - for (size_t i = 0; i < bs.size(); ++i) { - auto b = bs[i]; - if (b == NULL) gd_bs[i] = Ref(NULL); - Ref gd_b(memnew(SpineBone)); - gd_b->set_spine_object(b); - gd_bs[i] = gd_b; - } - return gd_bs; -} - -Ref SpinePathConstraint::get_target() { - auto s = path_constraint->getTarget(); - if (s == NULL) return NULL; - Ref gd_s(memnew(SpineSlot)); - gd_s->set_spine_object(s); - return gd_s; -} -void SpinePathConstraint::set_target(Ref v) { - if (v.is_valid()) { - path_constraint->setTarget(v->get_spine_object()); - } else { - path_constraint->setTarget(NULL); - } -} - -Ref SpinePathConstraint::get_data() { - auto &sd = path_constraint->getData(); - Ref gd_sd(memnew(SpinePathConstraintData)); - gd_sd->set_spine_object(&sd); - return gd_sd; -} - -bool SpinePathConstraint::is_active() { - return path_constraint->isActive(); -} -void SpinePathConstraint::set_active(bool v) { - path_constraint->setActive(v); -} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpinePathConstraint.h b/spine-godot/spine_godot/SpinePathConstraint.h deleted file mode 100644 index dcd41d09e..000000000 --- a/spine-godot/spine_godot/SpinePathConstraint.h +++ /dev/null @@ -1,94 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINEPATHCONSTRAINT_H -#define GODOT_SPINEPATHCONSTRAINT_H - -#include "core/variant_parser.h" - -#include - -#include "SpineBone.h" -#include "SpineSlot.h" -#include "SpinePathConstraintData.h" - -class SpinePathConstraint : public Reference { - GDCLASS(SpinePathConstraint, Reference); - -protected: - static void _bind_methods(); - -private: - spine::PathConstraint *path_constraint; - -public: - SpinePathConstraint(); - ~SpinePathConstraint(); - - inline void set_spine_object(spine::PathConstraint *pc) { - path_constraint = pc; - } - inline spine::PathConstraint *get_spine_object() { - return path_constraint; - } - - // The spine-runtime-cpp 4.0 seems to not have a apply function implementation. - // void apply(); - - void update(); - - int get_order(); - - float get_position(); - void set_position(float v); - - float get_spacing(); - void set_spacing(float v); - - float get_mix_rotate(); - void set_mix_rotate(float v); - - float get_mix_x(); - void set_mix_x(float v); - - float get_mix_y(); - void set_mix_y(float v); - - Array get_bones(); - - Ref get_target(); - void set_target(Ref v); - - Ref get_data(); - - bool is_active(); - void set_active(bool v); -}; - -#endif//GODOT_SPINEPATHCONSTRAINT_H diff --git a/spine-godot/spine_godot/SpinePathConstraintData.cpp b/spine-godot/spine_godot/SpinePathConstraintData.cpp deleted file mode 100644 index 5d0f34b64..000000000 --- a/spine-godot/spine_godot/SpinePathConstraintData.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpinePathConstraintData.h" - - -void SpinePathConstraintData::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_all_bone_data"), &SpinePathConstraintData::get_bones); - ClassDB::bind_method(D_METHOD("get_target"), &SpinePathConstraintData::get_target); - ClassDB::bind_method(D_METHOD("set_target", "V"), &SpinePathConstraintData::set_target); - ClassDB::bind_method(D_METHOD("get_position_mode"), &SpinePathConstraintData::get_position_mode); - ClassDB::bind_method(D_METHOD("set_position_mode", "V"), &SpinePathConstraintData::set_position_mode); - ClassDB::bind_method(D_METHOD("get_spacing_mode"), &SpinePathConstraintData::get_spacing_mode); - ClassDB::bind_method(D_METHOD("set_spacing_mode", "V"), &SpinePathConstraintData::set_spacing_mode); - ClassDB::bind_method(D_METHOD("get_rotate_mode"), &SpinePathConstraintData::get_rotate_mode); - ClassDB::bind_method(D_METHOD("set_rotate_mode", "V"), &SpinePathConstraintData::set_rotate_mode); - ClassDB::bind_method(D_METHOD("get_offset_rotation"), &SpinePathConstraintData::get_offset_rotation); - ClassDB::bind_method(D_METHOD("set_offset_rotation", "V"), &SpinePathConstraintData::set_offset_rotation); - ClassDB::bind_method(D_METHOD("get_position"), &SpinePathConstraintData::get_position); - ClassDB::bind_method(D_METHOD("set_position", "V"), &SpinePathConstraintData::set_position); - ClassDB::bind_method(D_METHOD("get_spacing"), &SpinePathConstraintData::get_spacing); - ClassDB::bind_method(D_METHOD("set_spacing", "V"), &SpinePathConstraintData::set_spacing); - ClassDB::bind_method(D_METHOD("get_mix_rotate"), &SpinePathConstraintData::get_mix_rotate); - ClassDB::bind_method(D_METHOD("set_mix_rotate", "V"), &SpinePathConstraintData::set_mix_rotate); - ClassDB::bind_method(D_METHOD("get_mix_x"), &SpinePathConstraintData::get_mix_x); - ClassDB::bind_method(D_METHOD("set_mix_x", "V"), &SpinePathConstraintData::set_mix_x); - ClassDB::bind_method(D_METHOD("get_mix_y"), &SpinePathConstraintData::get_mix_y); - ClassDB::bind_method(D_METHOD("set_mix_y", "V"), &SpinePathConstraintData::set_mix_y); - - BIND_ENUM_CONSTANT(POSITIONMODE_FIXED); - BIND_ENUM_CONSTANT(POSITIONMODE_PERCENT); - - BIND_ENUM_CONSTANT(SPACINGMODE_LENGTH); - BIND_ENUM_CONSTANT(SPACINGMODE_FIXED); - BIND_ENUM_CONSTANT(SPACINGMODE_PERCENT); - - BIND_ENUM_CONSTANT(ROTATEMODE_TANGENT); - BIND_ENUM_CONSTANT(ROTATEMODE_CHAIN); - BIND_ENUM_CONSTANT(ROTATEMODE_CHAINSCALE); -} - -SpinePathConstraintData::SpinePathConstraintData() {} -SpinePathConstraintData::~SpinePathConstraintData() {} - -Array SpinePathConstraintData::get_bones() { - auto bs = get_spine_data()->getBones(); - Array gd_bs; - gd_bs.resize(bs.size()); - for (size_t i = 0; i < bs.size(); ++i) { - if (bs[i] == NULL) gd_bs[i] = Ref(NULL); - else { - Ref gd_b(memnew(SpineBoneData)); - gd_b->set_spine_object(bs[i]); - gd_bs[i] = gd_b; - } - } - return gd_bs; -} - -Ref SpinePathConstraintData::get_target() { - auto s = get_spine_data()->getTarget(); - if (s == NULL) return NULL; - Ref gd_s(memnew(SpineSlotData)); - gd_s->set_spine_object(s); - return gd_s; -} -void SpinePathConstraintData::set_target(Ref v) { - if (v.is_valid()) { - get_spine_data()->setTarget(v->get_spine_object()); - } else { - get_spine_data()->setTarget(NULL); - } -} - -SpinePathConstraintData::PositionMode SpinePathConstraintData::get_position_mode() { - auto m = (int) get_spine_data()->getPositionMode(); - return (PositionMode) m; -} -void SpinePathConstraintData::set_position_mode(PositionMode v) { - auto m = (int) v; - get_spine_data()->setPositionMode((spine::PositionMode) m); -} - -SpinePathConstraintData::SpacingMode SpinePathConstraintData::get_spacing_mode() { - auto m = (int) get_spine_data()->getSpacingMode(); - return (SpacingMode) m; -} -void SpinePathConstraintData::set_spacing_mode(SpacingMode v) { - auto m = (int) v; - get_spine_data()->setSpacingMode((spine::SpacingMode) m); -} - -SpinePathConstraintData::RotateMode SpinePathConstraintData::get_rotate_mode() { - auto m = (int) get_spine_data()->getRotateMode(); - return (RotateMode) m; -} -void SpinePathConstraintData::set_rotate_mode(RotateMode v) { - auto m = (int) v; - get_spine_data()->setRotateMode((spine::RotateMode) m); -} - -float SpinePathConstraintData::get_offset_rotation() { - return get_spine_data()->getOffsetRotation(); -} -void SpinePathConstraintData::set_offset_rotation(float v) { - get_spine_data()->setOffsetRotation(v); -} - -float SpinePathConstraintData::get_position() { - return get_spine_data()->getPosition(); -} -void SpinePathConstraintData::set_position(float v) { - get_spine_data()->setPosition(v); -} - -float SpinePathConstraintData::get_spacing() { - return get_spine_data()->getSpacing(); -} -void SpinePathConstraintData::set_spacing(float v) { - get_spine_data()->setSpacing(v); -} - -float SpinePathConstraintData::get_mix_rotate() { - return get_spine_data()->getMixRotate(); -} -void SpinePathConstraintData::set_mix_rotate(float v) { - get_spine_data()->setMixRotate(v); -} - -float SpinePathConstraintData::get_mix_x() { - return get_spine_data()->getMixX(); -} -void SpinePathConstraintData::set_mix_x(float v) { - get_spine_data()->setMixX(v); -} - -float SpinePathConstraintData::get_mix_y() { - return get_spine_data()->getMixY(); -} -void SpinePathConstraintData::set_mix_y(float v) { - get_spine_data()->setMixY(v); -} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpinePathConstraintData.h b/spine-godot/spine_godot/SpinePathConstraintData.h deleted file mode 100644 index 068a68ec0..000000000 --- a/spine-godot/spine_godot/SpinePathConstraintData.h +++ /dev/null @@ -1,108 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINEPATHCONSTRAINTDATA_H -#define GODOT_SPINEPATHCONSTRAINTDATA_H - -#include "core/variant_parser.h" - -#include - -#include "SpineConstraintData.h" -#include "SpineBoneData.h" -#include "SpineSlotData.h" - -class SpinePathConstraintData : public SpineConstraintData { - GDCLASS(SpinePathConstraintData, SpineConstraintData); - -protected: - static void _bind_methods(); - -public: - SpinePathConstraintData(); - ~SpinePathConstraintData(); - - virtual inline spine::PathConstraintData *get_spine_data() { - return (spine::PathConstraintData *) SpineConstraintData::get_spine_object(); - } - - enum PositionMode { - POSITIONMODE_FIXED = 0, - POSITIONMODE_PERCENT - }; - - enum SpacingMode { - SPACINGMODE_LENGTH = 0, - SPACINGMODE_FIXED, - SPACINGMODE_PERCENT - }; - - enum RotateMode { - ROTATEMODE_TANGENT = 0, - ROTATEMODE_CHAIN, - ROTATEMODE_CHAINSCALE - }; - - Array get_bones(); - - Ref get_target(); - void set_target(Ref v); - - PositionMode get_position_mode(); - void set_position_mode(PositionMode v); - - SpacingMode get_spacing_mode(); - void set_spacing_mode(SpacingMode v); - - RotateMode get_rotate_mode(); - void set_rotate_mode(RotateMode v); - - float get_offset_rotation(); - void set_offset_rotation(float v); - - float get_position(); - void set_position(float v); - - float get_spacing(); - void set_spacing(float v); - - float get_mix_rotate(); - void set_mix_rotate(float v); - - float get_mix_x(); - void set_mix_x(float v); - - float get_mix_y(); - void set_mix_y(float v); -}; - -VARIANT_ENUM_CAST(SpinePathConstraintData::PositionMode); -VARIANT_ENUM_CAST(SpinePathConstraintData::SpacingMode); -VARIANT_ENUM_CAST(SpinePathConstraintData::RotateMode); -#endif//GODOT_SPINEPATHCONSTRAINTDATA_H diff --git a/spine-godot/spine_godot/SpineRendererObject.h b/spine-godot/spine_godot/SpineRendererObject.h deleted file mode 100644 index 11b9370a9..000000000 --- a/spine-godot/spine_godot/SpineRendererObject.h +++ /dev/null @@ -1,41 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINERENDEREROBJECT_H -#define GODOT_SPINERENDEREROBJECT_H - -#include - -struct SpineRendererObject { - Ref texture; - Ref normal_map; -}; - - -#endif diff --git a/spine-godot/spine_godot/SpineRuntimeEditorPlugin.cpp b/spine-godot/spine_godot/SpineRuntimeEditorPlugin.cpp deleted file mode 100644 index 80de73af7..000000000 --- a/spine-godot/spine_godot/SpineRuntimeEditorPlugin.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 TOOLS_ENABLED -#include "SpineRuntimeEditorPlugin.h" - -#include "SpineAtlasResource.h" -#include "SpineSkeletonJsonDataResource.h" -#include "SpineSpriteAnimateDialog.h" - -#include "SpineSprite.h" - -Error SpineAtlasResourceImportPlugin::import(const String &p_source_file, const String &p_save_path, const Map &p_options, List *r_platform_variants, List *r_gen_files, Variant *r_metadata) { - Ref res(memnew(SpineAtlasResource)); - res->set_normal_texture_prefix(p_options["normal_texture_prefix"]); - res->load_from_atlas_file(p_source_file); - - String file_name = vformat("%s.%s", p_save_path, get_save_extension()); - auto err = ResourceSaver::save(file_name, res); - return err; -} - -void SpineAtlasResourceImportPlugin::get_import_options(List *r_options, int p_preset) const { - if (p_preset == 0) { - ImportOption op; - op.option.name = "normal_texture_prefix"; - op.option.type = Variant::STRING; - op.option.hint_string = "String"; - op.default_value = String("n"); - r_options->push_back(op); - } -} - -Error SpineJsonResourceImportPlugin::import(const String &p_source_file, const String &p_save_path, const Map &p_options, List *r_platform_variants, List *r_gen_files, Variant *r_metadata) { - Ref res(memnew(SpineSkeletonJsonDataResource)); - res->load_from_file(p_source_file); - - String file_name = vformat("%s.%s", p_save_path, get_save_extension()); - auto err = ResourceSaver::save(file_name, res); - return err; -} - -//=======================| SpineRuntimeEditorPlugin |============================ -SpineRuntimeEditorPlugin::SpineRuntimeEditorPlugin(EditorNode *p_node) { - add_import_plugin(memnew(SpineAtlasResourceImportPlugin)); - add_import_plugin(memnew(SpineJsonResourceImportPlugin)); - - auto animate_button = memnew(ToolButton); - animate_button->set_text("Animate"); - add_control_to_container(CONTAINER_CANVAS_EDITOR_MENU, animate_button); - - animate_dialog = memnew(SpineSpriteAnimateDialog); - get_editor_interface()->get_base_control()->add_child(animate_dialog); - animate_dialog->set_animate_button(animate_button); - animate_dialog->set_plugin(this); -} - -SpineRuntimeEditorPlugin::~SpineRuntimeEditorPlugin() { -} - -bool SpineRuntimeEditorPlugin::handles(Object *p_object) const { - return p_object->is_class("SpineSprite"); -} - -void SpineRuntimeEditorPlugin::make_visible(bool p_visible) { - if (get_editor_interface()->get_selection()->get_selected_node_list().size() != 1) { - p_visible = false; - } - animate_dialog->get_animate_button()->set_visible(p_visible); -} - - -#endif \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineRuntimeEditorPlugin.h b/spine-godot/spine_godot/SpineRuntimeEditorPlugin.h deleted file mode 100644 index cf95ec696..000000000 --- a/spine-godot/spine_godot/SpineRuntimeEditorPlugin.h +++ /dev/null @@ -1,98 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINERUNTIMEEDITORPLUGIN_H -#define GODOT_SPINERUNTIMEEDITORPLUGIN_H - -#ifdef TOOLS_ENABLED -#include "editor/editor_node.h" - -class SpineAtlasResourceImportPlugin : public EditorImportPlugin { - GDCLASS(SpineAtlasResourceImportPlugin, EditorImportPlugin); - -public: - String get_importer_name() const override { return "spine.atlas"; } - String get_visible_name() const override { return "Spine Runtime Atlas"; } - void get_recognized_extensions(List *p_extensions) const override { p_extensions->push_back("atlas"); } - String get_preset_name(int p_idx) const override { - if (p_idx == 0) return "Default"; - else - return "Unknown"; - } - int get_preset_count() const override { return 1; } - String get_save_extension() const override { return "spatlas"; } - String get_resource_type() const override { return "SpineAtlasResource"; } - void get_import_options(List *r_options, int p_preset) const override; - bool get_option_visibility(const String &p_option, const Map &p_options) const override { return true; } - Error import(const String &p_source_file, const String &p_save_path, const Map &p_options, List *r_platform_variants, List *r_gen_files, Variant *r_metadata) override; -}; - -class SpineJsonResourceImportPlugin : public EditorImportPlugin { - GDCLASS(SpineJsonResourceImportPlugin, EditorImportPlugin); - -public: - String get_importer_name() const override { return "spine.json"; } - String get_visible_name() const override { return "Spine Runtime Json"; } - void get_recognized_extensions(List *p_extensions) const override { p_extensions->push_back("json"); } - String get_preset_name(int p_idx) const override { - if (p_idx == 0) return "Default"; - else - return "Unknown"; - } - int get_preset_count() const override { return 1; } - String get_save_extension() const override { return "spjson"; } - String get_resource_type() const override { return "SpineSkeletonJsonDataResource"; } - void get_import_options(List *r_options, int p_preset) const override {} - bool get_option_visibility(const String &p_option, const Map &p_options) const override { return true; } - Error import(const String &p_source_file, const String &p_save_path, const Map &p_options, List *r_platform_variants, List *r_gen_files, Variant *r_metadata) override; -}; - -class SpineSpriteAnimateDialog; - -class SpineRuntimeEditorPlugin : public EditorPlugin { - GDCLASS(SpineRuntimeEditorPlugin, EditorPlugin); - -protected: - SpineSpriteAnimateDialog *animate_dialog; - -public: - SpineRuntimeEditorPlugin(EditorNode *p_node); - ~SpineRuntimeEditorPlugin(); - - String get_name() const override { return "SpineRuntimeEditorPlugin"; } - bool has_main_screen() const { return false; } - - bool handles(Object *p_object) const override; - void make_visible(bool p_visible) override; - - void _on_animate_button_pressed(); -}; -#endif - -#endif//GODOT_SPINERUNTIMEEDITORPLUGIN_H diff --git a/spine-godot/spine_godot/SpineSkeleton.cpp b/spine-godot/spine_godot/SpineSkeleton.cpp deleted file mode 100644 index b8cedf0d5..000000000 --- a/spine-godot/spine_godot/SpineSkeleton.cpp +++ /dev/null @@ -1,427 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpineSkeleton.h" - -void SpineSkeleton::_bind_methods() { - //void update_world_transform(); - // - // void set_to_setup_pose(); - // - // void set_bones_to_setup_pose(); - // - // void set_slots_to_setup_pose(); - ClassDB::bind_method(D_METHOD("update_world_transform"), &SpineSkeleton::update_world_transform); - ClassDB::bind_method(D_METHOD("set_to_setup_pose"), &SpineSkeleton::set_to_setup_pose); - ClassDB::bind_method(D_METHOD("set_bones_to_setup_pose"), &SpineSkeleton::set_bones_to_setup_pose); - ClassDB::bind_method(D_METHOD("set_slots_to_setup_pose"), &SpineSkeleton::set_slots_to_setup_pose); - // - // Ref find_bone(const String &name); - // int find_bone_index(const String &name); - // - // Ref find_slot(const String &name); - // int find_slot_index(const String &name); - // - // void set_skin_by_name(const String &skin_name); - // void set_skin(Ref new_skin); - // - // Ref get_attachment_by_slot_name(const String &slot_name, const String &attachment_name); - // Ref get_attachment_by_slot_index(int slot_index, const String &attachment_name); - ClassDB::bind_method(D_METHOD("find_bone", "bone_name"), &SpineSkeleton::find_bone); - ClassDB::bind_method(D_METHOD("find_slot", "slot_name"), &SpineSkeleton::find_slot); - ClassDB::bind_method(D_METHOD("set_skin_by_name", "skin_name"), &SpineSkeleton::set_skin_by_name); - ClassDB::bind_method(D_METHOD("set_skin", "new_skin"), &SpineSkeleton::set_skin); - ClassDB::bind_method(D_METHOD("get_attachment_by_slot_name", "slot_name", "attachment_name"), &SpineSkeleton::get_attachment_by_slot_name); - ClassDB::bind_method(D_METHOD("get_attachment_by_slot_index", "slot_index", "attachment_name"), &SpineSkeleton::get_attachment_by_slot_index); - // - // void set_attachment(const String &slot_name, const String &attachment_name); - // - // Ref find_ik_constraint(const String &constraint_name); - // Ref find_transform_constraint(const String &constraint_name); - // Ref find_path_constraint(const String &constraint_name); - // - // void update(float delta); - // - // Dictionary get_bounds(); - // - // Ref get_root_bone(); - // - // Ref get_data(); - ClassDB::bind_method(D_METHOD("set_attachment", "slot_name", "attachment_name"), &SpineSkeleton::set_attachment); - ClassDB::bind_method(D_METHOD("find_ik_constraint", "constraint_name"), &SpineSkeleton::find_ik_constraint); - ClassDB::bind_method(D_METHOD("find_transform_constraint", "constraint_name"), &SpineSkeleton::find_transform_constraint); - ClassDB::bind_method(D_METHOD("find_path_constraint", "constraint_name"), &SpineSkeleton::find_path_constraint); - ClassDB::bind_method(D_METHOD("update", "delta"), &SpineSkeleton::update); - ClassDB::bind_method(D_METHOD("get_bounds"), &SpineSkeleton::get_bounds); - ClassDB::bind_method(D_METHOD("get_root_bone"), &SpineSkeleton::get_root_bone); - ClassDB::bind_method(D_METHOD("get_data"), &SpineSkeleton::get_data); - // - // Array get_bones(); - // Array get_slots(); - // Array get_draw_orders(); - // Array get_ik_constraints(); - // Array get_path_constraints(); - // Array get_transform_constraints(); - // - // Ref get_skin(); - ClassDB::bind_method(D_METHOD("get_bones"), &SpineSkeleton::get_bones); - ClassDB::bind_method(D_METHOD("get_slots"), &SpineSkeleton::get_slots); - ClassDB::bind_method(D_METHOD("get_draw_orders"), &SpineSkeleton::get_draw_orders); - ClassDB::bind_method(D_METHOD("get_ik_constraints"), &SpineSkeleton::get_ik_constraints); - ClassDB::bind_method(D_METHOD("get_path_constraints"), &SpineSkeleton::get_path_constraints); - ClassDB::bind_method(D_METHOD("get_transform_constraints"), &SpineSkeleton::get_transform_constraints); - ClassDB::bind_method(D_METHOD("get_skin"), &SpineSkeleton::get_skin); - // - // Color get_color(); - // void set_color(Color v); - // - // float get_time(); - // void set_time(float v); - // - // void set_position(Vector2 pos); - ClassDB::bind_method(D_METHOD("get_color"), &SpineSkeleton::get_color); - ClassDB::bind_method(D_METHOD("set_color", "v"), &SpineSkeleton::set_color); - ClassDB::bind_method(D_METHOD("get_time"), &SpineSkeleton::get_time); - ClassDB::bind_method(D_METHOD("set_time", "v"), &SpineSkeleton::set_time); - ClassDB::bind_method(D_METHOD("set_position", "pos"), &SpineSkeleton::set_position); - // - // float get_x(); - // void set_x(float v); - // - // float get_y(); - // void set_y(float v); - // - // float get_scale_x(); - // void set_scale_x(float v); - // - // float get_scale_y(); - // void set_scale_y(float v); - ClassDB::bind_method(D_METHOD("get_x"), &SpineSkeleton::get_x); - ClassDB::bind_method(D_METHOD("set_x", "v"), &SpineSkeleton::set_x); - ClassDB::bind_method(D_METHOD("get_y"), &SpineSkeleton::get_y); - ClassDB::bind_method(D_METHOD("set_y", "v"), &SpineSkeleton::set_y); - ClassDB::bind_method(D_METHOD("get_scale_x"), &SpineSkeleton::get_scale_x); - ClassDB::bind_method(D_METHOD("set_scale_x", "v"), &SpineSkeleton::set_scale_x); - ClassDB::bind_method(D_METHOD("get_scale_y"), &SpineSkeleton::get_scale_y); - ClassDB::bind_method(D_METHOD("set_scale_y", "v"), &SpineSkeleton::set_scale_y); -} - -SpineSkeleton::SpineSkeleton() : skeleton(NULL), spine_object(false), the_sprite(nullptr) { -} - -SpineSkeleton::~SpineSkeleton() { - if (skeleton && !spine_object) { - delete skeleton; - skeleton = NULL; - } -} - -void SpineSkeleton::load_skeleton(Ref sd) { - if (skeleton && !spine_object) { - delete skeleton; - skeleton = NULL; - } - skeleton = new spine::Skeleton(sd->get_skeleton_data()); - spine_object = false; -} - -#define S_T(x) (spine::String(x.utf8())) -void SpineSkeleton::update_world_transform() { - skeleton->updateWorldTransform(); -} - -void SpineSkeleton::set_to_setup_pose() { - skeleton->setToSetupPose(); -} - -void SpineSkeleton::set_bones_to_setup_pose() { - skeleton->setBonesToSetupPose(); -} - -void SpineSkeleton::set_slots_to_setup_pose() { - skeleton->setSlotsToSetupPose(); -} - -Ref SpineSkeleton::find_bone(const String &name) { - if (name.empty()) return NULL; - auto b = skeleton->findBone(S_T(name)); - if (b == NULL) return NULL; - Ref gd_b(memnew(SpineBone)); - gd_b->set_spine_object(b); - gd_b->set_spine_sprite(the_sprite); - return gd_b; -} - -Ref SpineSkeleton::find_slot(const String &name) { - if (name.empty()) return NULL; - auto s = skeleton->findSlot(S_T(name)); - if (s == NULL) return NULL; - Ref gd_s(memnew(SpineSlot)); - gd_s->set_spine_object(s); - return gd_s; -} - -void SpineSkeleton::set_skin_by_name(const String &skin_name) { - skeleton->setSkin(S_T(skin_name)); -} -void SpineSkeleton::set_skin(Ref new_skin) { - if (new_skin.is_valid()) { - skeleton->setSkin(new_skin->get_spine_object()); - } else { - skeleton->setSkin(NULL); - } -} - -Ref SpineSkeleton::get_attachment_by_slot_name(const String &slot_name, const String &attachment_name) { - auto a = skeleton->getAttachment(S_T(slot_name), S_T(attachment_name)); - if (a == NULL) return NULL; - Ref gd_a(memnew(SpineAttachment)); - gd_a->set_spine_object(a); - return gd_a; -} -Ref SpineSkeleton::get_attachment_by_slot_index(int slot_index, const String &attachment_name) { - auto a = skeleton->getAttachment(slot_index, S_T(attachment_name)); - if (a == NULL) return NULL; - Ref gd_a(memnew(SpineAttachment)); - gd_a->set_spine_object(a); - return gd_a; -} - -void SpineSkeleton::set_attachment(const String &slot_name, const String &attachment_name) { - ERR_FAIL_COND(slot_name.empty()); - ERR_FAIL_COND(get_attachment_by_slot_name(slot_name, attachment_name) == NULL); - skeleton->setAttachment(S_T(slot_name), S_T(attachment_name)); -} - -Ref SpineSkeleton::find_ik_constraint(const String &constraint_name) { - if (constraint_name.empty()) return NULL; - auto c = skeleton->findIkConstraint(S_T(constraint_name)); - if (c == NULL) return NULL; - Ref gd_c(memnew(SpineIkConstraint)); - gd_c->set_spine_object(c); - return gd_c; -} -Ref SpineSkeleton::find_transform_constraint(const String &constraint_name) { - if (constraint_name.empty()) return NULL; - auto c = skeleton->findTransformConstraint(S_T(constraint_name)); - if (c == NULL) return NULL; - Ref gd_c(memnew(SpineTransformConstraint)); - gd_c->set_spine_object(c); - return gd_c; -} -Ref SpineSkeleton::find_path_constraint(const String &constraint_name) { - if (constraint_name.empty()) return NULL; - auto c = skeleton->findPathConstraint(S_T(constraint_name)); - if (c == NULL) return NULL; - Ref gd_c(memnew(SpinePathConstraint)); - gd_c->set_spine_object(c); - return gd_c; -} - -void SpineSkeleton::update(float delta) { - skeleton->update(delta); -} - -Dictionary SpineSkeleton::get_bounds() { - float x, y, w, h; - spine::Vector vertex_buffer; - skeleton->getBounds(x, y, w, h, vertex_buffer); - - Dictionary res; - res["x"] = x; - res["y"] = y; - res["w"] = w; - res["h"] = h; - - Array gd_a; - gd_a.resize(vertex_buffer.size()); - for (size_t i = 0; i < gd_a.size(); ++i) { - gd_a[i] = vertex_buffer[i]; - } - res["vertex_buffer"] = gd_a; - - return res; -} - -Ref SpineSkeleton::get_root_bone() { - auto b = skeleton->getRootBone(); - if (b == NULL) return NULL; - Ref gd_b(memnew(SpineBone)); - gd_b->set_spine_object(b); - gd_b->set_spine_sprite(the_sprite); - return gd_b; -} - -Ref SpineSkeleton::get_data() const { - auto sd = skeleton->getData(); - if (sd == NULL) return NULL; - Ref gd_sd(memnew(SpineSkeletonDataResource)); - gd_sd->set_spine_object(sd); - return gd_sd; -} - -Array SpineSkeleton::get_bones() { - auto &as = skeleton->getBones(); - Array gd_as; - gd_as.resize(as.size()); - for (size_t i = 0; i < gd_as.size(); ++i) { - auto b = as[i]; - if (b == NULL) gd_as[i] = Ref(NULL); - Ref gd_a(memnew(SpineBone)); - gd_a->set_spine_object(b); - gd_a->set_spine_sprite(the_sprite); - gd_as[i] = gd_a; - } - return gd_as; -} -Array SpineSkeleton::get_slots() { - auto &as = skeleton->getSlots(); - Array gd_as; - gd_as.resize(as.size()); - for (size_t i = 0; i < gd_as.size(); ++i) { - auto b = as[i]; - if (b == NULL) gd_as[i] = Ref(NULL); - Ref gd_a(memnew(SpineSlot)); - gd_a->set_spine_object(b); - gd_as[i] = gd_a; - } - return gd_as; -} -Array SpineSkeleton::get_draw_orders() { - auto &as = skeleton->getDrawOrder(); - Array gd_as; - gd_as.resize(as.size()); - for (size_t i = 0; i < gd_as.size(); ++i) { - auto b = as[i]; - if (b == NULL) gd_as[i] = Ref(NULL); - Ref gd_a(memnew(SpineSlot)); - gd_a->set_spine_object(b); - gd_as[i] = gd_a; - } - return gd_as; -} -Array SpineSkeleton::get_ik_constraints() { - auto &as = skeleton->getIkConstraints(); - Array gd_as; - gd_as.resize(as.size()); - for (size_t i = 0; i < gd_as.size(); ++i) { - auto b = as[i]; - if (b == NULL) gd_as[i] = Ref(NULL); - Ref gd_a(memnew(SpineIkConstraint)); - gd_a->set_spine_object(b); - gd_as[i] = gd_a; - } - return gd_as; -} -Array SpineSkeleton::get_path_constraints() { - auto &as = skeleton->getPathConstraints(); - Array gd_as; - gd_as.resize(as.size()); - for (size_t i = 0; i < gd_as.size(); ++i) { - auto b = as[i]; - if (b == NULL) gd_as[i] = Ref(NULL); - Ref gd_a(memnew(SpinePathConstraint)); - gd_a->set_spine_object(b); - gd_as[i] = gd_a; - } - return gd_as; -} -Array SpineSkeleton::get_transform_constraints() { - auto &as = skeleton->getTransformConstraints(); - Array gd_as; - gd_as.resize(as.size()); - for (size_t i = 0; i < gd_as.size(); ++i) { - auto b = as[i]; - if (b == NULL) gd_as[i] = Ref(NULL); - Ref gd_a(memnew(SpineTransformConstraint)); - gd_a->set_spine_object(b); - gd_as[i] = gd_a; - } - return gd_as; -} - -Ref SpineSkeleton::get_skin() { - auto s = skeleton->getSkin(); - if (s == NULL) return NULL; - Ref gd_s(memnew(SpineSkin)); - gd_s->set_spine_object(s); - return gd_s; -} - -Color SpineSkeleton::get_color() { - auto &c = skeleton->getColor(); - return Color(c.r, c.g, c.b, c.a); -} -void SpineSkeleton::set_color(Color v) { - auto &c = skeleton->getColor(); - c.set(v.r, v.g, v.b, v.a); -} - -float SpineSkeleton::get_time() { - return skeleton->getTime(); -} -void SpineSkeleton::set_time(float v) { - skeleton->setTime(v); -} - -void SpineSkeleton::set_position(Vector2 pos) { - skeleton->setPosition(pos.x, pos.y); -} - -float SpineSkeleton::get_x() { - return skeleton->getX(); -} -void SpineSkeleton::set_x(float v) { - skeleton->setX(v); -} - -float SpineSkeleton::get_y() { - return skeleton->getY(); -} -void SpineSkeleton::set_y(float v) { - skeleton->setY(v); -} - -float SpineSkeleton::get_scale_x() { - return skeleton->getScaleX(); -} -void SpineSkeleton::set_scale_x(float v) { - skeleton->setScaleX(v); -} - -float SpineSkeleton::get_scale_y() { - return skeleton->getScaleY(); -} -void SpineSkeleton::set_scale_y(float v) { - skeleton->setScaleY(v); -} - -void SpineSkeleton::set_spine_sprite(SpineSprite *s) { - the_sprite = s; -} diff --git a/spine-godot/spine_godot/SpineSkeleton.h b/spine-godot/spine_godot/SpineSkeleton.h deleted file mode 100644 index 14e5bc3bb..000000000 --- a/spine-godot/spine_godot/SpineSkeleton.h +++ /dev/null @@ -1,134 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINESKELETON_H -#define GODOT_SPINESKELETON_H - -#include "core/variant_parser.h" - -#include - -#include "SpineSkeletonDataResource.h" -#include "SpineBone.h" -#include "SpineSlot.h" - -class SpineSprite; - -class SpineSkeleton : public Reference { - GDCLASS(SpineSkeleton, Reference); - -protected: - static void _bind_methods(); - -private: - spine::Skeleton *skeleton; - bool spine_object; - - SpineSprite *the_sprite; - -public: - SpineSkeleton(); - ~SpineSkeleton(); - - void load_skeleton(Ref sd); - - inline void set_spine_object(spine::Skeleton *s) { - skeleton = s; - spine_object = true; - } - inline spine::Skeleton *get_spine_object() { - return skeleton; - } - - void set_spine_sprite(SpineSprite *s); - - - void update_world_transform(); - - void set_to_setup_pose(); - - void set_bones_to_setup_pose(); - - void set_slots_to_setup_pose(); - - Ref find_bone(const String &name); - - Ref find_slot(const String &name); - - void set_skin_by_name(const String &skin_name); - void set_skin(Ref new_skin); - - Ref get_attachment_by_slot_name(const String &slot_name, const String &attachment_name); - Ref get_attachment_by_slot_index(int slot_index, const String &attachment_name); - - void set_attachment(const String &slot_name, const String &attachment_name); - - Ref find_ik_constraint(const String &constraint_name); - Ref find_transform_constraint(const String &constraint_name); - Ref find_path_constraint(const String &constraint_name); - - void update(float delta); - - Dictionary get_bounds(); - - Ref get_root_bone(); - - Ref get_data() const; - - Array get_bones(); - Array get_slots(); - Array get_draw_orders(); - Array get_ik_constraints(); - Array get_path_constraints(); - Array get_transform_constraints(); - - Ref get_skin(); - - Color get_color(); - void set_color(Color v); - - float get_time(); - void set_time(float v); - - void set_position(Vector2 pos); - - float get_x(); - void set_x(float v); - - float get_y(); - void set_y(float v); - - float get_scale_x(); - void set_scale_x(float v); - - float get_scale_y(); - void set_scale_y(float v); -}; - -#endif//GODOT_SPINESKELETON_H diff --git a/spine-godot/spine_godot/SpineSkeletonDataResource.cpp b/spine-godot/spine_godot/SpineSkeletonDataResource.cpp deleted file mode 100644 index 977913c61..000000000 --- a/spine-godot/spine_godot/SpineSkeletonDataResource.cpp +++ /dev/null @@ -1,455 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpineSkeletonDataResource.h" - -void SpineSkeletonDataResource::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_atlas_res", "atlas_res"), &SpineSkeletonDataResource::set_atlas_res); - ClassDB::bind_method(D_METHOD("get_atlas_res"), &SpineSkeletonDataResource::get_atlas_res); - ClassDB::bind_method(D_METHOD("set_skeleton_json_res", "skeleton_json_res"), &SpineSkeletonDataResource::set_skeleton_json_res); - ClassDB::bind_method(D_METHOD("get_skeleton_json_res"), &SpineSkeletonDataResource::get_skeleton_json_res); - ClassDB::bind_method(D_METHOD("is_skeleton_data_loaded"), &SpineSkeletonDataResource::is_skeleton_data_loaded); - ClassDB::bind_method(D_METHOD("find_animation", "animation_name"), &SpineSkeletonDataResource::find_animation); - ClassDB::bind_method(D_METHOD("get_sk_name"), &SpineSkeletonDataResource::get_sk_name); - ClassDB::bind_method(D_METHOD("set_sk_name", "sk_name"), &SpineSkeletonDataResource::set_sk_name); - ClassDB::bind_method(D_METHOD("get_x"), &SpineSkeletonDataResource::get_x); - ClassDB::bind_method(D_METHOD("set_x", "v"), &SpineSkeletonDataResource::set_x); - ClassDB::bind_method(D_METHOD("get_y"), &SpineSkeletonDataResource::get_y); - ClassDB::bind_method(D_METHOD("set_y", "v"), &SpineSkeletonDataResource::set_y); - ClassDB::bind_method(D_METHOD("get_width"), &SpineSkeletonDataResource::get_width); - ClassDB::bind_method(D_METHOD("get_height"), &SpineSkeletonDataResource::get_height); - ClassDB::bind_method(D_METHOD("get_version"), &SpineSkeletonDataResource::get_version); - ClassDB::bind_method(D_METHOD("get_fps"), &SpineSkeletonDataResource::get_fps); - ClassDB::bind_method(D_METHOD("set_fps", "v"), &SpineSkeletonDataResource::set_fps); - - ClassDB::bind_method(D_METHOD("find_bone", "bone_name"), &SpineSkeletonDataResource::find_bone); - ClassDB::bind_method(D_METHOD("find_slot", "slot_name"), &SpineSkeletonDataResource::find_slot); - ClassDB::bind_method(D_METHOD("find_skin", "skin_name"), &SpineSkeletonDataResource::find_skin); - ClassDB::bind_method(D_METHOD("find_event", "event_data_name"), &SpineSkeletonDataResource::find_event); - ClassDB::bind_method(D_METHOD("find_ik_constraint_data", "constraint_name"), &SpineSkeletonDataResource::find_ik_constraint); - ClassDB::bind_method(D_METHOD("find_transform_constraint_data", "constraint_name"), &SpineSkeletonDataResource::find_transform_constraint); - ClassDB::bind_method(D_METHOD("find_path_constraint_data", "constraint_name"), &SpineSkeletonDataResource::find_path_constraint); - ClassDB::bind_method(D_METHOD("get_all_bone_data"), &SpineSkeletonDataResource::get_bones); - ClassDB::bind_method(D_METHOD("get_all_slot_data"), &SpineSkeletonDataResource::get_slots); - ClassDB::bind_method(D_METHOD("get_skins"), &SpineSkeletonDataResource::get_skins); - ClassDB::bind_method(D_METHOD("get_default_skin"), &SpineSkeletonDataResource::get_default_skin); - ClassDB::bind_method(D_METHOD("set_default_skin", "v"), &SpineSkeletonDataResource::set_default_skin); - ClassDB::bind_method(D_METHOD("get_all_event_data"), &SpineSkeletonDataResource::get_events); - ClassDB::bind_method(D_METHOD("get_animations"), &SpineSkeletonDataResource::get_animations); - ClassDB::bind_method(D_METHOD("get_all_ik_constraint_data"), &SpineSkeletonDataResource::get_ik_constraints); - ClassDB::bind_method(D_METHOD("get_all_transform_constraint_data"), &SpineSkeletonDataResource::get_transform_constraints); - ClassDB::bind_method(D_METHOD("get_all_path_constraint_data"), &SpineSkeletonDataResource::get_path_constraints); - - ADD_SIGNAL(MethodInfo("skeleton_data_loaded")); - ADD_SIGNAL(MethodInfo("atlas_res_changed")); - ADD_SIGNAL(MethodInfo("skeleton_json_res_changed")); - - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "atlas_res", PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "SpineAtlasResource"), "set_atlas_res", "get_atlas_res"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "skeleton_json_res", PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "SpineSkeletonJsonDataResource"), "set_skeleton_json_res", "get_skeleton_json_res"); -} - -SpineSkeletonDataResource::SpineSkeletonDataResource() : valid(false), spine_object(false), skeleton_data(NULL) { -} -SpineSkeletonDataResource::~SpineSkeletonDataResource() { - if (skeleton_data && !spine_object) { - delete skeleton_data; - skeleton_data = NULL; - } -} - -bool SpineSkeletonDataResource::is_skeleton_data_loaded() const { - return valid || spine_object; -} - -void SpineSkeletonDataResource::load_res(spine::Atlas *a, const String &json_string) { - if (json_string.empty()) return; - auto path = get_path(); - spine::SkeletonJson json(a); - auto temp_skeleton_data = json.readSkeletonData(json_string.utf8()); - if (!temp_skeleton_data) { - print_error(String("Error happened while loading skeleton json data: ") + path); - print_error(String("Error msg: ") + json.getError().buffer()); - return; - } - if (skeleton_data) { - delete skeleton_data; - skeleton_data = NULL; - } - skeleton_data = temp_skeleton_data; - - valid = true; - // print_line("Skeleton json data loaded!"); -} - -void SpineSkeletonDataResource::update_skeleton_data() { - if (atlas_res.is_valid() && skeleton_json_res.is_valid()) { - load_res(atlas_res->get_spine_atlas(), skeleton_json_res->get_json_string()); - if (valid) { - emit_signal("skeleton_data_loaded"); - } - } -} - -void SpineSkeletonDataResource::set_atlas_res(const Ref &a) { - atlas_res = a; - valid = false; - emit_signal("atlas_res_changed"); - update_skeleton_data(); -} -Ref SpineSkeletonDataResource::get_atlas_res() { - if (spine_object) { - print_line("Getting atlas res from a spine_object skeleton! The result may be NULL!"); - } - return atlas_res; -} - -void SpineSkeletonDataResource::set_skeleton_json_res(const Ref &s) { - skeleton_json_res = s; - valid = false; - // print_line("skeleton_json_res_changed emitted"); - emit_signal("skeleton_json_res_changed"); - update_skeleton_data(); -} -Ref SpineSkeletonDataResource::get_skeleton_json_res() { - if (spine_object) { - print_line("Getting atlas res from a spine_object skeleton! The result may be NULL!"); - } - return skeleton_json_res; -} - -#define CHECK_V \ - if (!is_skeleton_data_loaded()) { \ - ERR_PRINT("skeleton data has not loaded yet!"); \ - return; \ - } -#define CHECK_X(x) \ - if (!is_skeleton_data_loaded()) { \ - ERR_PRINT("skeleton data has not loaded yet!"); \ - return x; \ - } -#define S_T(x) (spine::String(x.utf8())) -Ref SpineSkeletonDataResource::find_animation(const String &animation_name) { - CHECK_X(NULL); - if (animation_name.empty()) { - return NULL; - } - auto a = skeleton_data->findAnimation(S_T(animation_name)); - if (!a) return NULL; - Ref sa(memnew(SpineAnimation)); - sa->set_spine_object(a); - return sa; -} -String SpineSkeletonDataResource::get_sk_name() { - CHECK_X("error"); - return skeleton_data->getName().buffer(); -} -void SpineSkeletonDataResource::set_sk_name(const String &v) { - CHECK_V; - skeleton_data->setName(S_T(v)); -} -float SpineSkeletonDataResource::get_x() { - CHECK_X(0); - return skeleton_data->getX(); -} -void SpineSkeletonDataResource::set_x(float v) { - CHECK_V; - skeleton_data->setX(v); -} -float SpineSkeletonDataResource::get_y() { - CHECK_X(0); - return skeleton_data->getY(); -} -void SpineSkeletonDataResource::set_y(float v) { - CHECK_V; - skeleton_data->setY(v); -} -float SpineSkeletonDataResource::get_width() { - CHECK_X(0); - return skeleton_data->getWidth(); -} -float SpineSkeletonDataResource::get_height() { - CHECK_X(0); - return skeleton_data->getHeight(); -} -String SpineSkeletonDataResource::get_version() { - CHECK_X("error"); - return skeleton_data->getVersion().buffer(); -} -float SpineSkeletonDataResource::get_fps() { - CHECK_X(0); - return skeleton_data->getFps(); -} -void SpineSkeletonDataResource::set_fps(float v) { - CHECK_V; - skeleton_data->setFps(v); -} - -Ref SpineSkeletonDataResource::find_bone(const String &bone_name) { - if (bone_name.empty()) return NULL; - auto b = skeleton_data->findBone(S_T(bone_name)); - if (b == NULL) return NULL; - Ref gd_b(memnew(SpineBoneData)); - gd_b->set_spine_object(b); - return gd_b; -} - -Ref SpineSkeletonDataResource::find_slot(const String &slot_name) { - if (slot_name.empty()) return NULL; - auto b = skeleton_data->findSlot(S_T(slot_name)); - if (b == NULL) return NULL; - Ref gd_b(memnew(SpineSlotData)); - gd_b->set_spine_object(b); - return gd_b; -} - -Ref SpineSkeletonDataResource::find_skin(const String &skin_name) { - if (skin_name.empty()) return NULL; - auto b = skeleton_data->findSkin(S_T(skin_name)); - if (b == NULL) return NULL; - Ref gd_b(memnew(SpineSkin)); - gd_b->set_spine_object(b); - return gd_b; -} - -Ref SpineSkeletonDataResource::find_event(const String &event_data_name) { - if (event_data_name.empty()) return NULL; - auto b = skeleton_data->findEvent(S_T(event_data_name)); - if (b == NULL) return NULL; - Ref gd_b(memnew(SpineEventData)); - gd_b->set_spine_object(b); - return gd_b; -} - -Ref SpineSkeletonDataResource::find_ik_constraint(const String &constraint_name) { - if (constraint_name.empty()) return NULL; - auto b = skeleton_data->findIkConstraint(S_T(constraint_name)); - if (b == NULL) return NULL; - Ref gd_b(memnew(SpineIkConstraintData)); - gd_b->set_spine_object(b); - return gd_b; -} -Ref SpineSkeletonDataResource::find_transform_constraint(const String &constraint_name) { - if (constraint_name.empty()) return NULL; - auto b = skeleton_data->findTransformConstraint(S_T(constraint_name)); - if (b == NULL) return NULL; - Ref gd_b(memnew(SpineTransformConstraintData)); - gd_b->set_spine_object(b); - return gd_b; -} -Ref SpineSkeletonDataResource::find_path_constraint(const String &constraint_name) { - if (constraint_name.empty()) return NULL; - auto b = skeleton_data->findPathConstraint(S_T(constraint_name)); - if (b == NULL) return NULL; - Ref gd_b(memnew(SpinePathConstraintData)); - gd_b->set_spine_object(b); - return gd_b; -} - -Array SpineSkeletonDataResource::get_bones() { - auto bs = skeleton_data->getBones(); - Array gd_bs; - gd_bs.resize(bs.size()); - for (size_t i = 0; i < bs.size(); ++i) { - if (bs[i] == NULL) gd_bs[i] = Ref(NULL); - else { - Ref gd_b(memnew(SpineBoneData)); - gd_b->set_spine_object(bs[i]); - gd_bs[i] = gd_b; - } - } - return gd_bs; -} -Array SpineSkeletonDataResource::get_slots() { - auto bs = skeleton_data->getSlots(); - Array gd_bs; - gd_bs.resize(bs.size()); - for (size_t i = 0; i < bs.size(); ++i) { - if (bs[i] == NULL) gd_bs[i] = Ref(NULL); - else { - Ref gd_b(memnew(SpineSlotData)); - gd_b->set_spine_object(bs[i]); - gd_bs[i] = gd_b; - } - } - return gd_bs; -} -Array SpineSkeletonDataResource::get_skins() const { - auto bs = skeleton_data->getSkins(); - Array gd_bs; - gd_bs.resize(bs.size()); - for (size_t i = 0; i < bs.size(); ++i) { - if (bs[i] == NULL) gd_bs[i] = Ref(NULL); - else { - Ref gd_b(memnew(SpineSkin)); - gd_b->set_spine_object(bs[i]); - gd_bs[i] = gd_b; - } - } - return gd_bs; -} - -Ref SpineSkeletonDataResource::get_default_skin() { - auto b = skeleton_data->getDefaultSkin(); - if (b == NULL) return NULL; - Ref gd_b(memnew(SpineSkin)); - gd_b->set_spine_object(b); - return gd_b; -} -void SpineSkeletonDataResource::set_default_skin(Ref v) { - if (v.is_valid()) { - skeleton_data->setDefaultSkin(v->get_spine_object()); - } else - skeleton_data->setDefaultSkin(NULL); -} - -Array SpineSkeletonDataResource::get_events() { - auto bs = skeleton_data->getEvents(); - Array gd_bs; - gd_bs.resize(bs.size()); - for (size_t i = 0; i < bs.size(); ++i) { - if (bs[i] == NULL) gd_bs[i] = Ref(NULL); - else { - Ref gd_b(memnew(SpineEventData)); - gd_b->set_spine_object(bs[i]); - gd_bs[i] = gd_b; - } - } - return gd_bs; -} -Array SpineSkeletonDataResource::get_animations() { - auto bs = skeleton_data->getAnimations(); - Array gd_bs; - gd_bs.resize(bs.size()); - for (size_t i = 0; i < bs.size(); ++i) { - if (bs[i] == NULL) gd_bs[i] = Ref(NULL); - else { - Ref gd_b(memnew(SpineAnimation)); - gd_b->set_spine_object(bs[i]); - gd_bs[i] = gd_b; - } - } - return gd_bs; -} -Array SpineSkeletonDataResource::get_ik_constraints() { - auto bs = skeleton_data->getIkConstraints(); - Array gd_bs; - gd_bs.resize(bs.size()); - for (size_t i = 0; i < bs.size(); ++i) { - if (bs[i] == NULL) gd_bs[i] = Ref(NULL); - else { - Ref gd_b(memnew(SpineIkConstraintData)); - gd_b->set_spine_object(bs[i]); - gd_bs[i] = gd_b; - } - } - return gd_bs; -} -Array SpineSkeletonDataResource::get_transform_constraints() { - auto bs = skeleton_data->getTransformConstraints(); - Array gd_bs; - gd_bs.resize(bs.size()); - for (size_t i = 0; i < bs.size(); ++i) { - if (bs[i] == NULL) gd_bs[i] = Ref(NULL); - else { - Ref gd_b(memnew(SpineTransformConstraintData)); - gd_b->set_spine_object(bs[i]); - gd_bs[i] = gd_b; - } - } - return gd_bs; -} -Array SpineSkeletonDataResource::get_path_constraints() { - auto bs = skeleton_data->getPathConstraints(); - Array gd_bs; - gd_bs.resize(bs.size()); - for (size_t i = 0; i < bs.size(); ++i) { - if (bs[i] == NULL) gd_bs[i] = Ref(NULL); - else { - Ref gd_b(memnew(SpinePathConstraintData)); - gd_b->set_spine_object(bs[i]); - gd_bs[i] = gd_b; - } - } - return gd_bs; -} -#undef S_T -#undef CHECK_V -#undef CHECK_X - -//External feature functions -void SpineSkeletonDataResource::get_animation_names(Vector &res) const { - res.clear(); - if (!is_skeleton_data_loaded()) { - return; - } - auto as = skeleton_data->getAnimations(); - for (size_t i = 0; i < as.size(); ++i) { - auto a = as[i]; - if (a) { - res.push_back(a->getName().buffer()); - } else { - res.push_back(""); - } - } -} -void SpineSkeletonDataResource::get_skin_names(Vector &res) const { - res.clear(); - if (!is_skeleton_data_loaded()) { - return; - } - auto as = get_skins(); - res.resize(as.size()); - for (size_t i = 0; i < as.size(); ++i) { - auto a = Ref(as[i]); - if (a.is_valid()) { - res.push_back(a->get_skin_name()); - } else { - res.push_back(""); - } - } -} - -void SpineSkeletonDataResource::_get_property_list(List *p_list) const { - PropertyInfo p; - Vector res; - - p.name = "animations"; - p.type = Variant::STRING; - get_animation_names(res); - p.hint_string = String(",").join(res); - p.hint = PROPERTY_HINT_ENUM; - p_list->push_back(p); - - p.name = "skins"; - p.type = Variant::STRING; - get_skin_names(res); - p.hint_string = String(",").join(res); - p.hint = PROPERTY_HINT_ENUM; - p_list->push_back(p); -} diff --git a/spine-godot/spine_godot/SpineSkeletonDataResource.h b/spine-godot/spine_godot/SpineSkeletonDataResource.h deleted file mode 100644 index eaabaa11c..000000000 --- a/spine-godot/spine_godot/SpineSkeletonDataResource.h +++ /dev/null @@ -1,140 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINESKELETONDATARESOURCE_H -#define GODOT_SPINESKELETONDATARESOURCE_H - -#include "core/variant_parser.h" - -#include - -#include "SpineAtlasResource.h" -#include "SpineSkeletonJsonDataResource.h" -#include "SpineAnimation.h" -#include "SpineBoneData.h" -#include "SpineSlotData.h" -#include "SpineSkin.h" -#include "SpineIkConstraintData.h" -#include "SpineTransformConstraintData.h" -#include "SpinePathConstraintData.h" -#include "SpineEventData.h" - -class SpineSkeletonDataResource : public Resource { - GDCLASS(SpineSkeletonDataResource, Resource); - -protected: - static void _bind_methods(); - -private: - Ref atlas_res; - Ref skeleton_json_res; - bool valid; - bool spine_object; - - spine::SkeletonData *skeleton_data; - - void update_skeleton_data(); - -public: - inline void set_spine_object(spine::SkeletonData *s) { - skeleton_data = s; - if (s) - spine_object = true; - } - inline spine::SkeletonData *get_spine_object() { - return skeleton_data; - } - - void load_res(spine::Atlas *a, const String &json_path); - - SpineSkeletonDataResource(); - virtual ~SpineSkeletonDataResource(); - - void _get_property_list(List *p_list) const; - - void set_atlas_res(const Ref &a); - Ref get_atlas_res(); - - void set_skeleton_json_res(const Ref &s); - Ref get_skeleton_json_res(); - - inline spine::SkeletonData *get_skeleton_data() { return skeleton_data; } - - bool is_skeleton_data_loaded() const; - - void get_animation_names(Vector &l) const; - void get_skin_names(Vector &l) const; - - // spine api - Ref find_bone(const String &bone_name); - - Ref find_slot(const String &slot_name); - - Ref find_skin(const String &skin_name); - - Ref find_event(const String &event_data_name); - - Ref find_animation(const String &animation_name); - - Ref find_ik_constraint(const String &constraint_name); - Ref find_transform_constraint(const String &constraint_name); - Ref find_path_constraint(const String &constraint_name); - - Array get_bones(); - Array get_slots(); - Array get_skins() const; - - Ref get_default_skin(); - void set_default_skin(Ref v); - - Array get_events(); - Array get_animations(); - Array get_ik_constraints(); - Array get_transform_constraints(); - Array get_path_constraints(); - - String get_sk_name(); - void set_sk_name(const String &v); - - float get_x(); - void set_x(float v); - - float get_y(); - void set_y(float v); - - float get_width(); - float get_height(); - - String get_version(); - - float get_fps(); - void set_fps(float v); -}; - -#endif//GODOT_SPINESKELETONDATARESOURCE_H diff --git a/spine-godot/spine_godot/SpineSkeletonJsonDataResource.cpp b/spine-godot/spine_godot/SpineSkeletonJsonDataResource.cpp deleted file mode 100644 index d332a791a..000000000 --- a/spine-godot/spine_godot/SpineSkeletonJsonDataResource.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpineSkeletonJsonDataResource.h" - - -void SpineSkeletonJsonDataResource::_bind_methods() { -} - -Error SpineSkeletonJsonDataResource::load_from_file(const String &p_path) { - Error err; - - json_string = FileAccess::get_file_as_string(p_path, &err); - return err; -} - -Error SpineSkeletonJsonDataResource::save_to_file(const String &p_path) { - Error err; - FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &err); - if (err != OK) { - if (file) file->close(); - return err; - } - - file->store_string(json_string); - file->close(); - - return OK; -} diff --git a/spine-godot/spine_godot/SpineSkeletonJsonDataResource.h b/spine-godot/spine_godot/SpineSkeletonJsonDataResource.h deleted file mode 100644 index 8b6045bf6..000000000 --- a/spine-godot/spine_godot/SpineSkeletonJsonDataResource.h +++ /dev/null @@ -1,50 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINESKELETONJSONDATARESOURCE_H -#define GODOT_SPINESKELETONJSONDATARESOURCE_H - -#include "core/variant_parser.h" - -class SpineSkeletonJsonDataResource : public Resource { - GDCLASS(SpineSkeletonJsonDataResource, Resource); - -protected: - static void _bind_methods(); - - String json_string; - -public: - inline const String &get_json_string() { return json_string; } - - Error load_from_file(const String &p_path); - Error save_to_file(const String &p_path); -}; - -#endif//GODOT_SPINESKELETONJSONDATARESOURCE_H diff --git a/spine-godot/spine_godot/SpineSkin.cpp b/spine-godot/spine_godot/SpineSkin.cpp deleted file mode 100644 index b30f01ae5..000000000 --- a/spine-godot/spine_godot/SpineSkin.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpineSkin.h" - -#include "SpineBoneData.h" -#include "SpineConstraintData.h" - -void SpineSkin::_bind_methods() { - ClassDB::bind_method(D_METHOD("init", "name"), &SpineSkin::init); - ClassDB::bind_method(D_METHOD("set_attachment", "slot_index", "name", "attachment"), &SpineSkin::set_attachment); - ClassDB::bind_method(D_METHOD("get_attachment", "slot_index", "name"), &SpineSkin::get_attachment); - ClassDB::bind_method(D_METHOD("remove_attachment", "slot_index", "name"), &SpineSkin::remove_attachment); - ClassDB::bind_method(D_METHOD("find_names_for_slot", "slot_index"), &SpineSkin::find_names_for_slot); - ClassDB::bind_method(D_METHOD("find_attachments_for_slot", "slot_index"), &SpineSkin::find_attachments_for_slot); - ClassDB::bind_method(D_METHOD("get_skin_name"), &SpineSkin::get_skin_name); - ClassDB::bind_method(D_METHOD("add_skin", "other"), &SpineSkin::add_skin); - ClassDB::bind_method(D_METHOD("copy_skin", "other"), &SpineSkin::copy_skin); - ClassDB::bind_method(D_METHOD("get_attachments"), &SpineSkin::get_attachments); - ClassDB::bind_method(D_METHOD("get_all_bone_data"), &SpineSkin::get_bones); - ClassDB::bind_method(D_METHOD("get_all_constraint_data"), &SpineSkin::get_constraint); -} - -SpineSkin::SpineSkin() : skin(NULL) {} -SpineSkin::~SpineSkin() {} - -#define S_T(x) (spine::String(x.utf8())) -Ref SpineSkin::init(const String &name) { - skin = new spine::Skin(S_T(name)); - return this; -} - -void SpineSkin::set_attachment(uint64_t slot_index, const String &name, Ref attachment) { - if (!attachment.is_valid()) { - ERR_PRINT("attachment is invalid!"); - return; - } - skin->setAttachment(slot_index, S_T(name), attachment->get_spine_object()); -} - -Ref SpineSkin::get_attachment(uint64_t slot_index, const String &name) { - auto a = skin->getAttachment(slot_index, S_T(name)); - if (a == NULL) return NULL; - Ref gd_attachment(memnew(SpineAttachment)); - gd_attachment->set_spine_object(a); - return gd_attachment; -} - -void SpineSkin::remove_attachment(uint64_t slot_index, const String &name) { - skin->removeAttachment(slot_index, S_T(name)); -} - -Array SpineSkin::find_names_for_slot(uint64_t slot_index) { - spine::Vector names; - skin->findNamesForSlot(slot_index, names); - Array gd_names; - gd_names.resize(names.size()); - for (size_t i = 0; i < names.size(); ++i) { - gd_names[i] = names[i].buffer(); - } - return gd_names; -} - -Array SpineSkin::find_attachments_for_slot(uint64_t slot_index) { - spine::Vector as; - skin->findAttachmentsForSlot(slot_index, as); - Array gd_as; - gd_as.resize(as.size()); - for (size_t i = 0; i < as.size(); ++i) { - if (as[i] == NULL) gd_as[i] = Ref(NULL); - else { - Ref gd_a(memnew(SpineAttachment)); - gd_a->set_spine_object(as[i]); - gd_as[i] = gd_a; - } - } - return gd_as; -} - -String SpineSkin::get_skin_name() { - return skin->getName().buffer(); -} - -void SpineSkin::add_skin(Ref other) { - if (other.is_valid() && other->get_spine_object()) { - skin->addSkin(other->get_spine_object()); - } else { - ERR_PRINT("other is NULL!"); - } -} - -void SpineSkin::copy_skin(Ref other) { - if (other.is_valid() && other->get_spine_object()) { - skin->copySkin(other->get_spine_object()); - } else { - ERR_PRINT("other is NULL!"); - } -} - -Ref SpineSkin::get_attachments() { - auto *es = new spine::Skin::AttachmentMap::Entries(skin->getAttachments()); - Ref gd_es(memnew(SpineSkinAttachmentMapEntries)); - gd_es->set_spine_object(es); - return gd_es; -} - -Array SpineSkin::get_bones() { - auto bs = skin->getBones(); - Array gd_bs; - gd_bs.resize(bs.size()); - for (size_t i = 0; i < bs.size(); ++i) { - if (bs[i] == NULL) gd_bs[i] = Ref(NULL); - else { - Ref gd_b(memnew(SpineBoneData)); - gd_b->set_spine_object(bs[i]); - gd_bs[i] = gd_b; - } - } - return gd_bs; -} - -Array SpineSkin::get_constraint() { - auto cs = skin->getConstraints(); - Array gd_cs; - gd_cs.resize(cs.size()); - for (size_t i = 0; i < cs.size(); ++i) { - if (cs[i] == NULL) gd_cs[i] = Ref(NULL); - else { - Ref gd_c(memnew(SpineConstraintData)); - gd_c->set_spine_object(cs[i]); - gd_cs[i] = gd_c; - } - } - return gd_cs; -} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineSkin.h b/spine-godot/spine_godot/SpineSkin.h deleted file mode 100644 index 3e1780f2a..000000000 --- a/spine-godot/spine_godot/SpineSkin.h +++ /dev/null @@ -1,85 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINESKIN_H -#define GODOT_SPINESKIN_H - -#include "core/variant_parser.h" - -#include - -#include "SpineAttachment.h" -#include "SpineSkinAttachmentMapEntries.h" - -class SpineSkin : public Reference { - GDCLASS(SpineSkin, Reference); - -protected: - static void _bind_methods(); - -private: - spine::Skin *skin; - -public: - SpineSkin(); - ~SpineSkin(); - - inline void set_spine_object(spine::Skin *s) { - skin = s; - } - spine::Skin *get_spine_object() { - return skin; - } - - Ref init(const String &name); - - void set_attachment(uint64_t slot_index, const String &name, Ref attachment); - - Ref get_attachment(uint64_t slot_index, const String &name); - - void remove_attachment(uint64_t slot_index, const String &name); - - Array find_names_for_slot(uint64_t slot_index); - - Array find_attachments_for_slot(uint64_t slot_index); - - String get_skin_name(); - - void add_skin(Ref other); - - void copy_skin(Ref other); - - Ref get_attachments(); - - Array get_bones(); - - Array get_constraint(); -}; - -#endif//GODOT_SPINESKIN_H diff --git a/spine-godot/spine_godot/SpineSkinAttachmentMapEntries.cpp b/spine-godot/spine_godot/SpineSkinAttachmentMapEntries.cpp deleted file mode 100644 index 67089b011..000000000 --- a/spine-godot/spine_godot/SpineSkinAttachmentMapEntries.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpineSkinAttachmentMapEntries.h" - -void SpineSkinAttachmentMapEntry::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_slot_index"), &SpineSkinAttachmentMapEntry::get_slot_index); - ClassDB::bind_method(D_METHOD("set_slot_index", "v"), &SpineSkinAttachmentMapEntry::set_slot_index); - ClassDB::bind_method(D_METHOD("get_entry_name"), &SpineSkinAttachmentMapEntry::get_entry_name); - ClassDB::bind_method(D_METHOD("set_entry_name", "v"), &SpineSkinAttachmentMapEntry::set_entry_name); - ClassDB::bind_method(D_METHOD("get_attachment"), &SpineSkinAttachmentMapEntry::get_attachment); - ClassDB::bind_method(D_METHOD("set_attachment", "v"), &SpineSkinAttachmentMapEntry::set_attachment); -} - -SpineSkinAttachmentMapEntry::SpineSkinAttachmentMapEntry() : entry(NULL) {} -SpineSkinAttachmentMapEntry::~SpineSkinAttachmentMapEntry() {} - -uint64_t SpineSkinAttachmentMapEntry::get_slot_index() { - return entry->_slotIndex; -} -void SpineSkinAttachmentMapEntry::set_slot_index(uint64_t v) { - entry->_slotIndex = v; -} - -String SpineSkinAttachmentMapEntry::get_entry_name() { - return entry->_name.buffer(); -} -void SpineSkinAttachmentMapEntry::set_entry_name(const String &v) { - entry->_name = spine::String(v.utf8()); -} - -Ref SpineSkinAttachmentMapEntry::get_attachment() { - if (entry->_attachment == NULL) return NULL; - Ref gd_attachment(memnew(SpineAttachment)); - gd_attachment->set_spine_object(entry->_attachment); - return gd_attachment; -} -void SpineSkinAttachmentMapEntry::set_attachment(Ref v) { - if (v.is_valid()) { - entry->_attachment = v->get_spine_object(); - } else { - entry->_attachment = NULL; - } -} - -void SpineSkinAttachmentMapEntries::_bind_methods() { - ClassDB::bind_method(D_METHOD("has_next"), &SpineSkinAttachmentMapEntries::has_next); - ClassDB::bind_method(D_METHOD("next"), &SpineSkinAttachmentMapEntries::next); -} - -SpineSkinAttachmentMapEntries::SpineSkinAttachmentMapEntries() : entries(NULL) {} -SpineSkinAttachmentMapEntries::~SpineSkinAttachmentMapEntries() { - if (entries) { - delete entries; - return; - } -} - -bool SpineSkinAttachmentMapEntries::has_next() { - return entries->hasNext(); -} -Ref SpineSkinAttachmentMapEntries::next() { - auto &e = entries->next(); - Ref gd_entry(memnew(SpineSkinAttachmentMapEntry)); - gd_entry->set_spine_object(&e); - return gd_entry; -} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineSkinAttachmentMapEntries.h b/spine-godot/spine_godot/SpineSkinAttachmentMapEntries.h deleted file mode 100644 index b0f3922ef..000000000 --- a/spine-godot/spine_godot/SpineSkinAttachmentMapEntries.h +++ /dev/null @@ -1,93 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINESKINATTACHMENTMAPENTRIES_H -#define GODOT_SPINESKINATTACHMENTMAPENTRIES_H - -#include "core/variant_parser.h" - -#include - -#include "SpineAttachment.h" - -class SpineSkinAttachmentMapEntry : public Reference { - GDCLASS(SpineSkinAttachmentMapEntry, Reference); - -protected: - static void _bind_methods(); - -private: - spine::Skin::AttachmentMap::Entry *entry; - -public: - SpineSkinAttachmentMapEntry(); - ~SpineSkinAttachmentMapEntry(); - - inline void set_spine_object(spine::Skin::AttachmentMap::Entry *e) { - entry = e; - } - inline spine::Skin::AttachmentMap::Entry *get_spine_object() { - return entry; - } - - uint64_t get_slot_index(); - void set_slot_index(uint64_t v); - - String get_entry_name(); - void set_entry_name(const String &v); - - Ref get_attachment(); - void set_attachment(Ref v); -}; - -class SpineSkinAttachmentMapEntries : public Reference { - GDCLASS(SpineSkinAttachmentMapEntries, Reference); - -protected: - static void _bind_methods(); - -private: - spine::Skin::AttachmentMap::Entries *entries; - -public: - SpineSkinAttachmentMapEntries(); - ~SpineSkinAttachmentMapEntries(); - - inline void set_spine_object(spine::Skin::AttachmentMap::Entries *e) { - entries = e; - } - inline spine::Skin::AttachmentMap::Entries *get_spine_object() { - return entries; - } - - bool has_next(); - Ref next(); -}; - -#endif//GODOT_SPINESKINATTACHMENTMAPENTRIES_H diff --git a/spine-godot/spine_godot/SpineSlot.cpp b/spine-godot/spine_godot/SpineSlot.cpp deleted file mode 100644 index b1bbab708..000000000 --- a/spine-godot/spine_godot/SpineSlot.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpineSlot.h" - -#include "SpineBone.h" -#include "SpineSkeleton.h" - - -void SpineSlot::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_to_setup_pos"), &SpineSlot::set_to_setup_pos); - ClassDB::bind_method(D_METHOD("get_data"), &SpineSlot::get_data); - ClassDB::bind_method(D_METHOD("get_bone"), &SpineSlot::get_bone); - ClassDB::bind_method(D_METHOD("get_skeleton"), &SpineSlot::get_skeleton); - ClassDB::bind_method(D_METHOD("get_color"), &SpineSlot::get_color); - ClassDB::bind_method(D_METHOD("set_color"), &SpineSlot::set_color); - ClassDB::bind_method(D_METHOD("get_dark_color"), &SpineSlot::get_dark_color); - ClassDB::bind_method(D_METHOD("set_dark_color", "v"), &SpineSlot::set_dark_color); - ClassDB::bind_method(D_METHOD("has_dark_color"), &SpineSlot::has_dark_color); - ClassDB::bind_method(D_METHOD("get_attachment"), &SpineSlot::get_attachment); - ClassDB::bind_method(D_METHOD("set_attachment", "v"), &SpineSlot::set_attachment); - ClassDB::bind_method(D_METHOD("get_attachment_state"), &SpineSlot::get_attachment_state); - ClassDB::bind_method(D_METHOD("set_attachment_state", "v"), &SpineSlot::set_attachment_state); - ClassDB::bind_method(D_METHOD("get_deform"), &SpineSlot::get_deform); - ClassDB::bind_method(D_METHOD("set_deform", "v"), &SpineSlot::set_deform); -} - -SpineSlot::SpineSlot() : slot(NULL) {} -SpineSlot::~SpineSlot() {} - -void SpineSlot::set_to_setup_pos() { - slot->setToSetupPose(); -} - -Ref SpineSlot::get_data() { - auto &sd = slot->getData(); - Ref gd_sd(memnew(SpineSlotData)); - gd_sd->set_spine_object(&sd); - return gd_sd; -} - -Ref SpineSlot::get_bone() { - auto &b = slot->getBone(); - Ref gd_b(memnew(SpineBone)); - gd_b->set_spine_object(&b); - return gd_b; -} - -Ref SpineSlot::get_skeleton() { - auto &s = slot->getSkeleton(); - Ref gd_s(memnew(SpineSkeleton)); - gd_s->set_spine_object(&s); - return gd_s; -} - -Color SpineSlot::get_color() { - auto &c = slot->getColor(); - return Color(c.r, c.g, c.b, c.a); -} -void SpineSlot::set_color(Color v) { - auto &c = slot->getColor(); - c.set(v.r, v.g, v.b, v.a); -} - -Color SpineSlot::get_dark_color() { - auto &c = slot->getDarkColor(); - return Color(c.r, c.g, c.b, c.a); -} -void SpineSlot::set_dark_color(Color v) { - auto &c = slot->getDarkColor(); - c.set(v.r, v.g, v.b, v.a); -} - -bool SpineSlot::has_dark_color() { - return slot->hasDarkColor(); -} - -Ref SpineSlot::get_attachment() { - auto a = slot->getAttachment(); - if (a == NULL) return NULL; - Ref gd_a(memnew(SpineAttachment)); - gd_a->set_spine_object(a); - return gd_a; -} -void SpineSlot::set_attachment(Ref v) { - if (v.is_valid()) { - slot->setAttachment(v->get_spine_object()); - } else { - slot->setAttachment(NULL); - } -} - -int SpineSlot::get_attachment_state() { - return slot->getAttachmentState(); -} -void SpineSlot::set_attachment_state(int v) { - slot->setAttachmentState(v); -} - -float SpineSlot::get_attachment_time() { - return slot->getAttachmentTime(); -} -void SpineSlot::set_attachment_time(float v) { - slot->setAttachmentTime(v); -} - -Array SpineSlot::get_deform() { - auto &ds = slot->getDeform(); - Array gd_ds; - gd_ds.resize(ds.size()); - for (size_t i = 0; i < ds.size(); ++i) { - gd_ds[i] = ds[i]; - } - return gd_ds; -} -void SpineSlot::set_deform(Array gd_ds) { - auto &ds = slot->getDeform(); - ds.setSize(gd_ds.size(), 0); - for (size_t i = 0; i < gd_ds.size(); ++i) { - ds[i] = gd_ds[i]; - } -} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineSlot.h b/spine-godot/spine_godot/SpineSlot.h deleted file mode 100644 index 1d71eddb1..000000000 --- a/spine-godot/spine_godot/SpineSlot.h +++ /dev/null @@ -1,93 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINESLOT_H -#define GODOT_SPINESLOT_H - -#include "core/variant_parser.h" - -#include - -#include "SpineSlotData.h" -#include "SpineAttachment.h" - -class SpineSkeleton; - -class SpineBone; - -class SpineSlot : public Reference { - GDCLASS(SpineSlot, Reference); - -protected: - static void _bind_methods(); - -private: - spine::Slot *slot; - -public: - SpineSlot(); - ~SpineSlot(); - - inline void set_spine_object(spine::Slot *s) { - slot = s; - } - inline spine::Slot *get_spine_object() { - return slot; - } - - void set_to_setup_pos(); - - Ref get_data(); - - Ref get_bone(); - - Ref get_skeleton(); - - Color get_color(); - void set_color(Color v); - - Color get_dark_color(); - void set_dark_color(Color v); - - bool has_dark_color(); - - Ref get_attachment(); - void set_attachment(Ref v); - - int get_attachment_state(); - void set_attachment_state(int v); - - float get_attachment_time(); - void set_attachment_time(float v); - - Array get_deform(); - void set_deform(Array v); -}; - -#endif//GODOT_SPINESLOT_H diff --git a/spine-godot/spine_godot/SpineSlotData.cpp b/spine-godot/spine_godot/SpineSlotData.cpp deleted file mode 100644 index bf3c48f20..000000000 --- a/spine-godot/spine_godot/SpineSlotData.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpineSlotData.h" - -void SpineSlotData::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_index"), &SpineSlotData::get_index); - ClassDB::bind_method(D_METHOD("get_slot_name"), &SpineSlotData::get_slot_name); - ClassDB::bind_method(D_METHOD("get_bone_data"), &SpineSlotData::get_bone_data); - ClassDB::bind_method(D_METHOD("get_color"), &SpineSlotData::get_color); - ClassDB::bind_method(D_METHOD("get_dark_color"), &SpineSlotData::get_dark_color); - ClassDB::bind_method(D_METHOD("has_dark_color"), &SpineSlotData::has_dark_color); - ClassDB::bind_method(D_METHOD("set_has_dark_color", "v"), &SpineSlotData::set_has_dark_color); - ClassDB::bind_method(D_METHOD("get_attachment_name"), &SpineSlotData::get_attachment_name); - ClassDB::bind_method(D_METHOD("set_attachment_name", "v"), &SpineSlotData::set_attachment_name); - ClassDB::bind_method(D_METHOD("get_blend_mode"), &SpineSlotData::get_blend_mode); - ClassDB::bind_method(D_METHOD("set_blend_mode", "v"), &SpineSlotData::set_blend_mode); - - ClassDB::bind_method(D_METHOD("set_color", "v"), &SpineSlotData::set_color); - ClassDB::bind_method(D_METHOD("set_dark_color", "v"), &SpineSlotData::set_dark_color); - - BIND_ENUM_CONSTANT(BLENDMODE_NORMAL); - BIND_ENUM_CONSTANT(BLENDMODE_ADDITIVE); - BIND_ENUM_CONSTANT(BLENDMODE_MULTIPLY); - BIND_ENUM_CONSTANT(BLENDMODE_SCREEN); -} - -SpineSlotData::SpineSlotData() : slot_data(NULL) {} -SpineSlotData::~SpineSlotData() {} - -#define S_T(x) (spine::String(x.utf8())) -int SpineSlotData::get_index() { - return slot_data->getIndex(); -} - -String SpineSlotData::get_slot_name() { - return slot_data->getName().buffer(); -} - -Ref SpineSlotData::get_bone_data() { - auto &bd = slot_data->getBoneData(); - Ref gd_bone_data(memnew(SpineBoneData)); - gd_bone_data->set_spine_object(&bd); - return gd_bone_data; -} - -Color SpineSlotData::get_color() { - auto &c = slot_data->getColor(); - return Color(c.r, c.g, c.b, c.a); -} -void SpineSlotData::set_color(Color v) { - auto &c = slot_data->getColor(); - c.set(v.r, v.g, v.b, v.a); -} - -Color SpineSlotData::get_dark_color() { - auto &c = slot_data->getDarkColor(); - return Color(c.r, c.g, c.b, c.a); -} -void SpineSlotData::set_dark_color(Color v) { - auto &c = slot_data->getDarkColor(); - c.set(v.r, v.g, v.b, v.a); -} - -bool SpineSlotData::has_dark_color() { - return slot_data->hasDarkColor(); -} -void SpineSlotData::set_has_dark_color(bool v) { - slot_data->setHasDarkColor(v); -} - -String SpineSlotData::get_attachment_name() { - return slot_data->getAttachmentName().buffer(); -} -void SpineSlotData::set_attachment_name(const String &v) { - slot_data->setAttachmentName(S_T(v)); -} - -SpineSlotData::BlendMode SpineSlotData::get_blend_mode() { - auto bm = (int) slot_data->getBlendMode(); - return (BlendMode) bm; -} -void SpineSlotData::set_blend_mode(BlendMode v) { - auto bm = (int) v; - slot_data->setBlendMode((spine::BlendMode) bm); -} - -#undef S_T \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineSlotData.h b/spine-godot/spine_godot/SpineSlotData.h deleted file mode 100644 index 1778bba55..000000000 --- a/spine-godot/spine_godot/SpineSlotData.h +++ /dev/null @@ -1,88 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINESLOTDATA_H -#define GODOT_SPINESLOTDATA_H -#include "core/variant_parser.h" - -#include - -#include "SpineBoneData.h" - -class SpineSlotData : public Reference { - GDCLASS(SpineSlotData, Reference); - -protected: - static void _bind_methods(); - -private: - spine::SlotData *slot_data; - -public: - SpineSlotData(); - ~SpineSlotData(); - - inline void set_spine_object(spine::SlotData *s) { - slot_data = s; - } - inline spine::SlotData *get_spine_object() { - return slot_data; - } - - enum BlendMode { - BLENDMODE_NORMAL = 0, - BLENDMODE_ADDITIVE, - BLENDMODE_MULTIPLY, - BLENDMODE_SCREEN - }; - - int get_index(); - - String get_slot_name(); - - Ref get_bone_data(); - - Color get_color(); - void set_color(Color c); - - Color get_dark_color(); - void set_dark_color(Color c); - - bool has_dark_color(); - void set_has_dark_color(bool v); - - String get_attachment_name(); - void set_attachment_name(const String &v); - - BlendMode get_blend_mode(); - void set_blend_mode(BlendMode v); -}; - -VARIANT_ENUM_CAST(SpineSlotData::BlendMode); -#endif//GODOT_SPINESLOTDATA_H diff --git a/spine-godot/spine_godot/SpineSprite.cpp b/spine-godot/spine_godot/SpineSprite.cpp deleted file mode 100644 index 1da9c898d..000000000 --- a/spine-godot/spine_godot/SpineSprite.cpp +++ /dev/null @@ -1,966 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpineSprite.h" - -#include "SpineEvent.h" -#include "SpineTrackEntry.h" - -void SpineSprite::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_animation_state_data_res", "animation_state_data_res"), &SpineSprite::set_animation_state_data_res); - ClassDB::bind_method(D_METHOD("get_animation_state_data_res"), &SpineSprite::get_animation_state_data_res); - ClassDB::bind_method(D_METHOD("_on_animation_data_created"), &SpineSprite::_on_animation_data_created); - ClassDB::bind_method(D_METHOD("get_skeleton"), &SpineSprite::get_skeleton); - ClassDB::bind_method(D_METHOD("get_animation_state"), &SpineSprite::get_animation_state); - ClassDB::bind_method(D_METHOD("_on_animation_data_changed"), &SpineSprite::_on_animation_data_changed); - - ClassDB::bind_method(D_METHOD("get_current_animations"), &SpineSprite::get_current_animations); - ClassDB::bind_method(D_METHOD("set_current_animations", "current_animations"), &SpineSprite::set_current_animations); - - ClassDB::bind_method(D_METHOD("get_select_track_id"), &SpineSprite::get_select_track_id); - ClassDB::bind_method(D_METHOD("set_select_track_id", "track_id"), &SpineSprite::set_select_track_id); - ClassDB::bind_method(D_METHOD("get_clear_track"), &SpineSprite::get_clear_track); - ClassDB::bind_method(D_METHOD("set_clear_track", "v"), &SpineSprite::set_clear_track); - ClassDB::bind_method(D_METHOD("get_clear_tracks"), &SpineSprite::get_clear_tracks); - ClassDB::bind_method(D_METHOD("set_clear_tracks", "v"), &SpineSprite::set_clear_tracks); - - ClassDB::bind_method(D_METHOD("get_empty_animation_duration"), &SpineSprite::get_empty_animation_duration); - ClassDB::bind_method(D_METHOD("set_empty_animation_duration", "track_id"), &SpineSprite::set_empty_animation_duration); - ClassDB::bind_method(D_METHOD("get_set_empty_animation"), &SpineSprite::get_set_empty_animation); - ClassDB::bind_method(D_METHOD("set_set_empty_animation", "v"), &SpineSprite::set_set_empty_animation); - ClassDB::bind_method(D_METHOD("get_set_empty_animations"), &SpineSprite::get_set_empty_animations); - ClassDB::bind_method(D_METHOD("set_set_empty_animations", "v"), &SpineSprite::set_set_empty_animations); - - ClassDB::bind_method(D_METHOD("get_bind_slot_nodes"), &SpineSprite::get_bind_slot_nodes); - ClassDB::bind_method(D_METHOD("set_bind_slot_nodes", "v"), &SpineSprite::set_bind_slot_nodes); - ClassDB::bind_method(D_METHOD("get_overlap"), &SpineSprite::get_overlap); - ClassDB::bind_method(D_METHOD("set_overlap", "v"), &SpineSprite::set_overlap); - - ClassDB::bind_method(D_METHOD("bone_get_global_transform", "bone_name"), &SpineSprite::bone_get_global_transform); - ClassDB::bind_method(D_METHOD("bone_set_global_transform", "bone_name", "global_transform"), &SpineSprite::bone_set_global_transform); - - ClassDB::bind_method(D_METHOD("set_process_mode", "v"), &SpineSprite::set_process_mode); - ClassDB::bind_method(D_METHOD("get_process_mode"), &SpineSprite::get_process_mode); - - ClassDB::bind_method(D_METHOD("manual_update", "delta"), &SpineSprite::_update_all); - - ADD_SIGNAL(MethodInfo("animation_state_ready", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "skeleton", PROPERTY_HINT_TYPE_STRING, "SpineSkeleton"))); - ADD_SIGNAL(MethodInfo("animation_start", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent"))); - ADD_SIGNAL(MethodInfo("animation_interrupt", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent"))); - ADD_SIGNAL(MethodInfo("animation_end", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent"))); - ADD_SIGNAL(MethodInfo("animation_complete", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent"))); - ADD_SIGNAL(MethodInfo("animation_dispose", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent"))); - ADD_SIGNAL(MethodInfo("animation_event", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent"))); - - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "animation_state_data_res", PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "SpineAnimationStateDataResource"), "set_animation_state_data_res", "get_animation_state_data_res"); - - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "overlap"), "set_overlap", "get_overlap"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "bind_slot_nodes"), "set_bind_slot_nodes", "get_bind_slot_nodes"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "custom_skin_resource", PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "SpineCustomSkinResource"), "set_skin", "get_skin"); - - ADD_GROUP("animation", ""); - ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Process,Physics,Manually"), "set_process_mode", "get_process_mode"); - - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "current_animations"), "set_current_animations", "get_current_animations"); - - BIND_ENUM_CONSTANT(ProcessMode::ProcessMode_Process); - BIND_ENUM_CONSTANT(ProcessMode::ProcessMode_Physics); - BIND_ENUM_CONSTANT(ProcessMode::ProcessMode_Manual); -} - -SpineSprite::SpineSprite() : select_track_id(0), empty_animation_duration(0.2f), skeleton_clipper(NULL), - overlap(false), - process_mode(ProcessMode_Process) { - skeleton_clipper = new spine::SkeletonClipping(); -} -SpineSprite::~SpineSprite() { - delete skeleton_clipper; -} - -void SpineSprite::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_READY: { - set_process_internal(process_mode == ProcessMode_Process); - set_physics_process_internal(process_mode == ProcessMode_Physics); - remove_redundant_mesh_instances(); - } break; - case NOTIFICATION_INTERNAL_PROCESS: { - if (process_mode == ProcessMode_Process) - _update_all(get_process_delta_time()); - } break; - case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { - if (process_mode == ProcessMode_Physics) - _update_all(get_physics_process_delta_time()); - } break; - } -} - -void SpineSprite::_update_all(float delta) { - if (!(skeleton.is_valid() && animation_state.is_valid()) || mesh_instances.empty()) - return; - - animation_state->update(delta); - if (!is_visible_in_tree()) - return; - - animation_state->apply(skeleton); - - skeleton->update_world_transform(); - - update_mesh_from_skeleton(skeleton); - - update(); - - update_bind_slot_nodes(); -} - -void SpineSprite::update_bind_slot_nodes() { - if (animation_state.is_valid() && skeleton.is_valid()) { - for (size_t i = 0, n = bind_slot_nodes.size(); i < n; ++i) { - auto a = bind_slot_nodes[i]; - if (a.get_type() == Variant::DICTIONARY) { - auto d = (Dictionary) a; - if (d.has("slot_name") && d.has("node_path")) { - NodePath node_path = d["node_path"]; - Node *node = get_node_or_null(node_path); - if (node && node->is_class("Node2D")) { - Node2D *node2d = (Node2D *) node; - - String slot_name = d["slot_name"]; - auto slot = skeleton->find_slot(slot_name); - if (slot.is_valid()) { - auto bone = slot->get_bone(); - if (bone.is_valid()) { - update_bind_slot_node_transform(bone, node2d); - update_bind_slot_node_draw_order(slot_name, node2d); - } - } - } - } - } else if (a.get_type() == Variant::ARRAY) { - auto as = (Array) a;// 0: slot_name, 1: node_path - if (as.size() >= 2 && as[0].get_type() == Variant::STRING && as[1].get_type() == Variant::NODE_PATH) { - NodePath node_path = as[1]; - Node *node = get_node_or_null(node_path); - if (node && node->is_class("Node2D")) { - Node2D *node2d = (Node2D *) node; - - String slot_name = as[0]; - auto slot = skeleton->find_slot(slot_name); - if (slot.is_valid()) { - auto bone = slot->get_bone(); - if (bone.is_valid()) { - update_bind_slot_node_transform(bone, node2d); - update_bind_slot_node_draw_order(slot_name, node2d); - } - } - } - } - } - } - } -} -void SpineSprite::update_bind_slot_node_transform(Ref bone, Node2D *node2d) { - bone->apply_world_transform_2d(node2d); -} -void SpineSprite::update_bind_slot_node_draw_order(const String &slot_name, Node2D *node2d) { - auto mesh_ins = find_node(slot_name); - if (mesh_ins) { - auto pos = mesh_ins->get_index(); - - // get child - auto node = find_child_node_by_node(node2d); - if (node && node->get_index() != pos + 1) { - move_child(node, pos + 1); - } - } -} -Node *SpineSprite::find_child_node_by_node(Node *node) { - if (node == NULL) return NULL; - while (node && node->get_parent() != this) node = node->get_parent(); - return node; -} - -void SpineSprite::set_animation_state_data_res(const Ref &s) { - animation_state_data_res = s; - - // update run time skeleton and meshes - _on_animation_data_changed(); -} -Ref SpineSprite::get_animation_state_data_res() { - return animation_state_data_res; -} - -void SpineSprite::_on_animation_data_created() { - // print_line("_on_animation_data_created"); - skeleton = Ref(memnew(SpineSkeleton)); - skeleton->load_skeleton(animation_state_data_res->get_skeleton()); - skeleton->set_spine_sprite(this); - // print_line("Run time skeleton created."); - - animation_state = Ref(memnew(SpineAnimationState)); - animation_state->load_animation_state(animation_state_data_res); - animation_state->get_animation_state()->setListener(this); - // print_line("Run time animation state created."); - - // add mesh instances related by current skeleton - animation_state->update(0); - animation_state->apply(skeleton); - skeleton->update_world_transform(); - gen_mesh_from_skeleton(skeleton); - - if (process_mode == ProcessMode_Process) { - _notification(NOTIFICATION_INTERNAL_PROCESS); - } else if (process_mode == ProcessMode_Physics) { - _notification(NOTIFICATION_INTERNAL_PHYSICS_PROCESS); - } - - emit_signal("animation_state_ready", animation_state, skeleton); -} -void SpineSprite::_on_animation_data_changed() { - // print_line("_on_animation_data_changed"); - remove_mesh_instances(); - skeleton.unref(); - animation_state.unref(); - if (!animation_state_data_res.is_null()) { - if (!animation_state_data_res->is_connected("animation_state_data_created", this, "_on_animation_data_created")) - animation_state_data_res->connect("animation_state_data_created", this, "_on_animation_data_created"); - if (!animation_state_data_res->is_connected("skeleton_data_res_changed", this, "_on_animation_data_changed")) - animation_state_data_res->connect("skeleton_data_res_changed", this, "_on_animation_data_changed"); - if (!animation_state_data_res->is_connected("animation_state_data_changed", this, "_on_animation_data_changed")) - animation_state_data_res->connect("animation_state_data_changed", this, "_on_animation_data_changed"); - - if (animation_state_data_res->is_animation_state_data_created()) { - _on_animation_data_created(); - } - } -} - -Ref SpineSprite::get_skeleton() { - return skeleton; -} -Ref SpineSprite::get_animation_state() { - return animation_state; -} - -void SpineSprite::gen_mesh_from_skeleton(Ref s) { - auto sk = s->get_spine_object(); - for (size_t i = 0, n = sk->getSlots().size(); i < n; ++i) { - // creat a mesh instance 2d for every slot - auto mesh_ins = memnew(SpineSpriteMeshInstance2D); - add_child(mesh_ins); - mesh_ins->set_position(Vector2(0, 0)); - mesh_ins->set_owner(this); - mesh_instances.push_back(mesh_ins); - - spine::Slot *slot = sk->getDrawOrder()[i]; - mesh_ins->set_name(slot->getData().getName().buffer()); - Ref gd_slot(memnew(SpineSlot)); - gd_slot->set_spine_object(slot); - mesh_ins->set_slot(gd_slot); - - // creat a material - Ref mat(memnew(CanvasItemMaterial)); - CanvasItemMaterial::BlendMode blend_mode; - switch (slot->getData().getBlendMode()) { - case spine::BlendMode_Normal: - blend_mode = CanvasItemMaterial::BLEND_MODE_MIX; - break; - case spine::BlendMode_Additive: - blend_mode = CanvasItemMaterial::BLEND_MODE_ADD; - break; - case spine::BlendMode_Multiply: - blend_mode = CanvasItemMaterial::BLEND_MODE_MUL; - break; - case spine::BlendMode_Screen: - blend_mode = CanvasItemMaterial::BLEND_MODE_MIX; - break; - default: - blend_mode = CanvasItemMaterial::BLEND_MODE_MIX; - } - mat->set_blend_mode(blend_mode); - mesh_ins->set_material(mat); - } -} - -void SpineSprite::remove_mesh_instances() { - for (size_t i = 0; i < mesh_instances.size(); ++i) { - remove_child(mesh_instances[i]); - memdelete(mesh_instances[i]); - } - mesh_instances.clear(); -} - -void SpineSprite::remove_redundant_mesh_instances() { - Vector ms; - // remove the redundant mesh instances that added by duplicating - // print_line("start clearing"); - for (size_t i = 0, n = get_child_count(); i < n; ++i) { - auto node = get_child(i); - // print_line(String("get a node: ") + node->get_name()); - if (node && node->is_class("SpineSpriteMeshInstance2D")) { - if (mesh_instances.find((SpineSpriteMeshInstance2D *) node) == -1) { - // print_line("marked clear"); - ms.push_back(node); - } - } - } - for (size_t i = 0, n = ms.size(); i < n; ++i) { - remove_child(ms[i]); - memdelete(ms[i]); - } - ms.clear(); - // print_line("end clearing"); -} - -#define TEMP_COPY(t, get_res) \ - do { \ - auto &temp_uvs = get_res; \ - t.setSize(temp_uvs.size(), 0); \ - for (size_t j = 0; j < t.size(); ++j) { \ - t[j] = temp_uvs[j]; \ - } \ - } while (false); -void SpineSprite::update_mesh_from_skeleton(Ref s) { - static const unsigned short VERTEX_STRIDE = 2; - static const unsigned short UV_STRIDE = 2; - static unsigned short quad_indices[] = {0, 1, 2, 2, 3, 0}; - - auto sk = s->get_spine_object(); - for (size_t i = 0, n = sk->getSlots().size(); i < n; ++i) { - spine::Vector vertices; - spine::Vector uvs; - spine::Vector indices; - - spine::Slot *slot = sk->getDrawOrder()[i]; - - spine::Attachment *attachment = slot->getAttachment(); - if (!attachment) { - // set invisible to mesh instance - mesh_instances[i]->set_visible(false); - - skeleton_clipper->clipEnd(*slot); - continue; - } - mesh_instances[i]->set_visible(true); - - spine::Color skeleton_color = sk->getColor(); - spine::Color slot_color = slot->getColor(); - spine::Color tint(skeleton_color.r * slot_color.r, skeleton_color.g * slot_color.g, skeleton_color.b * slot_color.b, skeleton_color.a * slot_color.a); - - Ref tex; - Ref normal_tex; - size_t v_num = 0; - - if (attachment->getRTTI().isExactly(spine::RegionAttachment::rtti)) { - spine::RegionAttachment *region_attachment = (spine::RegionAttachment *) attachment; - - auto p_spine_renderer_object = (SpineRendererObject *) ((spine::AtlasRegion *) region_attachment->getRendererObject())->page->getRendererObject(); - tex = p_spine_renderer_object->texture; - normal_tex = p_spine_renderer_object->normal_map; - - v_num = 4; - vertices.setSize(v_num * VERTEX_STRIDE, 0); - - region_attachment->computeWorldVertices(slot->getBone(), vertices, 0); - - TEMP_COPY(uvs, region_attachment->getUVs()); - - indices.setSize(sizeof(quad_indices) / sizeof(unsigned short), 0); - for (size_t j = 0, qn = indices.size(); j < qn; ++j) { - indices[j] = quad_indices[j]; - } - - auto attachment_color = region_attachment->getColor(); - tint.r *= attachment_color.r; - tint.g *= attachment_color.g; - tint.b *= attachment_color.b; - tint.a *= attachment_color.a; - } else if (attachment->getRTTI().isExactly(spine::MeshAttachment::rtti)) { - spine::MeshAttachment *mesh = (spine::MeshAttachment *) attachment; - - auto p_spine_renderer_object = (SpineRendererObject *) ((spine::AtlasRegion *) mesh->getRendererObject())->page->getRendererObject(); - tex = p_spine_renderer_object->texture; - normal_tex = p_spine_renderer_object->normal_map; - - v_num = mesh->getWorldVerticesLength() / VERTEX_STRIDE; - vertices.setSize(mesh->getWorldVerticesLength(), 0); - - mesh->computeWorldVertices(*slot, vertices); - - // uvs = mesh->getUVs(); - // indices = mesh->getTriangles(); - TEMP_COPY(uvs, mesh->getUVs()); - TEMP_COPY(indices, mesh->getTriangles()); - - auto attachment_color = mesh->getColor(); - tint.r *= attachment_color.r; - tint.g *= attachment_color.g; - tint.b *= attachment_color.b; - tint.a *= attachment_color.a; - } else if (attachment->getRTTI().isExactly(spine::ClippingAttachment::rtti)) { - auto clip = (spine::ClippingAttachment *) attachment; - skeleton_clipper->clipStart(*slot, clip); - continue; - } else { - skeleton_clipper->clipEnd(*slot); - continue; - } - - auto mesh_ins = mesh_instances[i]; - VisualServer::get_singleton()->canvas_item_clear(mesh_ins->get_canvas_item()); - - if (skeleton_clipper->isClipping()) { - skeleton_clipper->clipTriangles(vertices, indices, uvs, VERTEX_STRIDE); - - if (skeleton_clipper->getClippedTriangles().size() == 0) { - skeleton_clipper->clipEnd(*slot); - continue; - } - - auto &clipped_vertices = skeleton_clipper->getClippedVertices(); - v_num = clipped_vertices.size() / VERTEX_STRIDE; - auto &clipped_uvs = skeleton_clipper->getClippedUVs(); - auto &clipped_indices = skeleton_clipper->getClippedTriangles(); - - if (indices.size() > 0) { - Vector p_points, p_uvs; - Vector p_colors; - Vector p_indices; - p_points.resize(v_num); - p_uvs.resize(v_num); - p_colors.resize(v_num); - for (size_t j = 0; j < v_num; j++) { - p_points.set(j, Vector2(clipped_vertices[j * VERTEX_STRIDE], -clipped_vertices[j * VERTEX_STRIDE + 1])); - p_uvs.set(j, Vector2(clipped_uvs[j * VERTEX_STRIDE], clipped_uvs[j * VERTEX_STRIDE + 1])); - p_colors.set(j, Color(tint.r, tint.g, tint.b, tint.a)); - } - p_indices.resize(clipped_indices.size()); - for (size_t j = 0; j < clipped_indices.size(); ++j) { - p_indices.set(j, clipped_indices[j]); - } - - VisualServer::get_singleton()->canvas_item_add_triangle_array(mesh_ins->get_canvas_item(), - p_indices, - p_points, - p_colors, - p_uvs, - Vector(), - Vector(), - tex.is_null() ? RID() : tex->get_rid(), - -1, - normal_tex.is_null() ? RID() : normal_tex->get_rid()); - } - } else { - if (indices.size() > 0) { - Vector p_points, p_uvs; - Vector p_colors; - Vector p_indices; - p_points.resize(v_num); - p_uvs.resize(v_num); - p_colors.resize(v_num); - for (size_t j = 0; j < v_num; j++) { - p_points.set(j, Vector2(vertices[j * VERTEX_STRIDE], -vertices[j * VERTEX_STRIDE + 1])); - p_uvs.set(j, Vector2(uvs[j * VERTEX_STRIDE], uvs[j * VERTEX_STRIDE + 1])); - p_colors.set(j, Color(tint.r, tint.g, tint.b, tint.a)); - } - p_indices.resize(indices.size()); - for (size_t j = 0; j < indices.size(); ++j) { - p_indices.set(j, indices[j]); - } - - VisualServer::get_singleton()->canvas_item_add_triangle_array(mesh_ins->get_canvas_item(), - p_indices, - p_points, - p_colors, - p_uvs, - Vector(), - Vector(), - tex.is_null() ? RID() : tex->get_rid(), - -1, - normal_tex.is_null() ? RID() : normal_tex->get_rid()); - } - } - skeleton_clipper->clipEnd(*slot); - - if (mesh_ins->get_material()->is_class("CanvasItemMaterial")) { - Ref mat = mesh_ins->get_material(); - CanvasItemMaterial::BlendMode blend_mode; - switch (slot->getData().getBlendMode()) { - case spine::BlendMode_Normal: - blend_mode = CanvasItemMaterial::BLEND_MODE_MIX; - break; - case spine::BlendMode_Additive: - blend_mode = CanvasItemMaterial::BLEND_MODE_ADD; - break; - case spine::BlendMode_Multiply: - blend_mode = CanvasItemMaterial::BLEND_MODE_MUL; - break; - case spine::BlendMode_Screen: - blend_mode = CanvasItemMaterial::BLEND_MODE_MIX; - break; - default: - blend_mode = CanvasItemMaterial::BLEND_MODE_MIX; - } - mat->set_blend_mode(blend_mode); - } - } - skeleton_clipper->clipEnd(); -} - -void SpineSprite::callback(spine::AnimationState *state, spine::EventType type, spine::TrackEntry *entry, spine::Event *event) { - Ref gd_entry(NULL); - Ref gd_event(NULL); - - if (entry) { - gd_entry = Ref(memnew(SpineTrackEntry)); - gd_entry->set_spine_object(entry); - } - if (event) { - gd_event = Ref(memnew(SpineEvent)); - gd_event->set_spine_object(event); - } - - switch (type) { - case spine::EventType_Start: { - emit_signal("animation_start", animation_state, gd_entry, gd_event); - } break; - case spine::EventType_Interrupt: { - emit_signal("animation_interrupt", animation_state, gd_entry, gd_event); - } break; - case spine::EventType_End: { - emit_signal("animation_end", animation_state, gd_entry, gd_event); - } break; - case spine::EventType_Complete: { - emit_signal("animation_complete", animation_state, gd_entry, gd_event); - } break; - case spine::EventType_Dispose: { - emit_signal("animation_dispose", animation_state, gd_entry, gd_event); - } break; - case spine::EventType_Event: { - emit_signal("animation_event", animation_state, gd_entry, gd_event); - } break; - } -} - -// External feature functions -Array SpineSprite::get_current_animations() { - return current_animations.duplicate(true); -} -void SpineSprite::set_current_animations(Array as) { - current_animations = as.duplicate(true); - - // validate it then play the animations - _validate_and_play_current_animations(); -} - -int SpineSprite::get_select_track_id() { - return select_track_id; -} -void SpineSprite::set_select_track_id(int v) { - select_track_id = v; - - if (select_track_id < 0) select_track_id = 0; -} - -bool SpineSprite::get_clear_track() { - return false; -} -void SpineSprite::set_clear_track(bool v) { - if (v && animation_state.is_valid() && skeleton.is_valid()) - animation_state->clear_track(select_track_id); -} - -bool SpineSprite::get_clear_tracks() { - return false; -} -void SpineSprite::set_clear_tracks(bool v) { - if (v && animation_state.is_valid() && skeleton.is_valid()) - animation_state->clear_tracks(); -} - -float SpineSprite::get_empty_animation_duration() { - return empty_animation_duration; -} -void SpineSprite::set_empty_animation_duration(float v) { - empty_animation_duration = v; -} - -bool SpineSprite::get_set_empty_animation() { - return false; -} -void SpineSprite::set_set_empty_animation(bool v) { - if (v && animation_state.is_valid() && skeleton.is_valid()) - animation_state->set_empty_animation(select_track_id, empty_animation_duration); -} - -bool SpineSprite::get_set_empty_animations() { - return false; -} -void SpineSprite::set_set_empty_animations(bool v) { - if (v && animation_state.is_valid() && skeleton.is_valid()) - animation_state->set_empty_animations(empty_animation_duration); -} - -Array SpineSprite::get_bind_slot_nodes() { - return bind_slot_nodes; -} - -void SpineSprite::set_bind_slot_nodes(Array v) { - bind_slot_nodes = v; -} - -bool SpineSprite::get_overlap() { - return overlap; -} - -void SpineSprite::set_overlap(bool v) { - overlap = v; -} - -void SpineSprite::bind_slot_with_node_2d(const String &slot_name, Node2D *n) { - auto node_path = n->get_path_to(this); - - // check if has the same binding - for (size_t i = 0, size = bind_slot_nodes.size(); i < size; ++i) { - auto a = bind_slot_nodes[i]; - if (a.get_type() == Variant::DICTIONARY) { - auto d = (Dictionary) a; - if (d.has("slot_name") && d.has("node_path")) { - if (slot_name == d["slot_name"] && node_path == d["node_path"]) { - return; - } - } - } else if (a.get_type() == Variant::ARRAY) { - auto as = (Array) a; - if (as.size() >= 2 && as[0].get_type() == Variant::STRING && as[1].get_type() == Variant::NODE_PATH) { - if (slot_name == as[0] && node_path == as[1]) { - return; - } - } - } - } - - Array bound; - bound.resize(2); - bound[0] = slot_name; - bound[1] = node_path; - - bind_slot_nodes.append(bound); -} -void SpineSprite::unbind_slot_with_node_2d(const String &slot_name, Node2D *n) { - auto node_path = n->get_path_to(this); - - for (size_t i = 0, size = bind_slot_nodes.size(); i < size; ++i) { - auto a = bind_slot_nodes[i]; - if (a.get_type() == Variant::DICTIONARY) { - auto d = (Dictionary) a; - if (d.has("slot_name") && d.has("node_path")) { - if (slot_name == d["slot_name"] && node_path == d["node_path"]) { - bind_slot_nodes.remove(i); - return; - } - } - } else if (a.get_type() == Variant::ARRAY) { - auto as = (Array) a; - if (as.size() >= 2 && as[0].get_type() == Variant::STRING && as[1].get_type() == Variant::NODE_PATH) { - if (slot_name == as[0] && node_path == as[1]) { - bind_slot_nodes.remove(i); - return; - } - } - } - } -} - -Transform2D SpineSprite::bone_get_global_transform(const String &bone_name) { - if (!animation_state.is_valid() && !skeleton.is_valid()) { - return get_global_transform(); - } - auto bone = skeleton->find_bone(bone_name); - if (!bone.is_valid()) { - print_error(vformat("Bone: '%s' not found.", bone_name)); - return get_global_transform(); - } - return bone->get_godot_global_transform(); -} - -void SpineSprite::bone_set_global_transform(const String &bone_name, Transform2D transform) { - if (!animation_state.is_valid() && !skeleton.is_valid()) { - return; - } - auto bone = skeleton->find_bone(bone_name); - if (!bone.is_valid()) { - return; - } - bone->set_godot_global_transform(transform); -} - -SpineSprite::ProcessMode SpineSprite::get_process_mode() { - return process_mode; -} - -void SpineSprite::set_process_mode(SpineSprite::ProcessMode v) { - process_mode = v; - set_process_internal(process_mode == ProcessMode_Process); - set_physics_process_internal(process_mode == ProcessMode_Physics); -} - -void SpineSprite::_get_property_list(List *p_list) const { - p_list->push_back(PropertyInfo(Variant::NIL, "Current Animation Editor", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_CATEGORY)); - p_list->push_back(PropertyInfo(Variant::BOOL, "setup_pose_trigger", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - p_list->push_back(PropertyInfo(Variant::BOOL, "clear_tracks_trigger", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - p_list->push_back(PropertyInfo(Variant::BOOL, "set_empty_animations_trigger", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - p_list->push_back(PropertyInfo(Variant::REAL, "empty_animation_duration")); - p_list->push_back(PropertyInfo(Variant::INT, "track_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - - for (size_t i = 0; i < current_animations.size(); ++i) { - String prefix = vformat("ca/%d/", (unsigned int) i); - p_list->push_back(PropertyInfo(Variant::NIL, vformat("ID %d", (unsigned int) i), PROPERTY_HINT_NONE, prefix, PROPERTY_USAGE_GROUP)); - p_list->push_back(PropertyInfo(Variant::INT, vformat("%strack_id", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - - Vector anim_list; - if (skeleton.is_valid() && skeleton->get_data().is_valid()) { - skeleton->get_data()->get_animation_names(anim_list); - } - if (anim_list.empty()) anim_list.push_back("No Animation"); - p_list->push_back(PropertyInfo(Variant::STRING, vformat("%sanimation", prefix), PROPERTY_HINT_ENUM, String(",").join(anim_list), PROPERTY_USAGE_EDITOR)); - - p_list->push_back(PropertyInfo(Variant::REAL, vformat("%sdelay", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - - p_list->push_back(PropertyInfo(Variant::BOOL, vformat("%sloop", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - - p_list->push_back(PropertyInfo(Variant::BOOL, vformat("%sempty", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - p_list->push_back(PropertyInfo(Variant::REAL, vformat("%sempty_animation_duration", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - - p_list->push_back(PropertyInfo(Variant::BOOL, vformat("%sclear", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - } -} - -bool SpineSprite::_get(const StringName &p_property, Variant &r_value) const { - if (p_property == "setup_pose_trigger" || p_property == "clear_tracks_trigger" || p_property == "set_empty_animations_trigger") { - r_value = false; - return true; - } - if (p_property == "empty_animation_duration") { - r_value = empty_animation_duration; - return true; - } - if (p_property == "track_count") { - r_value = get_current_animation_count(); - return true; - } - String p = p_property; - if (p.size() > 2 && p[0] == 'c' && p[1] == 'a' && p[2] == '/') { - Vector sp = p.split("/"); - if (sp.size() > 2) { - int64_t id = sp[1].to_int64(); - if (id >= 0 && id < current_animations.size()) { - auto &key = sp[2]; - if (current_animations[id].get_type() == Variant::DICTIONARY) { - Dictionary dic = current_animations.get(id); - if (dic.has(key)) { - r_value = dic[key]; - } else { - if (key == "track_id") r_value = 0; - else if (key == "animation") - r_value = ""; - else if (key == "loop") - r_value = true; - else if (key == "empty") - r_value = false; - else if (key == "empty_animation_duration") - r_value = 0.3; - else if (key == "clear") - r_value = false; - else if (key == "delay") - r_value = 0; - else - return false; - } - return true; - } - } - } - } - return false; -} - -bool SpineSprite::_set(const StringName &p_property, const Variant &p_value) { - if (p_property == "setup_pose_trigger") { - if (p_value) { - if (skeleton.is_valid()) { - skeleton->set_bones_to_setup_pose(); - skeleton->set_slots_to_setup_pose(); - } - } - return true; - } - if (p_property == "clear_tracks_trigger") { - if (p_value) { - if (animation_state.is_valid() && skeleton.is_valid()) { - animation_state->clear_tracks(); - } - } - return true; - } - if (p_property == "set_empty_animations_trigger") { - if (p_value) { - if (animation_state.is_valid() && skeleton.is_valid()) { - animation_state->set_empty_animations(empty_animation_duration); - } - } - return true; - } - if (p_property == "empty_animation_duration") { - empty_animation_duration = p_value; - return true; - } - if (p_property == "track_count") { - set_current_animation_count(p_value); - return true; - } - String p = p_property; - if (p.size() > 2 && p[0] == 'c' && p[1] == 'a' && p[2] == '/') { - Vector sp = p.split("/"); - if (sp.size() > 2) { - int64_t id = sp[1].to_int64(); - if (id >= 0 && id < current_animations.size()) { - auto &key = sp[2]; - if (current_animations[id].get_type() != Variant::DICTIONARY) { - current_animations.set(id, Dictionary()); - } - - Dictionary dic = current_animations.get(id); - dic[key] = p_value; - - _validate_and_play_current_animations(); - return true; - } - } - } - return false; -} - -int64_t SpineSprite::get_current_animation_count() const { - return current_animations.size(); -} - -void SpineSprite::set_current_animation_count(int64_t v) { - if (v < 0) v = 0; - while (current_animations.size() < v) { - Dictionary d; - d["track_id"] = current_animations.size(); - d["animation"] = ""; - d["delay"] = 0; - d["loop"] = true; - d["empty"] = false; - d["empty_animation_duration"] = 0.3; - d["clear"] = false; - current_animations.push_back(d); - } - while (current_animations.size() > v) { - if (animation_state.is_valid() && skeleton.is_valid()) { - if (current_animations.back().get_type() == Variant::DICTIONARY) { - Dictionary back = current_animations.back(); - if (back.has("track_id")) { - int64_t track_id = back["track_id"]; - int track_cnt = 0; - for (size_t i = 0; i < current_animations.size(); ++i) { - if (current_animations[i].get_type() == Variant::DICTIONARY) { - Dictionary d = current_animations[i]; - if (d.has("track_id") && track_id == (int64_t) d["track_id"]) { - track_cnt += 1; - } - } - } - if (track_cnt == 0) - animation_state->clear_track(track_id); - } - } - } - current_animations.pop_back(); - } - property_list_changed_notify(); -} - -void SpineSprite::_validate_and_play_current_animations() { - if (animation_state.is_valid() && skeleton.is_valid()) { - int64_t track_cnt = 0; - HashMap has_track; - for (size_t i = 0; i < current_animations.size(); ++i) { - auto a = current_animations[i]; - if (a.get_type() == Variant::DICTIONARY) { - Dictionary d = a; - - int64_t track_id = 0; - String animation = ""; - float delay = 0; - bool loop = true; - bool empty = false; - float empty_animation_duration = 0.3; - bool clear = false; - - if (d.has("track_id")) track_id = d["track_id"]; - if (d.has("animation")) animation = d["animation"]; - if (d.has("delay")) delay = d["delay"]; - if (d.has("loop")) loop = d["loop"]; - if (d.has("empty")) empty = d["empty"]; - if (d.has("empty_animation_duration")) empty_animation_duration = d["empty_animation_duration"]; - if (d.has("clear")) clear = d["clear"]; - - if (track_id < 0) { - print_line(vformat("track_id at 'ID %d' can not be less than 0!", (unsigned int) i)); - continue; - } - - track_cnt += 1; - - - if (empty) { - if (has_track.has(track_id)) - animation_state->add_empty_animation(track_id, empty_animation_duration, delay); - else - animation_state->set_empty_animation(track_id, empty_animation_duration); - has_track[track_id] = true; - } else if (clear) { - animation_state->clear_track(track_id); - } else if (skeleton->get_data()->find_animation(animation).is_valid()) { - if (has_track.has(track_id)) - animation_state->add_animation(animation, delay, loop, track_id); - else - animation_state->set_animation(animation, loop, track_id); - has_track[track_id] = true; - } - } - } - - if (track_cnt == 0) animation_state->clear_tracks(); - } -} diff --git a/spine-godot/spine_godot/SpineSprite.h b/spine-godot/spine_godot/SpineSprite.h deleted file mode 100644 index fc7276091..000000000 --- a/spine-godot/spine_godot/SpineSprite.h +++ /dev/null @@ -1,154 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINESPRITE_H -#define GODOT_SPINESPRITE_H - -#include -#include - -#include "SpineAnimationState.h" -#include "SpineAnimationStateDataResource.h" -#include "SpineSkeleton.h" -#include "SpineSpriteMeshInstance2D.h" - -class SpineSprite : public Node2D, public spine::AnimationStateListenerObject { - GDCLASS(SpineSprite, Node2D); - -protected: - static void _bind_methods(); - - void _notification(int p_what); - - void _get_property_list(List *p_list) const; - bool _get(const StringName &p_property, Variant &r_value) const; - bool _set(const StringName &p_property, const Variant &p_value); - - void _validate_and_play_current_animations(); - -public: - enum ProcessMode { - ProcessMode_Process, - ProcessMode_Physics, - ProcessMode_Manual - }; - -private: - Ref animation_state_data_res; - - Ref skeleton; - Ref animation_state; - - Vector mesh_instances; - - Array current_animations; - int select_track_id; - float empty_animation_duration; - - Array bind_slot_nodes; - bool overlap; - - ProcessMode process_mode; - - spine::SkeletonClipping *skeleton_clipper; - -public: - SpineSprite(); - ~SpineSprite(); - - void set_animation_state_data_res(const Ref &a); - Ref get_animation_state_data_res(); - - Ref get_skeleton(); - Ref get_animation_state(); - - void gen_mesh_from_skeleton(Ref s); - void remove_mesh_instances(); - void remove_redundant_mesh_instances(); - - void update_mesh_from_skeleton(Ref s); - - void update_bind_slot_nodes(); - void update_bind_slot_node_transform(Ref bone, Node2D *node2d); - void update_bind_slot_node_draw_order(const String &slot_name, Node2D *node2d); - Node *find_child_node_by_node(Node *node); - - virtual void callback(spine::AnimationState *state, spine::EventType type, spine::TrackEntry *entry, spine::Event *event); - - void _on_animation_data_created(); - void _on_animation_data_changed(); - - void _update_all(float delta); - - // External feature functions - Array get_current_animations(); - void set_current_animations(Array as); - - int get_select_track_id(); - void set_select_track_id(int v); - - bool get_clear_track(); - void set_clear_track(bool v); - - bool get_clear_tracks(); - void set_clear_tracks(bool v); - - float get_empty_animation_duration(); - void set_empty_animation_duration(float v); - - bool get_set_empty_animation(); - void set_set_empty_animation(bool v); - - bool get_set_empty_animations(); - void set_set_empty_animations(bool v); - - Array get_bind_slot_nodes(); - void set_bind_slot_nodes(Array v); - - void bind_slot_with_node_2d(const String &slot_name, Node2D *n); - void unbind_slot_with_node_2d(const String &slot_name, Node2D *n); - - // bone manipulations - Transform2D bone_get_global_transform(const String &bone_name); - void bone_set_global_transform(const String &bone_name, Transform2D transform); - - //allow z-manipulation - bool get_overlap(); - void set_overlap(bool v); - - // current animation count - int64_t get_current_animation_count() const; - void set_current_animation_count(int64_t v); - - ProcessMode get_process_mode(); - void set_process_mode(ProcessMode v); -}; - -VARIANT_ENUM_CAST(SpineSprite::ProcessMode); -#endif//GODOT_SPINESPRITE_H diff --git a/spine-godot/spine_godot/SpineSpriteAnimateDialog.cpp b/spine-godot/spine_godot/SpineSpriteAnimateDialog.cpp deleted file mode 100644 index 33bebdd66..000000000 --- a/spine-godot/spine_godot/SpineSpriteAnimateDialog.cpp +++ /dev/null @@ -1,351 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpineSpriteAnimateDialog.h" - -#ifdef TOOLS_ENABLED - -#include "SpineSprite.h" - -void SpineSpriteAnimateDialog::_bind_methods() { - ClassDB::bind_method(D_METHOD("_on_animate_button_pressed"), &SpineSpriteAnimateDialog::_on_animate_button_pressed); - ClassDB::bind_method(D_METHOD("_on_scene_tree_selected"), &SpineSpriteAnimateDialog::_on_scene_tree_selected); - ClassDB::bind_method(D_METHOD("_on_scene_tree_hide"), &SpineSpriteAnimateDialog::_on_scene_tree_hide); - ClassDB::bind_method(D_METHOD("_on_animate_dialog_action"), &SpineSpriteAnimateDialog::_on_animate_dialog_action); -} - -SpineSpriteAnimateDialog::SpineSpriteAnimateDialog() { - animate_dialog = memnew(ConfirmationDialog); - add_child(animate_dialog); - animate_dialog->get_ok()->set_text("Generate"); - animate_dialog_override_button = animate_dialog->add_button("Override", false, "override"); - animate_dialog_override_button->set_visible(false); - animate_dialog->set_title("Animations Generator"); - animate_dialog->set_resizable(true); - animate_dialog->set_custom_minimum_size(Vector2(550, 400)); - animate_dialog->set_hide_on_ok(false); - animate_dialog->connect("custom_action", this, "_on_animate_dialog_action"); - Vector al; - al.push_back("confirmed"); - animate_dialog->connect("confirmed", this, "_on_animate_dialog_action", al); - - auto vb = memnew(VBoxContainer); - animate_dialog->add_child(vb); - - auto scroll = memnew(ScrollContainer); - scroll->set_h_size_flags(SIZE_EXPAND_FILL); - scroll->set_v_size_flags(SIZE_EXPAND_FILL); - // vb->add_margin_child("Animations", scroll); - vb->add_child(scroll); - - animate_dialog_tree = memnew(Tree); - animate_dialog_tree->set_h_size_flags(SIZE_EXPAND_FILL); - animate_dialog_tree->set_v_size_flags(SIZE_EXPAND_FILL); - scroll->add_child(animate_dialog_tree); - - animate_dialog_tree->set_columns(3); - animate_dialog_tree->set_column_titles_visible(true); - animate_dialog_tree->set_hide_folding(true); - animate_dialog_tree->set_hide_root(true); - - animate_dialog_tree->set_column_title(0, TTR("Animation")); - animate_dialog_tree->set_column_title(1, TTR("Loop")); - animate_dialog_tree->set_column_title(2, TTR("Track ID")); - - animate_dialog_tree->create_item(); - add_row("test1"); - add_row("test12"); - add_row("test13"); - - auto l = memnew(Label); - l->set_text("W.I.P"); - vb->add_child(l); - - scene_tree_dialog = memnew(SceneTreeDialog); - scene_tree_dialog->set_title("Choose a AnimationPlayer to override, or choose none to create a new one."); - Vector valid_types; - valid_types.push_back("AnimationPlayer"); - scene_tree_dialog->get_scene_tree()->set_valid_types(valid_types); - scene_tree_dialog->get_scene_tree()->set_show_enabled_subscene(true); - scene_tree_dialog->get_ok()->hide(); - add_child(scene_tree_dialog); - scene_tree_dialog->connect("selected", this, "_on_scene_tree_selected"); - scene_tree_dialog->connect("popup_hide", this, "_on_scene_tree_hide"); - - error_dialog = memnew(AcceptDialog); - add_child(error_dialog); -} - -SpineSpriteAnimateDialog::~SpineSpriteAnimateDialog() { -} - -void SpineSpriteAnimateDialog::set_animate_button(ToolButton *b) { - animate_button = b; - animate_button->connect("pressed", this, "_on_animate_button_pressed"); -} - -void SpineSpriteAnimateDialog::add_row(const String &animation, bool loop, int64_t track_id) { - auto item = animate_dialog_tree->create_item(); - item->set_text(0, animation); - - item->set_cell_mode(1, TreeItem::CELL_MODE_CHECK); - item->set_checked(1, loop); - item->set_editable(1, true); - - item->set_cell_mode(2, TreeItem::CELL_MODE_RANGE); - item->set_range(2, track_id); - item->set_editable(2, true); -} - -void SpineSpriteAnimateDialog::clear_tree() { - animate_dialog_tree->clear(); - animate_dialog_tree->create_item(); -} - -void SpineSpriteAnimateDialog::error(const String &text, const String &title) { - error_dialog->set_text(text); - error_dialog->set_title(title); - error_dialog->popup_centered(); -} - -#define ERROR_MSG(x) \ - do { \ - error(x); \ - err = true; \ - return; \ - } while (false) -void SpineSpriteAnimateDialog::load_data_from_sprite(SpineSprite *sprite, bool &err) { - if (sprite == nullptr) { - ERROR_MSG("The sprite is null."); - } - if (!sprite->get_animation_state().is_valid() || !sprite->get_skeleton().is_valid()) { - ERROR_MSG("The sprite is not loaded."); - } - clear_tree(); - - Vector animations; - sprite->get_skeleton()->get_data()->get_animation_names(animations); - - for (size_t i = 0; i < animations.size(); ++i) { - add_row(animations[i]); - } - - err = false; -} - -#define MIN_TRACK_LENGTH 0.15 - -void SpineSpriteAnimateDialog::gen_new_animation_player(SpineSprite *sprite, bool &err) { - if (sprite == nullptr) { - ERROR_MSG("The sprite player is null."); - } - if (!sprite->get_animation_state().is_valid() || !sprite->get_skeleton().is_valid()) { - ERROR_MSG("The sprite is not loaded."); - } - auto p = sprite->get_parent(); - if (p == nullptr) { - p = sprite; - } - - auto anim_player = memnew(AnimationPlayer); - anim_player->set_name("AnimationPlayer"); - p->add_child(anim_player); - anim_player->set_owner(sprite->get_owner()); - anim_player->set_root(anim_player->get_path_to(p)); - - gen_animations(sprite, anim_player, get_data_from_tree(), MIN_TRACK_LENGTH, err); -} - -Dictionary SpineSpriteAnimateDialog::get_data_from_tree() { - Dictionary res; - if (animate_dialog_tree->get_root() == nullptr) return res; - - auto item = animate_dialog_tree->get_root()->get_children(); - while (item) { - Dictionary row; - row["loop"] = item->is_checked(1); - row["track_id"] = item->get_range(2); - - res[item->get_text(0)] = row; - item = item->get_next(); - } - return res; -} - -void SpineSpriteAnimateDialog::gen_animations(SpineSprite *sprite, AnimationPlayer *anim_player, const Dictionary &config, float min_duration, bool &err) { - if (sprite == nullptr || anim_player == nullptr) { - ERROR_MSG("The sprite or animation player is null."); - } - if (!sprite->get_animation_state().is_valid() || !sprite->get_skeleton().is_valid()) { - ERROR_MSG("The sprite is not loaded."); - } - if (anim_player->get_node_or_null(anim_player->get_root()) == nullptr) { - ERROR_MSG("The root node of animation player is null."); - } - - auto path_to_sprite = anim_player->get_node(anim_player->get_root())->get_path_to(sprite); - - Array animations = sprite->get_skeleton()->get_data()->get_animations(); - for (size_t i = 0; i < animations.size(); ++i) { - auto spine_anim = (Ref) animations[i]; - - Dictionary ca; - if (config.has(spine_anim->get_anim_name())) { - ca = config[spine_anim->get_anim_name()]; - } - - if (!ca.has("loop")) ca["loop"] = true; - if (!ca.has("track_id")) ca["track_id"] = 0; - - Array key_frame_value; - key_frame_value.push_back(gen_current_animation_data(spine_anim->get_anim_name(), ca["track_id"], ca["loop"], false, false, 0.3, 0)); - - auto anim = Ref(memnew(Animation)); - auto track_index = anim->add_track(Animation::TYPE_VALUE); - anim->set_length(min_duration > spine_anim->get_duration() ? min_duration : spine_anim->get_duration()); - anim->track_set_path(track_index, NodePath(vformat("%s:current_animations", path_to_sprite))); - anim->track_insert_key(track_index, 0.0, key_frame_value); - anim->value_track_set_update_mode(track_index, Animation::UPDATE_DISCRETE); - - if (anim_player->has_animation(spine_anim->get_anim_name())) - anim_player->remove_animation(spine_anim->get_anim_name()); - anim_player->add_animation(spine_anim->get_anim_name(), anim); - } - - err = false; -} - -Dictionary SpineSpriteAnimateDialog::gen_current_animation_data(const String &animation, int64_t track_id, bool loop, bool clear, bool empty, bool empty_duration, float delay) { - Dictionary res; - res["animation"] = animation; - res["track_id"] = track_id; - res["loop"] = loop; - res["clear"] = clear; - res["empty"] = empty; - res["empty_animation_duration"] = empty_duration; - res["delay"] = delay; - return res; -} - - -void SpineSpriteAnimateDialog::load_data_from_anim_player(AnimationPlayer *anim_player, bool &err) { - if (anim_player == nullptr) { - ERROR_MSG("The animation player is null."); - } - auto root = anim_player->get_node_or_null(anim_player->get_root()); - if (root == nullptr) return; - - auto sprite = get_node_or_null(spine_sprite_path); - if (sprite == nullptr) return; - - auto item = animate_dialog_tree->get_root()->get_children(); - while (item) { - String animation = item->get_text(0); - - auto anim = anim_player->get_animation(animation); - if (anim.is_valid() && anim->get_track_count() > 0) { - if (anim->track_get_type(0) == Animation::TYPE_VALUE) { - auto track_path = anim->track_get_path(0); - if (root->get_node_or_null(track_path) == sprite) { - if (anim->track_get_key_count(0) > 0) { - Array key_frame_value = anim->track_get_key_value(0, 0); - if (!key_frame_value.empty()) { - Dictionary _ca = key_frame_value.front(); - if (_ca.has("loop")) item->set_checked(1, _ca["loop"]); - if (_ca.has("track_id")) item->set_range(2, _ca["track_id"]); - } - } - } - } - } - - item = item->get_next(); - } - - err = false; -} - -//----- Signals ----- -void SpineSpriteAnimateDialog::_on_scene_tree_selected(NodePath path) { - // print_line(vformat("anime: %s", path)); - auto node = get_node_or_null(path); - if (node == nullptr) { - error("The node you chose is null."); - return; - } - if (!node->is_class("AnimationPlayer")) { - error("The node you chose is not AnimationPlayer."); - return; - } - anim_player_path = path; -} - -void SpineSpriteAnimateDialog::_on_animate_button_pressed() { - anim_player_path = String(""); - auto node = (Node *) the_plugin->get_editor_interface()->get_selection()->get_selected_nodes().back(); - spine_sprite_path = node->get_path(); - - // print_line(vformat("sp: %s", spine_sprite_path)); - - animate_dialog_override_button->set_visible(false); - scene_tree_dialog->popup_centered_ratio(); -} - -void SpineSpriteAnimateDialog::_on_scene_tree_hide() { - animate_dialog->popup_centered(); - - bool err = false; - load_data_from_sprite((SpineSprite *) get_node_or_null(spine_sprite_path), err); - - if (err) animate_dialog->hide(); - - err = false; - auto node = get_node_or_null(anim_player_path); - if (node != nullptr) { - load_data_from_anim_player((AnimationPlayer *) node, err); - animate_dialog_override_button->set_visible(!err); - } else { - animate_dialog_override_button->set_visible(false); - } -} - -void SpineSpriteAnimateDialog::_on_animate_dialog_action(const String &act) { - bool err = false; - if (act == "confirmed") { - gen_new_animation_player((SpineSprite *) get_node_or_null(spine_sprite_path), err); - } else if (act == "override") { - gen_animations((SpineSprite *) get_node_or_null(spine_sprite_path), (AnimationPlayer *) get_node_or_null(anim_player_path), get_data_from_tree(), MIN_TRACK_LENGTH, err); - } - if (!err) { - animate_dialog->hide(); - } -} - - -#endif \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineSpriteAnimateDialog.h b/spine-godot/spine_godot/SpineSpriteAnimateDialog.h deleted file mode 100644 index 04f26d619..000000000 --- a/spine-godot/spine_godot/SpineSpriteAnimateDialog.h +++ /dev/null @@ -1,87 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINESPRITEANIMATEDIALOG_H -#define GODOT_SPINESPRITEANIMATEDIALOG_H - -#ifdef TOOLS_ENABLED -#include "editor/editor_node.h" - -class SpineSprite; - -class SpineSpriteAnimateDialog : public Control { - GDCLASS(SpineSpriteAnimateDialog, Control); - -protected: - static void _bind_methods(); - - AcceptDialog *error_dialog; - - ToolButton *animate_button; - EditorPlugin *the_plugin; - - ConfirmationDialog *animate_dialog; - Button *animate_dialog_override_button; - Tree *animate_dialog_tree; - SceneTreeDialog *scene_tree_dialog; - - NodePath spine_sprite_path; - NodePath anim_player_path; - - void add_row(const String &animation, bool loop = true, int64_t track_id = 0); - void clear_tree(); - - void error(const String &text, const String &title = "Error"); - - void load_data_from_sprite(SpineSprite *sprite, bool &err); - void load_data_from_anim_player(AnimationPlayer *anim_player, bool &err); - - Dictionary get_data_from_tree(); - - void gen_new_animation_player(SpineSprite *sprite, bool &err); - void gen_animations(SpineSprite *sprite, AnimationPlayer *anim_player, const Dictionary &config, float min_duration, bool &err); - Dictionary gen_current_animation_data(const String &animation, int64_t track_id, bool loop, bool clear, bool empty, bool empty_duration, float delay); - -public: - SpineSpriteAnimateDialog(); - ~SpineSpriteAnimateDialog(); - - void set_animate_button(ToolButton *b); - inline ToolButton *get_animate_button() { return animate_button; } - - inline void set_plugin(EditorPlugin *p) { the_plugin = p; } - - void _on_animate_button_pressed(); - void _on_scene_tree_selected(NodePath path); - void _on_scene_tree_hide(); - void _on_animate_dialog_action(const String &act); -}; -#endif - -#endif//GODOT_SPINESPRITEANIMATEDIALOG_H diff --git a/spine-godot/spine_godot/SpineSpriteMeshInstance2D.cpp b/spine-godot/spine_godot/SpineSpriteMeshInstance2D.cpp deleted file mode 100644 index aba2064f0..000000000 --- a/spine-godot/spine_godot/SpineSpriteMeshInstance2D.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpineSpriteMeshInstance2D.h" - -#include "SpineBone.h" - -void SpineSpriteMeshInstance2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_slot"), &SpineSpriteMeshInstance2D::get_slot); - ClassDB::bind_method(D_METHOD("apply_transform_2d", "node2d"), &SpineSpriteMeshInstance2D::apply_transform_2d); -} - -SpineSpriteMeshInstance2D::SpineSpriteMeshInstance2D() {} -SpineSpriteMeshInstance2D::~SpineSpriteMeshInstance2D() {} - -Ref SpineSpriteMeshInstance2D::get_slot() { - return slot; -} - -void SpineSpriteMeshInstance2D::apply_transform_2d(Variant o) { - slot->get_bone()->apply_world_transform_2d(o); -} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineSpriteMeshInstance2D.h b/spine-godot/spine_godot/SpineSpriteMeshInstance2D.h deleted file mode 100644 index c748b21cb..000000000 --- a/spine-godot/spine_godot/SpineSpriteMeshInstance2D.h +++ /dev/null @@ -1,57 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINESPRITEMESHINSTANCE2D_H -#define GODOT_SPINESPRITEMESHINSTANCE2D_H - -#include - -#include "SpineSlot.h" - -class SpineSpriteMeshInstance2D : public MeshInstance2D { - GDCLASS(SpineSpriteMeshInstance2D, MeshInstance2D); - -protected: - static void _bind_methods(); - - Ref slot; - -public: - SpineSpriteMeshInstance2D(); - ~SpineSpriteMeshInstance2D(); - - inline void set_slot(Ref s) { - slot = s; - } - Ref get_slot(); - - void apply_transform_2d(Variant o); -}; - -#endif//GODOT_SPINESPRITEMESHINSTANCE2D_H diff --git a/spine-godot/spine_godot/SpineTimeline.cpp b/spine-godot/spine_godot/SpineTimeline.cpp deleted file mode 100644 index 29561c595..000000000 --- a/spine-godot/spine_godot/SpineTimeline.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpineTimeline.h" - -#include "SpineSkeleton.h" -#include "SpineEvent.h" - -// enable more than 5 arguments of a method bind function -#include "core/method_bind_ext.gen.inc" - -void SpineTimeline::_bind_methods() { - ClassDB::bind_method(D_METHOD("apply", "skeleton", "lastTime", "time", "pEvents", "alpha", "blend", "direction"), &SpineTimeline::apply); - ClassDB::bind_method(D_METHOD("get_frame_entries"), &SpineTimeline::get_frame_entries); - ClassDB::bind_method(D_METHOD("get_frame_count"), &SpineTimeline::get_frame_count); - ClassDB::bind_method(D_METHOD("get_frames"), &SpineTimeline::get_frames); - ClassDB::bind_method(D_METHOD("get_duration"), &SpineTimeline::get_duration); - ClassDB::bind_method(D_METHOD("getPropertyIds"), &SpineTimeline::getPropertyIds); -} - - -SpineTimeline::SpineTimeline() : timeline(nullptr) { -} - -SpineTimeline::~SpineTimeline() { -} - -void SpineTimeline::apply(Ref skeleton, float lastTime, float time, Array pEvents, float alpha, - SpineConstant::MixBlend blend, SpineConstant::MixDirection direction) { - spine::Vector events; - events.setSize(pEvents.size(), nullptr); - for (size_t i = 0; i < events.size(); ++i) { - events[i] = ((Ref) pEvents[i])->get_spine_object(); - } - - timeline->apply(*(skeleton->get_spine_object()), lastTime, time, &events, alpha, (spine::MixBlend) blend, (spine::MixDirection) direction); -} - -int64_t SpineTimeline::get_frame_entries() { - return timeline->getFrameEntries(); -} - -int64_t SpineTimeline::get_frame_count() { - return timeline->getFrameCount(); -} - -Array SpineTimeline::get_frames() { - auto &frames = timeline->getFrames(); - Array res; - res.resize(frames.size()); - - for (size_t i = 0; i < res.size(); ++i) { - res[i] = frames[i]; - } - - return res; -} - -float SpineTimeline::get_duration() { - return timeline->getDuration(); -} - -Array SpineTimeline::getPropertyIds() { - auto &ids = timeline->getPropertyIds(); - Array res; - res.resize(ids.size()); - - for (size_t i = 0; i < res.size(); ++i) { - res[i] = (int64_t) ids[i]; - } - - return res; -} diff --git a/spine-godot/spine_godot/SpineTimeline.h b/spine-godot/spine_godot/SpineTimeline.h deleted file mode 100644 index 404d7dd26..000000000 --- a/spine-godot/spine_godot/SpineTimeline.h +++ /dev/null @@ -1,75 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINETIMELINE_H -#define GODOT_SPINETIMELINE_H - -#include "core/variant_parser.h" - -#include "spine/Timeline.h" - -#include "SpineConstant.h" - -class SpineSkeleton; -class SpineEvent; - -class SpineTimeline : public Reference { - GDCLASS(SpineTimeline, Reference); - -protected: - static void _bind_methods(); - -private: - spine::Timeline *timeline; - -public: - SpineTimeline(); - ~SpineTimeline(); - - inline void set_spine_object(spine::Timeline *v) { timeline = v; } - inline spine::Timeline *get_spine_object() { return timeline; } - - // Vector - void apply(Ref skeleton, float lastTime, float time, Array pEvents, float alpha, SpineConstant::MixBlend blend, SpineConstant::MixDirection direction); - - int64_t get_frame_entries(); - - int64_t get_frame_count(); - - // Vector - Array get_frames(); - - float get_duration(); - - // Vector - Array getPropertyIds(); -}; - - -#endif//GODOT_SPINETIMELINE_H diff --git a/spine-godot/spine_godot/SpineTrackEntry.cpp b/spine-godot/spine_godot/SpineTrackEntry.cpp deleted file mode 100644 index fe6979af9..000000000 --- a/spine-godot/spine_godot/SpineTrackEntry.cpp +++ /dev/null @@ -1,265 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpineTrackEntry.h" - -void SpineTrackEntry::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_track_index"), &SpineTrackEntry::get_track_index); - - ClassDB::bind_method(D_METHOD("get_animation"), &SpineTrackEntry::get_animation); - - ClassDB::bind_method(D_METHOD("get_loop"), &SpineTrackEntry::get_loop); - ClassDB::bind_method(D_METHOD("set_loop", "v"), &SpineTrackEntry::set_loop); - - ClassDB::bind_method(D_METHOD("get_hold_previous"), &SpineTrackEntry::get_hold_previous); - ClassDB::bind_method(D_METHOD("set_hold_previous", "v"), &SpineTrackEntry::set_hold_previous); - - ClassDB::bind_method(D_METHOD("get_reverse"), &SpineTrackEntry::get_reverse); - ClassDB::bind_method(D_METHOD("set_reverse", "v"), &SpineTrackEntry::set_reverse); - - ClassDB::bind_method(D_METHOD("get_delay"), &SpineTrackEntry::get_delay); - ClassDB::bind_method(D_METHOD("set_delay", "v"), &SpineTrackEntry::set_delay); - - ClassDB::bind_method(D_METHOD("get_track_time"), &SpineTrackEntry::get_track_time); - ClassDB::bind_method(D_METHOD("set_track_time", "v"), &SpineTrackEntry::set_track_time); - - ClassDB::bind_method(D_METHOD("get_track_end"), &SpineTrackEntry::get_track_end); - ClassDB::bind_method(D_METHOD("set_track_end", "v"), &SpineTrackEntry::set_track_end); - - ClassDB::bind_method(D_METHOD("get_animation_start"), &SpineTrackEntry::get_animation_start); - ClassDB::bind_method(D_METHOD("set_animation_start", "v"), &SpineTrackEntry::set_animation_start); - - ClassDB::bind_method(D_METHOD("get_animation_last"), &SpineTrackEntry::get_animation_last); - ClassDB::bind_method(D_METHOD("set_animation_last", "v"), &SpineTrackEntry::set_animation_last); - - ClassDB::bind_method(D_METHOD("get_animation_time"), &SpineTrackEntry::get_animation_time); - - ClassDB::bind_method(D_METHOD("get_time_scale"), &SpineTrackEntry::get_time_scale); - ClassDB::bind_method(D_METHOD("set_time_scale", "v"), &SpineTrackEntry::set_time_scale); - - ClassDB::bind_method(D_METHOD("get_alpha"), &SpineTrackEntry::get_alpha); - ClassDB::bind_method(D_METHOD("set_alpha", "v"), &SpineTrackEntry::set_alpha); - - ClassDB::bind_method(D_METHOD("get_event_threshold"), &SpineTrackEntry::get_event_threshold); - ClassDB::bind_method(D_METHOD("set_event_threshold", "v"), &SpineTrackEntry::set_event_threshold); - - ClassDB::bind_method(D_METHOD("get_attachment_threshold"), &SpineTrackEntry::get_attachment_threshold); - ClassDB::bind_method(D_METHOD("set_attachment_threshold", "v"), &SpineTrackEntry::set_attachment_threshold); - - ClassDB::bind_method(D_METHOD("get_draw_order_threshold"), &SpineTrackEntry::get_draw_order_threshold); - ClassDB::bind_method(D_METHOD("set_draw_order_threshold", "v"), &SpineTrackEntry::set_draw_order_threshold); - - ClassDB::bind_method(D_METHOD("get_next"), &SpineTrackEntry::get_next); - - ClassDB::bind_method(D_METHOD("is_complete"), &SpineTrackEntry::is_complete); - - ClassDB::bind_method(D_METHOD("get_mix_time"), &SpineTrackEntry::get_mix_time); - ClassDB::bind_method(D_METHOD("set_mix_time", "v"), &SpineTrackEntry::set_mix_time); - - ClassDB::bind_method(D_METHOD("get_mix_duration"), &SpineTrackEntry::get_mix_duration); - ClassDB::bind_method(D_METHOD("set_mix_duration", "v"), &SpineTrackEntry::set_mix_duration); - - ClassDB::bind_method(D_METHOD("get_mix_blend"), &SpineTrackEntry::get_mix_blend); - ClassDB::bind_method(D_METHOD("set_mix_blend", "v"), &SpineTrackEntry::set_mix_blend); - - ClassDB::bind_method(D_METHOD("get_mixing_from"), &SpineTrackEntry::get_mixing_from); - ClassDB::bind_method(D_METHOD("get_mixing_to"), &SpineTrackEntry::get_mixing_to); - - ClassDB::bind_method(D_METHOD("reset_rotation_directions"), &SpineTrackEntry::reset_rotation_directions); - - BIND_ENUM_CONSTANT(MIXBLEND_SETUP); - BIND_ENUM_CONSTANT(MIXBLEND_FIRST); - BIND_ENUM_CONSTANT(MIXBLEND_REPLACE); - BIND_ENUM_CONSTANT(MIXBLEND_ADD); -} - -SpineTrackEntry::SpineTrackEntry() : track_entry(NULL) {} -SpineTrackEntry::~SpineTrackEntry() {} - -int SpineTrackEntry::get_track_index() { - return track_entry->getTrackIndex(); -} - -Ref SpineTrackEntry::get_animation() { - Ref gd_anim(memnew(SpineAnimation)); - auto anim = track_entry->getAnimation(); - if (anim == NULL) return NULL; - gd_anim->set_spine_object(anim); - return gd_anim; -} - -bool SpineTrackEntry::get_loop() { - return track_entry->getLoop(); -} -void SpineTrackEntry::set_loop(bool v) { - track_entry->setLoop(v); -} - -bool SpineTrackEntry::get_hold_previous() { - return track_entry->getHoldPrevious(); -} -void SpineTrackEntry::set_hold_previous(bool v) { - track_entry->setHoldPrevious(v); -} - -float SpineTrackEntry::get_delay() { - return track_entry->getDelay(); -} -void SpineTrackEntry::set_delay(float v) { - track_entry->setDelay(v); -} - -float SpineTrackEntry::get_track_time() { - return track_entry->getTrackTime(); -} -void SpineTrackEntry::set_track_time(float v) { - track_entry->setTrackTime(v); -} - -float SpineTrackEntry::get_track_end() { - return track_entry->getTrackEnd(); -} -void SpineTrackEntry::set_track_end(float v) { - track_entry->setTrackEnd(v); -} - -float SpineTrackEntry::get_animation_start() { - return track_entry->getAnimationStart(); -} -void SpineTrackEntry::set_animation_start(float v) { - track_entry->setAnimationStart(v); -} - -float SpineTrackEntry::get_animation_last() { - return track_entry->getAnimationLast(); -} -void SpineTrackEntry::set_animation_last(float v) { - track_entry->setAnimationLast(v); -} - -float SpineTrackEntry::get_animation_time() { - return track_entry->getAnimationTime(); -} - -float SpineTrackEntry::get_time_scale() { - return track_entry->getTimeScale(); -} -void SpineTrackEntry::set_time_scale(float v) { - track_entry->setTimeScale(v); -} - -float SpineTrackEntry::get_alpha() { - return track_entry->getAlpha(); -} -void SpineTrackEntry::set_alpha(float v) { - track_entry->setAlpha(v); -} - -float SpineTrackEntry::get_event_threshold() { - return track_entry->getEventThreshold(); -} -void SpineTrackEntry::set_event_threshold(float v) { - track_entry->setEventThreshold(v); -} - -float SpineTrackEntry::get_attachment_threshold() { - return track_entry->getAttachmentThreshold(); -} -void SpineTrackEntry::set_attachment_threshold(float v) { - track_entry->setAttachmentThreshold(v); -} - -float SpineTrackEntry::get_draw_order_threshold() { - return track_entry->getDrawOrderThreshold(); -} -void SpineTrackEntry::set_draw_order_threshold(float v) { - track_entry->setDrawOrderThreshold(v); -} - -Ref SpineTrackEntry::get_next() { - Ref gd_entry(memnew(SpineTrackEntry)); - auto entry = track_entry->getNext(); - if (entry == NULL) return NULL; - gd_entry->set_spine_object(entry); - return gd_entry; -} - -bool SpineTrackEntry::is_complete() { - return track_entry->isComplete(); -} - -float SpineTrackEntry::get_mix_time() { - return track_entry->getMixTime(); -} -void SpineTrackEntry::set_mix_time(float v) { - track_entry->setMixTime(v); -} - -float SpineTrackEntry::get_mix_duration() { - return track_entry->getMixDuration(); -} -void SpineTrackEntry::set_mix_duration(float v) { - track_entry->setMixDuration(v); -} - -SpineTrackEntry::MixBlend SpineTrackEntry::get_mix_blend() { - int mb = track_entry->getMixBlend(); - return (MixBlend) mb; -} -void SpineTrackEntry::set_mix_blend(SpineTrackEntry::MixBlend v) { - int mb = (int) v; - track_entry->setMixBlend((spine::MixBlend) mb); -} - -Ref SpineTrackEntry::get_mixing_from() { - Ref gd_entry(memnew(SpineTrackEntry)); - auto entry = track_entry->getMixingFrom(); - if (entry == NULL) return NULL; - gd_entry->set_spine_object(entry); - return gd_entry; -} -Ref SpineTrackEntry::get_mixing_to() { - Ref gd_entry(memnew(SpineTrackEntry)); - auto entry = track_entry->getMixingTo(); - if (entry == NULL) return NULL; - gd_entry->set_spine_object(entry); - return gd_entry; -} - -void SpineTrackEntry::reset_rotation_directions() { - track_entry->resetRotationDirections(); -} - -bool SpineTrackEntry::get_reverse() { - return track_entry->getReverse(); -} - -void SpineTrackEntry::set_reverse(bool v) { - track_entry->setReverse(v); -} diff --git a/spine-godot/spine_godot/SpineTrackEntry.h b/spine-godot/spine_godot/SpineTrackEntry.h deleted file mode 100644 index 25c4b785f..000000000 --- a/spine-godot/spine_godot/SpineTrackEntry.h +++ /dev/null @@ -1,131 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINETRACKENTRY_H -#define GODOT_SPINETRACKENTRY_H - -#include "core/variant_parser.h" - -#include - -#include "SpineAnimation.h" - -class SpineTrackEntry : public Reference { - GDCLASS(SpineTrackEntry, Reference); - -protected: - static void _bind_methods(); - -private: - spine::TrackEntry *track_entry; - -public: - SpineTrackEntry(); - ~SpineTrackEntry(); - - inline void set_spine_object(spine::TrackEntry *t) { - track_entry = t; - } - inline spine::TrackEntry *get_spine_object() { - return track_entry; - } - - enum MixBlend { - MIXBLEND_SETUP = 0, - MIXBLEND_FIRST, - MIXBLEND_REPLACE, - MIXBLEND_ADD - }; - - int get_track_index(); - - Ref get_animation(); - - bool get_loop(); - void set_loop(bool v); - - bool get_hold_previous(); - void set_hold_previous(bool v); - - bool get_reverse(); - void set_reverse(bool v); - - float get_delay(); - void set_delay(float v); - - float get_track_time(); - void set_track_time(float v); - - float get_track_end(); - void set_track_end(float v); - - float get_animation_start(); - void set_animation_start(float v); - - float get_animation_last(); - void set_animation_last(float v); - - float get_animation_time(); - - float get_time_scale(); - void set_time_scale(float v); - - float get_alpha(); - void set_alpha(float v); - - float get_event_threshold(); - void set_event_threshold(float v); - - float get_attachment_threshold(); - void set_attachment_threshold(float v); - - float get_draw_order_threshold(); - void set_draw_order_threshold(float v); - - Ref get_next(); - - bool is_complete(); - - float get_mix_time(); - void set_mix_time(float v); - - float get_mix_duration(); - void set_mix_duration(float v); - - MixBlend get_mix_blend(); - void set_mix_blend(MixBlend v); - - Ref get_mixing_from(); - Ref get_mixing_to(); - - void reset_rotation_directions(); -}; - -VARIANT_ENUM_CAST(SpineTrackEntry::MixBlend); -#endif//GODOT_SPINETRACKENTRY_H diff --git a/spine-godot/spine_godot/SpineTransformConstraint.cpp b/spine-godot/spine_godot/SpineTransformConstraint.cpp deleted file mode 100644 index 2166a5917..000000000 --- a/spine-godot/spine_godot/SpineTransformConstraint.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpineTransformConstraint.h" - -void SpineTransformConstraint::_bind_methods() { - ClassDB::bind_method(D_METHOD("update"), &SpineTransformConstraint::update); - ClassDB::bind_method(D_METHOD("get_data"), &SpineTransformConstraint::get_data); - ClassDB::bind_method(D_METHOD("get_bones"), &SpineTransformConstraint::get_bones); - ClassDB::bind_method(D_METHOD("get_target"), &SpineTransformConstraint::get_target); - ClassDB::bind_method(D_METHOD("set_target", "v"), &SpineTransformConstraint::set_target); - ClassDB::bind_method(D_METHOD("get_mix_rotate"), &SpineTransformConstraint::get_mix_rotate); - ClassDB::bind_method(D_METHOD("set_mix_rotate", "v"), &SpineTransformConstraint::set_mix_rotate); - ClassDB::bind_method(D_METHOD("get_mix_x"), &SpineTransformConstraint::get_mix_x); - ClassDB::bind_method(D_METHOD("set_mix_x", "v"), &SpineTransformConstraint::set_mix_x); - ClassDB::bind_method(D_METHOD("get_mix_y"), &SpineTransformConstraint::get_mix_y); - ClassDB::bind_method(D_METHOD("set_mix_y", "v"), &SpineTransformConstraint::set_mix_y); - ClassDB::bind_method(D_METHOD("get_mix_scale_x"), &SpineTransformConstraint::get_mix_scale_x); - ClassDB::bind_method(D_METHOD("set_mix_scale_x", "v"), &SpineTransformConstraint::set_mix_scale_x); - ClassDB::bind_method(D_METHOD("get_mix_scale_y"), &SpineTransformConstraint::get_mix_scale_y); - ClassDB::bind_method(D_METHOD("set_mix_scale_y", "v"), &SpineTransformConstraint::set_mix_scale_y); - ClassDB::bind_method(D_METHOD("get_mix_shear_y"), &SpineTransformConstraint::get_mix_shear_y); - ClassDB::bind_method(D_METHOD("set_mix_shear_y", "v"), &SpineTransformConstraint::set_mix_shear_y); - ClassDB::bind_method(D_METHOD("is_active"), &SpineTransformConstraint::is_active); - ClassDB::bind_method(D_METHOD("set_active", "v"), &SpineTransformConstraint::set_active); -} - -SpineTransformConstraint::SpineTransformConstraint() : transform_constraint(NULL) {} -SpineTransformConstraint::~SpineTransformConstraint() {} - -void SpineTransformConstraint::update() { - transform_constraint->update(); -} - -int SpineTransformConstraint::get_order() { - return transform_constraint->getOrder(); -} - -Ref SpineTransformConstraint::get_data() { - auto &d = transform_constraint->getData(); - Ref gd_d(memnew(SpineTransformConstraintData)); - gd_d->set_spine_object(&d); - return gd_d; -} - -Array SpineTransformConstraint::get_bones() { - auto &bs = transform_constraint->getBones(); - Array gd_bs; - gd_bs.resize(bs.size()); - for (size_t i = 0; i < bs.size(); ++i) { - auto b = bs[i]; - if (b == NULL) gd_bs[i] = Ref(NULL); - Ref gd_b(memnew(SpineBone)); - gd_b->set_spine_object(b); - gd_bs[i] = gd_b; - } - return gd_bs; -} - -Ref SpineTransformConstraint::get_target() { - auto b = transform_constraint->getTarget(); - if (b == NULL) return NULL; - Ref gd_b(memnew(SpineBone)); - gd_b->set_spine_object(b); - return gd_b; -} -void SpineTransformConstraint::set_target(Ref v) { - if (v.is_valid()) { - transform_constraint->setTarget(v->get_spine_object()); - } else { - transform_constraint->setTarget(NULL); - } -} - -float SpineTransformConstraint::get_mix_rotate() { - return transform_constraint->getMixRotate(); -} -void SpineTransformConstraint::set_mix_rotate(float v) { - transform_constraint->setMixRotate(v); -} - -float SpineTransformConstraint::get_mix_x() { - return transform_constraint->getMixX(); -} -void SpineTransformConstraint::set_mix_x(float v) { - transform_constraint->setMixX(v); -} - -float SpineTransformConstraint::get_mix_y() { - return transform_constraint->getMixY(); -} -void SpineTransformConstraint::set_mix_y(float v) { - transform_constraint->setMixY(v); -} - -float SpineTransformConstraint::get_mix_scale_x() { - return transform_constraint->getMixScaleX(); -} -void SpineTransformConstraint::set_mix_scale_x(float v) { - transform_constraint->setMixScaleX(v); -} - -float SpineTransformConstraint::get_mix_scale_y() { - return transform_constraint->getMixScaleY(); -} -void SpineTransformConstraint::set_mix_scale_y(float v) { - transform_constraint->setMixScaleY(v); -} - -float SpineTransformConstraint::get_mix_shear_y() { - return transform_constraint->getMixShearY(); -} -void SpineTransformConstraint::set_mix_shear_y(float v) { - transform_constraint->setMixShearY(v); -} - -bool SpineTransformConstraint::is_active() { - return transform_constraint->isActive(); -} -void SpineTransformConstraint::set_active(bool v) { - transform_constraint->setActive(v); -} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineTransformConstraint.h b/spine-godot/spine_godot/SpineTransformConstraint.h deleted file mode 100644 index 6430f05fb..000000000 --- a/spine-godot/spine_godot/SpineTransformConstraint.h +++ /dev/null @@ -1,93 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINETRANSFORMCONSTRAINT_H -#define GODOT_SPINETRANSFORMCONSTRAINT_H - -#include "core/variant_parser.h" - -#include - -#include "SpineTransformConstraintData.h" -#include "SpineBone.h" - -class SpineTransformConstraint : public Reference { - GDCLASS(SpineTransformConstraint, Reference); - -protected: - static void _bind_methods(); - -private: - spine::TransformConstraint *transform_constraint; - -public: - SpineTransformConstraint(); - ~SpineTransformConstraint(); - - inline void set_spine_object(spine::TransformConstraint *tc) { - transform_constraint = tc; - } - inline spine::TransformConstraint *get_spine_object() { - return transform_constraint; - } - - void update(); - - int get_order(); - - Ref get_data(); - - Array get_bones(); - - Ref get_target(); - void set_target(Ref v); - - float get_mix_rotate(); - void set_mix_rotate(float v); - - float get_mix_x(); - void set_mix_x(float v); - - float get_mix_y(); - void set_mix_y(float v); - - float get_mix_scale_x(); - void set_mix_scale_x(float v); - - float get_mix_scale_y(); - void set_mix_scale_y(float v); - - float get_mix_shear_y(); - void set_mix_shear_y(float v); - - bool is_active(); - void set_active(bool v); -}; - -#endif//GODOT_SPINETRANSFORMCONSTRAINT_H diff --git a/spine-godot/spine_godot/SpineTransformConstraintData.cpp b/spine-godot/spine_godot/SpineTransformConstraintData.cpp deleted file mode 100644 index c7534cafb..000000000 --- a/spine-godot/spine_godot/SpineTransformConstraintData.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "SpineTransformConstraintData.h" - -void SpineTransformConstraintData::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_all_bone_data"), &SpineTransformConstraintData::get_bones); - ClassDB::bind_method(D_METHOD("get_target"), &SpineTransformConstraintData::get_target); - ClassDB::bind_method(D_METHOD("get_mix_rotate"), &SpineTransformConstraintData::get_mix_rotate); - ClassDB::bind_method(D_METHOD("get_mix_x"), &SpineTransformConstraintData::get_mix_x); - ClassDB::bind_method(D_METHOD("get_mix_y"), &SpineTransformConstraintData::get_mix_y); - ClassDB::bind_method(D_METHOD("get_mix_scale_x"), &SpineTransformConstraintData::get_mix_scale_x); - ClassDB::bind_method(D_METHOD("get_mix_scale_y"), &SpineTransformConstraintData::get_mix_scale_y); - ClassDB::bind_method(D_METHOD("get_mix_shear_y"), &SpineTransformConstraintData::get_mix_shear_y); - ClassDB::bind_method(D_METHOD("get_offset_rotation"), &SpineTransformConstraintData::get_offset_rotation); - ClassDB::bind_method(D_METHOD("get_offset_x"), &SpineTransformConstraintData::get_offset_x); - ClassDB::bind_method(D_METHOD("get_offset_y"), &SpineTransformConstraintData::get_offset_y); - ClassDB::bind_method(D_METHOD("get_offset_scale_x"), &SpineTransformConstraintData::get_offset_scale_x); - ClassDB::bind_method(D_METHOD("get_offset_scale_y"), &SpineTransformConstraintData::get_offset_scale_y); - ClassDB::bind_method(D_METHOD("get_offset_shear_y"), &SpineTransformConstraintData::get_offset_shear_y); - ClassDB::bind_method(D_METHOD("is_relative"), &SpineTransformConstraintData::is_relative); - ClassDB::bind_method(D_METHOD("is_local"), &SpineTransformConstraintData::is_local); -} - -SpineTransformConstraintData::SpineTransformConstraintData() {} -SpineTransformConstraintData::~SpineTransformConstraintData() {} - -Array SpineTransformConstraintData::get_bones() { - auto bs = get_spine_data()->getBones(); - Array gd_bs; - gd_bs.resize(bs.size()); - for (size_t i = 0; i < bs.size(); ++i) { - if (bs[i] == NULL) gd_bs[i] = Ref(NULL); - else { - Ref gd_b(memnew(SpineBoneData)); - gd_b->set_spine_object(bs[i]); - gd_bs[i] = gd_b; - } - } - return gd_bs; -} -Ref SpineTransformConstraintData::get_target() { - auto b = get_spine_data()->getTarget(); - if (b == NULL) return NULL; - Ref gd_b(memnew(SpineBoneData)); - gd_b->set_spine_object(b); - return gd_b; -} -float SpineTransformConstraintData::get_mix_rotate() { - return get_spine_data()->getMixRotate(); -} -float SpineTransformConstraintData::get_mix_x() { - return get_spine_data()->getMixX(); -} -float SpineTransformConstraintData::get_mix_y() { - return get_spine_data()->getMixY(); -} -float SpineTransformConstraintData::get_mix_scale_x() { - return get_spine_data()->getMixScaleX(); -} -float SpineTransformConstraintData::get_mix_scale_y() { - return get_spine_data()->getMixScaleY(); -} -float SpineTransformConstraintData::get_mix_shear_y() { - return get_spine_data()->getMixShearY(); -} - -float SpineTransformConstraintData::get_offset_rotation() { - return get_spine_data()->getOffsetRotation(); -} -float SpineTransformConstraintData::get_offset_x() { - return get_spine_data()->getOffsetX(); -} -float SpineTransformConstraintData::get_offset_y() { - return get_spine_data()->getOffsetY(); -} -float SpineTransformConstraintData::get_offset_scale_x() { - return get_spine_data()->getOffsetScaleX(); -} -float SpineTransformConstraintData::get_offset_scale_y() { - return get_spine_data()->getOffsetScaleY(); -} -float SpineTransformConstraintData::get_offset_shear_y() { - return get_spine_data()->getOffsetShearY(); -} - -bool SpineTransformConstraintData::is_relative() { - return get_spine_data()->isRelative(); -} -bool SpineTransformConstraintData::is_local() { - return get_spine_data()->isLocal(); -} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineTransformConstraintData.h b/spine-godot/spine_godot/SpineTransformConstraintData.h deleted file mode 100644 index 6c1b21569..000000000 --- a/spine-godot/spine_godot/SpineTransformConstraintData.h +++ /dev/null @@ -1,74 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef GODOT_SPINETRANSFORMCONSTRAINTDATA_H -#define GODOT_SPINETRANSFORMCONSTRAINTDATA_H - -#include "core/variant_parser.h" - -#include - -#include "SpineConstraintData.h" -#include "SpineBoneData.h" - -class SpineTransformConstraintData : public SpineConstraintData { - GDCLASS(SpineTransformConstraintData, SpineConstraintData); - -protected: - static void _bind_methods(); - -public: - SpineTransformConstraintData(); - ~SpineTransformConstraintData(); - - virtual inline spine::TransformConstraintData *get_spine_data() { - return (spine::TransformConstraintData *) SpineConstraintData::get_spine_object(); - } - - Array get_bones(); - Ref get_target(); - float get_mix_rotate(); - float get_mix_x(); - float get_mix_y(); - float get_mix_scale_x(); - float get_mix_scale_y(); - float get_mix_shear_y(); - - float get_offset_rotation(); - float get_offset_x(); - float get_offset_y(); - float get_offset_scale_x(); - float get_offset_scale_y(); - float get_offset_shear_y(); - - bool is_relative(); - bool is_local(); -}; - -#endif//GODOT_SPINETRANSFORMCONSTRAINTDATA_H diff --git a/spine-godot/spine_godot/config.py b/spine-godot/spine_godot/config.py deleted file mode 100644 index 827e2c435..000000000 --- a/spine-godot/spine_godot/config.py +++ /dev/null @@ -1,5 +0,0 @@ -def can_build(env, platform): - return True - -def configure(env): - pass \ No newline at end of file diff --git a/spine-godot/spine_godot/register_types.cpp b/spine-godot/spine_godot/register_types.cpp deleted file mode 100644 index 1fd9ad626..000000000 --- a/spine-godot/spine_godot/register_types.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING 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 "register_types.h" - -#include "core/class_db.h" - -#include "SpineAtlasResource.h" -#include "SpineSkeletonDataResource.h" -#include "ResourceFormatLoaderSpineSkeletonJsonData.h" -#include "ResourceFormatSaverSpineSkeletonJsonData.h" -#include "SpineSprite.h" -#include "SpineAnimationStateDataResource.h" -#include "SpineSkeleton.h" -#include "SpineAnimationState.h" -#include "SpineEventData.h" -#include "SpineEvent.h" -#include "SpineTrackEntry.h" -#include "SpineBoneData.h" -#include "SpineSlotData.h" -#include "SpineAttachment.h" -#include "SpineSkinAttachmentMapEntries.h" -#include "SpineConstraintData.h" -#include "SpineSkin.h" -#include "SpineIkConstraintData.h" -#include "SpineTransformConstraintData.h" -#include "SpinePathConstraintData.h" -#include "SpineSpriteMeshInstance2D.h" -#include "SpineTimeline.h" -#include "SpineConstant.h" -#include "SpineCollisionShapeProxy.h" -#include "SpineSpriteAnimateDialog.h" - - -static Ref atlas_loader; -static Ref atlas_saver; -static Ref json_skeleton_loader; -static Ref json_skeleton_saver; - -// editor plugin -#ifdef TOOLS_ENABLED -#include "editor/editor_export.h" -#include "editor/editor_node.h" - -#include "SpineRuntimeEditorPlugin.h" - -static void editor_init_callback() { - EditorNode::get_singleton()->add_editor_plugin(memnew(SpineRuntimeEditorPlugin(EditorNode::get_singleton()))); -} - - -#endif - -void register_spine_godot_types() { -#ifdef TOOLS_ENABLED - ClassDB::register_class(); - - EditorNode::add_init_callback(editor_init_callback); - -#endif - - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - - atlas_loader.instance(); - ResourceLoader::add_resource_format_loader(atlas_loader); - - atlas_saver.instance(); - ResourceSaver::add_resource_format_saver(atlas_saver); - - json_skeleton_loader.instance(); - ResourceLoader::add_resource_format_loader(json_skeleton_loader); - - json_skeleton_saver.instance(); - ResourceSaver::add_resource_format_saver(json_skeleton_saver); -} - -void unregister_spine_godot_types() { - ResourceLoader::remove_resource_format_loader(atlas_loader); - atlas_loader.unref(); - - ResourceSaver::remove_resource_format_saver(atlas_saver); - atlas_saver.unref(); - - ResourceLoader::remove_resource_format_loader(json_skeleton_loader); - json_skeleton_loader.unref(); - - ResourceSaver::remove_resource_format_saver(json_skeleton_saver); - json_skeleton_saver.unref(); -} \ No newline at end of file diff --git a/spine-godot/spine_godot/register_types.h b/spine-godot/spine_godot/register_types.h deleted file mode 100644 index 59ef9515f..000000000 --- a/spine-godot/spine_godot/register_types.h +++ /dev/null @@ -1,31 +0,0 @@ -/****************************************************************************** - * Spine Runtimes License Agreement - * Last updated January 1, 2020. Replaces all prior versions. - * - * Copyright (c) 2013-2020, Esoteric Software LLC - * - * Integration of the Spine Runtimes into software or otherwise creating - * derivative works of the Spine Runtimes is permitted under the terms and - * conditions of Section 2 of the Spine Editor License Agreement: - * http://esotericsoftware.com/spine-editor-license - * - * Otherwise, it is permitted to integrate the Spine Runtimes into software - * or otherwise create derivative works of the Spine Runtimes (collectively, - * "Products"), provided that each user of the Products must obtain their own - * Spine Editor license and redistribution of the Products in any form must - * include this license and copyright notice. - * - * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, - * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -void register_spine_godot_types(); -void unregister_spine_godot_types(); From 7f4ee229f59d077030fef85dc7c2b5ae5152eb54 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Mon, 4 Apr 2022 12:22:47 +0200 Subject: [PATCH 13/18] [godot] Fix git ignore. --- .../spine_godot/GodotSpineExtension.cpp | 73 ++ spine-godot/spine_godot/GodotSpineExtension.h | 54 + ...ourceFormatLoaderSpineSkeletonJsonData.cpp | 56 + ...esourceFormatLoaderSpineSkeletonJsonData.h | 45 + ...sourceFormatSaverSpineSkeletonJsonData.cpp | 48 + ...ResourceFormatSaverSpineSkeletonJsonData.h | 45 + spine-godot/spine_godot/SCsub | 9 + spine-godot/spine_godot/SpineAnimation.cpp | 96 ++ spine-godot/spine_godot/SpineAnimation.h | 74 ++ .../spine_godot/SpineAnimationState.cpp | 191 ++++ spine-godot/spine_godot/SpineAnimationState.h | 94 ++ .../SpineAnimationStateDataResource.cpp | 163 +++ .../SpineAnimationStateDataResource.h | 76 ++ .../spine_godot/SpineAtlasResource.cpp | 239 +++++ spine-godot/spine_godot/SpineAtlasResource.h | 100 ++ spine-godot/spine_godot/SpineAttachment.cpp | 55 + spine-godot/spine_godot/SpineAttachment.h | 64 ++ spine-godot/spine_godot/SpineBone.cpp | 536 ++++++++++ spine-godot/spine_godot/SpineBone.h | 175 ++++ spine-godot/spine_godot/SpineBoneData.cpp | 163 +++ spine-godot/spine_godot/SpineBoneData.h | 103 ++ .../spine_godot/SpineCollisionShapeProxy.cpp | 196 ++++ .../spine_godot/SpineCollisionShapeProxy.h | 80 ++ spine-godot/spine_godot/SpineConstant.cpp | 60 ++ spine-godot/spine_godot/SpineConstant.h | 81 ++ .../spine_godot/SpineConstraintData.cpp | 59 ++ spine-godot/spine_godot/SpineConstraintData.h | 66 ++ spine-godot/spine_godot/SpineEvent.cpp | 110 ++ spine-godot/spine_godot/SpineEvent.h | 91 ++ spine-godot/spine_godot/SpineEventData.cpp | 36 + spine-godot/spine_godot/SpineEventData.h | 58 ++ spine-godot/spine_godot/SpineIkConstraint.cpp | 146 +++ spine-godot/spine_godot/SpineIkConstraint.h | 94 ++ .../spine_godot/SpineIkConstraintData.cpp | 123 +++ .../spine_godot/SpineIkConstraintData.h | 78 ++ .../spine_godot/SpinePathConstraint.cpp | 145 +++ spine-godot/spine_godot/SpinePathConstraint.h | 94 ++ .../spine_godot/SpinePathConstraintData.cpp | 168 +++ .../spine_godot/SpinePathConstraintData.h | 108 ++ spine-godot/spine_godot/SpineRendererObject.h | 41 + .../spine_godot/SpineRuntimeEditorPlugin.cpp | 99 ++ .../spine_godot/SpineRuntimeEditorPlugin.h | 98 ++ spine-godot/spine_godot/SpineSkeleton.cpp | 413 ++++++++ spine-godot/spine_godot/SpineSkeleton.h | 129 +++ .../spine_godot/SpineSkeletonDataResource.cpp | 455 +++++++++ .../spine_godot/SpineSkeletonDataResource.h | 140 +++ .../SpineSkeletonJsonDataResource.cpp | 55 + .../SpineSkeletonJsonDataResource.h | 50 + spine-godot/spine_godot/SpineSkin.cpp | 161 +++ spine-godot/spine_godot/SpineSkin.h | 85 ++ .../SpineSkinAttachmentMapEntries.cpp | 93 ++ .../SpineSkinAttachmentMapEntries.h | 93 ++ spine-godot/spine_godot/SpineSlot.cpp | 141 +++ spine-godot/spine_godot/SpineSlot.h | 90 ++ spine-godot/spine_godot/SpineSlotData.cpp | 114 +++ spine-godot/spine_godot/SpineSlotData.h | 88 ++ spine-godot/spine_godot/SpineSprite.cpp | 966 ++++++++++++++++++ spine-godot/spine_godot/SpineSprite.h | 154 +++ .../spine_godot/SpineSpriteAnimateDialog.cpp | 351 +++++++ .../spine_godot/SpineSpriteAnimateDialog.h | 87 ++ .../spine_godot/SpineSpriteMeshInstance2D.cpp | 48 + .../spine_godot/SpineSpriteMeshInstance2D.h | 57 ++ spine-godot/spine_godot/SpineTimeline.cpp | 99 ++ spine-godot/spine_godot/SpineTimeline.h | 75 ++ spine-godot/spine_godot/SpineTrackEntry.cpp | 265 +++++ spine-godot/spine_godot/SpineTrackEntry.h | 131 +++ .../spine_godot/SpineTransformConstraint.cpp | 148 +++ .../spine_godot/SpineTransformConstraint.h | 93 ++ .../SpineTransformConstraintData.cpp | 118 +++ .../SpineTransformConstraintData.h | 74 ++ spine-godot/spine_godot/config.py | 5 + spine-godot/spine_godot/register_types.cpp | 144 +++ spine-godot/spine_godot/register_types.h | 31 + 73 files changed, 9443 insertions(+) create mode 100644 spine-godot/spine_godot/GodotSpineExtension.cpp create mode 100644 spine-godot/spine_godot/GodotSpineExtension.h create mode 100644 spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.cpp create mode 100644 spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.h create mode 100644 spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.cpp create mode 100644 spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.h create mode 100644 spine-godot/spine_godot/SCsub create mode 100644 spine-godot/spine_godot/SpineAnimation.cpp create mode 100644 spine-godot/spine_godot/SpineAnimation.h create mode 100644 spine-godot/spine_godot/SpineAnimationState.cpp create mode 100644 spine-godot/spine_godot/SpineAnimationState.h create mode 100644 spine-godot/spine_godot/SpineAnimationStateDataResource.cpp create mode 100644 spine-godot/spine_godot/SpineAnimationStateDataResource.h create mode 100644 spine-godot/spine_godot/SpineAtlasResource.cpp create mode 100644 spine-godot/spine_godot/SpineAtlasResource.h create mode 100644 spine-godot/spine_godot/SpineAttachment.cpp create mode 100644 spine-godot/spine_godot/SpineAttachment.h create mode 100644 spine-godot/spine_godot/SpineBone.cpp create mode 100644 spine-godot/spine_godot/SpineBone.h create mode 100644 spine-godot/spine_godot/SpineBoneData.cpp create mode 100644 spine-godot/spine_godot/SpineBoneData.h create mode 100644 spine-godot/spine_godot/SpineCollisionShapeProxy.cpp create mode 100644 spine-godot/spine_godot/SpineCollisionShapeProxy.h create mode 100644 spine-godot/spine_godot/SpineConstant.cpp create mode 100644 spine-godot/spine_godot/SpineConstant.h create mode 100644 spine-godot/spine_godot/SpineConstraintData.cpp create mode 100644 spine-godot/spine_godot/SpineConstraintData.h create mode 100644 spine-godot/spine_godot/SpineEvent.cpp create mode 100644 spine-godot/spine_godot/SpineEvent.h create mode 100644 spine-godot/spine_godot/SpineEventData.cpp create mode 100644 spine-godot/spine_godot/SpineEventData.h create mode 100644 spine-godot/spine_godot/SpineIkConstraint.cpp create mode 100644 spine-godot/spine_godot/SpineIkConstraint.h create mode 100644 spine-godot/spine_godot/SpineIkConstraintData.cpp create mode 100644 spine-godot/spine_godot/SpineIkConstraintData.h create mode 100644 spine-godot/spine_godot/SpinePathConstraint.cpp create mode 100644 spine-godot/spine_godot/SpinePathConstraint.h create mode 100644 spine-godot/spine_godot/SpinePathConstraintData.cpp create mode 100644 spine-godot/spine_godot/SpinePathConstraintData.h create mode 100644 spine-godot/spine_godot/SpineRendererObject.h create mode 100644 spine-godot/spine_godot/SpineRuntimeEditorPlugin.cpp create mode 100644 spine-godot/spine_godot/SpineRuntimeEditorPlugin.h create mode 100644 spine-godot/spine_godot/SpineSkeleton.cpp create mode 100644 spine-godot/spine_godot/SpineSkeleton.h create mode 100644 spine-godot/spine_godot/SpineSkeletonDataResource.cpp create mode 100644 spine-godot/spine_godot/SpineSkeletonDataResource.h create mode 100644 spine-godot/spine_godot/SpineSkeletonJsonDataResource.cpp create mode 100644 spine-godot/spine_godot/SpineSkeletonJsonDataResource.h create mode 100644 spine-godot/spine_godot/SpineSkin.cpp create mode 100644 spine-godot/spine_godot/SpineSkin.h create mode 100644 spine-godot/spine_godot/SpineSkinAttachmentMapEntries.cpp create mode 100644 spine-godot/spine_godot/SpineSkinAttachmentMapEntries.h create mode 100644 spine-godot/spine_godot/SpineSlot.cpp create mode 100644 spine-godot/spine_godot/SpineSlot.h create mode 100644 spine-godot/spine_godot/SpineSlotData.cpp create mode 100644 spine-godot/spine_godot/SpineSlotData.h create mode 100644 spine-godot/spine_godot/SpineSprite.cpp create mode 100644 spine-godot/spine_godot/SpineSprite.h create mode 100644 spine-godot/spine_godot/SpineSpriteAnimateDialog.cpp create mode 100644 spine-godot/spine_godot/SpineSpriteAnimateDialog.h create mode 100644 spine-godot/spine_godot/SpineSpriteMeshInstance2D.cpp create mode 100644 spine-godot/spine_godot/SpineSpriteMeshInstance2D.h create mode 100644 spine-godot/spine_godot/SpineTimeline.cpp create mode 100644 spine-godot/spine_godot/SpineTimeline.h create mode 100644 spine-godot/spine_godot/SpineTrackEntry.cpp create mode 100644 spine-godot/spine_godot/SpineTrackEntry.h create mode 100644 spine-godot/spine_godot/SpineTransformConstraint.cpp create mode 100644 spine-godot/spine_godot/SpineTransformConstraint.h create mode 100644 spine-godot/spine_godot/SpineTransformConstraintData.cpp create mode 100644 spine-godot/spine_godot/SpineTransformConstraintData.h create mode 100644 spine-godot/spine_godot/config.py create mode 100644 spine-godot/spine_godot/register_types.cpp create mode 100644 spine-godot/spine_godot/register_types.h diff --git a/spine-godot/spine_godot/GodotSpineExtension.cpp b/spine-godot/spine_godot/GodotSpineExtension.cpp new file mode 100644 index 000000000..cace4e354 --- /dev/null +++ b/spine-godot/spine_godot/GodotSpineExtension.cpp @@ -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. + *****************************************************************************/ + +#include "GodotSpineExtension.h" + +#include "core/variant_parser.h" +#include + +#include + +spine::SpineExtension *spine::getDefaultExtension() { + return new GodotSpineExtension(); +} + +GodotSpineExtension::GodotSpineExtension() {} +GodotSpineExtension::~GodotSpineExtension() {} + +void *GodotSpineExtension::_alloc(size_t size, const char *file, int line) { + return memalloc(size); +} + +void *GodotSpineExtension::_calloc(size_t size, const char *file, int line) { + auto p = memalloc(size); + memset(p, 0, size); + return p; +} + +void *GodotSpineExtension::_realloc(void *ptr, size_t size, const char *file, int line) { + return memrealloc(ptr, size); +} + +void GodotSpineExtension::_free(void *mem, const char *file, int line) { + memfree(mem); +} + +char *GodotSpineExtension::_readFile(const spine::String &path, int *length) { + Error error; + auto res = FileAccess::get_file_as_array(String(path.buffer()), &error); + if (error != OK) { + if (length) *length = 0; + return NULL; + } + auto r = alloc(res.size(), __FILE__, __LINE__); + memcpy(r, res.ptr(), res.size()); + if (length) *length = res.size(); + return r; +} \ No newline at end of file diff --git a/spine-godot/spine_godot/GodotSpineExtension.h b/spine-godot/spine_godot/GodotSpineExtension.h new file mode 100644 index 000000000..e00726051 --- /dev/null +++ b/spine-godot/spine_godot/GodotSpineExtension.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 GODOT_SPINEEXTENSION_H +#define GODOT_SPINEEXTENSION_H + + +#include +class GodotSpineExtension : public spine::SpineExtension { +public: + GodotSpineExtension(); + + virtual ~GodotSpineExtension(); + +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 spine::String &path, int *length); +}; + + +#endif//GODOT_SPINEEXTENSION_H diff --git a/spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.cpp b/spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.cpp new file mode 100644 index 000000000..9c1cc80e5 --- /dev/null +++ b/spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.cpp @@ -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. + *****************************************************************************/ + +#include "ResourceFormatLoaderSpineSkeletonJsonData.h" +#include "SpineSkeletonJsonDataResource.h" + +RES ResourceFormatLoaderSpineSkeletonJsonData::load(const String &p_path, const String &p_original_path, Error *r_error) { + Ref skeleton = memnew(SpineSkeletonJsonDataResource); + skeleton->load_from_file(p_path); + + if (r_error) { + *r_error = OK; + } + return skeleton; +} + +void ResourceFormatLoaderSpineSkeletonJsonData::get_recognized_extensions(List *r_extensions) const { + const char json_ext[] = "spjson"; + if (!r_extensions->find(json_ext)) { + r_extensions->push_back(json_ext); + } +} + +String ResourceFormatLoaderSpineSkeletonJsonData::get_resource_type(const String &p_path) const { + return "SpineSkeletonJsonDataResource"; +} + +bool ResourceFormatLoaderSpineSkeletonJsonData::handles_type(const String &p_type) const { + return p_type == "SpineSkeletonJsonDataResource" || ClassDB::is_parent_class(p_type, "SpineSkeletonJsonDataResource"); +} \ No newline at end of file diff --git a/spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.h b/spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.h new file mode 100644 index 000000000..9736655f6 --- /dev/null +++ b/spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.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 GODOT_RESOURCEFORMATLOADERSPINESKELETONJSONDATA_H +#define GODOT_RESOURCEFORMATLOADERSPINESKELETONJSONDATA_H + +#include "core/io/resource_loader.h" + +class ResourceFormatLoaderSpineSkeletonJsonData : public ResourceFormatLoader { + GDCLASS(ResourceFormatLoaderSpineSkeletonJsonData, ResourceFormatLoader); + +public: + virtual RES load(const String &p_path, const String &p_original_path, Error *r_error = NULL); + virtual void get_recognized_extensions(List *r_extensions) const; + virtual bool handles_type(const String &p_type) const; + virtual String get_resource_type(const String &p_path) const; +}; + +#endif//GODOT_RESOURCEFORMATLOADERSPINESKELETONJSONDATA_H diff --git a/spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.cpp b/spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.cpp new file mode 100644 index 000000000..5fa669c04 --- /dev/null +++ b/spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.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. + *****************************************************************************/ + +#include "ResourceFormatSaverSpineSkeletonJsonData.h" + +#include "SpineSkeletonJsonDataResource.h" + +Error ResourceFormatSaverSpineSkeletonJsonData::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { + Ref res = p_resource.get_ref_ptr(); + Error error = res->save_to_file(p_path); + return error; +} + +void ResourceFormatSaverSpineSkeletonJsonData::get_recognized_extensions(const RES &p_resource, List *p_extensions) const { + if (Object::cast_to(*p_resource)) { + p_extensions->push_back("spjson"); + } +} + +bool ResourceFormatSaverSpineSkeletonJsonData::recognize(const RES &p_resource) const { + return Object::cast_to(*p_resource) != nullptr; +} diff --git a/spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.h b/spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.h new file mode 100644 index 000000000..2c42ee5d0 --- /dev/null +++ b/spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.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 GODOT_RESOURCEFORMATSAVERSPINESKELETONJSONDATA_H +#define GODOT_RESOURCEFORMATSAVERSPINESKELETONJSONDATA_H + +#include "core/io/resource_saver.h" + +class ResourceFormatSaverSpineSkeletonJsonData : public ResourceFormatSaver { + GDCLASS(ResourceFormatSaverSpineSkeletonJsonData, ResourceFormatSaver); + +public: + Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0) override; + void get_recognized_extensions(const RES &p_resource, List *p_extensions) const override; + bool recognize(const RES &p_resource) const override; +}; + + +#endif//GODOT_RESOURCEFORMATSAVERSPINESKELETONJSONDATA_H diff --git a/spine-godot/spine_godot/SCsub b/spine-godot/spine_godot/SCsub new file mode 100644 index 000000000..f7d88af0b --- /dev/null +++ b/spine-godot/spine_godot/SCsub @@ -0,0 +1,9 @@ +Import('env') + +env_spine_runtime = env.Clone() + +env_spine_runtime.Prepend(CPPPATH=["spine-cpp/include"]) +env_spine_runtime.Append(CCFLAGS=['-O2']) + +env_spine_runtime.add_source_files(env.modules_sources, "spine-cpp/src/spine/*.cpp") +env_spine_runtime.add_source_files(env.modules_sources, "*.cpp") diff --git a/spine-godot/spine_godot/SpineAnimation.cpp b/spine-godot/spine_godot/SpineAnimation.cpp new file mode 100644 index 000000000..7f0772f24 --- /dev/null +++ b/spine-godot/spine_godot/SpineAnimation.cpp @@ -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. + *****************************************************************************/ + +#include "SpineAnimation.h" + +#include "SpineSkeleton.h" +#include "SpineEvent.h" +#include "SpineTimeline.h" + +// enable more than 5 arguments of a method bind function +#include "core/method_bind_ext.gen.inc" + +void SpineAnimation::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_anim_name"), &SpineAnimation::get_anim_name); + ClassDB::bind_method(D_METHOD("get_duration"), &SpineAnimation::get_duration); + ClassDB::bind_method(D_METHOD("set_duration", "v"), &SpineAnimation::set_duration); + + ClassDB::bind_method(D_METHOD("apply", "skeleton", "last_time", "time", "loop", "events", "alpha", "blend", "direction"), &SpineAnimation::apply); + ClassDB::bind_method(D_METHOD("get_timelines"), &SpineAnimation::get_timelines); + ClassDB::bind_method(D_METHOD("has_timeline", "ids"), &SpineAnimation::has_timeline); +} + +SpineAnimation::SpineAnimation() : animation(NULL) {} +SpineAnimation::~SpineAnimation() {} + +String SpineAnimation::get_anim_name() { + return animation->getName().buffer(); +} + +float SpineAnimation::get_duration() { + return animation->getDuration(); +} +void SpineAnimation::set_duration(float v) { + animation->setDuration(v); +} + +void SpineAnimation::apply(Ref skeleton, float lastTime, float time, bool loop, + Array pEvents, float alpha, SpineConstant::MixBlend blend, + SpineConstant::MixDirection direction) { + spine::Vector events; + events.setSize(pEvents.size(), nullptr); + for (size_t i = 0; i < events.size(); ++i) { + events[i] = ((Ref) (pEvents[i]))->get_spine_object(); + } + animation->apply(*(skeleton->get_spine_object()), lastTime, time, loop, &events, alpha, (spine::MixBlend) blend, (spine::MixDirection) direction); +} + +Array SpineAnimation::get_timelines() { + auto &timelines = animation->getTimelines(); + Array res; + res.resize(timelines.size()); + + for (size_t i = 0; i < res.size(); ++i) { + auto a = Ref(memnew(SpineTimeline)); + a->set_spine_object(timelines[i]); + res.set(i, a); + } + + return res; +} + +bool SpineAnimation::has_timeline(Array ids) { + spine::Vector list; + list.setSize(ids.size(), 0); + + for (size_t i = 0; i < list.size(); ++i) { + list[i] = (int64_t) ids[i]; + } + return animation->hasTimeline(list); +} diff --git a/spine-godot/spine_godot/SpineAnimation.h b/spine-godot/spine_godot/SpineAnimation.h new file mode 100644 index 000000000..98dbed587 --- /dev/null +++ b/spine-godot/spine_godot/SpineAnimation.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 GODOT_SPINEANIMATION_H +#define GODOT_SPINEANIMATION_H + +#include "core/variant_parser.h" + +#include "SpineConstant.h" + +#include + +class SpineEvent; +class SpineSkeleton; +class SpineTimeline; + +class SpineAnimation : public Reference { + GDCLASS(SpineAnimation, Reference); + +private: + spine::Animation *animation; + +protected: + static void _bind_methods(); + +public: + SpineAnimation(); + ~SpineAnimation(); + + inline void set_spine_object(spine::Animation *a) { + animation = a; + } + inline spine::Animation *get_spine_object() { + return animation; + } + + // Vector> pEvents + void apply(Ref skeleton, float lastTime, float time, bool loop, Array pEvents, float alpha, SpineConstant::MixBlend blend, SpineConstant::MixDirection direction); + + Array get_timelines(); // Vector> + bool has_timeline(Array ids);// Vector + + String get_anim_name(); + float get_duration(); + void set_duration(float v); +}; + +#endif//GODOT_SPINEANIMATION_H diff --git a/spine-godot/spine_godot/SpineAnimationState.cpp b/spine-godot/spine_godot/SpineAnimationState.cpp new file mode 100644 index 000000000..155a1d6d3 --- /dev/null +++ b/spine-godot/spine_godot/SpineAnimationState.cpp @@ -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. + *****************************************************************************/ + +#include "SpineAnimationState.h" + +void SpineAnimationState::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_animation", "anim_name", "loop", "track_id"), &SpineAnimationState::set_animation, DEFVAL(true), DEFVAL(0)); + ClassDB::bind_method(D_METHOD("update", "delta"), &SpineAnimationState::update, DEFVAL(0)); + ClassDB::bind_method(D_METHOD("apply", "skeleton"), &SpineAnimationState::apply); + ClassDB::bind_method(D_METHOD("clear_tracks"), &SpineAnimationState::clear_tracks); + ClassDB::bind_method(D_METHOD("clear_track"), &SpineAnimationState::clear_track); + ClassDB::bind_method(D_METHOD("add_animation", "anim_name", "delay", "loop", "track_id"), &SpineAnimationState::add_animation, DEFVAL(0), DEFVAL(true), DEFVAL(0)); + ClassDB::bind_method(D_METHOD("set_empty_animation", "track_id", "mix_duration"), &SpineAnimationState::set_empty_animation); + ClassDB::bind_method(D_METHOD("add_empty_animation", "track_id", "mix_duration", "delay"), &SpineAnimationState::add_empty_animation); + ClassDB::bind_method(D_METHOD("set_empty_animations", "mix_duration"), &SpineAnimationState::set_empty_animations); + ClassDB::bind_method(D_METHOD("get_data"), &SpineAnimationState::get_data); + ClassDB::bind_method(D_METHOD("get_time_scale"), &SpineAnimationState::get_time_scale); + ClassDB::bind_method(D_METHOD("set_time_scale", "time_scale"), &SpineAnimationState::set_time_scale); + ClassDB::bind_method(D_METHOD("disable_queue"), &SpineAnimationState::disable_queue); + ClassDB::bind_method(D_METHOD("enable_queue"), &SpineAnimationState::enable_queue); + // ClassDB::bind_method(D_METHOD("reload"), &SpineAnimationState::reload_animation_state); + ClassDB::bind_method(D_METHOD("get_current", "track_id"), &SpineAnimationState::get_current); +} + +SpineAnimationState::SpineAnimationState() : animation_state(NULL) { +} + +SpineAnimationState::~SpineAnimationState() { + if (animation_state) { + delete animation_state; + animation_state = NULL; + } +} + +void SpineAnimationState::load_animation_state(Ref ad) { + if (animation_state) { + delete animation_state; + animation_state = NULL; + } + animation_state = new spine::AnimationState(ad->get_animation_state_data()); + anim_state_data_res = ad; +} + +void SpineAnimationState::reload_animation_state() { + if (!anim_state_data_res.is_valid()) { + ERR_PRINT(" Reload animation state fail, because anim_state_data_res not set!"); + return; + } + if (animation_state) { + delete animation_state; + animation_state = NULL; + } + animation_state = new spine::AnimationState(anim_state_data_res->get_animation_state_data()); +} + +#define CHECK_V \ + if (!animation_state) { \ + ERR_PRINT("The animation state is not loaded yet!"); \ + return; \ + } +#define CHECK_X(x) \ + if (!animation_state) { \ + ERR_PRINT("The animation state is not loaded yet!"); \ + return x; \ + } +#define S_T(x) (spine::String(x.utf8())) +Ref SpineAnimationState::set_animation(const String &anim_name, bool loop, uint64_t track) { + CHECK_X(NULL); + auto skeleton_data = anim_state_data_res->get_skeleton(); + auto anim = skeleton_data->find_animation(anim_name); + if (!anim.is_valid() || anim->get_spine_object() == NULL) { + ERR_PRINT(String("Can not find animation: ") + anim_name); + return NULL; + } + auto entry = animation_state->setAnimation(track, anim->get_spine_object(), loop); + Ref gd_entry(memnew(SpineTrackEntry)); + gd_entry->set_spine_object(entry); + return gd_entry; +} +Ref SpineAnimationState::add_animation(const String &anim_name, float delay, bool loop, uint64_t track) { + CHECK_X(NULL); + auto skeleton_data = anim_state_data_res->get_skeleton(); + auto anim = skeleton_data->find_animation(anim_name); + if (!anim.is_valid() || anim->get_spine_object() == NULL) { + ERR_PRINT(String("Can not find animation: ") + anim_name); + return NULL; + } + auto entry = animation_state->addAnimation(track, anim->get_spine_object(), loop, delay); + Ref gd_entry(memnew(SpineTrackEntry)); + gd_entry->set_spine_object(entry); + return gd_entry; +} + +Ref SpineAnimationState::set_empty_animation(uint64_t track_id, float mix_duration) { + CHECK_X(NULL); + auto entry = animation_state->setEmptyAnimation(track_id, mix_duration); + Ref gd_entry(memnew(SpineTrackEntry)); + gd_entry->set_spine_object(entry); + return gd_entry; +} +Ref SpineAnimationState::add_empty_animation(uint64_t track_id, float mix_duration, float delay) { + CHECK_X(NULL); + auto entry = animation_state->addEmptyAnimation(track_id, mix_duration, delay); + Ref gd_entry(memnew(SpineTrackEntry)); + gd_entry->set_spine_object(entry); + return gd_entry; +} +void SpineAnimationState::set_empty_animations(float mix_duration) { + CHECK_V; + animation_state->setEmptyAnimations(mix_duration); +} + +void SpineAnimationState::update(float delta) { + CHECK_V; + animation_state->update(delta); +} +bool SpineAnimationState::apply(Ref skeleton) { + CHECK_X(false); + return animation_state->apply(*(skeleton->get_spine_object())); +} + + +void SpineAnimationState::clear_tracks() { + CHECK_V; + animation_state->clearTracks(); +} +void SpineAnimationState::clear_track(uint64_t track_id) { + CHECK_V; + animation_state->clearTrack(track_id); +} + +Ref SpineAnimationState::get_data() { + CHECK_X(NULL); + return anim_state_data_res; +} + +float SpineAnimationState::get_time_scale() { + CHECK_X(0); + return animation_state->getTimeScale(); +} +void SpineAnimationState::set_time_scale(float v) { + CHECK_V; + animation_state->setTimeScale(v); +} + +void SpineAnimationState::disable_queue() { + CHECK_V; + animation_state->disableQueue(); +} +void SpineAnimationState::enable_queue() { + CHECK_V; + animation_state->enableQueue(); +} + +Ref SpineAnimationState::get_current(uint64_t track_index) { + CHECK_X(NULL); + Ref gd_entry(memnew(SpineTrackEntry)); + auto entry = animation_state->getCurrent(track_index); + if (entry == NULL) return NULL; + gd_entry->set_spine_object(entry); + return gd_entry; +} + +#undef CHECK_V +#undef CHECK_X diff --git a/spine-godot/spine_godot/SpineAnimationState.h b/spine-godot/spine_godot/SpineAnimationState.h new file mode 100644 index 000000000..097be72ac --- /dev/null +++ b/spine-godot/spine_godot/SpineAnimationState.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 GODOT_SPINEANIMATIONSTATE_H +#define GODOT_SPINEANIMATIONSTATE_H + +#include "core/variant_parser.h" + +#include "SpineAnimationStateDataResource.h" +#include "SpineSkeleton.h" +#include "SpineTrackEntry.h" + +class SpineAnimationState : public Reference { + GDCLASS(SpineAnimationState, Reference); + +protected: + static void _bind_methods(); + +private: + spine::AnimationState *animation_state; + + Ref anim_state_data_res; + +public: + void load_animation_state(Ref ad); + + inline void set_animation_state(spine::AnimationState *a) { + animation_state = a; + } + inline spine::AnimationState *get_animation_state() { + return animation_state; + } + + void reload_animation_state(); + + Ref set_animation(const String &anim_name, bool loop, uint64_t track_id); + inline void set_animation_by_ref(Ref anim, bool loop, uint64_t track_id) { + if (anim.is_valid()) { + animation_state->setAnimation(track_id, anim->get_spine_object(), loop); + } + } + Ref add_animation(const String &anim_name, float delay, bool loop, uint64_t track_id); + + Ref set_empty_animation(uint64_t track_id, float mix_duration); + Ref add_empty_animation(uint64_t track_id, float mix_duration, float delay); + void set_empty_animations(float mix_duration); + + Ref get_data(); + + float get_time_scale(); + void set_time_scale(float v); + + void disable_queue(); + void enable_queue(); + + void update(float delta); + bool apply(Ref skeleton); + + void clear_tracks(); + void clear_track(uint64_t track_id); + + Ref get_current(uint64_t track_index); + + SpineAnimationState(); + ~SpineAnimationState(); +}; + +#endif//GODOT_SPINEANIMATIONSTATE_H diff --git a/spine-godot/spine_godot/SpineAnimationStateDataResource.cpp b/spine-godot/spine_godot/SpineAnimationStateDataResource.cpp new file mode 100644 index 000000000..de4041ec2 --- /dev/null +++ b/spine-godot/spine_godot/SpineAnimationStateDataResource.cpp @@ -0,0 +1,163 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineAnimationStateDataResource.h" + +SpineAnimationStateDataResource::SpineAnimationStateDataResource() : animation_state_data(NULL), animation_state_data_created(false), default_mix(0.5f) { +} +SpineAnimationStateDataResource::~SpineAnimationStateDataResource() { + if (animation_state_data) { + delete animation_state_data; + animation_state_data = NULL; + } +} + +void SpineAnimationStateDataResource::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_skeleton", "skeleton"), &SpineAnimationStateDataResource::set_skeleton); + ClassDB::bind_method(D_METHOD("get_spine_object"), &SpineAnimationStateDataResource::get_skeleton); + ClassDB::bind_method(D_METHOD("_on_skeleton_data_loaded"), &SpineAnimationStateDataResource::_on_skeleton_data_loaded); + ClassDB::bind_method(D_METHOD("is_animation_state_data_created"), &SpineAnimationStateDataResource::is_animation_state_data_created); + ClassDB::bind_method(D_METHOD("_on_skeleton_data_changed"), &SpineAnimationStateDataResource::_on_skeleton_data_changed); + ClassDB::bind_method(D_METHOD("set_default_mix", "mix"), &SpineAnimationStateDataResource::set_default_mix); + ClassDB::bind_method(D_METHOD("get_default_mix"), &SpineAnimationStateDataResource::get_default_mix); + ClassDB::bind_method(D_METHOD("get_mix", "from", "to"), &SpineAnimationStateDataResource::get_mix); + ClassDB::bind_method(D_METHOD("set_mix", "from", "to", "mix"), &SpineAnimationStateDataResource::set_mix); + + ADD_SIGNAL(MethodInfo("animation_state_data_created")); + ADD_SIGNAL(MethodInfo("skeleton_data_res_changed")); + ADD_SIGNAL(MethodInfo("animation_state_data_changed")); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "skeleton", PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "SpineSkeletonDataResource"), "set_skeleton", "get_spine_object"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "default_mix", PropertyHint::PROPERTY_HINT_EXP_RANGE, "0,1,0.01"), "set_default_mix", "get_default_mix"); +} + +void SpineAnimationStateDataResource::set_skeleton(const Ref &s) { + skeleton = s; + + _on_skeleton_data_changed(); + if (skeleton.is_valid()) { + skeleton->connect("skeleton_data_loaded", this, "_on_skeleton_data_loaded"); + skeleton->connect("atlas_res_changed", this, "_on_skeleton_data_changed"); + skeleton->connect("skeleton_json_res_changed", this, "_on_skeleton_data_changed"); + + if (skeleton->is_skeleton_data_loaded()) { + _on_skeleton_data_loaded(); + } + } else { + if (animation_state_data) { + delete animation_state_data; + animation_state_data = NULL; + animation_state_data_created = false; + // print_line("Animation state data deleted."); + } + } +} +Ref SpineAnimationStateDataResource::get_skeleton() { + return skeleton; +} + +void SpineAnimationStateDataResource::set_default_mix(float m) { + default_mix = m; + if (!is_animation_state_data_created()) { + // ERR_PRINT("'set_default_mix' fail. Animation state data is not created!"); + return; + } + animation_state_data->setDefaultMix(((m >= 0 && m <= 1) ? m : m <= 0 ? 0 + : 1)); + // emit_signal("animation_state_data_changed"); +} +float SpineAnimationStateDataResource::get_default_mix() { + if (!is_animation_state_data_created()) { + // ERR_PRINT("'get_default_mix' fail. Animation state data is not created!"); + return default_mix; + } + default_mix = animation_state_data->getDefaultMix(); + return default_mix; +} + +void SpineAnimationStateDataResource::set_mix(const String &from, const String &to, float mix_duration) { + if (!is_animation_state_data_created()) { + ERR_PRINT("'set_mix' fail. Animation state data is not created!"); + return; + } + auto anim_from = get_skeleton()->find_animation(from); + auto anim_to = get_skeleton()->find_animation(to); + if (!anim_from.is_valid()) { + ERR_PRINT("'set_mix' fail. From animation animation not found!"); + return; + } + if (!anim_to.is_valid()) { + ERR_PRINT("'set_mix' fail. To animation animation not found!"); + return; + } + animation_state_data->setMix(anim_from->get_spine_object(), anim_to->get_spine_object(), mix_duration); +} +float SpineAnimationStateDataResource::get_mix(const String &from, const String &to) { + if (!is_animation_state_data_created()) { + ERR_PRINT("'set_mix' fail. Animation state data is not created!"); + return 0; + } + auto anim_from = get_skeleton()->find_animation(from); + auto anim_to = get_skeleton()->find_animation(to); + if (!anim_from.is_valid()) { + ERR_PRINT("'set_mix' fail. From animation animation not found!"); + return 0; + } + if (!anim_to.is_valid()) { + ERR_PRINT("'set_mix' fail. To animation animation not found!"); + return 0; + } + return animation_state_data->getMix(anim_from->get_spine_object(), anim_to->get_spine_object()); +} + +void SpineAnimationStateDataResource::_on_skeleton_data_loaded() { + animation_state_data = new spine::AnimationStateData(skeleton->get_skeleton_data()); + // print_line("Animation state data created."); + + + emit_signal("animation_state_data_created"); + animation_state_data->setDefaultMix(default_mix); + animation_state_data_created = true; +} + +void SpineAnimationStateDataResource::_on_skeleton_data_changed() { + animation_state_data_created = false; + if (animation_state_data) { + delete animation_state_data; + animation_state_data = NULL; + // print_line("Animation state data deleted."); + } + + // print_line("skeleton_data_res_changed emitted"); + emit_signal("skeleton_data_res_changed"); +} + +bool SpineAnimationStateDataResource::is_animation_state_data_created() { + return animation_state_data_created; +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineAnimationStateDataResource.h b/spine-godot/spine_godot/SpineAnimationStateDataResource.h new file mode 100644 index 000000000..58f0cd536 --- /dev/null +++ b/spine-godot/spine_godot/SpineAnimationStateDataResource.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 GODOT_SPINEANIMATIONSTATEDATARESOURCE_H +#define GODOT_SPINEANIMATIONSTATEDATARESOURCE_H + +#include "core/variant_parser.h" + +#include "SpineSkeletonDataResource.h" + +class SpineAnimationStateDataResource : public Resource { + GDCLASS(SpineAnimationStateDataResource, Resource); + +protected: + static void _bind_methods(); + +private: + Ref skeleton; + + spine::AnimationStateData *animation_state_data; + + bool animation_state_data_created; + + float default_mix; + +public: + void set_skeleton(const Ref &s); + Ref get_skeleton(); + + inline spine::AnimationStateData *get_animation_state_data() { + return animation_state_data; + } + + void set_default_mix(float m); + float get_default_mix(); + + void set_mix(const String &from, const String &to, float mix_duration); + float get_mix(const String &from, const String &to); + + + void _on_skeleton_data_loaded(); + void _on_skeleton_data_changed(); + + bool is_animation_state_data_created(); + + SpineAnimationStateDataResource(); + ~SpineAnimationStateDataResource(); +}; + +#endif//GODOT_SPINEANIMATIONSTATEDATARESOURCE_H diff --git a/spine-godot/spine_godot/SpineAtlasResource.cpp b/spine-godot/spine_godot/SpineAtlasResource.cpp new file mode 100644 index 000000000..088426621 --- /dev/null +++ b/spine-godot/spine_godot/SpineAtlasResource.cpp @@ -0,0 +1,239 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineAtlasResource.h" +#include "core/io/json.h" + +#include + +class GodotSpineTextureLoader : public spine::TextureLoader { +private: + Array *textures, *normal_maps; + String normal_map_prefix; + +public: + GodotSpineTextureLoader(Array *t, Array *nt, const String &p) : textures(t), normal_maps(nt), normal_map_prefix(p) { + if (textures) textures->clear(); + if (normal_maps) normal_maps->clear(); + } + + String fix_path(const String &path) { + if (path.size() > 5 && path[4] == '/' && path[5] == '/') return path; + const String prefix = "res:/"; + auto i = path.find(prefix); + auto sub_str_pos = i + prefix.size() - 1; + if (sub_str_pos < 0) return path; + auto res = path.substr(sub_str_pos); + + if (res.size() > 0) { + if (res[0] != '/') { + return prefix + "/" + res; + } else { + return prefix + res; + } + } + return path; + } + + virtual void load(spine::AtlasPage &page, const spine::String &path) { + Error err = OK; + auto fixed_path = fix_path(String(path.buffer())); + + Ref texture = ResourceLoader::load(fixed_path, "", false, &err); + if (err != OK) { + print_error(vformat("Can't load texture: \"%s\"", String(path.buffer()))); + page.setRendererObject((void *) memnew(SpineRendererObject{nullptr})); + return; + } + + if (textures) textures->append(texture); + auto spine_renderer_object = memnew(SpineRendererObject); + spine_renderer_object->texture = texture; + + String temp_path = fixed_path; + String new_path = vformat("%s/%s_%s", temp_path.get_base_dir(), normal_map_prefix, temp_path.get_file()); + if (ResourceLoader::exists(new_path)) { + Ref normal_map = ResourceLoader::load(new_path); + if (normal_maps) normal_maps->append(normal_map); + spine_renderer_object->normal_map = normal_map; + } + + page.setRendererObject((void *) spine_renderer_object); + + page.width = texture->get_width(); + page.height = texture->get_height(); + } + + virtual void unload(void *p) { + auto spine_renderer_object = (SpineRendererObject *) p; + Ref &texture = spine_renderer_object->texture; + if (texture.is_valid()) texture.unref(); + Ref &normal_map = spine_renderer_object->normal_map; + if (normal_map.is_valid()) normal_map.unref(); + memdelete(spine_renderer_object); + } +}; + +SpineAtlasResource::SpineAtlasResource() : atlas(nullptr), normal_texture_prefix("n") {} + +SpineAtlasResource::~SpineAtlasResource() { + if (atlas) delete atlas; +} + +void SpineAtlasResource::_bind_methods() { + ClassDB::bind_method(D_METHOD("load_from_atlas_file", "path"), &SpineAtlasResource::load_from_atlas_file); + + ClassDB::bind_method(D_METHOD("get_source_path"), &SpineAtlasResource::get_source_path); + + ClassDB::bind_method(D_METHOD("get_textures"), &SpineAtlasResource::get_textures); + ClassDB::bind_method(D_METHOD("get_normal_maps"), &SpineAtlasResource::get_normal_maps); + + ADD_PROPERTY(PropertyInfo(Variant::STRING, "source_path"), "", "get_source_path"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "textures"), "", "get_textures"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "normal_maps"), "", "get_normal_maps"); +} + + +Array SpineAtlasResource::get_textures() { + return textures; +} + +Array SpineAtlasResource::get_normal_maps() { + return normal_maps; +} + +String SpineAtlasResource::get_source_path() { + return source_path; +} + +Error SpineAtlasResource::load_from_atlas_file(const String &p_path) { + source_path = p_path; + Error err; + + atlas_data = FileAccess::get_file_as_string(p_path, &err); + if (err != OK) return err; + + if (atlas) delete atlas; + textures.clear(); + normal_maps.clear(); + atlas = new spine::Atlas(atlas_data.utf8(), atlas_data.size(), source_path.get_base_dir().utf8(), new GodotSpineTextureLoader(&textures, &normal_maps, normal_texture_prefix)); + if (atlas) return OK; + + textures.clear(); + normal_maps.clear(); + return ERR_FILE_UNRECOGNIZED; +} + +Error SpineAtlasResource::load_from_file(const String &p_path) { + Error err; + String json_string = FileAccess::get_file_as_string(p_path, &err); + if (err != OK) return err; + + String error_string; + int error_line; + JSON json; + Variant result; + err = json.parse(json_string, result, error_string, error_line); + if (err != OK) return err; + + Dictionary content = Dictionary(result); + source_path = content["source_path"]; + atlas_data = content["atlas_data"]; + normal_texture_prefix = content["normal_texture_prefix"]; + + if (atlas) delete atlas; + textures.clear(); + normal_maps.clear(); + atlas = new spine::Atlas(atlas_data.utf8(), atlas_data.size(), source_path.get_base_dir().utf8(), new GodotSpineTextureLoader(&textures, &normal_maps, normal_texture_prefix)); + if (atlas) return OK; + + textures.clear(); + normal_maps.clear(); + return ERR_FILE_UNRECOGNIZED; +} + +Error SpineAtlasResource::save_to_file(const String &p_path) { + Error err; + FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &err); + if (err != OK) { + if (file) file->close(); + return err; + } + + Dictionary content; + content["source_path"] = source_path; + content["atlas_data"] = atlas_data; + content["normal_texture_prefix"] = normal_texture_prefix; + + file->store_string(JSON::print(content)); + file->close(); + + return OK; +} + +RES SpineAtlasResourceFormatLoader::load(const String &p_path, const String &p_original_path, Error *r_error) { + Ref atlas = memnew(SpineAtlasResource); + atlas->load_from_file(p_path); + + if (r_error) { + *r_error = OK; + } + return atlas; +} + +void SpineAtlasResourceFormatLoader::get_recognized_extensions(List *r_extensions) const { + const char atlas_ext[] = "spatlas"; + if (!r_extensions->find(atlas_ext)) { + r_extensions->push_back(atlas_ext); + } +} + +String SpineAtlasResourceFormatLoader::get_resource_type(const String &p_path) const { + return "SpineAtlasResource"; +} + +bool SpineAtlasResourceFormatLoader::handles_type(const String &p_type) const { + return p_type == "SpineAtlasResource" || ClassDB::is_parent_class(p_type, "SpineAtlasResource"); +} + +Error SpineAtlasResourceFormatSaver::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { + Ref res = p_resource.get_ref_ptr(); + Error error = res->save_to_file(p_path); + return error; +} + +void SpineAtlasResourceFormatSaver::get_recognized_extensions(const RES &p_resource, List *p_extensions) const { + if (Object::cast_to(*p_resource)) { + p_extensions->push_back("spatlas"); + } +} + +bool SpineAtlasResourceFormatSaver::recognize(const RES &p_resource) const { + return Object::cast_to(*p_resource) != nullptr; +} diff --git a/spine-godot/spine_godot/SpineAtlasResource.h b/spine-godot/spine_godot/SpineAtlasResource.h new file mode 100644 index 000000000..84c7cc9ca --- /dev/null +++ b/spine-godot/spine_godot/SpineAtlasResource.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 GODOT_SPINEATLASRESOURCE_H +#define GODOT_SPINEATLASRESOURCE_H + + +#include "core/variant_parser.h" +#include "core/io/resource_loader.h" +#include "core/io/resource_saver.h" +#include "core/io/image_loader.h" +#include "scene/resources/texture.h" + +#include +#include +#include +#include "SpineRendererObject.h" + +class SpineAtlasResource : public Resource { + GDCLASS(SpineAtlasResource, Resource); + +protected: + static void _bind_methods(); + + spine::Atlas *atlas; + + String source_path; + String atlas_data; + String normal_texture_prefix; + + Array textures; + Array normal_maps; + +public: + inline String &get_atlas_data() { return atlas_data; } + + inline spine::Atlas *get_spine_atlas() { return atlas; } + + inline void set_normal_texture_prefix(const String &p) { normal_texture_prefix = p; } + + Error load_from_atlas_file(const String &p_path);// .atlas + + Error load_from_file(const String &p_path);// .spatlas + Error save_to_file(const String &p_path); // .spatlas + + String get_source_path(); + Array get_textures(); + Array get_normal_maps(); + + SpineAtlasResource(); + virtual ~SpineAtlasResource(); +}; + +class SpineAtlasResourceFormatLoader : public ResourceFormatLoader { +GDCLASS(SpineAtlasResourceFormatLoader, ResourceFormatLoader); + +public: + virtual RES load(const String &p_path, const String &p_original_path, Error *r_error = NULL); + virtual void get_recognized_extensions(List *r_extensions) const; + virtual bool handles_type(const String &p_type) const; + virtual String get_resource_type(const String &p_path) const; +}; + +class SpineAtlasResourceFormatSaver : public ResourceFormatSaver { +GDCLASS(SpineAtlasResourceFormatSaver, ResourceFormatSaver); + +public: + Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0) override; + void get_recognized_extensions(const RES &p_resource, List *p_extensions) const override; + bool recognize(const RES &p_resource) const override; +}; + + +#endif//GODOT_SPINEATLASRESOURCE_H diff --git a/spine-godot/spine_godot/SpineAttachment.cpp b/spine-godot/spine_godot/SpineAttachment.cpp new file mode 100644 index 000000000..e25f54c5e --- /dev/null +++ b/spine-godot/spine_godot/SpineAttachment.cpp @@ -0,0 +1,55 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineAttachment.h" + +void SpineAttachment::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_attachment_name"), &SpineAttachment::get_attachment_name); + ClassDB::bind_method(D_METHOD("copy"), &SpineAttachment::copy); +} + +SpineAttachment::SpineAttachment() : attachment(NULL) {} +SpineAttachment::~SpineAttachment() { + if (attachment) { + attachment->dereference(); + attachment = NULL; + } +} + +String SpineAttachment::get_attachment_name() { + return attachment->getName().buffer(); +} + +Ref SpineAttachment::copy() { + auto a = attachment->copy(); + if (a == NULL) return NULL; + Ref gd_attachment(memnew(SpineAttachment)); + gd_attachment->set_spine_object(a); + return gd_attachment; +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineAttachment.h b/spine-godot/spine_godot/SpineAttachment.h new file mode 100644 index 000000000..81ec52c9d --- /dev/null +++ b/spine-godot/spine_godot/SpineAttachment.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 GODOT_SPINEATTACHMENT_H +#define GODOT_SPINEATTACHMENT_H + +#include "core/variant_parser.h" + +#include + +class SpineAttachment : public Reference { + GDCLASS(SpineAttachment, Reference); + +protected: + static void _bind_methods(); + +private: + spine::Attachment *attachment; + +public: + SpineAttachment(); + ~SpineAttachment(); + + inline void set_spine_object(spine::Attachment *a) { + attachment = a; + if (attachment) + attachment->reference(); + } + inline spine::Attachment *get_spine_object() { + return attachment; + } + + String get_attachment_name(); + + Ref copy(); +}; + +#endif//GODOT_SPINEATTACHMENT_H diff --git a/spine-godot/spine_godot/SpineBone.cpp b/spine-godot/spine_godot/SpineBone.cpp new file mode 100644 index 000000000..afde7a781 --- /dev/null +++ b/spine-godot/spine_godot/SpineBone.cpp @@ -0,0 +1,536 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineBone.h" + +#include "SpineSprite.h" +#include "SpineSkeleton.h" + +void SpineBone::_bind_methods() { + ClassDB::bind_method(D_METHOD("update_world_transform"), &SpineBone::update_world_transform); + // void set_to_setup_pose(); + // + // Vector2 world_to_local(Vector2 world_position); + // + // Vector2 local_to_world(Vector2 local_position); + // + // float world_to_local_rotation(float world_rotation); + // + // float local_to_world_rotation(float local_rotation); + // + // void rotate_world(float degrees); + ClassDB::bind_method(D_METHOD("set_to_setup_pose"), &SpineBone::set_to_setup_pose); + ClassDB::bind_method(D_METHOD("world_to_local", "world_position"), &SpineBone::world_to_local); + ClassDB::bind_method(D_METHOD("local_to_world", "local_position"), &SpineBone::local_to_world); + ClassDB::bind_method(D_METHOD("world_to_local_rotation", "world_rotation"), &SpineBone::world_to_local_rotation); + ClassDB::bind_method(D_METHOD("local_to_world_rotation", "local_rotation"), &SpineBone::local_to_world_rotation); + ClassDB::bind_method(D_METHOD("rotate_world"), &SpineBone::rotate_world); + // + // float get_world_to_local_rotation_x(); + // float get_world_to_local_rotation_y(); + // + // Ref get_data(); + // + // Ref get_skeleton(); + // + // Ref get_parent(); + // + // Array get_children(); + ClassDB::bind_method(D_METHOD("get_world_to_local_rotation_x"), &SpineBone::get_world_to_local_rotation_x); + ClassDB::bind_method(D_METHOD("get_world_to_local_rotation_y"), &SpineBone::get_world_to_local_rotation_y); + ClassDB::bind_method(D_METHOD("get_data"), &SpineBone::get_data); + ClassDB::bind_method(D_METHOD("get_skeleton"), &SpineBone::get_skeleton); + ClassDB::bind_method(D_METHOD("get_parent"), &SpineBone::get_parent); + ClassDB::bind_method(D_METHOD("get_children"), &SpineBone::get_children); + // + // float get_x(); + // void set_x(float v); + // + // float get_y(); + // void set_y(float v); + // + // float get_rotation(); + // void set_rotation(float v); + // + // float get_scale_x(); + // void set_scale_x(float v); + ClassDB::bind_method(D_METHOD("get_x"), &SpineBone::get_x); + ClassDB::bind_method(D_METHOD("set_x", "v"), &SpineBone::set_x); + ClassDB::bind_method(D_METHOD("get_y"), &SpineBone::get_y); + ClassDB::bind_method(D_METHOD("set_y", "v"), &SpineBone::set_y); + ClassDB::bind_method(D_METHOD("get_rotation"), &SpineBone::get_rotation); + ClassDB::bind_method(D_METHOD("set_rotation", "v"), &SpineBone::set_rotation); + ClassDB::bind_method(D_METHOD("get_scale_x"), &SpineBone::get_scale_x); + ClassDB::bind_method(D_METHOD("set_scale_x", "v"), &SpineBone::set_scale_x); + // + // float get_scale_y(); + // void set_scale_y(float v); + // + // float get_shear_x(); + // void set_shear_x(float v); + // + // float get_shear_y(); + // void set_shear_y(float v); + // + // float get_applied_rotation(); + // void set_applied_rotation(float v); + ClassDB::bind_method(D_METHOD("get_scale_y"), &SpineBone::get_scale_y); + ClassDB::bind_method(D_METHOD("set_scale_y", "v"), &SpineBone::set_scale_y); + ClassDB::bind_method(D_METHOD("get_shear_x"), &SpineBone::get_shear_x); + ClassDB::bind_method(D_METHOD("set_shear_x", "v"), &SpineBone::set_shear_x); + ClassDB::bind_method(D_METHOD("get_shear_y"), &SpineBone::get_shear_y); + ClassDB::bind_method(D_METHOD("set_shear_y", "v"), &SpineBone::set_shear_y); + ClassDB::bind_method(D_METHOD("get_applied_rotation"), &SpineBone::get_applied_rotation); + ClassDB::bind_method(D_METHOD("set_applied_rotation", "v"), &SpineBone::set_applied_rotation); + // + // float get_a_x(); + // void set_a_x(float v); + // + // float get_a_y(); + // void set_a_y(float v); + // + // float get_a_scale_x(); + // void set_a_scale_x(float v); + // + // float get_a_scale_y(); + // void set_a_scale_y(float v); + ClassDB::bind_method(D_METHOD("get_a_x"), &SpineBone::get_a_x); + ClassDB::bind_method(D_METHOD("set_a_x", "v"), &SpineBone::set_a_x); + ClassDB::bind_method(D_METHOD("get_a_y"), &SpineBone::get_a_y); + ClassDB::bind_method(D_METHOD("set_a_y", "v"), &SpineBone::set_a_y); + ClassDB::bind_method(D_METHOD("get_a_scale_x"), &SpineBone::get_a_scale_x); + ClassDB::bind_method(D_METHOD("set_a_scale_x", "v"), &SpineBone::set_a_scale_x); + ClassDB::bind_method(D_METHOD("get_a_scale_y"), &SpineBone::get_a_scale_y); + ClassDB::bind_method(D_METHOD("set_a_scale_y", "v"), &SpineBone::set_a_scale_y); + // + // float get_a_shear_x(); + // void set_a_shear_x(float v); + // + // float get_a_shear_y(); + // void set_a_shear_y(float v); + // + // float get_a(); + // void set_a(float v); + // + // float get_b(); + // void set_b(float v); + ClassDB::bind_method(D_METHOD("get_a_shear_x"), &SpineBone::get_a_shear_x); + ClassDB::bind_method(D_METHOD("set_a_shear_x", "v"), &SpineBone::set_a_shear_x); + ClassDB::bind_method(D_METHOD("get_a_shear_y"), &SpineBone::get_a_shear_y); + ClassDB::bind_method(D_METHOD("set_a_shear_y", "v"), &SpineBone::set_a_shear_y); + ClassDB::bind_method(D_METHOD("get_a"), &SpineBone::get_a); + ClassDB::bind_method(D_METHOD("set_a", "v"), &SpineBone::set_a); + ClassDB::bind_method(D_METHOD("get_b"), &SpineBone::get_b); + ClassDB::bind_method(D_METHOD("set_b", "v"), &SpineBone::set_b); + // + // float get_c(); + // void set_c(float v); + // + // float get_d(); + // void set_d(float v); + // + // float get_world_x(); + // void set_world_x(float v); + // + // float get_world_y(); + // void set_world_y(float v); + ClassDB::bind_method(D_METHOD("get_c"), &SpineBone::get_c); + ClassDB::bind_method(D_METHOD("set_c", "v"), &SpineBone::set_c); + ClassDB::bind_method(D_METHOD("get_d"), &SpineBone::get_d); + ClassDB::bind_method(D_METHOD("set_d", "v"), &SpineBone::set_d); + ClassDB::bind_method(D_METHOD("get_world_x"), &SpineBone::get_world_x); + ClassDB::bind_method(D_METHOD("set_world_x", "v"), &SpineBone::set_world_x); + ClassDB::bind_method(D_METHOD("get_world_y"), &SpineBone::get_world_y); + ClassDB::bind_method(D_METHOD("set_world_y", "v"), &SpineBone::set_world_y); + // + // float get_world_rotation_x(); + // float get_world_rotation_y(); + // + // float get_world_scale_x(); + // float get_world_scale_y(); + // + // bool is_applied_valid(); + // void set_applied_valid(bool v); + // + // bool is_active(); + // void set_active(bool v); + ClassDB::bind_method(D_METHOD("get_world_rotation_x"), &SpineBone::get_world_rotation_x); + ClassDB::bind_method(D_METHOD("get_world_rotation_y"), &SpineBone::get_world_rotation_y); + ClassDB::bind_method(D_METHOD("get_world_scale_x"), &SpineBone::get_world_scale_x); + ClassDB::bind_method(D_METHOD("get_world_scale_y"), &SpineBone::get_world_scale_y); + ClassDB::bind_method(D_METHOD("is_active"), &SpineBone::is_active); + ClassDB::bind_method(D_METHOD("set_active", "v"), &SpineBone::set_active); + + ClassDB::bind_method(D_METHOD("get_godot_transform"), &SpineBone::get_godot_transform); + ClassDB::bind_method(D_METHOD("set_godot_transform", "local_transform"), &SpineBone::set_godot_transform); + ClassDB::bind_method(D_METHOD("get_godot_global_transform"), &SpineBone::get_godot_global_transform); + ClassDB::bind_method(D_METHOD("set_godot_global_transform", "global_transform"), &SpineBone::set_godot_global_transform); + + ClassDB::bind_method(D_METHOD("apply_world_transform_2d", "node2d"), &SpineBone::apply_world_transform_2d); +} + +SpineBone::SpineBone() : bone(NULL), the_sprite(nullptr) {} +SpineBone::~SpineBone() {} + +void SpineBone::update_world_transform() { + bone->updateWorldTransform(); +} + +void SpineBone::set_to_setup_pose() { + bone->setToSetupPose(); +} + +Vector2 SpineBone::world_to_local(Vector2 world_position) { + float x, y; + bone->worldToLocal(world_position.x, world_position.y, x, y); + return Vector2(x, y); +} + +Vector2 SpineBone::local_to_world(Vector2 local_position) { + float x, y; + bone->localToWorld(local_position.x, local_position.y, x, y); + return Vector2(x, y); +} + +float SpineBone::world_to_local_rotation(float world_rotation) { + return bone->worldToLocalRotation(world_rotation); +} + +float SpineBone::local_to_world_rotation(float local_rotation) { + return bone->localToWorldRotation(local_rotation); +} + +void SpineBone::rotate_world(float degrees) { + bone->rotateWorld(degrees); +} + +float SpineBone::get_world_to_local_rotation_x() { + return bone->getWorldToLocalRotationX(); +} +float SpineBone::get_world_to_local_rotation_y() { + return bone->getWorldToLocalRotationY(); +} + +Ref SpineBone::get_data() { + auto &bd = bone->getData(); + Ref gd_bd(memnew(SpineBoneData)); + gd_bd->set_spine_object(&bd); + return gd_bd; +} + +Ref SpineBone::get_skeleton() { + auto &s = bone->getSkeleton(); + Ref gd_s(memnew(SpineSkeleton)); + gd_s->set_spine_object(&s); + gd_s->set_spine_sprite(the_sprite); + return gd_s; +} + +Ref SpineBone::get_parent() { + auto b = bone->getParent(); + if (b == NULL) return NULL; + Ref gd_b(memnew(SpineBone)); + gd_b->set_spine_object(b); + gd_b->set_spine_sprite(the_sprite); + return gd_b; +} + +Array SpineBone::get_children() { + auto bs = bone->getChildren(); + Array gd_bs; + gd_bs.resize(bs.size()); + for (size_t i = 0; i < bs.size(); ++i) { + auto b = bs[i]; + if (b == NULL) gd_bs[i] = Ref(NULL); + Ref gd_b(memnew(SpineBone)); + gd_b->set_spine_object(b); + gd_b->set_spine_sprite(the_sprite); + gd_bs[i] = gd_b; + } + return gd_bs; +} + +float SpineBone::get_x() { + return bone->getX(); +} +void SpineBone::set_x(float v) { + bone->setX(v); +} + +float SpineBone::get_y() { + return bone->getY(); +} +void SpineBone::set_y(float v) { + bone->setY(v); +} + +float SpineBone::get_rotation() { + return bone->getRotation(); +} +void SpineBone::set_rotation(float v) { + bone->setRotation(v); +} + +float SpineBone::get_scale_x() { + return bone->getScaleX(); +} +void SpineBone::set_scale_x(float v) { + bone->setScaleX(v); +} + +float SpineBone::get_scale_y() { + return bone->getScaleY(); +} +void SpineBone::set_scale_y(float v) { + bone->setScaleY(v); +} + +float SpineBone::get_shear_x() { + return bone->getShearX(); +} +void SpineBone::set_shear_x(float v) { + bone->setShearX(v); +} + +float SpineBone::get_shear_y() { + return bone->getShearY(); +} +void SpineBone::set_shear_y(float v) { + bone->setShearY(v); +} + +float SpineBone::get_applied_rotation() { + return bone->getAppliedRotation(); +} +void SpineBone::set_applied_rotation(float v) { + bone->setAppliedRotation(v); +} + +float SpineBone::get_a_x() { + return bone->getAX(); +} +void SpineBone::set_a_x(float v) { + bone->setAX(v); +} + +float SpineBone::get_a_y() { + return bone->getAY(); +} +void SpineBone::set_a_y(float v) { + bone->setAY(v); +} + +float SpineBone::get_a_scale_x() { + return bone->getAScaleX(); +} +void SpineBone::set_a_scale_x(float v) { + bone->setAScaleX(v); +} + +float SpineBone::get_a_scale_y() { + return bone->getAScaleY(); +} +void SpineBone::set_a_scale_y(float v) { + bone->setAScaleY(v); +} + +float SpineBone::get_a_shear_x() { + return bone->getAShearX(); +} +void SpineBone::set_a_shear_x(float v) { + bone->setAShearX(v); +} + +float SpineBone::get_a_shear_y() { + return bone->getAShearY(); +} +void SpineBone::set_a_shear_y(float v) { + bone->setAShearY(v); +} + +float SpineBone::get_a() { + return bone->getA(); +} +void SpineBone::set_a(float v) { + bone->setA(v); +} + +float SpineBone::get_b() { + return bone->getB(); +} +void SpineBone::set_b(float v) { + bone->setB(v); +} + +float SpineBone::get_c() { + return bone->getC(); +} +void SpineBone::set_c(float v) { + bone->setC(v); +} + +float SpineBone::get_d() { + return bone->getD(); +} +void SpineBone::set_d(float v) { + bone->setD(v); +} + +float SpineBone::get_world_x() { + return bone->getWorldX(); +} +void SpineBone::set_world_x(float v) { + bone->setWorldX(v); +} + +float SpineBone::get_world_y() { + return bone->getWorldY(); +} +void SpineBone::set_world_y(float v) { + bone->setWorldY(v); +} + +float SpineBone::get_world_rotation_x() { + return bone->getWorldRotationX(); +} +float SpineBone::get_world_rotation_y() { + return bone->getWorldRotationY(); +} + +float SpineBone::get_world_scale_x() { + return bone->getWorldScaleX(); +} +float SpineBone::get_world_scale_y() { + return bone->getWorldScaleY(); +} + +bool SpineBone::is_active() { + return bone->isActive(); +} +void SpineBone::set_active(bool v) { + bone->setActive(v); +} + +// External feature functions +void SpineBone::apply_world_transform_2d(Variant o) { + if (o.get_type() == Variant::OBJECT) { + auto node = (Node *) o; + if (node->is_class("Node2D")) { + auto node2d = (Node2D *) node; + // In godot the y-axis is nag to spine + node2d->set_transform(Transform2D( + get_a(), get_c(), + get_b(), get_d(), + get_world_x(), -get_world_y())); + // Fix the rotation + auto pos = node2d->get_position(); + node2d->translate(-pos); + node2d->set_rotation(-node2d->get_rotation()); + node2d->translate(pos); + } + } +} + +Transform2D SpineBone::get_godot_transform() { + if (get_spine_object() == nullptr) + return Transform2D(); + Transform2D trans; + trans.translate(get_x(), -get_y()); + // It seems that spine uses degree for rotation + trans.rotate(Math::deg2rad(-get_rotation())); + trans.scale(Size2(get_scale_x(), get_scale_y())); + return trans; +} + +void SpineBone::set_godot_transform(Transform2D trans) { + if (get_spine_object() == nullptr) + return; + Vector2 position = trans.get_origin(); + position.y *= -1; + real_t rotation = trans.get_rotation(); + rotation = Math::rad2deg(-rotation); + Vector2 scale = trans.get_scale(); + + set_x(position.x); + set_y(position.y); + set_rotation(rotation); + set_scale_x(scale.x); + set_scale_y(scale.y); +} + +Transform2D SpineBone::get_godot_global_transform() { + if (get_spine_object() == nullptr) + return Transform2D(); + if (the_sprite == nullptr) + return get_godot_transform(); + Transform2D res = the_sprite->get_transform(); + res.translate(get_world_x(), -get_world_y()); + res.rotate(Math::deg2rad(-get_world_rotation_x())); + res.scale(Vector2(get_world_scale_x(), get_world_scale_y())); + auto p = the_sprite->get_parent() ? Object::cast_to(the_sprite->get_parent()) : nullptr; + if (p) { + return p->get_global_transform() * res; + } + return res; +} + +void SpineBone::set_godot_global_transform(Transform2D transform) { + if (get_spine_object() == nullptr) + return; + if (the_sprite == nullptr) + set_godot_transform(transform); + transform = the_sprite->get_global_transform().affine_inverse() * transform; + Vector2 position = transform.get_origin(); + real_t rotation = transform.get_rotation(); + Vector2 scale = transform.get_scale(); + position.y *= -1; + auto parent = get_parent(); + if (parent.is_valid()) { + position = parent->world_to_local(position); + if (parent->get_world_scale_x() != 0) + scale.x /= parent->get_world_scale_x(); + else + print_error("The parent scale.x is zero."); + if (parent->get_world_scale_y() != 0) + scale.y /= parent->get_world_scale_y(); + else + print_error("The parent scale.y is zero."); + } + rotation = world_to_local_rotation(Math::rad2deg(-rotation)); + + set_x(position.x); + set_y(position.y); + set_rotation(rotation); + set_scale_x(scale.x); + set_scale_y(scale.y); +} + +void SpineBone::set_spine_sprite(SpineSprite *s) { + the_sprite = s; +} diff --git a/spine-godot/spine_godot/SpineBone.h b/spine-godot/spine_godot/SpineBone.h new file mode 100644 index 000000000..b7efd1381 --- /dev/null +++ b/spine-godot/spine_godot/SpineBone.h @@ -0,0 +1,175 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef GODOT_SPINEBONE_H +#define GODOT_SPINEBONE_H + +#include "core/variant_parser.h" +#include + +#include +#include + +#include "SpineBoneData.h" +#include "SpineIkConstraint.h" +#include "SpinePathConstraint.h" +#include "SpineTransformConstraint.h" + +class SpineSkeleton; +class SpineSprite; + +class SpineBone : public Reference { + GDCLASS(SpineBone, Reference); + +protected: + static void _bind_methods(); + +private: + spine::Bone *bone; + + SpineSprite *the_sprite; + +public: + SpineBone(); + ~SpineBone(); + + inline void set_spine_object(spine::Bone *b) { + bone = b; + } + inline spine::Bone *get_spine_object() { + return bone; + } + + void set_spine_sprite(SpineSprite *s); + + void update_world_transform(); + + void set_to_setup_pose(); + + Vector2 world_to_local(Vector2 world_position); + + Vector2 local_to_world(Vector2 local_position); + + float world_to_local_rotation(float world_rotation); + + float local_to_world_rotation(float local_rotation); + + void rotate_world(float degrees); + + float get_world_to_local_rotation_x(); + float get_world_to_local_rotation_y(); + + Ref get_data(); + + Ref get_skeleton(); + + Ref get_parent(); + + Array get_children(); + + float get_x(); + void set_x(float v); + + float get_y(); + void set_y(float v); + + float get_rotation(); + void set_rotation(float v); + + float get_scale_x(); + void set_scale_x(float v); + + float get_scale_y(); + void set_scale_y(float v); + + float get_shear_x(); + void set_shear_x(float v); + + float get_shear_y(); + void set_shear_y(float v); + + float get_applied_rotation(); + void set_applied_rotation(float v); + + float get_a_x(); + void set_a_x(float v); + + float get_a_y(); + void set_a_y(float v); + + float get_a_scale_x(); + void set_a_scale_x(float v); + + float get_a_scale_y(); + void set_a_scale_y(float v); + + float get_a_shear_x(); + void set_a_shear_x(float v); + + float get_a_shear_y(); + void set_a_shear_y(float v); + + float get_a(); + void set_a(float v); + + float get_b(); + void set_b(float v); + + float get_c(); + void set_c(float v); + + float get_d(); + void set_d(float v); + + float get_world_x(); + void set_world_x(float v); + + float get_world_y(); + void set_world_y(float v); + + float get_world_rotation_x(); + float get_world_rotation_y(); + + float get_world_scale_x(); + float get_world_scale_y(); + + bool is_active(); + void set_active(bool v); + + // External feature functions + void apply_world_transform_2d(Variant o); + + Transform2D get_godot_transform(); + void set_godot_transform(Transform2D trans); + + Transform2D get_godot_global_transform(); + void set_godot_global_transform(Transform2D trans); +}; + +#endif//GODOT_SPINEBONE_H diff --git a/spine-godot/spine_godot/SpineBoneData.cpp b/spine-godot/spine_godot/SpineBoneData.cpp new file mode 100644 index 000000000..b870527dc --- /dev/null +++ b/spine-godot/spine_godot/SpineBoneData.cpp @@ -0,0 +1,163 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineBoneData.h" + +void SpineBoneData::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_index"), &SpineBoneData::get_index); + ClassDB::bind_method(D_METHOD("get_bone_name"), &SpineBoneData::get_bone_name); + ClassDB::bind_method(D_METHOD("get_parent"), &SpineBoneData::get_parent); + + ClassDB::bind_method(D_METHOD("get_length"), &SpineBoneData::get_length); + ClassDB::bind_method(D_METHOD("set_length", "v"), &SpineBoneData::set_length); + + ClassDB::bind_method(D_METHOD("get_x"), &SpineBoneData::get_x); + ClassDB::bind_method(D_METHOD("set_x", "v"), &SpineBoneData::set_x); + + ClassDB::bind_method(D_METHOD("get_y"), &SpineBoneData::get_y); + ClassDB::bind_method(D_METHOD("set_y", "v"), &SpineBoneData::set_y); + + ClassDB::bind_method(D_METHOD("get_rotation"), &SpineBoneData::get_rotation); + ClassDB::bind_method(D_METHOD("set_rotation", "v"), &SpineBoneData::set_rotation); + + ClassDB::bind_method(D_METHOD("get_scale_x"), &SpineBoneData::get_scale_x); + ClassDB::bind_method(D_METHOD("set_scale_x", "v"), &SpineBoneData::set_scale_x); + + ClassDB::bind_method(D_METHOD("get_scale_y"), &SpineBoneData::get_scale_y); + ClassDB::bind_method(D_METHOD("set_scale_y", "v"), &SpineBoneData::set_scale_y); + + ClassDB::bind_method(D_METHOD("get_shear_x"), &SpineBoneData::get_shear_x); + ClassDB::bind_method(D_METHOD("set_shear_x", "v"), &SpineBoneData::set_shear_x); + + ClassDB::bind_method(D_METHOD("get_shear_y"), &SpineBoneData::get_shear_y); + ClassDB::bind_method(D_METHOD("set_shear_y", "v"), &SpineBoneData::set_shear_y); + + ClassDB::bind_method(D_METHOD("get_transform_mode"), &SpineBoneData::get_transform_mode); + ClassDB::bind_method(D_METHOD("set_transform_mode", "v"), &SpineBoneData::set_transform_mode); + + ClassDB::bind_method(D_METHOD("is_skin_required"), &SpineBoneData::is_skin_required); + ClassDB::bind_method(D_METHOD("set_skin_required", "v"), &SpineBoneData::set_skin_required); + + BIND_ENUM_CONSTANT(TRANSFORMMODE_NORMAL); + BIND_ENUM_CONSTANT(TRANSFORMMODE_ONLYTRANSLATION); + BIND_ENUM_CONSTANT(TRANSFORMMODE_NOROTATIONORREFLECTION); + BIND_ENUM_CONSTANT(TRANSFORMMODE_NOSCALE); + BIND_ENUM_CONSTANT(TRANSFORMMODE_NOSCALEORREFLECTION); +} + +SpineBoneData::SpineBoneData() : bone_data(NULL) {} +SpineBoneData::~SpineBoneData() {} + +int SpineBoneData::get_index() { + return bone_data->getIndex(); +} + +String SpineBoneData::get_bone_name() { + return bone_data->getName().buffer(); +} + +Ref SpineBoneData::get_parent() { + auto p = bone_data->getParent(); + if (p == NULL) return NULL; + Ref gd_bone_data(memnew(SpineBoneData)); + gd_bone_data->set_spine_object(p); + return gd_bone_data; +} + +float SpineBoneData::get_length() { + return bone_data->getLength(); +} +void SpineBoneData::set_length(float v) { + bone_data->setLength(v); +} + +float SpineBoneData::get_x() { + return bone_data->getX(); +} +void SpineBoneData::set_x(float v) { + bone_data->setX(v); +} + +float SpineBoneData::get_y() { + return bone_data->getY(); +} +void SpineBoneData::set_y(float v) { + bone_data->setY(v); +} + +float SpineBoneData::get_rotation() { + return bone_data->getRotation(); +} +void SpineBoneData::set_rotation(float v) { + bone_data->setRotation(v); +} + +float SpineBoneData::get_scale_x() { + return bone_data->getScaleX(); +} +void SpineBoneData::set_scale_x(float v) { + bone_data->setScaleX(v); +} + +float SpineBoneData::get_scale_y() { + return bone_data->getScaleY(); +} +void SpineBoneData::set_scale_y(float v) { + bone_data->setScaleY(v); +} + +float SpineBoneData::get_shear_x() { + return bone_data->getShearX(); +} +void SpineBoneData::set_shear_x(float v) { + bone_data->setShearX(v); +} + +float SpineBoneData::get_shear_y() { + return bone_data->getShearY(); +} +void SpineBoneData::set_shear_y(float v) { + bone_data->setShearY(v); +} + +SpineBoneData::TransformMode SpineBoneData::get_transform_mode() { + auto tm = (int) bone_data->getTransformMode(); + return (TransformMode) tm; +} +void SpineBoneData::set_transform_mode(TransformMode v) { + auto tm = (int) v; + bone_data->setTransformMode((spine::TransformMode) tm); +} + +bool SpineBoneData::is_skin_required() { + return bone_data->isSkinRequired(); +} +void SpineBoneData::set_skin_required(bool v) { + bone_data->setSkinRequired(v); +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineBoneData.h b/spine-godot/spine_godot/SpineBoneData.h new file mode 100644 index 000000000..dc3e3feb6 --- /dev/null +++ b/spine-godot/spine_godot/SpineBoneData.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 GODOT_SPINEBONEDATA_H +#define GODOT_SPINEBONEDATA_H + +#include "core/variant_parser.h" + +#include + +class SpineBoneData : public Reference { + GDCLASS(SpineBoneData, Reference); + +protected: + static void _bind_methods(); + +private: + spine::BoneData *bone_data; + +public: + SpineBoneData(); + ~SpineBoneData(); + + inline void set_spine_object(spine::BoneData *b) { + bone_data = b; + } + inline spine::BoneData *get_spine_object() { + return bone_data; + } + + enum TransformMode { + TRANSFORMMODE_NORMAL = 0, + TRANSFORMMODE_ONLYTRANSLATION, + TRANSFORMMODE_NOROTATIONORREFLECTION, + TRANSFORMMODE_NOSCALE, + TRANSFORMMODE_NOSCALEORREFLECTION + }; + + int get_index(); + + String get_bone_name(); + + Ref get_parent(); + + float get_length(); + void set_length(float v); + + float get_x(); + void set_x(float v); + + float get_y(); + void set_y(float v); + + float get_rotation(); + void set_rotation(float v); + + float get_scale_x(); + void set_scale_x(float v); + + float get_scale_y(); + void set_scale_y(float v); + + float get_shear_x(); + void set_shear_x(float v); + + float get_shear_y(); + void set_shear_y(float v); + + TransformMode get_transform_mode(); + void set_transform_mode(TransformMode v); + + bool is_skin_required(); + void set_skin_required(bool v); +}; + +VARIANT_ENUM_CAST(SpineBoneData::TransformMode); +#endif//GODOT_SPINEBONEDATA_H diff --git a/spine-godot/spine_godot/SpineCollisionShapeProxy.cpp b/spine-godot/spine_godot/SpineCollisionShapeProxy.cpp new file mode 100644 index 000000000..9015db60d --- /dev/null +++ b/spine-godot/spine_godot/SpineCollisionShapeProxy.cpp @@ -0,0 +1,196 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineCollisionShapeProxy.h" + +#include "SpineSprite.h" + +void SpineCollisionShapeProxy::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_spine_sprite_path"), &SpineCollisionShapeProxy::get_spine_sprite_path); + ClassDB::bind_method(D_METHOD("set_spine_sprite_path", "v"), &SpineCollisionShapeProxy::set_spine_sprite_path); + + ClassDB::bind_method(D_METHOD("get_slot"), &SpineCollisionShapeProxy::get_slot); + ClassDB::bind_method(D_METHOD("set_slot", "v"), &SpineCollisionShapeProxy::set_slot); + + ClassDB::bind_method(D_METHOD("get_sync_transform"), &SpineCollisionShapeProxy::get_sync_transform); + ClassDB::bind_method(D_METHOD("set_sync_transform", "v"), &SpineCollisionShapeProxy::set_sync_transform); + + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "spine_sprite_path"), "set_spine_sprite_path", "get_spine_sprite_path"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync_transform"), "set_sync_transform", "get_sync_transform"); +} + +SpineCollisionShapeProxy::SpineCollisionShapeProxy() : sync_transform(true) { +} + +SpineCollisionShapeProxy::~SpineCollisionShapeProxy() { +} + +void SpineCollisionShapeProxy::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_READY: { + set_process_internal(true); + } break; + case NOTIFICATION_INTERNAL_PROCESS: { + if (!disabled) { + if (sync_transform) _sync_transform(get_spine_sprite()); + _update_polygon_from_spine_sprite(get_spine_sprite()); + if (is_visible()) update(); + } + } break; + } +} + +SpineSprite *SpineCollisionShapeProxy::get_spine_sprite() const { + return (SpineSprite *) get_node_or_null(spine_sprite_path); +} + +NodePath SpineCollisionShapeProxy::get_spine_sprite_path() { + return spine_sprite_path; +} + +void SpineCollisionShapeProxy::set_spine_sprite_path(NodePath v) { + spine_sprite_path = v; + + _update_polygon_from_spine_sprite(get_spine_sprite()); +} + +String SpineCollisionShapeProxy::get_slot() const { + return slot; +} + +void SpineCollisionShapeProxy::set_slot(const String &v) { + slot = v; + _update_polygon_from_spine_sprite(get_spine_sprite()); +} + +void SpineCollisionShapeProxy::_update_polygon_from_spine_sprite(SpineSprite *sprite) { + _clear_polygon(); + if (sprite == nullptr || slot.empty()) { + return; + } + + if (!sprite->get_skeleton().is_valid()) { + return; + } + + auto sk = sprite->get_skeleton()->get_spine_object(); + + spine::Vector vertices; + + spine::Slot *s = sk->findSlot(spine::String(slot.utf8())); + if (!s) { + return; + } + spine::Attachment *attachment = s->getAttachment(); + if (!attachment) { + return; + } + + if (attachment->getRTTI().isExactly(spine::BoundingBoxAttachment::rtti)) { + auto *box = (spine::BoundingBoxAttachment *) attachment; + + vertices.setSize(box->getWorldVerticesLength(), 0); + box->computeWorldVertices(*s, vertices); + } else { + return; + } + + polygon.resize(vertices.size() / 2); + for (size_t j = 0; j < vertices.size(); j += 2) { + polygon.set(j / 2, Vector2(vertices[j], -vertices[j + 1])); + } + + set_polygon(polygon); +} + +void SpineCollisionShapeProxy::_clear_polygon() { + polygon.clear(); + set_polygon(polygon); +} + +void SpineCollisionShapeProxy::_sync_transform(SpineSprite *sprite) { + if (sprite == nullptr) return; + set_global_transform(sprite->get_global_transform()); +} + +bool SpineCollisionShapeProxy::get_sync_transform() { + return sync_transform; +} + +void SpineCollisionShapeProxy::set_sync_transform(bool v) { + sync_transform = v; +} + +void SpineCollisionShapeProxy::_get_property_list(List *p_list) const { + PropertyInfo p; + Vector res; + + p.name = "slot"; + p.type = Variant::STRING; + _get_slot_list(res); + if (res.empty()) res.push_back("No Slot"); + p.hint_string = String(",").join(res); + p.hint = PROPERTY_HINT_ENUM; + p_list->push_back(p); +} + +bool SpineCollisionShapeProxy::_get(const StringName &p_property, Variant &r_value) const { + if (p_property == "slot") { + r_value = get_slot(); + return true; + } + return false; +} + +bool SpineCollisionShapeProxy::_set(const StringName &p_property, const Variant &p_value) { + if (p_property == "slot") { + set_slot(p_value); + return true; + } + return false; +} + +void SpineCollisionShapeProxy::_get_slot_list(Vector &res) const { + if (get_spine_sprite() == nullptr) { + return; + } + + auto sprite = get_spine_sprite(); + if (!sprite->get_skeleton().is_valid()) { + return; + } + + auto slots = sprite->get_skeleton()->get_slots(); + res.resize(slots.size()); + for (size_t i = 0; i < res.size(); ++i) { + auto slot = (Ref) slots[i]; + if (slot.is_valid()) + res.set(i, slot->get_data()->get_slot_name()); + } +} diff --git a/spine-godot/spine_godot/SpineCollisionShapeProxy.h b/spine-godot/spine_godot/SpineCollisionShapeProxy.h new file mode 100644 index 000000000..c29eaa591 --- /dev/null +++ b/spine-godot/spine_godot/SpineCollisionShapeProxy.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 GODOT_SPINECOLLISIONSHAPEPROXY_H +#define GODOT_SPINECOLLISIONSHAPEPROXY_H + +#include "scene/2d/collision_polygon_2d.h" + +class SpineSprite; +class SpineAnimationState; +class SpineSkeleton; + +class SpineCollisionShapeProxy : public CollisionPolygon2D { + GDCLASS(SpineCollisionShapeProxy, CollisionPolygon2D) +protected: + static void _bind_methods(); + + NodePath spine_sprite_path; + + String slot; + + bool sync_transform; + +protected: + void _notification(int p_what); + void _get_property_list(List *p_list) const; + bool _get(const StringName &p_property, Variant &r_value) const; + bool _set(const StringName &p_property, const Variant &p_value); + + + SpineSprite *get_spine_sprite() const; + + void _update_polygon_from_spine_sprite(SpineSprite *sprite); + void _clear_polygon(); + void _sync_transform(SpineSprite *sprite); + + void _get_slot_list(Vector &res) const; + +public: + SpineCollisionShapeProxy(); + ~SpineCollisionShapeProxy(); + + NodePath get_spine_sprite_path(); + void set_spine_sprite_path(NodePath v); + + String get_slot() const; + void set_slot(const String &v); + + bool get_sync_transform(); + void set_sync_transform(bool v); +}; + + +#endif//GODOT_SPINECOLLISIONSHAPEPROXY_H diff --git a/spine-godot/spine_godot/SpineConstant.cpp b/spine-godot/spine_godot/SpineConstant.cpp new file mode 100644 index 000000000..760ff668a --- /dev/null +++ b/spine-godot/spine_godot/SpineConstant.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. + *****************************************************************************/ + +#include "SpineConstant.h" + +void SpineConstant::_bind_methods() { + BIND_ENUM_CONSTANT(MixBlend_Setup); + BIND_ENUM_CONSTANT(MixBlend_First); + BIND_ENUM_CONSTANT(MixBlend_Replace); + BIND_ENUM_CONSTANT(MixBlend_Add); + + BIND_ENUM_CONSTANT(MixDirection_In); + BIND_ENUM_CONSTANT(MixDirection_Out); + + BIND_ENUM_CONSTANT(Property_Rotate); + BIND_ENUM_CONSTANT(Property_X); + BIND_ENUM_CONSTANT(Property_Y); + BIND_ENUM_CONSTANT(Property_ScaleX); + BIND_ENUM_CONSTANT(Property_ScaleY); + BIND_ENUM_CONSTANT(Property_ShearX); + BIND_ENUM_CONSTANT(Property_ShearY); + BIND_ENUM_CONSTANT(Property_Rgb); + BIND_ENUM_CONSTANT(Property_Alpha); + BIND_ENUM_CONSTANT(Property_Rgb2); + BIND_ENUM_CONSTANT(Property_Attachment); + BIND_ENUM_CONSTANT(Property_Deform); + BIND_ENUM_CONSTANT(Property_Event); + BIND_ENUM_CONSTANT(Property_DrawOrder); + BIND_ENUM_CONSTANT(Property_IkConstraint); + BIND_ENUM_CONSTANT(Property_TransformConstraint); + BIND_ENUM_CONSTANT(Property_PathConstraintPosition); + BIND_ENUM_CONSTANT(Property_PathConstraintSpacing); + BIND_ENUM_CONSTANT(Property_PathConstraintMix); +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineConstant.h b/spine-godot/spine_godot/SpineConstant.h new file mode 100644 index 000000000..c7f86d8b9 --- /dev/null +++ b/spine-godot/spine_godot/SpineConstant.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 GODOT_SPINECONSTANT_H +#define GODOT_SPINECONSTANT_H + +#include "core/variant_parser.h" + +class SpineConstant : public Object { + GDCLASS(SpineConstant, Object); + +protected: + static void _bind_methods(); + +public: + enum MixBlend { + MixBlend_Setup = 0, + MixBlend_First, + MixBlend_Replace, + MixBlend_Add + }; + + enum MixDirection { + MixDirection_In = 0, + MixDirection_Out + }; + + enum PropertyId { + 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 + }; +}; + +VARIANT_ENUM_CAST(SpineConstant::MixBlend); +VARIANT_ENUM_CAST(SpineConstant::MixDirection); +VARIANT_ENUM_CAST(SpineConstant::PropertyId); + +#endif//GODOT_SPINECONSTANT_H diff --git a/spine-godot/spine_godot/SpineConstraintData.cpp b/spine-godot/spine_godot/SpineConstraintData.cpp new file mode 100644 index 000000000..16bbac435 --- /dev/null +++ b/spine-godot/spine_godot/SpineConstraintData.cpp @@ -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. + *****************************************************************************/ + +#include "SpineConstraintData.h" + +void SpineConstraintData::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_constraint_data_name"), &SpineConstraintData::get_constraint_data_name); + ClassDB::bind_method(D_METHOD("get_order"), &SpineConstraintData::get_order); + ClassDB::bind_method(D_METHOD("set_order", "v"), &SpineConstraintData::set_order); + ClassDB::bind_method(D_METHOD("is_skin_required"), &SpineConstraintData::is_skin_required); + ClassDB::bind_method(D_METHOD("set_skin_required", "v"), &SpineConstraintData::set_skin_required); +} + +SpineConstraintData::SpineConstraintData() : constraint_data(NULL) {} +SpineConstraintData::~SpineConstraintData() {} + +String SpineConstraintData::get_constraint_data_name() { + return constraint_data->getName().buffer(); +} + +uint64_t SpineConstraintData::get_order() { + return constraint_data->getOrder(); +} +void SpineConstraintData::set_order(uint64_t v) { + constraint_data->setOrder(v); +} + +bool SpineConstraintData::is_skin_required() { + return constraint_data->isSkinRequired(); +} +void SpineConstraintData::set_skin_required(bool v) { + constraint_data->setSkinRequired(v); +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineConstraintData.h b/spine-godot/spine_godot/SpineConstraintData.h new file mode 100644 index 000000000..35b9dd52a --- /dev/null +++ b/spine-godot/spine_godot/SpineConstraintData.h @@ -0,0 +1,66 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef GODOT_SPINECONSTRAINTDATA_H +#define GODOT_SPINECONSTRAINTDATA_H + +#include "core/variant_parser.h" + +#include + +class SpineConstraintData : public Reference { + GDCLASS(SpineConstraintData, Reference); + +protected: + static void _bind_methods(); + +private: + spine::ConstraintData *constraint_data; + +public: + SpineConstraintData(); + ~SpineConstraintData(); + + inline void set_spine_object(spine::ConstraintData *c) { + constraint_data = c; + } + virtual inline spine::ConstraintData *get_spine_object() { + return constraint_data; + } + + String get_constraint_data_name(); + + uint64_t get_order(); + void set_order(uint64_t v); + + bool is_skin_required(); + void set_skin_required(bool v); +}; + +#endif//GODOT_SPINECONSTRAINTDATA_H diff --git a/spine-godot/spine_godot/SpineEvent.cpp b/spine-godot/spine_godot/SpineEvent.cpp new file mode 100644 index 000000000..9d753db33 --- /dev/null +++ b/spine-godot/spine_godot/SpineEvent.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. + *****************************************************************************/ + +#include "SpineEvent.h" + +void SpineEvent::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_data"), &SpineEvent::get_data); + ClassDB::bind_method(D_METHOD("get_event_name"), &SpineEvent::get_event_name); + ClassDB::bind_method(D_METHOD("get_time"), &SpineEvent::get_time); + ClassDB::bind_method(D_METHOD("get_int_value"), &SpineEvent::get_int_value); + ClassDB::bind_method(D_METHOD("set_int_value", "v"), &SpineEvent::set_int_value); + ClassDB::bind_method(D_METHOD("get_float_value"), &SpineEvent::get_float_value); + ClassDB::bind_method(D_METHOD("set_float_value", "v"), &SpineEvent::set_float_value); + ClassDB::bind_method(D_METHOD("get_string_value"), &SpineEvent::get_string_value); + ClassDB::bind_method(D_METHOD("set_string_value", "v"), &SpineEvent::set_string_value); + ClassDB::bind_method(D_METHOD("get_volume"), &SpineEvent::get_volume); + ClassDB::bind_method(D_METHOD("set_volume", "v"), &SpineEvent::set_volume); + ClassDB::bind_method(D_METHOD("get_balance"), &SpineEvent::get_balance); + ClassDB::bind_method(D_METHOD("set_balance", "v"), &SpineEvent::set_balance); + // + // BIND_ENUM_CONSTANT(EVENTTYPE_START); + // BIND_ENUM_CONSTANT(EVENTTYPE_INTERRUPT); + // BIND_ENUM_CONSTANT(EVENTTYPE_END); + // BIND_ENUM_CONSTANT(EVENTTYPE_COMPLETE); + // BIND_ENUM_CONSTANT(EVENTTYPE_DISPOSE); + // BIND_ENUM_CONSTANT(EVENTTYPE_EVENT); +} + +SpineEvent::SpineEvent() : event(NULL) {} +SpineEvent::~SpineEvent() {} + +Ref SpineEvent::get_data() { + Ref event_data(memnew(SpineEventData)); + event_data->set_spine_object(&(event->getData())); + return event_data; +} + +String SpineEvent::get_event_name() { + return event->getData().getName().buffer(); +} + +float SpineEvent::get_time() { + return event->getTime(); +} + +int SpineEvent::get_int_value() { + return event->getIntValue(); +} + +void SpineEvent::set_int_value(int v) { + event->setIntValue(v); +} + +float SpineEvent::get_float_value() { + return event->getFloatValue(); +} + +void SpineEvent::set_float_value(float v) { + event->setFloatValue(v); +} + +String SpineEvent::get_string_value() { + return event->getStringValue().buffer(); +} + +void SpineEvent::set_string_value(const String &v) { + event->setStringValue(spine::String(v.utf8())); +} + +float SpineEvent::get_volume() { + return event->getVolume(); +} + +void SpineEvent::set_volume(float v) { + event->setVolume(v); +} + +float SpineEvent::get_balance() { + return event->getBalance(); +} + +void SpineEvent::set_balance(float v) { + event->setBalance(v); +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineEvent.h b/spine-godot/spine_godot/SpineEvent.h new file mode 100644 index 000000000..bbbf0b986 --- /dev/null +++ b/spine-godot/spine_godot/SpineEvent.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 GODOT_SPINEEVENT_H +#define GODOT_SPINEEVENT_H + +#include "core/variant_parser.h" + +#include + +#include "SpineEventData.h" + +class SpineEvent : public Reference { + GDCLASS(SpineEvent, Reference); + +protected: + static void _bind_methods(); + +private: + spine::Event *event; + +public: + SpineEvent(); + ~SpineEvent(); + + inline void set_spine_object(spine::Event *e) { + event = e; + } + inline spine::Event *get_spine_object() const { + return event; + } + + enum EventType { + EVENTTYPE_START = spine::EventType_Start, + EVENTTYPE_INTERRUPT = spine::EventType_Interrupt, + EVENTTYPE_END = spine::EventType_End, + EVENTTYPE_COMPLETE = spine::EventType_Complete, + EVENTTYPE_DISPOSE = spine::EventType_Dispose, + EVENTTYPE_EVENT = spine::EventType_Event + }; + + + Ref get_data(); + + String get_event_name(); + + float get_time(); + + int get_int_value(); + void set_int_value(int inValue); + + float get_float_value(); + void set_float_value(float inValue); + + String get_string_value(); + void set_string_value(const String &inValue); + + float get_volume(); + void set_volume(float inValue); + + float get_balance(); + void set_balance(float inValue); +}; + +#endif//GODOT_SPINEEVENT_H diff --git a/spine-godot/spine_godot/SpineEventData.cpp b/spine-godot/spine_godot/SpineEventData.cpp new file mode 100644 index 000000000..bca195e79 --- /dev/null +++ b/spine-godot/spine_godot/SpineEventData.cpp @@ -0,0 +1,36 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineEventData.h" + +void SpineEventData::_bind_methods() { +} + +SpineEventData::SpineEventData() : event_data(NULL) {} +SpineEventData::~SpineEventData() {} diff --git a/spine-godot/spine_godot/SpineEventData.h b/spine-godot/spine_godot/SpineEventData.h new file mode 100644 index 000000000..1cf669f26 --- /dev/null +++ b/spine-godot/spine_godot/SpineEventData.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 GODOT_SPINEEVENTDATA_H +#define GODOT_SPINEEVENTDATA_H + +#include "core/variant_parser.h" + +#include + +class SpineEventData : public Reference { + GDCLASS(SpineEventData, Reference); + +protected: + static void _bind_methods(); + +private: + const spine::EventData *event_data; + +public: + SpineEventData(); + ~SpineEventData(); + + inline void set_spine_object(const spine::EventData *e) { + event_data = e; + } + inline const spine::EventData *get_spine_object() { + return event_data; + } +}; + +#endif//GODOT_SPINEEVENTDATA_H diff --git a/spine-godot/spine_godot/SpineIkConstraint.cpp b/spine-godot/spine_godot/SpineIkConstraint.cpp new file mode 100644 index 000000000..d88492b48 --- /dev/null +++ b/spine-godot/spine_godot/SpineIkConstraint.cpp @@ -0,0 +1,146 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineIkConstraint.h" +#include "SpineBone.h" + +void SpineIkConstraint::_bind_methods() { + // ClassDB::bind_method(D_METHOD("apply"), &SpineIkConstraint::apply); + ClassDB::bind_method(D_METHOD("update"), &SpineIkConstraint::update); + ClassDB::bind_method(D_METHOD("get_order"), &SpineIkConstraint::get_order); + ClassDB::bind_method(D_METHOD("get_data"), &SpineIkConstraint::get_data); + ClassDB::bind_method(D_METHOD("get_bones"), &SpineIkConstraint::get_bones); + ClassDB::bind_method(D_METHOD("get_target"), &SpineIkConstraint::get_target); + ClassDB::bind_method(D_METHOD("set_target", "v"), &SpineIkConstraint::set_target); + ClassDB::bind_method(D_METHOD("get_bend_direction"), &SpineIkConstraint::get_bend_direction); + ClassDB::bind_method(D_METHOD("set_bend_direction", "v"), &SpineIkConstraint::set_bend_direction); + ClassDB::bind_method(D_METHOD("get_compress"), &SpineIkConstraint::get_compress); + ClassDB::bind_method(D_METHOD("set_compress", "v"), &SpineIkConstraint::set_compress); + ClassDB::bind_method(D_METHOD("get_stretch"), &SpineIkConstraint::get_stretch); + ClassDB::bind_method(D_METHOD("set_stretch", "v"), &SpineIkConstraint::set_stretch); + ClassDB::bind_method(D_METHOD("get_mix"), &SpineIkConstraint::get_mix); + ClassDB::bind_method(D_METHOD("set_mix", "v"), &SpineIkConstraint::set_mix); + ClassDB::bind_method(D_METHOD("get_softness"), &SpineIkConstraint::get_softness); + ClassDB::bind_method(D_METHOD("set_softness", "v"), &SpineIkConstraint::set_softness); + ClassDB::bind_method(D_METHOD("is_active"), &SpineIkConstraint::is_active); + ClassDB::bind_method(D_METHOD("set_active", "v"), &SpineIkConstraint::set_active); +} + +SpineIkConstraint::SpineIkConstraint() : ik_constraint(NULL) {} +SpineIkConstraint::~SpineIkConstraint() {} + +// void SpineIkConstraint::apply(){ +// ik_constraint->apply(); +// } + +void SpineIkConstraint::update() { + ik_constraint->update(); +} + +int SpineIkConstraint::get_order() { + return ik_constraint->getOrder(); +} + +Ref SpineIkConstraint::get_data() { + auto &ikc = ik_constraint->getData(); + Ref gd_ikc(memnew(SpineIkConstraintData)); + gd_ikc->set_spine_object(&ikc); + return gd_ikc; +} + +Array SpineIkConstraint::get_bones() { + auto &bs = ik_constraint->getBones(); + Array gd_bs; + gd_bs.resize(bs.size()); + for (size_t i = 0; i < bs.size(); ++i) { + auto b = bs[i]; + if (b == NULL) gd_bs[i] = Ref(NULL); + Ref gd_b(memnew(SpineBone)); + gd_b->set_spine_object(b); + gd_bs[i] = gd_b; + } + return gd_bs; +} + +Ref SpineIkConstraint::get_target() { + auto b = ik_constraint->getTarget(); + if (b == NULL) return NULL; + Ref gd_b(memnew(SpineBone)); + gd_b->set_spine_object(b); + return gd_b; +} +void SpineIkConstraint::set_target(Ref v) { + if (v.is_valid()) { + ik_constraint->setTarget(v->get_spine_object()); + } else { + ik_constraint->setTarget(NULL); + } +} + +int SpineIkConstraint::get_bend_direction() { + return ik_constraint->getBendDirection(); +} +void SpineIkConstraint::set_bend_direction(int v) { + ik_constraint->setBendDirection(v); +} + +bool SpineIkConstraint::get_compress() { + return ik_constraint->getCompress(); +} +void SpineIkConstraint::set_compress(bool v) { + ik_constraint->setCompress(v); +} + +bool SpineIkConstraint::get_stretch() { + return ik_constraint->getStretch(); +} +void SpineIkConstraint::set_stretch(bool v) { + ik_constraint->setStretch(v); +} + +float SpineIkConstraint::get_mix() { + return ik_constraint->getMix(); +} +void SpineIkConstraint::set_mix(float v) { + ik_constraint->setMix(v); +} + +float SpineIkConstraint::get_softness() { + return ik_constraint->getSoftness(); +} +void SpineIkConstraint::set_softness(float v) { + ik_constraint->setSoftness(v); +} + +bool SpineIkConstraint::is_active() { + return ik_constraint->isActive(); +} +void SpineIkConstraint::set_active(bool v) { + ik_constraint->setActive(v); +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineIkConstraint.h b/spine-godot/spine_godot/SpineIkConstraint.h new file mode 100644 index 000000000..c7c4aeefe --- /dev/null +++ b/spine-godot/spine_godot/SpineIkConstraint.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 GODOT_SPINEIKCONSTRAINT_H +#define GODOT_SPINEIKCONSTRAINT_H + +#include "core/variant_parser.h" + +#include + +#include "SpineIkConstraintData.h" + +class SpineBone; + +class SpineIkConstraint : public Reference { + GDCLASS(SpineIkConstraint, Reference); + +protected: + static void _bind_methods(); + +private: + spine::IkConstraint *ik_constraint; + +public: + SpineIkConstraint(); + ~SpineIkConstraint(); + + inline void set_spine_object(spine::IkConstraint *ic) { + ik_constraint = ic; + } + inline spine::IkConstraint *get_spine_object() { + return ik_constraint; + } + + // The spine-runtime-cpp 4.0 seems to not have a apply function implementation. + // void apply(); + + void update(); + + int get_order(); + + Ref get_data(); + + Array get_bones(); + + Ref get_target(); + void set_target(Ref v); + + int get_bend_direction(); + void set_bend_direction(int v); + + bool get_compress(); + void set_compress(bool v); + + bool get_stretch(); + void set_stretch(bool v); + + float get_mix(); + void set_mix(float v); + + float get_softness(); + void set_softness(float v); + + bool is_active(); + void set_active(bool v); +}; + +#endif//GODOT_SPINEIKCONSTRAINT_H diff --git a/spine-godot/spine_godot/SpineIkConstraintData.cpp b/spine-godot/spine_godot/SpineIkConstraintData.cpp new file mode 100644 index 000000000..62731aecf --- /dev/null +++ b/spine-godot/spine_godot/SpineIkConstraintData.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 "SpineIkConstraintData.h" + +void SpineIkConstraintData::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_all_bone_data"), &SpineIkConstraintData::get_bones); + ClassDB::bind_method(D_METHOD("get_target"), &SpineIkConstraintData::get_target); + ClassDB::bind_method(D_METHOD("set_target", "v"), &SpineIkConstraintData::set_target); + ClassDB::bind_method(D_METHOD("get_bend_direction"), &SpineIkConstraintData::get_bend_direction); + ClassDB::bind_method(D_METHOD("set_bend_direction", "v"), &SpineIkConstraintData::set_bend_direction); + ClassDB::bind_method(D_METHOD("get_compress"), &SpineIkConstraintData::get_compress); + ClassDB::bind_method(D_METHOD("set_compress", "v"), &SpineIkConstraintData::set_compress); + ClassDB::bind_method(D_METHOD("get_stretch"), &SpineIkConstraintData::get_stretch); + ClassDB::bind_method(D_METHOD("set_stretch", "v"), &SpineIkConstraintData::set_stretch); + ClassDB::bind_method(D_METHOD("get_uniform"), &SpineIkConstraintData::get_uniform); + ClassDB::bind_method(D_METHOD("set_uniform", "v"), &SpineIkConstraintData::set_uniform); + ClassDB::bind_method(D_METHOD("get_mix"), &SpineIkConstraintData::get_mix); + ClassDB::bind_method(D_METHOD("set_mix", "v"), &SpineIkConstraintData::set_mix); + ClassDB::bind_method(D_METHOD("get_softness"), &SpineIkConstraintData::get_softness); + ClassDB::bind_method(D_METHOD("set_softness", "v"), &SpineIkConstraintData::set_softness); +} + +SpineIkConstraintData::SpineIkConstraintData() {} +SpineIkConstraintData::~SpineIkConstraintData() {} + +Array SpineIkConstraintData::get_bones() { + auto bs = get_spine_data()->getBones(); + Array gd_bs; + gd_bs.resize(bs.size()); + for (size_t i = 0; i < bs.size(); ++i) { + if (bs[i] == NULL) gd_bs[i] = Ref(NULL); + else { + Ref gd_b(memnew(SpineBoneData)); + gd_b->set_spine_object(bs[i]); + gd_bs[i] = gd_b; + } + } + return gd_bs; +} + +Ref SpineIkConstraintData::get_target() { + auto b = get_spine_data()->getTarget(); + if (b == NULL) return NULL; + Ref gd_b(memnew(SpineBoneData)); + gd_b->set_spine_object(b); + return gd_b; +} +void SpineIkConstraintData::set_target(Ref v) { + if (v.is_valid()) { + get_spine_data()->setTarget(v->get_spine_object()); + } else { + get_spine_data()->setTarget(NULL); + } +} + +int SpineIkConstraintData::get_bend_direction() { + return get_spine_data()->getBendDirection(); +} +void SpineIkConstraintData::set_bend_direction(int v) { + get_spine_data()->setBendDirection(v); +} + +bool SpineIkConstraintData::get_compress() { + return get_spine_data()->getCompress(); +} +void SpineIkConstraintData::set_compress(bool v) { + get_spine_data()->setCompress(v); +} + +bool SpineIkConstraintData::get_stretch() { + return get_spine_data()->getStretch(); +} +void SpineIkConstraintData::set_stretch(bool v) { + get_spine_data()->setStretch(v); +} + +bool SpineIkConstraintData::get_uniform() { + return get_spine_data()->getUniform(); +} +void SpineIkConstraintData::set_uniform(bool v) { + get_spine_data()->setUniform(v); +} + +float SpineIkConstraintData::get_mix() { + return get_spine_data()->getMix(); +} +void SpineIkConstraintData::set_mix(float v) { + get_spine_data()->setMix(v); +} + +float SpineIkConstraintData::get_softness() { + return get_spine_data()->getSoftness(); +} +void SpineIkConstraintData::set_softness(float v) { + get_spine_data()->setSoftness(v); +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineIkConstraintData.h b/spine-godot/spine_godot/SpineIkConstraintData.h new file mode 100644 index 000000000..da0434d0b --- /dev/null +++ b/spine-godot/spine_godot/SpineIkConstraintData.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 GODOT_SPINEIKCONSTRAINTDATA_H +#define GODOT_SPINEIKCONSTRAINTDATA_H + +#include "core/variant_parser.h" + +#include + +#include "SpineConstraintData.h" +#include "SpineBoneData.h" + +class SpineIkConstraintData : public SpineConstraintData { + GDCLASS(SpineIkConstraintData, SpineConstraintData); + +protected: + static void _bind_methods(); + +public: + SpineIkConstraintData(); + ~SpineIkConstraintData(); + + virtual inline spine::IkConstraintData *get_spine_data() { + return (spine::IkConstraintData *) SpineConstraintData::get_spine_object(); + } + + Array get_bones(); + + Ref get_target(); + void set_target(Ref v); + + int get_bend_direction(); + void set_bend_direction(int v); + + bool get_compress(); + void set_compress(bool v); + + bool get_stretch(); + void set_stretch(bool v); + + bool get_uniform(); + void set_uniform(bool v); + + float get_mix(); + void set_mix(float v); + + float get_softness(); + void set_softness(float v); +}; + +#endif//GODOT_SPINEIKCONSTRAINTDATA_H diff --git a/spine-godot/spine_godot/SpinePathConstraint.cpp b/spine-godot/spine_godot/SpinePathConstraint.cpp new file mode 100644 index 000000000..3df032a22 --- /dev/null +++ b/spine-godot/spine_godot/SpinePathConstraint.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. + *****************************************************************************/ + +#include "SpinePathConstraint.h" + +void SpinePathConstraint::_bind_methods() { + // ClassDB::bind_method(D_METHOD("apply"), &SpinePathConstraint::apply); + ClassDB::bind_method(D_METHOD("update"), &SpinePathConstraint::update); + ClassDB::bind_method(D_METHOD("get_order"), &SpinePathConstraint::get_order); + ClassDB::bind_method(D_METHOD("get_position"), &SpinePathConstraint::get_position); + ClassDB::bind_method(D_METHOD("set_position", "v"), &SpinePathConstraint::set_position); + ClassDB::bind_method(D_METHOD("get_spacing"), &SpinePathConstraint::get_spacing); + ClassDB::bind_method(D_METHOD("set_spacing", "v"), &SpinePathConstraint::set_spacing); + ClassDB::bind_method(D_METHOD("get_mix_rotate"), &SpinePathConstraint::get_mix_rotate); + ClassDB::bind_method(D_METHOD("set_mix_rotate", "v"), &SpinePathConstraint::set_mix_rotate); + ClassDB::bind_method(D_METHOD("get_mix_x"), &SpinePathConstraint::get_mix_x); + ClassDB::bind_method(D_METHOD("set_mix_x", "v"), &SpinePathConstraint::set_mix_x); + ClassDB::bind_method(D_METHOD("get_mix_y"), &SpinePathConstraint::get_mix_y); + ClassDB::bind_method(D_METHOD("set_mix_y", "v"), &SpinePathConstraint::set_mix_y); + ClassDB::bind_method(D_METHOD("get_bones"), &SpinePathConstraint::get_bones); + ClassDB::bind_method(D_METHOD("get_target"), &SpinePathConstraint::get_target); + ClassDB::bind_method(D_METHOD("set_target", "v"), &SpinePathConstraint::set_target); + ClassDB::bind_method(D_METHOD("get_data"), &SpinePathConstraint::get_data); + ClassDB::bind_method(D_METHOD("is_active"), &SpinePathConstraint::is_active); + ClassDB::bind_method(D_METHOD("set_active", "v"), &SpinePathConstraint::set_active); +} + +SpinePathConstraint::SpinePathConstraint() : path_constraint(NULL) {} +SpinePathConstraint::~SpinePathConstraint() {} + +// void SpinePathConstraint::apply(){ +// path_constraint->apply(); +// } + +void SpinePathConstraint::update() { + path_constraint->update(); +} + +int SpinePathConstraint::get_order() { + return path_constraint->getOrder(); +} + +float SpinePathConstraint::get_position() { + return path_constraint->getPosition(); +} +void SpinePathConstraint::set_position(float v) { + path_constraint->setPosition(v); +} + +float SpinePathConstraint::get_spacing() { + return path_constraint->getSpacing(); +} +void SpinePathConstraint::set_spacing(float v) { + path_constraint->setSpacing(v); +} + +float SpinePathConstraint::get_mix_rotate() { + return path_constraint->getMixRotate(); +} +void SpinePathConstraint::set_mix_rotate(float v) { + path_constraint->setMixRotate(v); +} + +float SpinePathConstraint::get_mix_x() { + return path_constraint->getMixX(); +} +void SpinePathConstraint::set_mix_x(float v) { + path_constraint->setMixX(v); +} + +float SpinePathConstraint::get_mix_y() { + return path_constraint->getMixY(); +} +void SpinePathConstraint::set_mix_y(float v) { + path_constraint->setMixY(v); +} + +Array SpinePathConstraint::get_bones() { + auto &bs = path_constraint->getBones(); + Array gd_bs; + gd_bs.resize(bs.size()); + for (size_t i = 0; i < bs.size(); ++i) { + auto b = bs[i]; + if (b == NULL) gd_bs[i] = Ref(NULL); + Ref gd_b(memnew(SpineBone)); + gd_b->set_spine_object(b); + gd_bs[i] = gd_b; + } + return gd_bs; +} + +Ref SpinePathConstraint::get_target() { + auto s = path_constraint->getTarget(); + if (s == NULL) return NULL; + Ref gd_s(memnew(SpineSlot)); + gd_s->set_spine_object(s); + return gd_s; +} +void SpinePathConstraint::set_target(Ref v) { + if (v.is_valid()) { + path_constraint->setTarget(v->get_spine_object()); + } else { + path_constraint->setTarget(NULL); + } +} + +Ref SpinePathConstraint::get_data() { + auto &sd = path_constraint->getData(); + Ref gd_sd(memnew(SpinePathConstraintData)); + gd_sd->set_spine_object(&sd); + return gd_sd; +} + +bool SpinePathConstraint::is_active() { + return path_constraint->isActive(); +} +void SpinePathConstraint::set_active(bool v) { + path_constraint->setActive(v); +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpinePathConstraint.h b/spine-godot/spine_godot/SpinePathConstraint.h new file mode 100644 index 000000000..dcd41d09e --- /dev/null +++ b/spine-godot/spine_godot/SpinePathConstraint.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 GODOT_SPINEPATHCONSTRAINT_H +#define GODOT_SPINEPATHCONSTRAINT_H + +#include "core/variant_parser.h" + +#include + +#include "SpineBone.h" +#include "SpineSlot.h" +#include "SpinePathConstraintData.h" + +class SpinePathConstraint : public Reference { + GDCLASS(SpinePathConstraint, Reference); + +protected: + static void _bind_methods(); + +private: + spine::PathConstraint *path_constraint; + +public: + SpinePathConstraint(); + ~SpinePathConstraint(); + + inline void set_spine_object(spine::PathConstraint *pc) { + path_constraint = pc; + } + inline spine::PathConstraint *get_spine_object() { + return path_constraint; + } + + // The spine-runtime-cpp 4.0 seems to not have a apply function implementation. + // void apply(); + + void update(); + + int get_order(); + + float get_position(); + void set_position(float v); + + float get_spacing(); + void set_spacing(float v); + + float get_mix_rotate(); + void set_mix_rotate(float v); + + float get_mix_x(); + void set_mix_x(float v); + + float get_mix_y(); + void set_mix_y(float v); + + Array get_bones(); + + Ref get_target(); + void set_target(Ref v); + + Ref get_data(); + + bool is_active(); + void set_active(bool v); +}; + +#endif//GODOT_SPINEPATHCONSTRAINT_H diff --git a/spine-godot/spine_godot/SpinePathConstraintData.cpp b/spine-godot/spine_godot/SpinePathConstraintData.cpp new file mode 100644 index 000000000..5d0f34b64 --- /dev/null +++ b/spine-godot/spine_godot/SpinePathConstraintData.cpp @@ -0,0 +1,168 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpinePathConstraintData.h" + + +void SpinePathConstraintData::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_all_bone_data"), &SpinePathConstraintData::get_bones); + ClassDB::bind_method(D_METHOD("get_target"), &SpinePathConstraintData::get_target); + ClassDB::bind_method(D_METHOD("set_target", "V"), &SpinePathConstraintData::set_target); + ClassDB::bind_method(D_METHOD("get_position_mode"), &SpinePathConstraintData::get_position_mode); + ClassDB::bind_method(D_METHOD("set_position_mode", "V"), &SpinePathConstraintData::set_position_mode); + ClassDB::bind_method(D_METHOD("get_spacing_mode"), &SpinePathConstraintData::get_spacing_mode); + ClassDB::bind_method(D_METHOD("set_spacing_mode", "V"), &SpinePathConstraintData::set_spacing_mode); + ClassDB::bind_method(D_METHOD("get_rotate_mode"), &SpinePathConstraintData::get_rotate_mode); + ClassDB::bind_method(D_METHOD("set_rotate_mode", "V"), &SpinePathConstraintData::set_rotate_mode); + ClassDB::bind_method(D_METHOD("get_offset_rotation"), &SpinePathConstraintData::get_offset_rotation); + ClassDB::bind_method(D_METHOD("set_offset_rotation", "V"), &SpinePathConstraintData::set_offset_rotation); + ClassDB::bind_method(D_METHOD("get_position"), &SpinePathConstraintData::get_position); + ClassDB::bind_method(D_METHOD("set_position", "V"), &SpinePathConstraintData::set_position); + ClassDB::bind_method(D_METHOD("get_spacing"), &SpinePathConstraintData::get_spacing); + ClassDB::bind_method(D_METHOD("set_spacing", "V"), &SpinePathConstraintData::set_spacing); + ClassDB::bind_method(D_METHOD("get_mix_rotate"), &SpinePathConstraintData::get_mix_rotate); + ClassDB::bind_method(D_METHOD("set_mix_rotate", "V"), &SpinePathConstraintData::set_mix_rotate); + ClassDB::bind_method(D_METHOD("get_mix_x"), &SpinePathConstraintData::get_mix_x); + ClassDB::bind_method(D_METHOD("set_mix_x", "V"), &SpinePathConstraintData::set_mix_x); + ClassDB::bind_method(D_METHOD("get_mix_y"), &SpinePathConstraintData::get_mix_y); + ClassDB::bind_method(D_METHOD("set_mix_y", "V"), &SpinePathConstraintData::set_mix_y); + + BIND_ENUM_CONSTANT(POSITIONMODE_FIXED); + BIND_ENUM_CONSTANT(POSITIONMODE_PERCENT); + + BIND_ENUM_CONSTANT(SPACINGMODE_LENGTH); + BIND_ENUM_CONSTANT(SPACINGMODE_FIXED); + BIND_ENUM_CONSTANT(SPACINGMODE_PERCENT); + + BIND_ENUM_CONSTANT(ROTATEMODE_TANGENT); + BIND_ENUM_CONSTANT(ROTATEMODE_CHAIN); + BIND_ENUM_CONSTANT(ROTATEMODE_CHAINSCALE); +} + +SpinePathConstraintData::SpinePathConstraintData() {} +SpinePathConstraintData::~SpinePathConstraintData() {} + +Array SpinePathConstraintData::get_bones() { + auto bs = get_spine_data()->getBones(); + Array gd_bs; + gd_bs.resize(bs.size()); + for (size_t i = 0; i < bs.size(); ++i) { + if (bs[i] == NULL) gd_bs[i] = Ref(NULL); + else { + Ref gd_b(memnew(SpineBoneData)); + gd_b->set_spine_object(bs[i]); + gd_bs[i] = gd_b; + } + } + return gd_bs; +} + +Ref SpinePathConstraintData::get_target() { + auto s = get_spine_data()->getTarget(); + if (s == NULL) return NULL; + Ref gd_s(memnew(SpineSlotData)); + gd_s->set_spine_object(s); + return gd_s; +} +void SpinePathConstraintData::set_target(Ref v) { + if (v.is_valid()) { + get_spine_data()->setTarget(v->get_spine_object()); + } else { + get_spine_data()->setTarget(NULL); + } +} + +SpinePathConstraintData::PositionMode SpinePathConstraintData::get_position_mode() { + auto m = (int) get_spine_data()->getPositionMode(); + return (PositionMode) m; +} +void SpinePathConstraintData::set_position_mode(PositionMode v) { + auto m = (int) v; + get_spine_data()->setPositionMode((spine::PositionMode) m); +} + +SpinePathConstraintData::SpacingMode SpinePathConstraintData::get_spacing_mode() { + auto m = (int) get_spine_data()->getSpacingMode(); + return (SpacingMode) m; +} +void SpinePathConstraintData::set_spacing_mode(SpacingMode v) { + auto m = (int) v; + get_spine_data()->setSpacingMode((spine::SpacingMode) m); +} + +SpinePathConstraintData::RotateMode SpinePathConstraintData::get_rotate_mode() { + auto m = (int) get_spine_data()->getRotateMode(); + return (RotateMode) m; +} +void SpinePathConstraintData::set_rotate_mode(RotateMode v) { + auto m = (int) v; + get_spine_data()->setRotateMode((spine::RotateMode) m); +} + +float SpinePathConstraintData::get_offset_rotation() { + return get_spine_data()->getOffsetRotation(); +} +void SpinePathConstraintData::set_offset_rotation(float v) { + get_spine_data()->setOffsetRotation(v); +} + +float SpinePathConstraintData::get_position() { + return get_spine_data()->getPosition(); +} +void SpinePathConstraintData::set_position(float v) { + get_spine_data()->setPosition(v); +} + +float SpinePathConstraintData::get_spacing() { + return get_spine_data()->getSpacing(); +} +void SpinePathConstraintData::set_spacing(float v) { + get_spine_data()->setSpacing(v); +} + +float SpinePathConstraintData::get_mix_rotate() { + return get_spine_data()->getMixRotate(); +} +void SpinePathConstraintData::set_mix_rotate(float v) { + get_spine_data()->setMixRotate(v); +} + +float SpinePathConstraintData::get_mix_x() { + return get_spine_data()->getMixX(); +} +void SpinePathConstraintData::set_mix_x(float v) { + get_spine_data()->setMixX(v); +} + +float SpinePathConstraintData::get_mix_y() { + return get_spine_data()->getMixY(); +} +void SpinePathConstraintData::set_mix_y(float v) { + get_spine_data()->setMixY(v); +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpinePathConstraintData.h b/spine-godot/spine_godot/SpinePathConstraintData.h new file mode 100644 index 000000000..068a68ec0 --- /dev/null +++ b/spine-godot/spine_godot/SpinePathConstraintData.h @@ -0,0 +1,108 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef GODOT_SPINEPATHCONSTRAINTDATA_H +#define GODOT_SPINEPATHCONSTRAINTDATA_H + +#include "core/variant_parser.h" + +#include + +#include "SpineConstraintData.h" +#include "SpineBoneData.h" +#include "SpineSlotData.h" + +class SpinePathConstraintData : public SpineConstraintData { + GDCLASS(SpinePathConstraintData, SpineConstraintData); + +protected: + static void _bind_methods(); + +public: + SpinePathConstraintData(); + ~SpinePathConstraintData(); + + virtual inline spine::PathConstraintData *get_spine_data() { + return (spine::PathConstraintData *) SpineConstraintData::get_spine_object(); + } + + enum PositionMode { + POSITIONMODE_FIXED = 0, + POSITIONMODE_PERCENT + }; + + enum SpacingMode { + SPACINGMODE_LENGTH = 0, + SPACINGMODE_FIXED, + SPACINGMODE_PERCENT + }; + + enum RotateMode { + ROTATEMODE_TANGENT = 0, + ROTATEMODE_CHAIN, + ROTATEMODE_CHAINSCALE + }; + + Array get_bones(); + + Ref get_target(); + void set_target(Ref v); + + PositionMode get_position_mode(); + void set_position_mode(PositionMode v); + + SpacingMode get_spacing_mode(); + void set_spacing_mode(SpacingMode v); + + RotateMode get_rotate_mode(); + void set_rotate_mode(RotateMode v); + + float get_offset_rotation(); + void set_offset_rotation(float v); + + float get_position(); + void set_position(float v); + + float get_spacing(); + void set_spacing(float v); + + float get_mix_rotate(); + void set_mix_rotate(float v); + + float get_mix_x(); + void set_mix_x(float v); + + float get_mix_y(); + void set_mix_y(float v); +}; + +VARIANT_ENUM_CAST(SpinePathConstraintData::PositionMode); +VARIANT_ENUM_CAST(SpinePathConstraintData::SpacingMode); +VARIANT_ENUM_CAST(SpinePathConstraintData::RotateMode); +#endif//GODOT_SPINEPATHCONSTRAINTDATA_H diff --git a/spine-godot/spine_godot/SpineRendererObject.h b/spine-godot/spine_godot/SpineRendererObject.h new file mode 100644 index 000000000..11b9370a9 --- /dev/null +++ b/spine-godot/spine_godot/SpineRendererObject.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 GODOT_SPINERENDEREROBJECT_H +#define GODOT_SPINERENDEREROBJECT_H + +#include + +struct SpineRendererObject { + Ref texture; + Ref normal_map; +}; + + +#endif diff --git a/spine-godot/spine_godot/SpineRuntimeEditorPlugin.cpp b/spine-godot/spine_godot/SpineRuntimeEditorPlugin.cpp new file mode 100644 index 000000000..80de73af7 --- /dev/null +++ b/spine-godot/spine_godot/SpineRuntimeEditorPlugin.cpp @@ -0,0 +1,99 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 TOOLS_ENABLED +#include "SpineRuntimeEditorPlugin.h" + +#include "SpineAtlasResource.h" +#include "SpineSkeletonJsonDataResource.h" +#include "SpineSpriteAnimateDialog.h" + +#include "SpineSprite.h" + +Error SpineAtlasResourceImportPlugin::import(const String &p_source_file, const String &p_save_path, const Map &p_options, List *r_platform_variants, List *r_gen_files, Variant *r_metadata) { + Ref res(memnew(SpineAtlasResource)); + res->set_normal_texture_prefix(p_options["normal_texture_prefix"]); + res->load_from_atlas_file(p_source_file); + + String file_name = vformat("%s.%s", p_save_path, get_save_extension()); + auto err = ResourceSaver::save(file_name, res); + return err; +} + +void SpineAtlasResourceImportPlugin::get_import_options(List *r_options, int p_preset) const { + if (p_preset == 0) { + ImportOption op; + op.option.name = "normal_texture_prefix"; + op.option.type = Variant::STRING; + op.option.hint_string = "String"; + op.default_value = String("n"); + r_options->push_back(op); + } +} + +Error SpineJsonResourceImportPlugin::import(const String &p_source_file, const String &p_save_path, const Map &p_options, List *r_platform_variants, List *r_gen_files, Variant *r_metadata) { + Ref res(memnew(SpineSkeletonJsonDataResource)); + res->load_from_file(p_source_file); + + String file_name = vformat("%s.%s", p_save_path, get_save_extension()); + auto err = ResourceSaver::save(file_name, res); + return err; +} + +//=======================| SpineRuntimeEditorPlugin |============================ +SpineRuntimeEditorPlugin::SpineRuntimeEditorPlugin(EditorNode *p_node) { + add_import_plugin(memnew(SpineAtlasResourceImportPlugin)); + add_import_plugin(memnew(SpineJsonResourceImportPlugin)); + + auto animate_button = memnew(ToolButton); + animate_button->set_text("Animate"); + add_control_to_container(CONTAINER_CANVAS_EDITOR_MENU, animate_button); + + animate_dialog = memnew(SpineSpriteAnimateDialog); + get_editor_interface()->get_base_control()->add_child(animate_dialog); + animate_dialog->set_animate_button(animate_button); + animate_dialog->set_plugin(this); +} + +SpineRuntimeEditorPlugin::~SpineRuntimeEditorPlugin() { +} + +bool SpineRuntimeEditorPlugin::handles(Object *p_object) const { + return p_object->is_class("SpineSprite"); +} + +void SpineRuntimeEditorPlugin::make_visible(bool p_visible) { + if (get_editor_interface()->get_selection()->get_selected_node_list().size() != 1) { + p_visible = false; + } + animate_dialog->get_animate_button()->set_visible(p_visible); +} + + +#endif \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineRuntimeEditorPlugin.h b/spine-godot/spine_godot/SpineRuntimeEditorPlugin.h new file mode 100644 index 000000000..cf95ec696 --- /dev/null +++ b/spine-godot/spine_godot/SpineRuntimeEditorPlugin.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 GODOT_SPINERUNTIMEEDITORPLUGIN_H +#define GODOT_SPINERUNTIMEEDITORPLUGIN_H + +#ifdef TOOLS_ENABLED +#include "editor/editor_node.h" + +class SpineAtlasResourceImportPlugin : public EditorImportPlugin { + GDCLASS(SpineAtlasResourceImportPlugin, EditorImportPlugin); + +public: + String get_importer_name() const override { return "spine.atlas"; } + String get_visible_name() const override { return "Spine Runtime Atlas"; } + void get_recognized_extensions(List *p_extensions) const override { p_extensions->push_back("atlas"); } + String get_preset_name(int p_idx) const override { + if (p_idx == 0) return "Default"; + else + return "Unknown"; + } + int get_preset_count() const override { return 1; } + String get_save_extension() const override { return "spatlas"; } + String get_resource_type() const override { return "SpineAtlasResource"; } + void get_import_options(List *r_options, int p_preset) const override; + bool get_option_visibility(const String &p_option, const Map &p_options) const override { return true; } + Error import(const String &p_source_file, const String &p_save_path, const Map &p_options, List *r_platform_variants, List *r_gen_files, Variant *r_metadata) override; +}; + +class SpineJsonResourceImportPlugin : public EditorImportPlugin { + GDCLASS(SpineJsonResourceImportPlugin, EditorImportPlugin); + +public: + String get_importer_name() const override { return "spine.json"; } + String get_visible_name() const override { return "Spine Runtime Json"; } + void get_recognized_extensions(List *p_extensions) const override { p_extensions->push_back("json"); } + String get_preset_name(int p_idx) const override { + if (p_idx == 0) return "Default"; + else + return "Unknown"; + } + int get_preset_count() const override { return 1; } + String get_save_extension() const override { return "spjson"; } + String get_resource_type() const override { return "SpineSkeletonJsonDataResource"; } + void get_import_options(List *r_options, int p_preset) const override {} + bool get_option_visibility(const String &p_option, const Map &p_options) const override { return true; } + Error import(const String &p_source_file, const String &p_save_path, const Map &p_options, List *r_platform_variants, List *r_gen_files, Variant *r_metadata) override; +}; + +class SpineSpriteAnimateDialog; + +class SpineRuntimeEditorPlugin : public EditorPlugin { + GDCLASS(SpineRuntimeEditorPlugin, EditorPlugin); + +protected: + SpineSpriteAnimateDialog *animate_dialog; + +public: + SpineRuntimeEditorPlugin(EditorNode *p_node); + ~SpineRuntimeEditorPlugin(); + + String get_name() const override { return "SpineRuntimeEditorPlugin"; } + bool has_main_screen() const { return false; } + + bool handles(Object *p_object) const override; + void make_visible(bool p_visible) override; + + void _on_animate_button_pressed(); +}; +#endif + +#endif//GODOT_SPINERUNTIMEEDITORPLUGIN_H diff --git a/spine-godot/spine_godot/SpineSkeleton.cpp b/spine-godot/spine_godot/SpineSkeleton.cpp new file mode 100644 index 000000000..2f3d1fd2b --- /dev/null +++ b/spine-godot/spine_godot/SpineSkeleton.cpp @@ -0,0 +1,413 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineSkeleton.h" + +void SpineSkeleton::_bind_methods() { + //void update_world_transform(); + // + // void set_to_setup_pose(); + // + // void set_bones_to_setup_pose(); + // + // void set_slots_to_setup_pose(); + ClassDB::bind_method(D_METHOD("update_world_transform"), &SpineSkeleton::update_world_transform); + ClassDB::bind_method(D_METHOD("set_to_setup_pose"), &SpineSkeleton::set_to_setup_pose); + ClassDB::bind_method(D_METHOD("set_bones_to_setup_pose"), &SpineSkeleton::set_bones_to_setup_pose); + ClassDB::bind_method(D_METHOD("set_slots_to_setup_pose"), &SpineSkeleton::set_slots_to_setup_pose); + // + // Ref find_bone(const String &name); + // int find_bone_index(const String &name); + // + // Ref find_slot(const String &name); + // int find_slot_index(const String &name); + // + // void set_skin_by_name(const String &skin_name); + // void set_skin(Ref new_skin); + // + // Ref get_attachment_by_slot_name(const String &slot_name, const String &attachment_name); + // Ref get_attachment_by_slot_index(int slot_index, const String &attachment_name); + ClassDB::bind_method(D_METHOD("find_bone", "bone_name"), &SpineSkeleton::find_bone); + ClassDB::bind_method(D_METHOD("find_slot", "slot_name"), &SpineSkeleton::find_slot); + ClassDB::bind_method(D_METHOD("set_skin_by_name", "skin_name"), &SpineSkeleton::set_skin_by_name); + ClassDB::bind_method(D_METHOD("set_skin", "new_skin"), &SpineSkeleton::set_skin); + ClassDB::bind_method(D_METHOD("get_attachment_by_slot_name", "slot_name", "attachment_name"), &SpineSkeleton::get_attachment_by_slot_name); + ClassDB::bind_method(D_METHOD("get_attachment_by_slot_index", "slot_index", "attachment_name"), &SpineSkeleton::get_attachment_by_slot_index); + // + // void set_attachment(const String &slot_name, const String &attachment_name); + // + // Ref find_ik_constraint(const String &constraint_name); + // Ref find_transform_constraint(const String &constraint_name); + // Ref find_path_constraint(const String &constraint_name); + // + // void update(float delta); + // + // Dictionary get_bounds(); + // + // Ref get_root_bone(); + // + // Ref get_data(); + ClassDB::bind_method(D_METHOD("set_attachment", "slot_name", "attachment_name"), &SpineSkeleton::set_attachment); + ClassDB::bind_method(D_METHOD("find_ik_constraint", "constraint_name"), &SpineSkeleton::find_ik_constraint); + ClassDB::bind_method(D_METHOD("find_transform_constraint", "constraint_name"), &SpineSkeleton::find_transform_constraint); + ClassDB::bind_method(D_METHOD("find_path_constraint", "constraint_name"), &SpineSkeleton::find_path_constraint); + ClassDB::bind_method(D_METHOD("get_bounds"), &SpineSkeleton::get_bounds); + ClassDB::bind_method(D_METHOD("get_root_bone"), &SpineSkeleton::get_root_bone); + ClassDB::bind_method(D_METHOD("get_data"), &SpineSkeleton::get_data); + // + // Array get_bones(); + // Array get_slots(); + // Array get_draw_orders(); + // Array get_ik_constraints(); + // Array get_path_constraints(); + // Array get_transform_constraints(); + // + // Ref get_skin(); + ClassDB::bind_method(D_METHOD("get_bones"), &SpineSkeleton::get_bones); + ClassDB::bind_method(D_METHOD("get_slots"), &SpineSkeleton::get_slots); + ClassDB::bind_method(D_METHOD("get_draw_orders"), &SpineSkeleton::get_draw_orders); + ClassDB::bind_method(D_METHOD("get_ik_constraints"), &SpineSkeleton::get_ik_constraints); + ClassDB::bind_method(D_METHOD("get_path_constraints"), &SpineSkeleton::get_path_constraints); + ClassDB::bind_method(D_METHOD("get_transform_constraints"), &SpineSkeleton::get_transform_constraints); + ClassDB::bind_method(D_METHOD("get_skin"), &SpineSkeleton::get_skin); + // + // Color get_color(); + // void set_color(Color v); + // + // float get_time(); + // void set_time(float v); + // + // void set_position(Vector2 pos); + ClassDB::bind_method(D_METHOD("get_color"), &SpineSkeleton::get_color); + ClassDB::bind_method(D_METHOD("set_color", "v"), &SpineSkeleton::set_color); + ClassDB::bind_method(D_METHOD("set_position", "pos"), &SpineSkeleton::set_position); + // + // float get_x(); + // void set_x(float v); + // + // float get_y(); + // void set_y(float v); + // + // float get_scale_x(); + // void set_scale_x(float v); + // + // float get_scale_y(); + // void set_scale_y(float v); + ClassDB::bind_method(D_METHOD("get_x"), &SpineSkeleton::get_x); + ClassDB::bind_method(D_METHOD("set_x", "v"), &SpineSkeleton::set_x); + ClassDB::bind_method(D_METHOD("get_y"), &SpineSkeleton::get_y); + ClassDB::bind_method(D_METHOD("set_y", "v"), &SpineSkeleton::set_y); + ClassDB::bind_method(D_METHOD("get_scale_x"), &SpineSkeleton::get_scale_x); + ClassDB::bind_method(D_METHOD("set_scale_x", "v"), &SpineSkeleton::set_scale_x); + ClassDB::bind_method(D_METHOD("get_scale_y"), &SpineSkeleton::get_scale_y); + ClassDB::bind_method(D_METHOD("set_scale_y", "v"), &SpineSkeleton::set_scale_y); +} + +SpineSkeleton::SpineSkeleton() : skeleton(NULL), spine_object(false), the_sprite(nullptr) { +} + +SpineSkeleton::~SpineSkeleton() { + if (skeleton && !spine_object) { + delete skeleton; + skeleton = NULL; + } +} + +void SpineSkeleton::load_skeleton(Ref sd) { + if (skeleton && !spine_object) { + delete skeleton; + skeleton = NULL; + } + skeleton = new spine::Skeleton(sd->get_skeleton_data()); + spine_object = false; +} + +#define S_T(x) (spine::String(x.utf8())) +void SpineSkeleton::update_world_transform() { + skeleton->updateWorldTransform(); +} + +void SpineSkeleton::set_to_setup_pose() { + skeleton->setToSetupPose(); +} + +void SpineSkeleton::set_bones_to_setup_pose() { + skeleton->setBonesToSetupPose(); +} + +void SpineSkeleton::set_slots_to_setup_pose() { + skeleton->setSlotsToSetupPose(); +} + +Ref SpineSkeleton::find_bone(const String &name) { + if (name.empty()) return NULL; + auto b = skeleton->findBone(S_T(name)); + if (b == NULL) return NULL; + Ref gd_b(memnew(SpineBone)); + gd_b->set_spine_object(b); + gd_b->set_spine_sprite(the_sprite); + return gd_b; +} + +Ref SpineSkeleton::find_slot(const String &name) { + if (name.empty()) return NULL; + auto s = skeleton->findSlot(S_T(name)); + if (s == NULL) return NULL; + Ref gd_s(memnew(SpineSlot)); + gd_s->set_spine_object(s); + return gd_s; +} + +void SpineSkeleton::set_skin_by_name(const String &skin_name) { + skeleton->setSkin(S_T(skin_name)); +} +void SpineSkeleton::set_skin(Ref new_skin) { + if (new_skin.is_valid()) { + skeleton->setSkin(new_skin->get_spine_object()); + } else { + skeleton->setSkin(NULL); + } +} + +Ref SpineSkeleton::get_attachment_by_slot_name(const String &slot_name, const String &attachment_name) { + auto a = skeleton->getAttachment(S_T(slot_name), S_T(attachment_name)); + if (a == NULL) return NULL; + Ref gd_a(memnew(SpineAttachment)); + gd_a->set_spine_object(a); + return gd_a; +} +Ref SpineSkeleton::get_attachment_by_slot_index(int slot_index, const String &attachment_name) { + auto a = skeleton->getAttachment(slot_index, S_T(attachment_name)); + if (a == NULL) return NULL; + Ref gd_a(memnew(SpineAttachment)); + gd_a->set_spine_object(a); + return gd_a; +} + +void SpineSkeleton::set_attachment(const String &slot_name, const String &attachment_name) { + ERR_FAIL_COND(slot_name.empty()); + ERR_FAIL_COND(get_attachment_by_slot_name(slot_name, attachment_name) == NULL); + skeleton->setAttachment(S_T(slot_name), S_T(attachment_name)); +} + +Ref SpineSkeleton::find_ik_constraint(const String &constraint_name) { + if (constraint_name.empty()) return NULL; + auto c = skeleton->findIkConstraint(S_T(constraint_name)); + if (c == NULL) return NULL; + Ref gd_c(memnew(SpineIkConstraint)); + gd_c->set_spine_object(c); + return gd_c; +} +Ref SpineSkeleton::find_transform_constraint(const String &constraint_name) { + if (constraint_name.empty()) return NULL; + auto c = skeleton->findTransformConstraint(S_T(constraint_name)); + if (c == NULL) return NULL; + Ref gd_c(memnew(SpineTransformConstraint)); + gd_c->set_spine_object(c); + return gd_c; +} +Ref SpineSkeleton::find_path_constraint(const String &constraint_name) { + if (constraint_name.empty()) return NULL; + auto c = skeleton->findPathConstraint(S_T(constraint_name)); + if (c == NULL) return NULL; + Ref gd_c(memnew(SpinePathConstraint)); + gd_c->set_spine_object(c); + return gd_c; +} + +Dictionary SpineSkeleton::get_bounds() { + float x, y, w, h; + spine::Vector vertex_buffer; + skeleton->getBounds(x, y, w, h, vertex_buffer); + + Dictionary res; + res["x"] = x; + res["y"] = y; + res["w"] = w; + res["h"] = h; + + Array gd_a; + gd_a.resize(vertex_buffer.size()); + for (size_t i = 0; i < gd_a.size(); ++i) { + gd_a[i] = vertex_buffer[i]; + } + res["vertex_buffer"] = gd_a; + + return res; +} + +Ref SpineSkeleton::get_root_bone() { + auto b = skeleton->getRootBone(); + if (b == NULL) return NULL; + Ref gd_b(memnew(SpineBone)); + gd_b->set_spine_object(b); + gd_b->set_spine_sprite(the_sprite); + return gd_b; +} + +Ref SpineSkeleton::get_data() const { + auto sd = skeleton->getData(); + if (sd == NULL) return NULL; + Ref gd_sd(memnew(SpineSkeletonDataResource)); + gd_sd->set_spine_object(sd); + return gd_sd; +} + +Array SpineSkeleton::get_bones() { + auto &as = skeleton->getBones(); + Array gd_as; + gd_as.resize(as.size()); + for (size_t i = 0; i < gd_as.size(); ++i) { + auto b = as[i]; + if (b == NULL) gd_as[i] = Ref(NULL); + Ref gd_a(memnew(SpineBone)); + gd_a->set_spine_object(b); + gd_a->set_spine_sprite(the_sprite); + gd_as[i] = gd_a; + } + return gd_as; +} +Array SpineSkeleton::get_slots() { + auto &as = skeleton->getSlots(); + Array gd_as; + gd_as.resize(as.size()); + for (size_t i = 0; i < gd_as.size(); ++i) { + auto b = as[i]; + if (b == NULL) gd_as[i] = Ref(NULL); + Ref gd_a(memnew(SpineSlot)); + gd_a->set_spine_object(b); + gd_as[i] = gd_a; + } + return gd_as; +} +Array SpineSkeleton::get_draw_orders() { + auto &as = skeleton->getDrawOrder(); + Array gd_as; + gd_as.resize(as.size()); + for (size_t i = 0; i < gd_as.size(); ++i) { + auto b = as[i]; + if (b == NULL) gd_as[i] = Ref(NULL); + Ref gd_a(memnew(SpineSlot)); + gd_a->set_spine_object(b); + gd_as[i] = gd_a; + } + return gd_as; +} +Array SpineSkeleton::get_ik_constraints() { + auto &as = skeleton->getIkConstraints(); + Array gd_as; + gd_as.resize(as.size()); + for (size_t i = 0; i < gd_as.size(); ++i) { + auto b = as[i]; + if (b == NULL) gd_as[i] = Ref(NULL); + Ref gd_a(memnew(SpineIkConstraint)); + gd_a->set_spine_object(b); + gd_as[i] = gd_a; + } + return gd_as; +} +Array SpineSkeleton::get_path_constraints() { + auto &as = skeleton->getPathConstraints(); + Array gd_as; + gd_as.resize(as.size()); + for (size_t i = 0; i < gd_as.size(); ++i) { + auto b = as[i]; + if (b == NULL) gd_as[i] = Ref(NULL); + Ref gd_a(memnew(SpinePathConstraint)); + gd_a->set_spine_object(b); + gd_as[i] = gd_a; + } + return gd_as; +} +Array SpineSkeleton::get_transform_constraints() { + auto &as = skeleton->getTransformConstraints(); + Array gd_as; + gd_as.resize(as.size()); + for (size_t i = 0; i < gd_as.size(); ++i) { + auto b = as[i]; + if (b == NULL) gd_as[i] = Ref(NULL); + Ref gd_a(memnew(SpineTransformConstraint)); + gd_a->set_spine_object(b); + gd_as[i] = gd_a; + } + return gd_as; +} + +Ref SpineSkeleton::get_skin() { + auto s = skeleton->getSkin(); + if (s == NULL) return NULL; + Ref gd_s(memnew(SpineSkin)); + gd_s->set_spine_object(s); + return gd_s; +} + +Color SpineSkeleton::get_color() { + auto &c = skeleton->getColor(); + return Color(c.r, c.g, c.b, c.a); +} +void SpineSkeleton::set_color(Color v) { + auto &c = skeleton->getColor(); + c.set(v.r, v.g, v.b, v.a); +} + +void SpineSkeleton::set_position(Vector2 pos) { + skeleton->setPosition(pos.x, pos.y); +} + +float SpineSkeleton::get_x() { + return skeleton->getX(); +} +void SpineSkeleton::set_x(float v) { + skeleton->setX(v); +} + +float SpineSkeleton::get_y() { + return skeleton->getY(); +} +void SpineSkeleton::set_y(float v) { + skeleton->setY(v); +} + +float SpineSkeleton::get_scale_x() { + return skeleton->getScaleX(); +} +void SpineSkeleton::set_scale_x(float v) { + skeleton->setScaleX(v); +} + +float SpineSkeleton::get_scale_y() { + return skeleton->getScaleY(); +} +void SpineSkeleton::set_scale_y(float v) { + skeleton->setScaleY(v); +} + +void SpineSkeleton::set_spine_sprite(SpineSprite *s) { + the_sprite = s; +} diff --git a/spine-godot/spine_godot/SpineSkeleton.h b/spine-godot/spine_godot/SpineSkeleton.h new file mode 100644 index 000000000..942665c6a --- /dev/null +++ b/spine-godot/spine_godot/SpineSkeleton.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 GODOT_SPINESKELETON_H +#define GODOT_SPINESKELETON_H + +#include "core/variant_parser.h" + +#include + +#include "SpineSkeletonDataResource.h" +#include "SpineBone.h" +#include "SpineSlot.h" + +class SpineSprite; + +class SpineSkeleton : public Reference { + GDCLASS(SpineSkeleton, Reference); + +protected: + static void _bind_methods(); + +private: + spine::Skeleton *skeleton; + bool spine_object; + + SpineSprite *the_sprite; + +public: + SpineSkeleton(); + ~SpineSkeleton(); + + void load_skeleton(Ref sd); + + inline void set_spine_object(spine::Skeleton *s) { + skeleton = s; + spine_object = true; + } + inline spine::Skeleton *get_spine_object() { + return skeleton; + } + + void set_spine_sprite(SpineSprite *s); + + + void update_world_transform(); + + void set_to_setup_pose(); + + void set_bones_to_setup_pose(); + + void set_slots_to_setup_pose(); + + Ref find_bone(const String &name); + + Ref find_slot(const String &name); + + void set_skin_by_name(const String &skin_name); + void set_skin(Ref new_skin); + + Ref get_attachment_by_slot_name(const String &slot_name, const String &attachment_name); + Ref get_attachment_by_slot_index(int slot_index, const String &attachment_name); + + void set_attachment(const String &slot_name, const String &attachment_name); + + Ref find_ik_constraint(const String &constraint_name); + Ref find_transform_constraint(const String &constraint_name); + Ref find_path_constraint(const String &constraint_name); + + Dictionary get_bounds(); + + Ref get_root_bone(); + + Ref get_data() const; + + Array get_bones(); + Array get_slots(); + Array get_draw_orders(); + Array get_ik_constraints(); + Array get_path_constraints(); + Array get_transform_constraints(); + + Ref get_skin(); + + Color get_color(); + void set_color(Color v); + + void set_position(Vector2 pos); + + float get_x(); + void set_x(float v); + + float get_y(); + void set_y(float v); + + float get_scale_x(); + void set_scale_x(float v); + + float get_scale_y(); + void set_scale_y(float v); +}; + +#endif//GODOT_SPINESKELETON_H diff --git a/spine-godot/spine_godot/SpineSkeletonDataResource.cpp b/spine-godot/spine_godot/SpineSkeletonDataResource.cpp new file mode 100644 index 000000000..977913c61 --- /dev/null +++ b/spine-godot/spine_godot/SpineSkeletonDataResource.cpp @@ -0,0 +1,455 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineSkeletonDataResource.h" + +void SpineSkeletonDataResource::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_atlas_res", "atlas_res"), &SpineSkeletonDataResource::set_atlas_res); + ClassDB::bind_method(D_METHOD("get_atlas_res"), &SpineSkeletonDataResource::get_atlas_res); + ClassDB::bind_method(D_METHOD("set_skeleton_json_res", "skeleton_json_res"), &SpineSkeletonDataResource::set_skeleton_json_res); + ClassDB::bind_method(D_METHOD("get_skeleton_json_res"), &SpineSkeletonDataResource::get_skeleton_json_res); + ClassDB::bind_method(D_METHOD("is_skeleton_data_loaded"), &SpineSkeletonDataResource::is_skeleton_data_loaded); + ClassDB::bind_method(D_METHOD("find_animation", "animation_name"), &SpineSkeletonDataResource::find_animation); + ClassDB::bind_method(D_METHOD("get_sk_name"), &SpineSkeletonDataResource::get_sk_name); + ClassDB::bind_method(D_METHOD("set_sk_name", "sk_name"), &SpineSkeletonDataResource::set_sk_name); + ClassDB::bind_method(D_METHOD("get_x"), &SpineSkeletonDataResource::get_x); + ClassDB::bind_method(D_METHOD("set_x", "v"), &SpineSkeletonDataResource::set_x); + ClassDB::bind_method(D_METHOD("get_y"), &SpineSkeletonDataResource::get_y); + ClassDB::bind_method(D_METHOD("set_y", "v"), &SpineSkeletonDataResource::set_y); + ClassDB::bind_method(D_METHOD("get_width"), &SpineSkeletonDataResource::get_width); + ClassDB::bind_method(D_METHOD("get_height"), &SpineSkeletonDataResource::get_height); + ClassDB::bind_method(D_METHOD("get_version"), &SpineSkeletonDataResource::get_version); + ClassDB::bind_method(D_METHOD("get_fps"), &SpineSkeletonDataResource::get_fps); + ClassDB::bind_method(D_METHOD("set_fps", "v"), &SpineSkeletonDataResource::set_fps); + + ClassDB::bind_method(D_METHOD("find_bone", "bone_name"), &SpineSkeletonDataResource::find_bone); + ClassDB::bind_method(D_METHOD("find_slot", "slot_name"), &SpineSkeletonDataResource::find_slot); + ClassDB::bind_method(D_METHOD("find_skin", "skin_name"), &SpineSkeletonDataResource::find_skin); + ClassDB::bind_method(D_METHOD("find_event", "event_data_name"), &SpineSkeletonDataResource::find_event); + ClassDB::bind_method(D_METHOD("find_ik_constraint_data", "constraint_name"), &SpineSkeletonDataResource::find_ik_constraint); + ClassDB::bind_method(D_METHOD("find_transform_constraint_data", "constraint_name"), &SpineSkeletonDataResource::find_transform_constraint); + ClassDB::bind_method(D_METHOD("find_path_constraint_data", "constraint_name"), &SpineSkeletonDataResource::find_path_constraint); + ClassDB::bind_method(D_METHOD("get_all_bone_data"), &SpineSkeletonDataResource::get_bones); + ClassDB::bind_method(D_METHOD("get_all_slot_data"), &SpineSkeletonDataResource::get_slots); + ClassDB::bind_method(D_METHOD("get_skins"), &SpineSkeletonDataResource::get_skins); + ClassDB::bind_method(D_METHOD("get_default_skin"), &SpineSkeletonDataResource::get_default_skin); + ClassDB::bind_method(D_METHOD("set_default_skin", "v"), &SpineSkeletonDataResource::set_default_skin); + ClassDB::bind_method(D_METHOD("get_all_event_data"), &SpineSkeletonDataResource::get_events); + ClassDB::bind_method(D_METHOD("get_animations"), &SpineSkeletonDataResource::get_animations); + ClassDB::bind_method(D_METHOD("get_all_ik_constraint_data"), &SpineSkeletonDataResource::get_ik_constraints); + ClassDB::bind_method(D_METHOD("get_all_transform_constraint_data"), &SpineSkeletonDataResource::get_transform_constraints); + ClassDB::bind_method(D_METHOD("get_all_path_constraint_data"), &SpineSkeletonDataResource::get_path_constraints); + + ADD_SIGNAL(MethodInfo("skeleton_data_loaded")); + ADD_SIGNAL(MethodInfo("atlas_res_changed")); + ADD_SIGNAL(MethodInfo("skeleton_json_res_changed")); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "atlas_res", PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "SpineAtlasResource"), "set_atlas_res", "get_atlas_res"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "skeleton_json_res", PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "SpineSkeletonJsonDataResource"), "set_skeleton_json_res", "get_skeleton_json_res"); +} + +SpineSkeletonDataResource::SpineSkeletonDataResource() : valid(false), spine_object(false), skeleton_data(NULL) { +} +SpineSkeletonDataResource::~SpineSkeletonDataResource() { + if (skeleton_data && !spine_object) { + delete skeleton_data; + skeleton_data = NULL; + } +} + +bool SpineSkeletonDataResource::is_skeleton_data_loaded() const { + return valid || spine_object; +} + +void SpineSkeletonDataResource::load_res(spine::Atlas *a, const String &json_string) { + if (json_string.empty()) return; + auto path = get_path(); + spine::SkeletonJson json(a); + auto temp_skeleton_data = json.readSkeletonData(json_string.utf8()); + if (!temp_skeleton_data) { + print_error(String("Error happened while loading skeleton json data: ") + path); + print_error(String("Error msg: ") + json.getError().buffer()); + return; + } + if (skeleton_data) { + delete skeleton_data; + skeleton_data = NULL; + } + skeleton_data = temp_skeleton_data; + + valid = true; + // print_line("Skeleton json data loaded!"); +} + +void SpineSkeletonDataResource::update_skeleton_data() { + if (atlas_res.is_valid() && skeleton_json_res.is_valid()) { + load_res(atlas_res->get_spine_atlas(), skeleton_json_res->get_json_string()); + if (valid) { + emit_signal("skeleton_data_loaded"); + } + } +} + +void SpineSkeletonDataResource::set_atlas_res(const Ref &a) { + atlas_res = a; + valid = false; + emit_signal("atlas_res_changed"); + update_skeleton_data(); +} +Ref SpineSkeletonDataResource::get_atlas_res() { + if (spine_object) { + print_line("Getting atlas res from a spine_object skeleton! The result may be NULL!"); + } + return atlas_res; +} + +void SpineSkeletonDataResource::set_skeleton_json_res(const Ref &s) { + skeleton_json_res = s; + valid = false; + // print_line("skeleton_json_res_changed emitted"); + emit_signal("skeleton_json_res_changed"); + update_skeleton_data(); +} +Ref SpineSkeletonDataResource::get_skeleton_json_res() { + if (spine_object) { + print_line("Getting atlas res from a spine_object skeleton! The result may be NULL!"); + } + return skeleton_json_res; +} + +#define CHECK_V \ + if (!is_skeleton_data_loaded()) { \ + ERR_PRINT("skeleton data has not loaded yet!"); \ + return; \ + } +#define CHECK_X(x) \ + if (!is_skeleton_data_loaded()) { \ + ERR_PRINT("skeleton data has not loaded yet!"); \ + return x; \ + } +#define S_T(x) (spine::String(x.utf8())) +Ref SpineSkeletonDataResource::find_animation(const String &animation_name) { + CHECK_X(NULL); + if (animation_name.empty()) { + return NULL; + } + auto a = skeleton_data->findAnimation(S_T(animation_name)); + if (!a) return NULL; + Ref sa(memnew(SpineAnimation)); + sa->set_spine_object(a); + return sa; +} +String SpineSkeletonDataResource::get_sk_name() { + CHECK_X("error"); + return skeleton_data->getName().buffer(); +} +void SpineSkeletonDataResource::set_sk_name(const String &v) { + CHECK_V; + skeleton_data->setName(S_T(v)); +} +float SpineSkeletonDataResource::get_x() { + CHECK_X(0); + return skeleton_data->getX(); +} +void SpineSkeletonDataResource::set_x(float v) { + CHECK_V; + skeleton_data->setX(v); +} +float SpineSkeletonDataResource::get_y() { + CHECK_X(0); + return skeleton_data->getY(); +} +void SpineSkeletonDataResource::set_y(float v) { + CHECK_V; + skeleton_data->setY(v); +} +float SpineSkeletonDataResource::get_width() { + CHECK_X(0); + return skeleton_data->getWidth(); +} +float SpineSkeletonDataResource::get_height() { + CHECK_X(0); + return skeleton_data->getHeight(); +} +String SpineSkeletonDataResource::get_version() { + CHECK_X("error"); + return skeleton_data->getVersion().buffer(); +} +float SpineSkeletonDataResource::get_fps() { + CHECK_X(0); + return skeleton_data->getFps(); +} +void SpineSkeletonDataResource::set_fps(float v) { + CHECK_V; + skeleton_data->setFps(v); +} + +Ref SpineSkeletonDataResource::find_bone(const String &bone_name) { + if (bone_name.empty()) return NULL; + auto b = skeleton_data->findBone(S_T(bone_name)); + if (b == NULL) return NULL; + Ref gd_b(memnew(SpineBoneData)); + gd_b->set_spine_object(b); + return gd_b; +} + +Ref SpineSkeletonDataResource::find_slot(const String &slot_name) { + if (slot_name.empty()) return NULL; + auto b = skeleton_data->findSlot(S_T(slot_name)); + if (b == NULL) return NULL; + Ref gd_b(memnew(SpineSlotData)); + gd_b->set_spine_object(b); + return gd_b; +} + +Ref SpineSkeletonDataResource::find_skin(const String &skin_name) { + if (skin_name.empty()) return NULL; + auto b = skeleton_data->findSkin(S_T(skin_name)); + if (b == NULL) return NULL; + Ref gd_b(memnew(SpineSkin)); + gd_b->set_spine_object(b); + return gd_b; +} + +Ref SpineSkeletonDataResource::find_event(const String &event_data_name) { + if (event_data_name.empty()) return NULL; + auto b = skeleton_data->findEvent(S_T(event_data_name)); + if (b == NULL) return NULL; + Ref gd_b(memnew(SpineEventData)); + gd_b->set_spine_object(b); + return gd_b; +} + +Ref SpineSkeletonDataResource::find_ik_constraint(const String &constraint_name) { + if (constraint_name.empty()) return NULL; + auto b = skeleton_data->findIkConstraint(S_T(constraint_name)); + if (b == NULL) return NULL; + Ref gd_b(memnew(SpineIkConstraintData)); + gd_b->set_spine_object(b); + return gd_b; +} +Ref SpineSkeletonDataResource::find_transform_constraint(const String &constraint_name) { + if (constraint_name.empty()) return NULL; + auto b = skeleton_data->findTransformConstraint(S_T(constraint_name)); + if (b == NULL) return NULL; + Ref gd_b(memnew(SpineTransformConstraintData)); + gd_b->set_spine_object(b); + return gd_b; +} +Ref SpineSkeletonDataResource::find_path_constraint(const String &constraint_name) { + if (constraint_name.empty()) return NULL; + auto b = skeleton_data->findPathConstraint(S_T(constraint_name)); + if (b == NULL) return NULL; + Ref gd_b(memnew(SpinePathConstraintData)); + gd_b->set_spine_object(b); + return gd_b; +} + +Array SpineSkeletonDataResource::get_bones() { + auto bs = skeleton_data->getBones(); + Array gd_bs; + gd_bs.resize(bs.size()); + for (size_t i = 0; i < bs.size(); ++i) { + if (bs[i] == NULL) gd_bs[i] = Ref(NULL); + else { + Ref gd_b(memnew(SpineBoneData)); + gd_b->set_spine_object(bs[i]); + gd_bs[i] = gd_b; + } + } + return gd_bs; +} +Array SpineSkeletonDataResource::get_slots() { + auto bs = skeleton_data->getSlots(); + Array gd_bs; + gd_bs.resize(bs.size()); + for (size_t i = 0; i < bs.size(); ++i) { + if (bs[i] == NULL) gd_bs[i] = Ref(NULL); + else { + Ref gd_b(memnew(SpineSlotData)); + gd_b->set_spine_object(bs[i]); + gd_bs[i] = gd_b; + } + } + return gd_bs; +} +Array SpineSkeletonDataResource::get_skins() const { + auto bs = skeleton_data->getSkins(); + Array gd_bs; + gd_bs.resize(bs.size()); + for (size_t i = 0; i < bs.size(); ++i) { + if (bs[i] == NULL) gd_bs[i] = Ref(NULL); + else { + Ref gd_b(memnew(SpineSkin)); + gd_b->set_spine_object(bs[i]); + gd_bs[i] = gd_b; + } + } + return gd_bs; +} + +Ref SpineSkeletonDataResource::get_default_skin() { + auto b = skeleton_data->getDefaultSkin(); + if (b == NULL) return NULL; + Ref gd_b(memnew(SpineSkin)); + gd_b->set_spine_object(b); + return gd_b; +} +void SpineSkeletonDataResource::set_default_skin(Ref v) { + if (v.is_valid()) { + skeleton_data->setDefaultSkin(v->get_spine_object()); + } else + skeleton_data->setDefaultSkin(NULL); +} + +Array SpineSkeletonDataResource::get_events() { + auto bs = skeleton_data->getEvents(); + Array gd_bs; + gd_bs.resize(bs.size()); + for (size_t i = 0; i < bs.size(); ++i) { + if (bs[i] == NULL) gd_bs[i] = Ref(NULL); + else { + Ref gd_b(memnew(SpineEventData)); + gd_b->set_spine_object(bs[i]); + gd_bs[i] = gd_b; + } + } + return gd_bs; +} +Array SpineSkeletonDataResource::get_animations() { + auto bs = skeleton_data->getAnimations(); + Array gd_bs; + gd_bs.resize(bs.size()); + for (size_t i = 0; i < bs.size(); ++i) { + if (bs[i] == NULL) gd_bs[i] = Ref(NULL); + else { + Ref gd_b(memnew(SpineAnimation)); + gd_b->set_spine_object(bs[i]); + gd_bs[i] = gd_b; + } + } + return gd_bs; +} +Array SpineSkeletonDataResource::get_ik_constraints() { + auto bs = skeleton_data->getIkConstraints(); + Array gd_bs; + gd_bs.resize(bs.size()); + for (size_t i = 0; i < bs.size(); ++i) { + if (bs[i] == NULL) gd_bs[i] = Ref(NULL); + else { + Ref gd_b(memnew(SpineIkConstraintData)); + gd_b->set_spine_object(bs[i]); + gd_bs[i] = gd_b; + } + } + return gd_bs; +} +Array SpineSkeletonDataResource::get_transform_constraints() { + auto bs = skeleton_data->getTransformConstraints(); + Array gd_bs; + gd_bs.resize(bs.size()); + for (size_t i = 0; i < bs.size(); ++i) { + if (bs[i] == NULL) gd_bs[i] = Ref(NULL); + else { + Ref gd_b(memnew(SpineTransformConstraintData)); + gd_b->set_spine_object(bs[i]); + gd_bs[i] = gd_b; + } + } + return gd_bs; +} +Array SpineSkeletonDataResource::get_path_constraints() { + auto bs = skeleton_data->getPathConstraints(); + Array gd_bs; + gd_bs.resize(bs.size()); + for (size_t i = 0; i < bs.size(); ++i) { + if (bs[i] == NULL) gd_bs[i] = Ref(NULL); + else { + Ref gd_b(memnew(SpinePathConstraintData)); + gd_b->set_spine_object(bs[i]); + gd_bs[i] = gd_b; + } + } + return gd_bs; +} +#undef S_T +#undef CHECK_V +#undef CHECK_X + +//External feature functions +void SpineSkeletonDataResource::get_animation_names(Vector &res) const { + res.clear(); + if (!is_skeleton_data_loaded()) { + return; + } + auto as = skeleton_data->getAnimations(); + for (size_t i = 0; i < as.size(); ++i) { + auto a = as[i]; + if (a) { + res.push_back(a->getName().buffer()); + } else { + res.push_back(""); + } + } +} +void SpineSkeletonDataResource::get_skin_names(Vector &res) const { + res.clear(); + if (!is_skeleton_data_loaded()) { + return; + } + auto as = get_skins(); + res.resize(as.size()); + for (size_t i = 0; i < as.size(); ++i) { + auto a = Ref(as[i]); + if (a.is_valid()) { + res.push_back(a->get_skin_name()); + } else { + res.push_back(""); + } + } +} + +void SpineSkeletonDataResource::_get_property_list(List *p_list) const { + PropertyInfo p; + Vector res; + + p.name = "animations"; + p.type = Variant::STRING; + get_animation_names(res); + p.hint_string = String(",").join(res); + p.hint = PROPERTY_HINT_ENUM; + p_list->push_back(p); + + p.name = "skins"; + p.type = Variant::STRING; + get_skin_names(res); + p.hint_string = String(",").join(res); + p.hint = PROPERTY_HINT_ENUM; + p_list->push_back(p); +} diff --git a/spine-godot/spine_godot/SpineSkeletonDataResource.h b/spine-godot/spine_godot/SpineSkeletonDataResource.h new file mode 100644 index 000000000..eaabaa11c --- /dev/null +++ b/spine-godot/spine_godot/SpineSkeletonDataResource.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 GODOT_SPINESKELETONDATARESOURCE_H +#define GODOT_SPINESKELETONDATARESOURCE_H + +#include "core/variant_parser.h" + +#include + +#include "SpineAtlasResource.h" +#include "SpineSkeletonJsonDataResource.h" +#include "SpineAnimation.h" +#include "SpineBoneData.h" +#include "SpineSlotData.h" +#include "SpineSkin.h" +#include "SpineIkConstraintData.h" +#include "SpineTransformConstraintData.h" +#include "SpinePathConstraintData.h" +#include "SpineEventData.h" + +class SpineSkeletonDataResource : public Resource { + GDCLASS(SpineSkeletonDataResource, Resource); + +protected: + static void _bind_methods(); + +private: + Ref atlas_res; + Ref skeleton_json_res; + bool valid; + bool spine_object; + + spine::SkeletonData *skeleton_data; + + void update_skeleton_data(); + +public: + inline void set_spine_object(spine::SkeletonData *s) { + skeleton_data = s; + if (s) + spine_object = true; + } + inline spine::SkeletonData *get_spine_object() { + return skeleton_data; + } + + void load_res(spine::Atlas *a, const String &json_path); + + SpineSkeletonDataResource(); + virtual ~SpineSkeletonDataResource(); + + void _get_property_list(List *p_list) const; + + void set_atlas_res(const Ref &a); + Ref get_atlas_res(); + + void set_skeleton_json_res(const Ref &s); + Ref get_skeleton_json_res(); + + inline spine::SkeletonData *get_skeleton_data() { return skeleton_data; } + + bool is_skeleton_data_loaded() const; + + void get_animation_names(Vector &l) const; + void get_skin_names(Vector &l) const; + + // spine api + Ref find_bone(const String &bone_name); + + Ref find_slot(const String &slot_name); + + Ref find_skin(const String &skin_name); + + Ref find_event(const String &event_data_name); + + Ref find_animation(const String &animation_name); + + Ref find_ik_constraint(const String &constraint_name); + Ref find_transform_constraint(const String &constraint_name); + Ref find_path_constraint(const String &constraint_name); + + Array get_bones(); + Array get_slots(); + Array get_skins() const; + + Ref get_default_skin(); + void set_default_skin(Ref v); + + Array get_events(); + Array get_animations(); + Array get_ik_constraints(); + Array get_transform_constraints(); + Array get_path_constraints(); + + String get_sk_name(); + void set_sk_name(const String &v); + + float get_x(); + void set_x(float v); + + float get_y(); + void set_y(float v); + + float get_width(); + float get_height(); + + String get_version(); + + float get_fps(); + void set_fps(float v); +}; + +#endif//GODOT_SPINESKELETONDATARESOURCE_H diff --git a/spine-godot/spine_godot/SpineSkeletonJsonDataResource.cpp b/spine-godot/spine_godot/SpineSkeletonJsonDataResource.cpp new file mode 100644 index 000000000..d332a791a --- /dev/null +++ b/spine-godot/spine_godot/SpineSkeletonJsonDataResource.cpp @@ -0,0 +1,55 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineSkeletonJsonDataResource.h" + + +void SpineSkeletonJsonDataResource::_bind_methods() { +} + +Error SpineSkeletonJsonDataResource::load_from_file(const String &p_path) { + Error err; + + json_string = FileAccess::get_file_as_string(p_path, &err); + return err; +} + +Error SpineSkeletonJsonDataResource::save_to_file(const String &p_path) { + Error err; + FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &err); + if (err != OK) { + if (file) file->close(); + return err; + } + + file->store_string(json_string); + file->close(); + + return OK; +} diff --git a/spine-godot/spine_godot/SpineSkeletonJsonDataResource.h b/spine-godot/spine_godot/SpineSkeletonJsonDataResource.h new file mode 100644 index 000000000..8b6045bf6 --- /dev/null +++ b/spine-godot/spine_godot/SpineSkeletonJsonDataResource.h @@ -0,0 +1,50 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef GODOT_SPINESKELETONJSONDATARESOURCE_H +#define GODOT_SPINESKELETONJSONDATARESOURCE_H + +#include "core/variant_parser.h" + +class SpineSkeletonJsonDataResource : public Resource { + GDCLASS(SpineSkeletonJsonDataResource, Resource); + +protected: + static void _bind_methods(); + + String json_string; + +public: + inline const String &get_json_string() { return json_string; } + + Error load_from_file(const String &p_path); + Error save_to_file(const String &p_path); +}; + +#endif//GODOT_SPINESKELETONJSONDATARESOURCE_H diff --git a/spine-godot/spine_godot/SpineSkin.cpp b/spine-godot/spine_godot/SpineSkin.cpp new file mode 100644 index 000000000..b30f01ae5 --- /dev/null +++ b/spine-godot/spine_godot/SpineSkin.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. + *****************************************************************************/ + +#include "SpineSkin.h" + +#include "SpineBoneData.h" +#include "SpineConstraintData.h" + +void SpineSkin::_bind_methods() { + ClassDB::bind_method(D_METHOD("init", "name"), &SpineSkin::init); + ClassDB::bind_method(D_METHOD("set_attachment", "slot_index", "name", "attachment"), &SpineSkin::set_attachment); + ClassDB::bind_method(D_METHOD("get_attachment", "slot_index", "name"), &SpineSkin::get_attachment); + ClassDB::bind_method(D_METHOD("remove_attachment", "slot_index", "name"), &SpineSkin::remove_attachment); + ClassDB::bind_method(D_METHOD("find_names_for_slot", "slot_index"), &SpineSkin::find_names_for_slot); + ClassDB::bind_method(D_METHOD("find_attachments_for_slot", "slot_index"), &SpineSkin::find_attachments_for_slot); + ClassDB::bind_method(D_METHOD("get_skin_name"), &SpineSkin::get_skin_name); + ClassDB::bind_method(D_METHOD("add_skin", "other"), &SpineSkin::add_skin); + ClassDB::bind_method(D_METHOD("copy_skin", "other"), &SpineSkin::copy_skin); + ClassDB::bind_method(D_METHOD("get_attachments"), &SpineSkin::get_attachments); + ClassDB::bind_method(D_METHOD("get_all_bone_data"), &SpineSkin::get_bones); + ClassDB::bind_method(D_METHOD("get_all_constraint_data"), &SpineSkin::get_constraint); +} + +SpineSkin::SpineSkin() : skin(NULL) {} +SpineSkin::~SpineSkin() {} + +#define S_T(x) (spine::String(x.utf8())) +Ref SpineSkin::init(const String &name) { + skin = new spine::Skin(S_T(name)); + return this; +} + +void SpineSkin::set_attachment(uint64_t slot_index, const String &name, Ref attachment) { + if (!attachment.is_valid()) { + ERR_PRINT("attachment is invalid!"); + return; + } + skin->setAttachment(slot_index, S_T(name), attachment->get_spine_object()); +} + +Ref SpineSkin::get_attachment(uint64_t slot_index, const String &name) { + auto a = skin->getAttachment(slot_index, S_T(name)); + if (a == NULL) return NULL; + Ref gd_attachment(memnew(SpineAttachment)); + gd_attachment->set_spine_object(a); + return gd_attachment; +} + +void SpineSkin::remove_attachment(uint64_t slot_index, const String &name) { + skin->removeAttachment(slot_index, S_T(name)); +} + +Array SpineSkin::find_names_for_slot(uint64_t slot_index) { + spine::Vector names; + skin->findNamesForSlot(slot_index, names); + Array gd_names; + gd_names.resize(names.size()); + for (size_t i = 0; i < names.size(); ++i) { + gd_names[i] = names[i].buffer(); + } + return gd_names; +} + +Array SpineSkin::find_attachments_for_slot(uint64_t slot_index) { + spine::Vector as; + skin->findAttachmentsForSlot(slot_index, as); + Array gd_as; + gd_as.resize(as.size()); + for (size_t i = 0; i < as.size(); ++i) { + if (as[i] == NULL) gd_as[i] = Ref(NULL); + else { + Ref gd_a(memnew(SpineAttachment)); + gd_a->set_spine_object(as[i]); + gd_as[i] = gd_a; + } + } + return gd_as; +} + +String SpineSkin::get_skin_name() { + return skin->getName().buffer(); +} + +void SpineSkin::add_skin(Ref other) { + if (other.is_valid() && other->get_spine_object()) { + skin->addSkin(other->get_spine_object()); + } else { + ERR_PRINT("other is NULL!"); + } +} + +void SpineSkin::copy_skin(Ref other) { + if (other.is_valid() && other->get_spine_object()) { + skin->copySkin(other->get_spine_object()); + } else { + ERR_PRINT("other is NULL!"); + } +} + +Ref SpineSkin::get_attachments() { + auto *es = new spine::Skin::AttachmentMap::Entries(skin->getAttachments()); + Ref gd_es(memnew(SpineSkinAttachmentMapEntries)); + gd_es->set_spine_object(es); + return gd_es; +} + +Array SpineSkin::get_bones() { + auto bs = skin->getBones(); + Array gd_bs; + gd_bs.resize(bs.size()); + for (size_t i = 0; i < bs.size(); ++i) { + if (bs[i] == NULL) gd_bs[i] = Ref(NULL); + else { + Ref gd_b(memnew(SpineBoneData)); + gd_b->set_spine_object(bs[i]); + gd_bs[i] = gd_b; + } + } + return gd_bs; +} + +Array SpineSkin::get_constraint() { + auto cs = skin->getConstraints(); + Array gd_cs; + gd_cs.resize(cs.size()); + for (size_t i = 0; i < cs.size(); ++i) { + if (cs[i] == NULL) gd_cs[i] = Ref(NULL); + else { + Ref gd_c(memnew(SpineConstraintData)); + gd_c->set_spine_object(cs[i]); + gd_cs[i] = gd_c; + } + } + return gd_cs; +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineSkin.h b/spine-godot/spine_godot/SpineSkin.h new file mode 100644 index 000000000..3e1780f2a --- /dev/null +++ b/spine-godot/spine_godot/SpineSkin.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 GODOT_SPINESKIN_H +#define GODOT_SPINESKIN_H + +#include "core/variant_parser.h" + +#include + +#include "SpineAttachment.h" +#include "SpineSkinAttachmentMapEntries.h" + +class SpineSkin : public Reference { + GDCLASS(SpineSkin, Reference); + +protected: + static void _bind_methods(); + +private: + spine::Skin *skin; + +public: + SpineSkin(); + ~SpineSkin(); + + inline void set_spine_object(spine::Skin *s) { + skin = s; + } + spine::Skin *get_spine_object() { + return skin; + } + + Ref init(const String &name); + + void set_attachment(uint64_t slot_index, const String &name, Ref attachment); + + Ref get_attachment(uint64_t slot_index, const String &name); + + void remove_attachment(uint64_t slot_index, const String &name); + + Array find_names_for_slot(uint64_t slot_index); + + Array find_attachments_for_slot(uint64_t slot_index); + + String get_skin_name(); + + void add_skin(Ref other); + + void copy_skin(Ref other); + + Ref get_attachments(); + + Array get_bones(); + + Array get_constraint(); +}; + +#endif//GODOT_SPINESKIN_H diff --git a/spine-godot/spine_godot/SpineSkinAttachmentMapEntries.cpp b/spine-godot/spine_godot/SpineSkinAttachmentMapEntries.cpp new file mode 100644 index 000000000..67089b011 --- /dev/null +++ b/spine-godot/spine_godot/SpineSkinAttachmentMapEntries.cpp @@ -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. + *****************************************************************************/ + +#include "SpineSkinAttachmentMapEntries.h" + +void SpineSkinAttachmentMapEntry::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_slot_index"), &SpineSkinAttachmentMapEntry::get_slot_index); + ClassDB::bind_method(D_METHOD("set_slot_index", "v"), &SpineSkinAttachmentMapEntry::set_slot_index); + ClassDB::bind_method(D_METHOD("get_entry_name"), &SpineSkinAttachmentMapEntry::get_entry_name); + ClassDB::bind_method(D_METHOD("set_entry_name", "v"), &SpineSkinAttachmentMapEntry::set_entry_name); + ClassDB::bind_method(D_METHOD("get_attachment"), &SpineSkinAttachmentMapEntry::get_attachment); + ClassDB::bind_method(D_METHOD("set_attachment", "v"), &SpineSkinAttachmentMapEntry::set_attachment); +} + +SpineSkinAttachmentMapEntry::SpineSkinAttachmentMapEntry() : entry(NULL) {} +SpineSkinAttachmentMapEntry::~SpineSkinAttachmentMapEntry() {} + +uint64_t SpineSkinAttachmentMapEntry::get_slot_index() { + return entry->_slotIndex; +} +void SpineSkinAttachmentMapEntry::set_slot_index(uint64_t v) { + entry->_slotIndex = v; +} + +String SpineSkinAttachmentMapEntry::get_entry_name() { + return entry->_name.buffer(); +} +void SpineSkinAttachmentMapEntry::set_entry_name(const String &v) { + entry->_name = spine::String(v.utf8()); +} + +Ref SpineSkinAttachmentMapEntry::get_attachment() { + if (entry->_attachment == NULL) return NULL; + Ref gd_attachment(memnew(SpineAttachment)); + gd_attachment->set_spine_object(entry->_attachment); + return gd_attachment; +} +void SpineSkinAttachmentMapEntry::set_attachment(Ref v) { + if (v.is_valid()) { + entry->_attachment = v->get_spine_object(); + } else { + entry->_attachment = NULL; + } +} + +void SpineSkinAttachmentMapEntries::_bind_methods() { + ClassDB::bind_method(D_METHOD("has_next"), &SpineSkinAttachmentMapEntries::has_next); + ClassDB::bind_method(D_METHOD("next"), &SpineSkinAttachmentMapEntries::next); +} + +SpineSkinAttachmentMapEntries::SpineSkinAttachmentMapEntries() : entries(NULL) {} +SpineSkinAttachmentMapEntries::~SpineSkinAttachmentMapEntries() { + if (entries) { + delete entries; + return; + } +} + +bool SpineSkinAttachmentMapEntries::has_next() { + return entries->hasNext(); +} +Ref SpineSkinAttachmentMapEntries::next() { + auto &e = entries->next(); + Ref gd_entry(memnew(SpineSkinAttachmentMapEntry)); + gd_entry->set_spine_object(&e); + return gd_entry; +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineSkinAttachmentMapEntries.h b/spine-godot/spine_godot/SpineSkinAttachmentMapEntries.h new file mode 100644 index 000000000..b0f3922ef --- /dev/null +++ b/spine-godot/spine_godot/SpineSkinAttachmentMapEntries.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 GODOT_SPINESKINATTACHMENTMAPENTRIES_H +#define GODOT_SPINESKINATTACHMENTMAPENTRIES_H + +#include "core/variant_parser.h" + +#include + +#include "SpineAttachment.h" + +class SpineSkinAttachmentMapEntry : public Reference { + GDCLASS(SpineSkinAttachmentMapEntry, Reference); + +protected: + static void _bind_methods(); + +private: + spine::Skin::AttachmentMap::Entry *entry; + +public: + SpineSkinAttachmentMapEntry(); + ~SpineSkinAttachmentMapEntry(); + + inline void set_spine_object(spine::Skin::AttachmentMap::Entry *e) { + entry = e; + } + inline spine::Skin::AttachmentMap::Entry *get_spine_object() { + return entry; + } + + uint64_t get_slot_index(); + void set_slot_index(uint64_t v); + + String get_entry_name(); + void set_entry_name(const String &v); + + Ref get_attachment(); + void set_attachment(Ref v); +}; + +class SpineSkinAttachmentMapEntries : public Reference { + GDCLASS(SpineSkinAttachmentMapEntries, Reference); + +protected: + static void _bind_methods(); + +private: + spine::Skin::AttachmentMap::Entries *entries; + +public: + SpineSkinAttachmentMapEntries(); + ~SpineSkinAttachmentMapEntries(); + + inline void set_spine_object(spine::Skin::AttachmentMap::Entries *e) { + entries = e; + } + inline spine::Skin::AttachmentMap::Entries *get_spine_object() { + return entries; + } + + bool has_next(); + Ref next(); +}; + +#endif//GODOT_SPINESKINATTACHMENTMAPENTRIES_H diff --git a/spine-godot/spine_godot/SpineSlot.cpp b/spine-godot/spine_godot/SpineSlot.cpp new file mode 100644 index 000000000..14149b9e1 --- /dev/null +++ b/spine-godot/spine_godot/SpineSlot.cpp @@ -0,0 +1,141 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineSlot.h" + +#include "SpineBone.h" +#include "SpineSkeleton.h" + + +void SpineSlot::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_to_setup_pos"), &SpineSlot::set_to_setup_pos); + ClassDB::bind_method(D_METHOD("get_data"), &SpineSlot::get_data); + ClassDB::bind_method(D_METHOD("get_bone"), &SpineSlot::get_bone); + ClassDB::bind_method(D_METHOD("get_skeleton"), &SpineSlot::get_skeleton); + ClassDB::bind_method(D_METHOD("get_color"), &SpineSlot::get_color); + ClassDB::bind_method(D_METHOD("set_color"), &SpineSlot::set_color); + ClassDB::bind_method(D_METHOD("get_dark_color"), &SpineSlot::get_dark_color); + ClassDB::bind_method(D_METHOD("set_dark_color", "v"), &SpineSlot::set_dark_color); + ClassDB::bind_method(D_METHOD("has_dark_color"), &SpineSlot::has_dark_color); + ClassDB::bind_method(D_METHOD("get_attachment"), &SpineSlot::get_attachment); + ClassDB::bind_method(D_METHOD("set_attachment", "v"), &SpineSlot::set_attachment); + ClassDB::bind_method(D_METHOD("get_attachment_state"), &SpineSlot::get_attachment_state); + ClassDB::bind_method(D_METHOD("set_attachment_state", "v"), &SpineSlot::set_attachment_state); + ClassDB::bind_method(D_METHOD("get_deform"), &SpineSlot::get_deform); + ClassDB::bind_method(D_METHOD("set_deform", "v"), &SpineSlot::set_deform); +} + +SpineSlot::SpineSlot() : slot(NULL) {} +SpineSlot::~SpineSlot() {} + +void SpineSlot::set_to_setup_pos() { + slot->setToSetupPose(); +} + +Ref SpineSlot::get_data() { + auto &sd = slot->getData(); + Ref gd_sd(memnew(SpineSlotData)); + gd_sd->set_spine_object(&sd); + return gd_sd; +} + +Ref SpineSlot::get_bone() { + auto &b = slot->getBone(); + Ref gd_b(memnew(SpineBone)); + gd_b->set_spine_object(&b); + return gd_b; +} + +Ref SpineSlot::get_skeleton() { + auto &s = slot->getSkeleton(); + Ref gd_s(memnew(SpineSkeleton)); + gd_s->set_spine_object(&s); + return gd_s; +} + +Color SpineSlot::get_color() { + auto &c = slot->getColor(); + return Color(c.r, c.g, c.b, c.a); +} +void SpineSlot::set_color(Color v) { + auto &c = slot->getColor(); + c.set(v.r, v.g, v.b, v.a); +} + +Color SpineSlot::get_dark_color() { + auto &c = slot->getDarkColor(); + return Color(c.r, c.g, c.b, c.a); +} +void SpineSlot::set_dark_color(Color v) { + auto &c = slot->getDarkColor(); + c.set(v.r, v.g, v.b, v.a); +} + +bool SpineSlot::has_dark_color() { + return slot->hasDarkColor(); +} + +Ref SpineSlot::get_attachment() { + auto a = slot->getAttachment(); + if (a == NULL) return NULL; + Ref gd_a(memnew(SpineAttachment)); + gd_a->set_spine_object(a); + return gd_a; +} +void SpineSlot::set_attachment(Ref v) { + if (v.is_valid()) { + slot->setAttachment(v->get_spine_object()); + } else { + slot->setAttachment(NULL); + } +} + +int SpineSlot::get_attachment_state() { + return slot->getAttachmentState(); +} +void SpineSlot::set_attachment_state(int v) { + slot->setAttachmentState(v); +} + +Array SpineSlot::get_deform() { + auto &ds = slot->getDeform(); + Array gd_ds; + gd_ds.resize(ds.size()); + for (size_t i = 0; i < ds.size(); ++i) { + gd_ds[i] = ds[i]; + } + return gd_ds; +} +void SpineSlot::set_deform(Array gd_ds) { + auto &ds = slot->getDeform(); + ds.setSize(gd_ds.size(), 0); + for (size_t i = 0; i < gd_ds.size(); ++i) { + ds[i] = gd_ds[i]; + } +} diff --git a/spine-godot/spine_godot/SpineSlot.h b/spine-godot/spine_godot/SpineSlot.h new file mode 100644 index 000000000..afca412af --- /dev/null +++ b/spine-godot/spine_godot/SpineSlot.h @@ -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. + *****************************************************************************/ + +#ifndef GODOT_SPINESLOT_H +#define GODOT_SPINESLOT_H + +#include "core/variant_parser.h" + +#include + +#include "SpineSlotData.h" +#include "SpineAttachment.h" + +class SpineSkeleton; + +class SpineBone; + +class SpineSlot : public Reference { + GDCLASS(SpineSlot, Reference); + +protected: + static void _bind_methods(); + +private: + spine::Slot *slot; + +public: + SpineSlot(); + ~SpineSlot(); + + inline void set_spine_object(spine::Slot *s) { + slot = s; + } + inline spine::Slot *get_spine_object() { + return slot; + } + + void set_to_setup_pos(); + + Ref get_data(); + + Ref get_bone(); + + Ref get_skeleton(); + + Color get_color(); + void set_color(Color v); + + Color get_dark_color(); + void set_dark_color(Color v); + + bool has_dark_color(); + + Ref get_attachment(); + void set_attachment(Ref v); + + int get_attachment_state(); + void set_attachment_state(int v); + + Array get_deform(); + void set_deform(Array v); +}; + +#endif//GODOT_SPINESLOT_H diff --git a/spine-godot/spine_godot/SpineSlotData.cpp b/spine-godot/spine_godot/SpineSlotData.cpp new file mode 100644 index 000000000..bf3c48f20 --- /dev/null +++ b/spine-godot/spine_godot/SpineSlotData.cpp @@ -0,0 +1,114 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineSlotData.h" + +void SpineSlotData::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_index"), &SpineSlotData::get_index); + ClassDB::bind_method(D_METHOD("get_slot_name"), &SpineSlotData::get_slot_name); + ClassDB::bind_method(D_METHOD("get_bone_data"), &SpineSlotData::get_bone_data); + ClassDB::bind_method(D_METHOD("get_color"), &SpineSlotData::get_color); + ClassDB::bind_method(D_METHOD("get_dark_color"), &SpineSlotData::get_dark_color); + ClassDB::bind_method(D_METHOD("has_dark_color"), &SpineSlotData::has_dark_color); + ClassDB::bind_method(D_METHOD("set_has_dark_color", "v"), &SpineSlotData::set_has_dark_color); + ClassDB::bind_method(D_METHOD("get_attachment_name"), &SpineSlotData::get_attachment_name); + ClassDB::bind_method(D_METHOD("set_attachment_name", "v"), &SpineSlotData::set_attachment_name); + ClassDB::bind_method(D_METHOD("get_blend_mode"), &SpineSlotData::get_blend_mode); + ClassDB::bind_method(D_METHOD("set_blend_mode", "v"), &SpineSlotData::set_blend_mode); + + ClassDB::bind_method(D_METHOD("set_color", "v"), &SpineSlotData::set_color); + ClassDB::bind_method(D_METHOD("set_dark_color", "v"), &SpineSlotData::set_dark_color); + + BIND_ENUM_CONSTANT(BLENDMODE_NORMAL); + BIND_ENUM_CONSTANT(BLENDMODE_ADDITIVE); + BIND_ENUM_CONSTANT(BLENDMODE_MULTIPLY); + BIND_ENUM_CONSTANT(BLENDMODE_SCREEN); +} + +SpineSlotData::SpineSlotData() : slot_data(NULL) {} +SpineSlotData::~SpineSlotData() {} + +#define S_T(x) (spine::String(x.utf8())) +int SpineSlotData::get_index() { + return slot_data->getIndex(); +} + +String SpineSlotData::get_slot_name() { + return slot_data->getName().buffer(); +} + +Ref SpineSlotData::get_bone_data() { + auto &bd = slot_data->getBoneData(); + Ref gd_bone_data(memnew(SpineBoneData)); + gd_bone_data->set_spine_object(&bd); + return gd_bone_data; +} + +Color SpineSlotData::get_color() { + auto &c = slot_data->getColor(); + return Color(c.r, c.g, c.b, c.a); +} +void SpineSlotData::set_color(Color v) { + auto &c = slot_data->getColor(); + c.set(v.r, v.g, v.b, v.a); +} + +Color SpineSlotData::get_dark_color() { + auto &c = slot_data->getDarkColor(); + return Color(c.r, c.g, c.b, c.a); +} +void SpineSlotData::set_dark_color(Color v) { + auto &c = slot_data->getDarkColor(); + c.set(v.r, v.g, v.b, v.a); +} + +bool SpineSlotData::has_dark_color() { + return slot_data->hasDarkColor(); +} +void SpineSlotData::set_has_dark_color(bool v) { + slot_data->setHasDarkColor(v); +} + +String SpineSlotData::get_attachment_name() { + return slot_data->getAttachmentName().buffer(); +} +void SpineSlotData::set_attachment_name(const String &v) { + slot_data->setAttachmentName(S_T(v)); +} + +SpineSlotData::BlendMode SpineSlotData::get_blend_mode() { + auto bm = (int) slot_data->getBlendMode(); + return (BlendMode) bm; +} +void SpineSlotData::set_blend_mode(BlendMode v) { + auto bm = (int) v; + slot_data->setBlendMode((spine::BlendMode) bm); +} + +#undef S_T \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineSlotData.h b/spine-godot/spine_godot/SpineSlotData.h new file mode 100644 index 000000000..1778bba55 --- /dev/null +++ b/spine-godot/spine_godot/SpineSlotData.h @@ -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. + *****************************************************************************/ + +#ifndef GODOT_SPINESLOTDATA_H +#define GODOT_SPINESLOTDATA_H +#include "core/variant_parser.h" + +#include + +#include "SpineBoneData.h" + +class SpineSlotData : public Reference { + GDCLASS(SpineSlotData, Reference); + +protected: + static void _bind_methods(); + +private: + spine::SlotData *slot_data; + +public: + SpineSlotData(); + ~SpineSlotData(); + + inline void set_spine_object(spine::SlotData *s) { + slot_data = s; + } + inline spine::SlotData *get_spine_object() { + return slot_data; + } + + enum BlendMode { + BLENDMODE_NORMAL = 0, + BLENDMODE_ADDITIVE, + BLENDMODE_MULTIPLY, + BLENDMODE_SCREEN + }; + + int get_index(); + + String get_slot_name(); + + Ref get_bone_data(); + + Color get_color(); + void set_color(Color c); + + Color get_dark_color(); + void set_dark_color(Color c); + + bool has_dark_color(); + void set_has_dark_color(bool v); + + String get_attachment_name(); + void set_attachment_name(const String &v); + + BlendMode get_blend_mode(); + void set_blend_mode(BlendMode v); +}; + +VARIANT_ENUM_CAST(SpineSlotData::BlendMode); +#endif//GODOT_SPINESLOTDATA_H diff --git a/spine-godot/spine_godot/SpineSprite.cpp b/spine-godot/spine_godot/SpineSprite.cpp new file mode 100644 index 000000000..dedb91940 --- /dev/null +++ b/spine-godot/spine_godot/SpineSprite.cpp @@ -0,0 +1,966 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineSprite.h" + +#include "SpineEvent.h" +#include "SpineTrackEntry.h" + +void SpineSprite::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_animation_state_data_res", "animation_state_data_res"), &SpineSprite::set_animation_state_data_res); + ClassDB::bind_method(D_METHOD("get_animation_state_data_res"), &SpineSprite::get_animation_state_data_res); + ClassDB::bind_method(D_METHOD("_on_animation_data_created"), &SpineSprite::_on_animation_data_created); + ClassDB::bind_method(D_METHOD("get_skeleton"), &SpineSprite::get_skeleton); + ClassDB::bind_method(D_METHOD("get_animation_state"), &SpineSprite::get_animation_state); + ClassDB::bind_method(D_METHOD("_on_animation_data_changed"), &SpineSprite::_on_animation_data_changed); + + ClassDB::bind_method(D_METHOD("get_current_animations"), &SpineSprite::get_current_animations); + ClassDB::bind_method(D_METHOD("set_current_animations", "current_animations"), &SpineSprite::set_current_animations); + + ClassDB::bind_method(D_METHOD("get_select_track_id"), &SpineSprite::get_select_track_id); + ClassDB::bind_method(D_METHOD("set_select_track_id", "track_id"), &SpineSprite::set_select_track_id); + ClassDB::bind_method(D_METHOD("get_clear_track"), &SpineSprite::get_clear_track); + ClassDB::bind_method(D_METHOD("set_clear_track", "v"), &SpineSprite::set_clear_track); + ClassDB::bind_method(D_METHOD("get_clear_tracks"), &SpineSprite::get_clear_tracks); + ClassDB::bind_method(D_METHOD("set_clear_tracks", "v"), &SpineSprite::set_clear_tracks); + + ClassDB::bind_method(D_METHOD("get_empty_animation_duration"), &SpineSprite::get_empty_animation_duration); + ClassDB::bind_method(D_METHOD("set_empty_animation_duration", "track_id"), &SpineSprite::set_empty_animation_duration); + ClassDB::bind_method(D_METHOD("get_set_empty_animation"), &SpineSprite::get_set_empty_animation); + ClassDB::bind_method(D_METHOD("set_set_empty_animation", "v"), &SpineSprite::set_set_empty_animation); + ClassDB::bind_method(D_METHOD("get_set_empty_animations"), &SpineSprite::get_set_empty_animations); + ClassDB::bind_method(D_METHOD("set_set_empty_animations", "v"), &SpineSprite::set_set_empty_animations); + + ClassDB::bind_method(D_METHOD("get_bind_slot_nodes"), &SpineSprite::get_bind_slot_nodes); + ClassDB::bind_method(D_METHOD("set_bind_slot_nodes", "v"), &SpineSprite::set_bind_slot_nodes); + ClassDB::bind_method(D_METHOD("get_overlap"), &SpineSprite::get_overlap); + ClassDB::bind_method(D_METHOD("set_overlap", "v"), &SpineSprite::set_overlap); + + ClassDB::bind_method(D_METHOD("bone_get_global_transform", "bone_name"), &SpineSprite::bone_get_global_transform); + ClassDB::bind_method(D_METHOD("bone_set_global_transform", "bone_name", "global_transform"), &SpineSprite::bone_set_global_transform); + + ClassDB::bind_method(D_METHOD("set_process_mode", "v"), &SpineSprite::set_process_mode); + ClassDB::bind_method(D_METHOD("get_process_mode"), &SpineSprite::get_process_mode); + + ClassDB::bind_method(D_METHOD("manual_update", "delta"), &SpineSprite::_update_all); + + ADD_SIGNAL(MethodInfo("animation_state_ready", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "skeleton", PROPERTY_HINT_TYPE_STRING, "SpineSkeleton"))); + ADD_SIGNAL(MethodInfo("animation_start", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent"))); + ADD_SIGNAL(MethodInfo("animation_interrupt", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent"))); + ADD_SIGNAL(MethodInfo("animation_end", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent"))); + ADD_SIGNAL(MethodInfo("animation_complete", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent"))); + ADD_SIGNAL(MethodInfo("animation_dispose", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent"))); + ADD_SIGNAL(MethodInfo("animation_event", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent"))); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "animation_state_data_res", PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "SpineAnimationStateDataResource"), "set_animation_state_data_res", "get_animation_state_data_res"); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "overlap"), "set_overlap", "get_overlap"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "bind_slot_nodes"), "set_bind_slot_nodes", "get_bind_slot_nodes"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "custom_skin_resource", PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "SpineCustomSkinResource"), "set_skin", "get_skin"); + + ADD_GROUP("animation", ""); + ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Process,Physics,Manually"), "set_process_mode", "get_process_mode"); + + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "current_animations"), "set_current_animations", "get_current_animations"); + + BIND_ENUM_CONSTANT(ProcessMode::ProcessMode_Process); + BIND_ENUM_CONSTANT(ProcessMode::ProcessMode_Physics); + BIND_ENUM_CONSTANT(ProcessMode::ProcessMode_Manual); +} + +SpineSprite::SpineSprite() : select_track_id(0), empty_animation_duration(0.2f), skeleton_clipper(NULL), + overlap(false), + process_mode(ProcessMode_Process) { + skeleton_clipper = new spine::SkeletonClipping(); +} +SpineSprite::~SpineSprite() { + delete skeleton_clipper; +} + +void SpineSprite::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_READY: { + set_process_internal(process_mode == ProcessMode_Process); + set_physics_process_internal(process_mode == ProcessMode_Physics); + remove_redundant_mesh_instances(); + } break; + case NOTIFICATION_INTERNAL_PROCESS: { + if (process_mode == ProcessMode_Process) + _update_all(get_process_delta_time()); + } break; + case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { + if (process_mode == ProcessMode_Physics) + _update_all(get_physics_process_delta_time()); + } break; + } +} + +void SpineSprite::_update_all(float delta) { + if (!(skeleton.is_valid() && animation_state.is_valid()) || mesh_instances.empty()) + return; + + animation_state->update(delta); + if (!is_visible_in_tree()) + return; + + animation_state->apply(skeleton); + + skeleton->update_world_transform(); + + update_mesh_from_skeleton(skeleton); + + update(); + + update_bind_slot_nodes(); +} + +void SpineSprite::update_bind_slot_nodes() { + if (animation_state.is_valid() && skeleton.is_valid()) { + for (size_t i = 0, n = bind_slot_nodes.size(); i < n; ++i) { + auto a = bind_slot_nodes[i]; + if (a.get_type() == Variant::DICTIONARY) { + auto d = (Dictionary) a; + if (d.has("slot_name") && d.has("node_path")) { + NodePath node_path = d["node_path"]; + Node *node = get_node_or_null(node_path); + if (node && node->is_class("Node2D")) { + Node2D *node2d = (Node2D *) node; + + String slot_name = d["slot_name"]; + auto slot = skeleton->find_slot(slot_name); + if (slot.is_valid()) { + auto bone = slot->get_bone(); + if (bone.is_valid()) { + update_bind_slot_node_transform(bone, node2d); + update_bind_slot_node_draw_order(slot_name, node2d); + } + } + } + } + } else if (a.get_type() == Variant::ARRAY) { + auto as = (Array) a;// 0: slot_name, 1: node_path + if (as.size() >= 2 && as[0].get_type() == Variant::STRING && as[1].get_type() == Variant::NODE_PATH) { + NodePath node_path = as[1]; + Node *node = get_node_or_null(node_path); + if (node && node->is_class("Node2D")) { + Node2D *node2d = (Node2D *) node; + + String slot_name = as[0]; + auto slot = skeleton->find_slot(slot_name); + if (slot.is_valid()) { + auto bone = slot->get_bone(); + if (bone.is_valid()) { + update_bind_slot_node_transform(bone, node2d); + update_bind_slot_node_draw_order(slot_name, node2d); + } + } + } + } + } + } + } +} +void SpineSprite::update_bind_slot_node_transform(Ref bone, Node2D *node2d) { + bone->apply_world_transform_2d(node2d); +} +void SpineSprite::update_bind_slot_node_draw_order(const String &slot_name, Node2D *node2d) { + auto mesh_ins = find_node(slot_name); + if (mesh_ins) { + auto pos = mesh_ins->get_index(); + + // get child + auto node = find_child_node_by_node(node2d); + if (node && node->get_index() != pos + 1) { + move_child(node, pos + 1); + } + } +} +Node *SpineSprite::find_child_node_by_node(Node *node) { + if (node == NULL) return NULL; + while (node && node->get_parent() != this) node = node->get_parent(); + return node; +} + +void SpineSprite::set_animation_state_data_res(const Ref &s) { + animation_state_data_res = s; + + // update run time skeleton and meshes + _on_animation_data_changed(); +} +Ref SpineSprite::get_animation_state_data_res() { + return animation_state_data_res; +} + +void SpineSprite::_on_animation_data_created() { + // print_line("_on_animation_data_created"); + skeleton = Ref(memnew(SpineSkeleton)); + skeleton->load_skeleton(animation_state_data_res->get_skeleton()); + skeleton->set_spine_sprite(this); + // print_line("Run time skeleton created."); + + animation_state = Ref(memnew(SpineAnimationState)); + animation_state->load_animation_state(animation_state_data_res); + animation_state->get_animation_state()->setListener(this); + // print_line("Run time animation state created."); + + // add mesh instances related by current skeleton + animation_state->update(0); + animation_state->apply(skeleton); + skeleton->update_world_transform(); + gen_mesh_from_skeleton(skeleton); + + if (process_mode == ProcessMode_Process) { + _notification(NOTIFICATION_INTERNAL_PROCESS); + } else if (process_mode == ProcessMode_Physics) { + _notification(NOTIFICATION_INTERNAL_PHYSICS_PROCESS); + } + + emit_signal("animation_state_ready", animation_state, skeleton); +} +void SpineSprite::_on_animation_data_changed() { + // print_line("_on_animation_data_changed"); + remove_mesh_instances(); + skeleton.unref(); + animation_state.unref(); + if (!animation_state_data_res.is_null()) { + if (!animation_state_data_res->is_connected("animation_state_data_created", this, "_on_animation_data_created")) + animation_state_data_res->connect("animation_state_data_created", this, "_on_animation_data_created"); + if (!animation_state_data_res->is_connected("skeleton_data_res_changed", this, "_on_animation_data_changed")) + animation_state_data_res->connect("skeleton_data_res_changed", this, "_on_animation_data_changed"); + if (!animation_state_data_res->is_connected("animation_state_data_changed", this, "_on_animation_data_changed")) + animation_state_data_res->connect("animation_state_data_changed", this, "_on_animation_data_changed"); + + if (animation_state_data_res->is_animation_state_data_created()) { + _on_animation_data_created(); + } + } +} + +Ref SpineSprite::get_skeleton() { + return skeleton; +} +Ref SpineSprite::get_animation_state() { + return animation_state; +} + +void SpineSprite::gen_mesh_from_skeleton(Ref s) { + auto sk = s->get_spine_object(); + for (size_t i = 0, n = sk->getSlots().size(); i < n; ++i) { + // creat a mesh instance 2d for every slot + auto mesh_ins = memnew(SpineSpriteMeshInstance2D); + add_child(mesh_ins); + mesh_ins->set_position(Vector2(0, 0)); + mesh_ins->set_owner(this); + mesh_instances.push_back(mesh_ins); + + spine::Slot *slot = sk->getDrawOrder()[i]; + mesh_ins->set_name(slot->getData().getName().buffer()); + Ref gd_slot(memnew(SpineSlot)); + gd_slot->set_spine_object(slot); + mesh_ins->set_slot(gd_slot); + + // creat a material + Ref mat(memnew(CanvasItemMaterial)); + CanvasItemMaterial::BlendMode blend_mode; + switch (slot->getData().getBlendMode()) { + case spine::BlendMode_Normal: + blend_mode = CanvasItemMaterial::BLEND_MODE_MIX; + break; + case spine::BlendMode_Additive: + blend_mode = CanvasItemMaterial::BLEND_MODE_ADD; + break; + case spine::BlendMode_Multiply: + blend_mode = CanvasItemMaterial::BLEND_MODE_MUL; + break; + case spine::BlendMode_Screen: + blend_mode = CanvasItemMaterial::BLEND_MODE_MIX; + break; + default: + blend_mode = CanvasItemMaterial::BLEND_MODE_MIX; + } + mat->set_blend_mode(blend_mode); + mesh_ins->set_material(mat); + } +} + +void SpineSprite::remove_mesh_instances() { + for (size_t i = 0; i < mesh_instances.size(); ++i) { + remove_child(mesh_instances[i]); + memdelete(mesh_instances[i]); + } + mesh_instances.clear(); +} + +void SpineSprite::remove_redundant_mesh_instances() { + Vector ms; + // remove the redundant mesh instances that added by duplicating + // print_line("start clearing"); + for (size_t i = 0, n = get_child_count(); i < n; ++i) { + auto node = get_child(i); + // print_line(String("get a node: ") + node->get_name()); + if (node && node->is_class("SpineSpriteMeshInstance2D")) { + if (mesh_instances.find((SpineSpriteMeshInstance2D *) node) == -1) { + // print_line("marked clear"); + ms.push_back(node); + } + } + } + for (size_t i = 0, n = ms.size(); i < n; ++i) { + remove_child(ms[i]); + memdelete(ms[i]); + } + ms.clear(); + // print_line("end clearing"); +} + +#define TEMP_COPY(t, get_res) \ + do { \ + auto &temp_uvs = get_res; \ + t.setSize(temp_uvs.size(), 0); \ + for (size_t j = 0; j < t.size(); ++j) { \ + t[j] = temp_uvs[j]; \ + } \ + } while (false); +void SpineSprite::update_mesh_from_skeleton(Ref s) { + static const unsigned short VERTEX_STRIDE = 2; + static const unsigned short UV_STRIDE = 2; + static unsigned short quad_indices[] = {0, 1, 2, 2, 3, 0}; + + auto sk = s->get_spine_object(); + for (size_t i = 0, n = sk->getSlots().size(); i < n; ++i) { + spine::Vector vertices; + spine::Vector uvs; + spine::Vector indices; + + spine::Slot *slot = sk->getDrawOrder()[i]; + + spine::Attachment *attachment = slot->getAttachment(); + if (!attachment) { + // set invisible to mesh instance + mesh_instances[i]->set_visible(false); + + skeleton_clipper->clipEnd(*slot); + continue; + } + mesh_instances[i]->set_visible(true); + + spine::Color skeleton_color = sk->getColor(); + spine::Color slot_color = slot->getColor(); + spine::Color tint(skeleton_color.r * slot_color.r, skeleton_color.g * slot_color.g, skeleton_color.b * slot_color.b, skeleton_color.a * slot_color.a); + + Ref tex; + Ref normal_tex; + size_t v_num = 0; + + if (attachment->getRTTI().isExactly(spine::RegionAttachment::rtti)) { + spine::RegionAttachment *region_attachment = (spine::RegionAttachment *) attachment; + + auto p_spine_renderer_object = (SpineRendererObject *) ((spine::AtlasRegion *) region_attachment->getRendererObject())->page->getRendererObject(); + tex = p_spine_renderer_object->texture; + normal_tex = p_spine_renderer_object->normal_map; + + v_num = 4; + vertices.setSize(v_num * VERTEX_STRIDE, 0); + + region_attachment->computeWorldVertices(*slot, vertices, 0); + + TEMP_COPY(uvs, region_attachment->getUVs()); + + indices.setSize(sizeof(quad_indices) / sizeof(unsigned short), 0); + for (size_t j = 0, qn = indices.size(); j < qn; ++j) { + indices[j] = quad_indices[j]; + } + + auto attachment_color = region_attachment->getColor(); + tint.r *= attachment_color.r; + tint.g *= attachment_color.g; + tint.b *= attachment_color.b; + tint.a *= attachment_color.a; + } else if (attachment->getRTTI().isExactly(spine::MeshAttachment::rtti)) { + spine::MeshAttachment *mesh = (spine::MeshAttachment *) attachment; + + auto p_spine_renderer_object = (SpineRendererObject *) ((spine::AtlasRegion *) mesh->getRendererObject())->page->getRendererObject(); + tex = p_spine_renderer_object->texture; + normal_tex = p_spine_renderer_object->normal_map; + + v_num = mesh->getWorldVerticesLength() / VERTEX_STRIDE; + vertices.setSize(mesh->getWorldVerticesLength(), 0); + + mesh->computeWorldVertices(*slot, 0, mesh->getWorldVerticesLength(), vertices, 0); + + // uvs = mesh->getUVs(); + // indices = mesh->getTriangles(); + TEMP_COPY(uvs, mesh->getUVs()); + TEMP_COPY(indices, mesh->getTriangles()); + + auto attachment_color = mesh->getColor(); + tint.r *= attachment_color.r; + tint.g *= attachment_color.g; + tint.b *= attachment_color.b; + tint.a *= attachment_color.a; + } else if (attachment->getRTTI().isExactly(spine::ClippingAttachment::rtti)) { + auto clip = (spine::ClippingAttachment *) attachment; + skeleton_clipper->clipStart(*slot, clip); + continue; + } else { + skeleton_clipper->clipEnd(*slot); + continue; + } + + auto mesh_ins = mesh_instances[i]; + VisualServer::get_singleton()->canvas_item_clear(mesh_ins->get_canvas_item()); + + if (skeleton_clipper->isClipping()) { + skeleton_clipper->clipTriangles(vertices, indices, uvs, VERTEX_STRIDE); + + if (skeleton_clipper->getClippedTriangles().size() == 0) { + skeleton_clipper->clipEnd(*slot); + continue; + } + + auto &clipped_vertices = skeleton_clipper->getClippedVertices(); + v_num = clipped_vertices.size() / VERTEX_STRIDE; + auto &clipped_uvs = skeleton_clipper->getClippedUVs(); + auto &clipped_indices = skeleton_clipper->getClippedTriangles(); + + if (indices.size() > 0) { + Vector p_points, p_uvs; + Vector p_colors; + Vector p_indices; + p_points.resize(v_num); + p_uvs.resize(v_num); + p_colors.resize(v_num); + for (size_t j = 0; j < v_num; j++) { + p_points.set(j, Vector2(clipped_vertices[j * VERTEX_STRIDE], -clipped_vertices[j * VERTEX_STRIDE + 1])); + p_uvs.set(j, Vector2(clipped_uvs[j * VERTEX_STRIDE], clipped_uvs[j * VERTEX_STRIDE + 1])); + p_colors.set(j, Color(tint.r, tint.g, tint.b, tint.a)); + } + p_indices.resize(clipped_indices.size()); + for (size_t j = 0; j < clipped_indices.size(); ++j) { + p_indices.set(j, clipped_indices[j]); + } + + VisualServer::get_singleton()->canvas_item_add_triangle_array(mesh_ins->get_canvas_item(), + p_indices, + p_points, + p_colors, + p_uvs, + Vector(), + Vector(), + tex.is_null() ? RID() : tex->get_rid(), + -1, + normal_tex.is_null() ? RID() : normal_tex->get_rid()); + } + } else { + if (indices.size() > 0) { + Vector p_points, p_uvs; + Vector p_colors; + Vector p_indices; + p_points.resize(v_num); + p_uvs.resize(v_num); + p_colors.resize(v_num); + for (size_t j = 0; j < v_num; j++) { + p_points.set(j, Vector2(vertices[j * VERTEX_STRIDE], -vertices[j * VERTEX_STRIDE + 1])); + p_uvs.set(j, Vector2(uvs[j * VERTEX_STRIDE], uvs[j * VERTEX_STRIDE + 1])); + p_colors.set(j, Color(tint.r, tint.g, tint.b, tint.a)); + } + p_indices.resize(indices.size()); + for (size_t j = 0; j < indices.size(); ++j) { + p_indices.set(j, indices[j]); + } + + VisualServer::get_singleton()->canvas_item_add_triangle_array(mesh_ins->get_canvas_item(), + p_indices, + p_points, + p_colors, + p_uvs, + Vector(), + Vector(), + tex.is_null() ? RID() : tex->get_rid(), + -1, + normal_tex.is_null() ? RID() : normal_tex->get_rid()); + } + } + skeleton_clipper->clipEnd(*slot); + + if (mesh_ins->get_material()->is_class("CanvasItemMaterial")) { + Ref mat = mesh_ins->get_material(); + CanvasItemMaterial::BlendMode blend_mode; + switch (slot->getData().getBlendMode()) { + case spine::BlendMode_Normal: + blend_mode = CanvasItemMaterial::BLEND_MODE_MIX; + break; + case spine::BlendMode_Additive: + blend_mode = CanvasItemMaterial::BLEND_MODE_ADD; + break; + case spine::BlendMode_Multiply: + blend_mode = CanvasItemMaterial::BLEND_MODE_MUL; + break; + case spine::BlendMode_Screen: + blend_mode = CanvasItemMaterial::BLEND_MODE_MIX; + break; + default: + blend_mode = CanvasItemMaterial::BLEND_MODE_MIX; + } + mat->set_blend_mode(blend_mode); + } + } + skeleton_clipper->clipEnd(); +} + +void SpineSprite::callback(spine::AnimationState *state, spine::EventType type, spine::TrackEntry *entry, spine::Event *event) { + Ref gd_entry(NULL); + Ref gd_event(NULL); + + if (entry) { + gd_entry = Ref(memnew(SpineTrackEntry)); + gd_entry->set_spine_object(entry); + } + if (event) { + gd_event = Ref(memnew(SpineEvent)); + gd_event->set_spine_object(event); + } + + switch (type) { + case spine::EventType_Start: { + emit_signal("animation_start", animation_state, gd_entry, gd_event); + } break; + case spine::EventType_Interrupt: { + emit_signal("animation_interrupt", animation_state, gd_entry, gd_event); + } break; + case spine::EventType_End: { + emit_signal("animation_end", animation_state, gd_entry, gd_event); + } break; + case spine::EventType_Complete: { + emit_signal("animation_complete", animation_state, gd_entry, gd_event); + } break; + case spine::EventType_Dispose: { + emit_signal("animation_dispose", animation_state, gd_entry, gd_event); + } break; + case spine::EventType_Event: { + emit_signal("animation_event", animation_state, gd_entry, gd_event); + } break; + } +} + +// External feature functions +Array SpineSprite::get_current_animations() { + return current_animations.duplicate(true); +} +void SpineSprite::set_current_animations(Array as) { + current_animations = as.duplicate(true); + + // validate it then play the animations + _validate_and_play_current_animations(); +} + +int SpineSprite::get_select_track_id() { + return select_track_id; +} +void SpineSprite::set_select_track_id(int v) { + select_track_id = v; + + if (select_track_id < 0) select_track_id = 0; +} + +bool SpineSprite::get_clear_track() { + return false; +} +void SpineSprite::set_clear_track(bool v) { + if (v && animation_state.is_valid() && skeleton.is_valid()) + animation_state->clear_track(select_track_id); +} + +bool SpineSprite::get_clear_tracks() { + return false; +} +void SpineSprite::set_clear_tracks(bool v) { + if (v && animation_state.is_valid() && skeleton.is_valid()) + animation_state->clear_tracks(); +} + +float SpineSprite::get_empty_animation_duration() { + return empty_animation_duration; +} +void SpineSprite::set_empty_animation_duration(float v) { + empty_animation_duration = v; +} + +bool SpineSprite::get_set_empty_animation() { + return false; +} +void SpineSprite::set_set_empty_animation(bool v) { + if (v && animation_state.is_valid() && skeleton.is_valid()) + animation_state->set_empty_animation(select_track_id, empty_animation_duration); +} + +bool SpineSprite::get_set_empty_animations() { + return false; +} +void SpineSprite::set_set_empty_animations(bool v) { + if (v && animation_state.is_valid() && skeleton.is_valid()) + animation_state->set_empty_animations(empty_animation_duration); +} + +Array SpineSprite::get_bind_slot_nodes() { + return bind_slot_nodes; +} + +void SpineSprite::set_bind_slot_nodes(Array v) { + bind_slot_nodes = v; +} + +bool SpineSprite::get_overlap() { + return overlap; +} + +void SpineSprite::set_overlap(bool v) { + overlap = v; +} + +void SpineSprite::bind_slot_with_node_2d(const String &slot_name, Node2D *n) { + auto node_path = n->get_path_to(this); + + // check if has the same binding + for (size_t i = 0, size = bind_slot_nodes.size(); i < size; ++i) { + auto a = bind_slot_nodes[i]; + if (a.get_type() == Variant::DICTIONARY) { + auto d = (Dictionary) a; + if (d.has("slot_name") && d.has("node_path")) { + if (slot_name == d["slot_name"] && node_path == d["node_path"]) { + return; + } + } + } else if (a.get_type() == Variant::ARRAY) { + auto as = (Array) a; + if (as.size() >= 2 && as[0].get_type() == Variant::STRING && as[1].get_type() == Variant::NODE_PATH) { + if (slot_name == as[0] && node_path == as[1]) { + return; + } + } + } + } + + Array bound; + bound.resize(2); + bound[0] = slot_name; + bound[1] = node_path; + + bind_slot_nodes.append(bound); +} +void SpineSprite::unbind_slot_with_node_2d(const String &slot_name, Node2D *n) { + auto node_path = n->get_path_to(this); + + for (size_t i = 0, size = bind_slot_nodes.size(); i < size; ++i) { + auto a = bind_slot_nodes[i]; + if (a.get_type() == Variant::DICTIONARY) { + auto d = (Dictionary) a; + if (d.has("slot_name") && d.has("node_path")) { + if (slot_name == d["slot_name"] && node_path == d["node_path"]) { + bind_slot_nodes.remove(i); + return; + } + } + } else if (a.get_type() == Variant::ARRAY) { + auto as = (Array) a; + if (as.size() >= 2 && as[0].get_type() == Variant::STRING && as[1].get_type() == Variant::NODE_PATH) { + if (slot_name == as[0] && node_path == as[1]) { + bind_slot_nodes.remove(i); + return; + } + } + } + } +} + +Transform2D SpineSprite::bone_get_global_transform(const String &bone_name) { + if (!animation_state.is_valid() && !skeleton.is_valid()) { + return get_global_transform(); + } + auto bone = skeleton->find_bone(bone_name); + if (!bone.is_valid()) { + print_error(vformat("Bone: '%s' not found.", bone_name)); + return get_global_transform(); + } + return bone->get_godot_global_transform(); +} + +void SpineSprite::bone_set_global_transform(const String &bone_name, Transform2D transform) { + if (!animation_state.is_valid() && !skeleton.is_valid()) { + return; + } + auto bone = skeleton->find_bone(bone_name); + if (!bone.is_valid()) { + return; + } + bone->set_godot_global_transform(transform); +} + +SpineSprite::ProcessMode SpineSprite::get_process_mode() { + return process_mode; +} + +void SpineSprite::set_process_mode(SpineSprite::ProcessMode v) { + process_mode = v; + set_process_internal(process_mode == ProcessMode_Process); + set_physics_process_internal(process_mode == ProcessMode_Physics); +} + +void SpineSprite::_get_property_list(List *p_list) const { + p_list->push_back(PropertyInfo(Variant::NIL, "Current Animation Editor", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_CATEGORY)); + p_list->push_back(PropertyInfo(Variant::BOOL, "setup_pose_trigger", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + p_list->push_back(PropertyInfo(Variant::BOOL, "clear_tracks_trigger", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + p_list->push_back(PropertyInfo(Variant::BOOL, "set_empty_animations_trigger", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + p_list->push_back(PropertyInfo(Variant::REAL, "empty_animation_duration")); + p_list->push_back(PropertyInfo(Variant::INT, "track_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + + for (size_t i = 0; i < current_animations.size(); ++i) { + String prefix = vformat("ca/%d/", (unsigned int) i); + p_list->push_back(PropertyInfo(Variant::NIL, vformat("ID %d", (unsigned int) i), PROPERTY_HINT_NONE, prefix, PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::INT, vformat("%strack_id", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + + Vector anim_list; + if (skeleton.is_valid() && skeleton->get_data().is_valid()) { + skeleton->get_data()->get_animation_names(anim_list); + } + if (anim_list.empty()) anim_list.push_back("No Animation"); + p_list->push_back(PropertyInfo(Variant::STRING, vformat("%sanimation", prefix), PROPERTY_HINT_ENUM, String(",").join(anim_list), PROPERTY_USAGE_EDITOR)); + + p_list->push_back(PropertyInfo(Variant::REAL, vformat("%sdelay", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + + p_list->push_back(PropertyInfo(Variant::BOOL, vformat("%sloop", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + + p_list->push_back(PropertyInfo(Variant::BOOL, vformat("%sempty", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + p_list->push_back(PropertyInfo(Variant::REAL, vformat("%sempty_animation_duration", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + + p_list->push_back(PropertyInfo(Variant::BOOL, vformat("%sclear", prefix), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + } +} + +bool SpineSprite::_get(const StringName &p_property, Variant &r_value) const { + if (p_property == "setup_pose_trigger" || p_property == "clear_tracks_trigger" || p_property == "set_empty_animations_trigger") { + r_value = false; + return true; + } + if (p_property == "empty_animation_duration") { + r_value = empty_animation_duration; + return true; + } + if (p_property == "track_count") { + r_value = get_current_animation_count(); + return true; + } + String p = p_property; + if (p.size() > 2 && p[0] == 'c' && p[1] == 'a' && p[2] == '/') { + Vector sp = p.split("/"); + if (sp.size() > 2) { + int64_t id = sp[1].to_int64(); + if (id >= 0 && id < current_animations.size()) { + auto &key = sp[2]; + if (current_animations[id].get_type() == Variant::DICTIONARY) { + Dictionary dic = current_animations.get(id); + if (dic.has(key)) { + r_value = dic[key]; + } else { + if (key == "track_id") r_value = 0; + else if (key == "animation") + r_value = ""; + else if (key == "loop") + r_value = true; + else if (key == "empty") + r_value = false; + else if (key == "empty_animation_duration") + r_value = 0.3; + else if (key == "clear") + r_value = false; + else if (key == "delay") + r_value = 0; + else + return false; + } + return true; + } + } + } + } + return false; +} + +bool SpineSprite::_set(const StringName &p_property, const Variant &p_value) { + if (p_property == "setup_pose_trigger") { + if (p_value) { + if (skeleton.is_valid()) { + skeleton->set_bones_to_setup_pose(); + skeleton->set_slots_to_setup_pose(); + } + } + return true; + } + if (p_property == "clear_tracks_trigger") { + if (p_value) { + if (animation_state.is_valid() && skeleton.is_valid()) { + animation_state->clear_tracks(); + } + } + return true; + } + if (p_property == "set_empty_animations_trigger") { + if (p_value) { + if (animation_state.is_valid() && skeleton.is_valid()) { + animation_state->set_empty_animations(empty_animation_duration); + } + } + return true; + } + if (p_property == "empty_animation_duration") { + empty_animation_duration = p_value; + return true; + } + if (p_property == "track_count") { + set_current_animation_count(p_value); + return true; + } + String p = p_property; + if (p.size() > 2 && p[0] == 'c' && p[1] == 'a' && p[2] == '/') { + Vector sp = p.split("/"); + if (sp.size() > 2) { + int64_t id = sp[1].to_int64(); + if (id >= 0 && id < current_animations.size()) { + auto &key = sp[2]; + if (current_animations[id].get_type() != Variant::DICTIONARY) { + current_animations.set(id, Dictionary()); + } + + Dictionary dic = current_animations.get(id); + dic[key] = p_value; + + _validate_and_play_current_animations(); + return true; + } + } + } + return false; +} + +int64_t SpineSprite::get_current_animation_count() const { + return current_animations.size(); +} + +void SpineSprite::set_current_animation_count(int64_t v) { + if (v < 0) v = 0; + while (current_animations.size() < v) { + Dictionary d; + d["track_id"] = current_animations.size(); + d["animation"] = ""; + d["delay"] = 0; + d["loop"] = true; + d["empty"] = false; + d["empty_animation_duration"] = 0.3; + d["clear"] = false; + current_animations.push_back(d); + } + while (current_animations.size() > v) { + if (animation_state.is_valid() && skeleton.is_valid()) { + if (current_animations.back().get_type() == Variant::DICTIONARY) { + Dictionary back = current_animations.back(); + if (back.has("track_id")) { + int64_t track_id = back["track_id"]; + int track_cnt = 0; + for (size_t i = 0; i < current_animations.size(); ++i) { + if (current_animations[i].get_type() == Variant::DICTIONARY) { + Dictionary d = current_animations[i]; + if (d.has("track_id") && track_id == (int64_t) d["track_id"]) { + track_cnt += 1; + } + } + } + if (track_cnt == 0) + animation_state->clear_track(track_id); + } + } + } + current_animations.pop_back(); + } + property_list_changed_notify(); +} + +void SpineSprite::_validate_and_play_current_animations() { + if (animation_state.is_valid() && skeleton.is_valid()) { + int64_t track_cnt = 0; + HashMap has_track; + for (size_t i = 0; i < current_animations.size(); ++i) { + auto a = current_animations[i]; + if (a.get_type() == Variant::DICTIONARY) { + Dictionary d = a; + + int64_t track_id = 0; + String animation = ""; + float delay = 0; + bool loop = true; + bool empty = false; + float empty_animation_duration = 0.3; + bool clear = false; + + if (d.has("track_id")) track_id = d["track_id"]; + if (d.has("animation")) animation = d["animation"]; + if (d.has("delay")) delay = d["delay"]; + if (d.has("loop")) loop = d["loop"]; + if (d.has("empty")) empty = d["empty"]; + if (d.has("empty_animation_duration")) empty_animation_duration = d["empty_animation_duration"]; + if (d.has("clear")) clear = d["clear"]; + + if (track_id < 0) { + print_line(vformat("track_id at 'ID %d' can not be less than 0!", (unsigned int) i)); + continue; + } + + track_cnt += 1; + + + if (empty) { + if (has_track.has(track_id)) + animation_state->add_empty_animation(track_id, empty_animation_duration, delay); + else + animation_state->set_empty_animation(track_id, empty_animation_duration); + has_track[track_id] = true; + } else if (clear) { + animation_state->clear_track(track_id); + } else if (skeleton->get_data()->find_animation(animation).is_valid()) { + if (has_track.has(track_id)) + animation_state->add_animation(animation, delay, loop, track_id); + else + animation_state->set_animation(animation, loop, track_id); + has_track[track_id] = true; + } + } + } + + if (track_cnt == 0) animation_state->clear_tracks(); + } +} diff --git a/spine-godot/spine_godot/SpineSprite.h b/spine-godot/spine_godot/SpineSprite.h new file mode 100644 index 000000000..fc7276091 --- /dev/null +++ b/spine-godot/spine_godot/SpineSprite.h @@ -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. + *****************************************************************************/ + +#ifndef GODOT_SPINESPRITE_H +#define GODOT_SPINESPRITE_H + +#include +#include + +#include "SpineAnimationState.h" +#include "SpineAnimationStateDataResource.h" +#include "SpineSkeleton.h" +#include "SpineSpriteMeshInstance2D.h" + +class SpineSprite : public Node2D, public spine::AnimationStateListenerObject { + GDCLASS(SpineSprite, Node2D); + +protected: + static void _bind_methods(); + + void _notification(int p_what); + + void _get_property_list(List *p_list) const; + bool _get(const StringName &p_property, Variant &r_value) const; + bool _set(const StringName &p_property, const Variant &p_value); + + void _validate_and_play_current_animations(); + +public: + enum ProcessMode { + ProcessMode_Process, + ProcessMode_Physics, + ProcessMode_Manual + }; + +private: + Ref animation_state_data_res; + + Ref skeleton; + Ref animation_state; + + Vector mesh_instances; + + Array current_animations; + int select_track_id; + float empty_animation_duration; + + Array bind_slot_nodes; + bool overlap; + + ProcessMode process_mode; + + spine::SkeletonClipping *skeleton_clipper; + +public: + SpineSprite(); + ~SpineSprite(); + + void set_animation_state_data_res(const Ref &a); + Ref get_animation_state_data_res(); + + Ref get_skeleton(); + Ref get_animation_state(); + + void gen_mesh_from_skeleton(Ref s); + void remove_mesh_instances(); + void remove_redundant_mesh_instances(); + + void update_mesh_from_skeleton(Ref s); + + void update_bind_slot_nodes(); + void update_bind_slot_node_transform(Ref bone, Node2D *node2d); + void update_bind_slot_node_draw_order(const String &slot_name, Node2D *node2d); + Node *find_child_node_by_node(Node *node); + + virtual void callback(spine::AnimationState *state, spine::EventType type, spine::TrackEntry *entry, spine::Event *event); + + void _on_animation_data_created(); + void _on_animation_data_changed(); + + void _update_all(float delta); + + // External feature functions + Array get_current_animations(); + void set_current_animations(Array as); + + int get_select_track_id(); + void set_select_track_id(int v); + + bool get_clear_track(); + void set_clear_track(bool v); + + bool get_clear_tracks(); + void set_clear_tracks(bool v); + + float get_empty_animation_duration(); + void set_empty_animation_duration(float v); + + bool get_set_empty_animation(); + void set_set_empty_animation(bool v); + + bool get_set_empty_animations(); + void set_set_empty_animations(bool v); + + Array get_bind_slot_nodes(); + void set_bind_slot_nodes(Array v); + + void bind_slot_with_node_2d(const String &slot_name, Node2D *n); + void unbind_slot_with_node_2d(const String &slot_name, Node2D *n); + + // bone manipulations + Transform2D bone_get_global_transform(const String &bone_name); + void bone_set_global_transform(const String &bone_name, Transform2D transform); + + //allow z-manipulation + bool get_overlap(); + void set_overlap(bool v); + + // current animation count + int64_t get_current_animation_count() const; + void set_current_animation_count(int64_t v); + + ProcessMode get_process_mode(); + void set_process_mode(ProcessMode v); +}; + +VARIANT_ENUM_CAST(SpineSprite::ProcessMode); +#endif//GODOT_SPINESPRITE_H diff --git a/spine-godot/spine_godot/SpineSpriteAnimateDialog.cpp b/spine-godot/spine_godot/SpineSpriteAnimateDialog.cpp new file mode 100644 index 000000000..33bebdd66 --- /dev/null +++ b/spine-godot/spine_godot/SpineSpriteAnimateDialog.cpp @@ -0,0 +1,351 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineSpriteAnimateDialog.h" + +#ifdef TOOLS_ENABLED + +#include "SpineSprite.h" + +void SpineSpriteAnimateDialog::_bind_methods() { + ClassDB::bind_method(D_METHOD("_on_animate_button_pressed"), &SpineSpriteAnimateDialog::_on_animate_button_pressed); + ClassDB::bind_method(D_METHOD("_on_scene_tree_selected"), &SpineSpriteAnimateDialog::_on_scene_tree_selected); + ClassDB::bind_method(D_METHOD("_on_scene_tree_hide"), &SpineSpriteAnimateDialog::_on_scene_tree_hide); + ClassDB::bind_method(D_METHOD("_on_animate_dialog_action"), &SpineSpriteAnimateDialog::_on_animate_dialog_action); +} + +SpineSpriteAnimateDialog::SpineSpriteAnimateDialog() { + animate_dialog = memnew(ConfirmationDialog); + add_child(animate_dialog); + animate_dialog->get_ok()->set_text("Generate"); + animate_dialog_override_button = animate_dialog->add_button("Override", false, "override"); + animate_dialog_override_button->set_visible(false); + animate_dialog->set_title("Animations Generator"); + animate_dialog->set_resizable(true); + animate_dialog->set_custom_minimum_size(Vector2(550, 400)); + animate_dialog->set_hide_on_ok(false); + animate_dialog->connect("custom_action", this, "_on_animate_dialog_action"); + Vector al; + al.push_back("confirmed"); + animate_dialog->connect("confirmed", this, "_on_animate_dialog_action", al); + + auto vb = memnew(VBoxContainer); + animate_dialog->add_child(vb); + + auto scroll = memnew(ScrollContainer); + scroll->set_h_size_flags(SIZE_EXPAND_FILL); + scroll->set_v_size_flags(SIZE_EXPAND_FILL); + // vb->add_margin_child("Animations", scroll); + vb->add_child(scroll); + + animate_dialog_tree = memnew(Tree); + animate_dialog_tree->set_h_size_flags(SIZE_EXPAND_FILL); + animate_dialog_tree->set_v_size_flags(SIZE_EXPAND_FILL); + scroll->add_child(animate_dialog_tree); + + animate_dialog_tree->set_columns(3); + animate_dialog_tree->set_column_titles_visible(true); + animate_dialog_tree->set_hide_folding(true); + animate_dialog_tree->set_hide_root(true); + + animate_dialog_tree->set_column_title(0, TTR("Animation")); + animate_dialog_tree->set_column_title(1, TTR("Loop")); + animate_dialog_tree->set_column_title(2, TTR("Track ID")); + + animate_dialog_tree->create_item(); + add_row("test1"); + add_row("test12"); + add_row("test13"); + + auto l = memnew(Label); + l->set_text("W.I.P"); + vb->add_child(l); + + scene_tree_dialog = memnew(SceneTreeDialog); + scene_tree_dialog->set_title("Choose a AnimationPlayer to override, or choose none to create a new one."); + Vector valid_types; + valid_types.push_back("AnimationPlayer"); + scene_tree_dialog->get_scene_tree()->set_valid_types(valid_types); + scene_tree_dialog->get_scene_tree()->set_show_enabled_subscene(true); + scene_tree_dialog->get_ok()->hide(); + add_child(scene_tree_dialog); + scene_tree_dialog->connect("selected", this, "_on_scene_tree_selected"); + scene_tree_dialog->connect("popup_hide", this, "_on_scene_tree_hide"); + + error_dialog = memnew(AcceptDialog); + add_child(error_dialog); +} + +SpineSpriteAnimateDialog::~SpineSpriteAnimateDialog() { +} + +void SpineSpriteAnimateDialog::set_animate_button(ToolButton *b) { + animate_button = b; + animate_button->connect("pressed", this, "_on_animate_button_pressed"); +} + +void SpineSpriteAnimateDialog::add_row(const String &animation, bool loop, int64_t track_id) { + auto item = animate_dialog_tree->create_item(); + item->set_text(0, animation); + + item->set_cell_mode(1, TreeItem::CELL_MODE_CHECK); + item->set_checked(1, loop); + item->set_editable(1, true); + + item->set_cell_mode(2, TreeItem::CELL_MODE_RANGE); + item->set_range(2, track_id); + item->set_editable(2, true); +} + +void SpineSpriteAnimateDialog::clear_tree() { + animate_dialog_tree->clear(); + animate_dialog_tree->create_item(); +} + +void SpineSpriteAnimateDialog::error(const String &text, const String &title) { + error_dialog->set_text(text); + error_dialog->set_title(title); + error_dialog->popup_centered(); +} + +#define ERROR_MSG(x) \ + do { \ + error(x); \ + err = true; \ + return; \ + } while (false) +void SpineSpriteAnimateDialog::load_data_from_sprite(SpineSprite *sprite, bool &err) { + if (sprite == nullptr) { + ERROR_MSG("The sprite is null."); + } + if (!sprite->get_animation_state().is_valid() || !sprite->get_skeleton().is_valid()) { + ERROR_MSG("The sprite is not loaded."); + } + clear_tree(); + + Vector animations; + sprite->get_skeleton()->get_data()->get_animation_names(animations); + + for (size_t i = 0; i < animations.size(); ++i) { + add_row(animations[i]); + } + + err = false; +} + +#define MIN_TRACK_LENGTH 0.15 + +void SpineSpriteAnimateDialog::gen_new_animation_player(SpineSprite *sprite, bool &err) { + if (sprite == nullptr) { + ERROR_MSG("The sprite player is null."); + } + if (!sprite->get_animation_state().is_valid() || !sprite->get_skeleton().is_valid()) { + ERROR_MSG("The sprite is not loaded."); + } + auto p = sprite->get_parent(); + if (p == nullptr) { + p = sprite; + } + + auto anim_player = memnew(AnimationPlayer); + anim_player->set_name("AnimationPlayer"); + p->add_child(anim_player); + anim_player->set_owner(sprite->get_owner()); + anim_player->set_root(anim_player->get_path_to(p)); + + gen_animations(sprite, anim_player, get_data_from_tree(), MIN_TRACK_LENGTH, err); +} + +Dictionary SpineSpriteAnimateDialog::get_data_from_tree() { + Dictionary res; + if (animate_dialog_tree->get_root() == nullptr) return res; + + auto item = animate_dialog_tree->get_root()->get_children(); + while (item) { + Dictionary row; + row["loop"] = item->is_checked(1); + row["track_id"] = item->get_range(2); + + res[item->get_text(0)] = row; + item = item->get_next(); + } + return res; +} + +void SpineSpriteAnimateDialog::gen_animations(SpineSprite *sprite, AnimationPlayer *anim_player, const Dictionary &config, float min_duration, bool &err) { + if (sprite == nullptr || anim_player == nullptr) { + ERROR_MSG("The sprite or animation player is null."); + } + if (!sprite->get_animation_state().is_valid() || !sprite->get_skeleton().is_valid()) { + ERROR_MSG("The sprite is not loaded."); + } + if (anim_player->get_node_or_null(anim_player->get_root()) == nullptr) { + ERROR_MSG("The root node of animation player is null."); + } + + auto path_to_sprite = anim_player->get_node(anim_player->get_root())->get_path_to(sprite); + + Array animations = sprite->get_skeleton()->get_data()->get_animations(); + for (size_t i = 0; i < animations.size(); ++i) { + auto spine_anim = (Ref) animations[i]; + + Dictionary ca; + if (config.has(spine_anim->get_anim_name())) { + ca = config[spine_anim->get_anim_name()]; + } + + if (!ca.has("loop")) ca["loop"] = true; + if (!ca.has("track_id")) ca["track_id"] = 0; + + Array key_frame_value; + key_frame_value.push_back(gen_current_animation_data(spine_anim->get_anim_name(), ca["track_id"], ca["loop"], false, false, 0.3, 0)); + + auto anim = Ref(memnew(Animation)); + auto track_index = anim->add_track(Animation::TYPE_VALUE); + anim->set_length(min_duration > spine_anim->get_duration() ? min_duration : spine_anim->get_duration()); + anim->track_set_path(track_index, NodePath(vformat("%s:current_animations", path_to_sprite))); + anim->track_insert_key(track_index, 0.0, key_frame_value); + anim->value_track_set_update_mode(track_index, Animation::UPDATE_DISCRETE); + + if (anim_player->has_animation(spine_anim->get_anim_name())) + anim_player->remove_animation(spine_anim->get_anim_name()); + anim_player->add_animation(spine_anim->get_anim_name(), anim); + } + + err = false; +} + +Dictionary SpineSpriteAnimateDialog::gen_current_animation_data(const String &animation, int64_t track_id, bool loop, bool clear, bool empty, bool empty_duration, float delay) { + Dictionary res; + res["animation"] = animation; + res["track_id"] = track_id; + res["loop"] = loop; + res["clear"] = clear; + res["empty"] = empty; + res["empty_animation_duration"] = empty_duration; + res["delay"] = delay; + return res; +} + + +void SpineSpriteAnimateDialog::load_data_from_anim_player(AnimationPlayer *anim_player, bool &err) { + if (anim_player == nullptr) { + ERROR_MSG("The animation player is null."); + } + auto root = anim_player->get_node_or_null(anim_player->get_root()); + if (root == nullptr) return; + + auto sprite = get_node_or_null(spine_sprite_path); + if (sprite == nullptr) return; + + auto item = animate_dialog_tree->get_root()->get_children(); + while (item) { + String animation = item->get_text(0); + + auto anim = anim_player->get_animation(animation); + if (anim.is_valid() && anim->get_track_count() > 0) { + if (anim->track_get_type(0) == Animation::TYPE_VALUE) { + auto track_path = anim->track_get_path(0); + if (root->get_node_or_null(track_path) == sprite) { + if (anim->track_get_key_count(0) > 0) { + Array key_frame_value = anim->track_get_key_value(0, 0); + if (!key_frame_value.empty()) { + Dictionary _ca = key_frame_value.front(); + if (_ca.has("loop")) item->set_checked(1, _ca["loop"]); + if (_ca.has("track_id")) item->set_range(2, _ca["track_id"]); + } + } + } + } + } + + item = item->get_next(); + } + + err = false; +} + +//----- Signals ----- +void SpineSpriteAnimateDialog::_on_scene_tree_selected(NodePath path) { + // print_line(vformat("anime: %s", path)); + auto node = get_node_or_null(path); + if (node == nullptr) { + error("The node you chose is null."); + return; + } + if (!node->is_class("AnimationPlayer")) { + error("The node you chose is not AnimationPlayer."); + return; + } + anim_player_path = path; +} + +void SpineSpriteAnimateDialog::_on_animate_button_pressed() { + anim_player_path = String(""); + auto node = (Node *) the_plugin->get_editor_interface()->get_selection()->get_selected_nodes().back(); + spine_sprite_path = node->get_path(); + + // print_line(vformat("sp: %s", spine_sprite_path)); + + animate_dialog_override_button->set_visible(false); + scene_tree_dialog->popup_centered_ratio(); +} + +void SpineSpriteAnimateDialog::_on_scene_tree_hide() { + animate_dialog->popup_centered(); + + bool err = false; + load_data_from_sprite((SpineSprite *) get_node_or_null(spine_sprite_path), err); + + if (err) animate_dialog->hide(); + + err = false; + auto node = get_node_or_null(anim_player_path); + if (node != nullptr) { + load_data_from_anim_player((AnimationPlayer *) node, err); + animate_dialog_override_button->set_visible(!err); + } else { + animate_dialog_override_button->set_visible(false); + } +} + +void SpineSpriteAnimateDialog::_on_animate_dialog_action(const String &act) { + bool err = false; + if (act == "confirmed") { + gen_new_animation_player((SpineSprite *) get_node_or_null(spine_sprite_path), err); + } else if (act == "override") { + gen_animations((SpineSprite *) get_node_or_null(spine_sprite_path), (AnimationPlayer *) get_node_or_null(anim_player_path), get_data_from_tree(), MIN_TRACK_LENGTH, err); + } + if (!err) { + animate_dialog->hide(); + } +} + + +#endif \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineSpriteAnimateDialog.h b/spine-godot/spine_godot/SpineSpriteAnimateDialog.h new file mode 100644 index 000000000..04f26d619 --- /dev/null +++ b/spine-godot/spine_godot/SpineSpriteAnimateDialog.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 GODOT_SPINESPRITEANIMATEDIALOG_H +#define GODOT_SPINESPRITEANIMATEDIALOG_H + +#ifdef TOOLS_ENABLED +#include "editor/editor_node.h" + +class SpineSprite; + +class SpineSpriteAnimateDialog : public Control { + GDCLASS(SpineSpriteAnimateDialog, Control); + +protected: + static void _bind_methods(); + + AcceptDialog *error_dialog; + + ToolButton *animate_button; + EditorPlugin *the_plugin; + + ConfirmationDialog *animate_dialog; + Button *animate_dialog_override_button; + Tree *animate_dialog_tree; + SceneTreeDialog *scene_tree_dialog; + + NodePath spine_sprite_path; + NodePath anim_player_path; + + void add_row(const String &animation, bool loop = true, int64_t track_id = 0); + void clear_tree(); + + void error(const String &text, const String &title = "Error"); + + void load_data_from_sprite(SpineSprite *sprite, bool &err); + void load_data_from_anim_player(AnimationPlayer *anim_player, bool &err); + + Dictionary get_data_from_tree(); + + void gen_new_animation_player(SpineSprite *sprite, bool &err); + void gen_animations(SpineSprite *sprite, AnimationPlayer *anim_player, const Dictionary &config, float min_duration, bool &err); + Dictionary gen_current_animation_data(const String &animation, int64_t track_id, bool loop, bool clear, bool empty, bool empty_duration, float delay); + +public: + SpineSpriteAnimateDialog(); + ~SpineSpriteAnimateDialog(); + + void set_animate_button(ToolButton *b); + inline ToolButton *get_animate_button() { return animate_button; } + + inline void set_plugin(EditorPlugin *p) { the_plugin = p; } + + void _on_animate_button_pressed(); + void _on_scene_tree_selected(NodePath path); + void _on_scene_tree_hide(); + void _on_animate_dialog_action(const String &act); +}; +#endif + +#endif//GODOT_SPINESPRITEANIMATEDIALOG_H diff --git a/spine-godot/spine_godot/SpineSpriteMeshInstance2D.cpp b/spine-godot/spine_godot/SpineSpriteMeshInstance2D.cpp new file mode 100644 index 000000000..aba2064f0 --- /dev/null +++ b/spine-godot/spine_godot/SpineSpriteMeshInstance2D.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. + *****************************************************************************/ + +#include "SpineSpriteMeshInstance2D.h" + +#include "SpineBone.h" + +void SpineSpriteMeshInstance2D::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_slot"), &SpineSpriteMeshInstance2D::get_slot); + ClassDB::bind_method(D_METHOD("apply_transform_2d", "node2d"), &SpineSpriteMeshInstance2D::apply_transform_2d); +} + +SpineSpriteMeshInstance2D::SpineSpriteMeshInstance2D() {} +SpineSpriteMeshInstance2D::~SpineSpriteMeshInstance2D() {} + +Ref SpineSpriteMeshInstance2D::get_slot() { + return slot; +} + +void SpineSpriteMeshInstance2D::apply_transform_2d(Variant o) { + slot->get_bone()->apply_world_transform_2d(o); +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineSpriteMeshInstance2D.h b/spine-godot/spine_godot/SpineSpriteMeshInstance2D.h new file mode 100644 index 000000000..c748b21cb --- /dev/null +++ b/spine-godot/spine_godot/SpineSpriteMeshInstance2D.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 GODOT_SPINESPRITEMESHINSTANCE2D_H +#define GODOT_SPINESPRITEMESHINSTANCE2D_H + +#include + +#include "SpineSlot.h" + +class SpineSpriteMeshInstance2D : public MeshInstance2D { + GDCLASS(SpineSpriteMeshInstance2D, MeshInstance2D); + +protected: + static void _bind_methods(); + + Ref slot; + +public: + SpineSpriteMeshInstance2D(); + ~SpineSpriteMeshInstance2D(); + + inline void set_slot(Ref s) { + slot = s; + } + Ref get_slot(); + + void apply_transform_2d(Variant o); +}; + +#endif//GODOT_SPINESPRITEMESHINSTANCE2D_H diff --git a/spine-godot/spine_godot/SpineTimeline.cpp b/spine-godot/spine_godot/SpineTimeline.cpp new file mode 100644 index 000000000..29561c595 --- /dev/null +++ b/spine-godot/spine_godot/SpineTimeline.cpp @@ -0,0 +1,99 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineTimeline.h" + +#include "SpineSkeleton.h" +#include "SpineEvent.h" + +// enable more than 5 arguments of a method bind function +#include "core/method_bind_ext.gen.inc" + +void SpineTimeline::_bind_methods() { + ClassDB::bind_method(D_METHOD("apply", "skeleton", "lastTime", "time", "pEvents", "alpha", "blend", "direction"), &SpineTimeline::apply); + ClassDB::bind_method(D_METHOD("get_frame_entries"), &SpineTimeline::get_frame_entries); + ClassDB::bind_method(D_METHOD("get_frame_count"), &SpineTimeline::get_frame_count); + ClassDB::bind_method(D_METHOD("get_frames"), &SpineTimeline::get_frames); + ClassDB::bind_method(D_METHOD("get_duration"), &SpineTimeline::get_duration); + ClassDB::bind_method(D_METHOD("getPropertyIds"), &SpineTimeline::getPropertyIds); +} + + +SpineTimeline::SpineTimeline() : timeline(nullptr) { +} + +SpineTimeline::~SpineTimeline() { +} + +void SpineTimeline::apply(Ref skeleton, float lastTime, float time, Array pEvents, float alpha, + SpineConstant::MixBlend blend, SpineConstant::MixDirection direction) { + spine::Vector events; + events.setSize(pEvents.size(), nullptr); + for (size_t i = 0; i < events.size(); ++i) { + events[i] = ((Ref) pEvents[i])->get_spine_object(); + } + + timeline->apply(*(skeleton->get_spine_object()), lastTime, time, &events, alpha, (spine::MixBlend) blend, (spine::MixDirection) direction); +} + +int64_t SpineTimeline::get_frame_entries() { + return timeline->getFrameEntries(); +} + +int64_t SpineTimeline::get_frame_count() { + return timeline->getFrameCount(); +} + +Array SpineTimeline::get_frames() { + auto &frames = timeline->getFrames(); + Array res; + res.resize(frames.size()); + + for (size_t i = 0; i < res.size(); ++i) { + res[i] = frames[i]; + } + + return res; +} + +float SpineTimeline::get_duration() { + return timeline->getDuration(); +} + +Array SpineTimeline::getPropertyIds() { + auto &ids = timeline->getPropertyIds(); + Array res; + res.resize(ids.size()); + + for (size_t i = 0; i < res.size(); ++i) { + res[i] = (int64_t) ids[i]; + } + + return res; +} diff --git a/spine-godot/spine_godot/SpineTimeline.h b/spine-godot/spine_godot/SpineTimeline.h new file mode 100644 index 000000000..404d7dd26 --- /dev/null +++ b/spine-godot/spine_godot/SpineTimeline.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 GODOT_SPINETIMELINE_H +#define GODOT_SPINETIMELINE_H + +#include "core/variant_parser.h" + +#include "spine/Timeline.h" + +#include "SpineConstant.h" + +class SpineSkeleton; +class SpineEvent; + +class SpineTimeline : public Reference { + GDCLASS(SpineTimeline, Reference); + +protected: + static void _bind_methods(); + +private: + spine::Timeline *timeline; + +public: + SpineTimeline(); + ~SpineTimeline(); + + inline void set_spine_object(spine::Timeline *v) { timeline = v; } + inline spine::Timeline *get_spine_object() { return timeline; } + + // Vector + void apply(Ref skeleton, float lastTime, float time, Array pEvents, float alpha, SpineConstant::MixBlend blend, SpineConstant::MixDirection direction); + + int64_t get_frame_entries(); + + int64_t get_frame_count(); + + // Vector + Array get_frames(); + + float get_duration(); + + // Vector + Array getPropertyIds(); +}; + + +#endif//GODOT_SPINETIMELINE_H diff --git a/spine-godot/spine_godot/SpineTrackEntry.cpp b/spine-godot/spine_godot/SpineTrackEntry.cpp new file mode 100644 index 000000000..fe6979af9 --- /dev/null +++ b/spine-godot/spine_godot/SpineTrackEntry.cpp @@ -0,0 +1,265 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "SpineTrackEntry.h" + +void SpineTrackEntry::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_track_index"), &SpineTrackEntry::get_track_index); + + ClassDB::bind_method(D_METHOD("get_animation"), &SpineTrackEntry::get_animation); + + ClassDB::bind_method(D_METHOD("get_loop"), &SpineTrackEntry::get_loop); + ClassDB::bind_method(D_METHOD("set_loop", "v"), &SpineTrackEntry::set_loop); + + ClassDB::bind_method(D_METHOD("get_hold_previous"), &SpineTrackEntry::get_hold_previous); + ClassDB::bind_method(D_METHOD("set_hold_previous", "v"), &SpineTrackEntry::set_hold_previous); + + ClassDB::bind_method(D_METHOD("get_reverse"), &SpineTrackEntry::get_reverse); + ClassDB::bind_method(D_METHOD("set_reverse", "v"), &SpineTrackEntry::set_reverse); + + ClassDB::bind_method(D_METHOD("get_delay"), &SpineTrackEntry::get_delay); + ClassDB::bind_method(D_METHOD("set_delay", "v"), &SpineTrackEntry::set_delay); + + ClassDB::bind_method(D_METHOD("get_track_time"), &SpineTrackEntry::get_track_time); + ClassDB::bind_method(D_METHOD("set_track_time", "v"), &SpineTrackEntry::set_track_time); + + ClassDB::bind_method(D_METHOD("get_track_end"), &SpineTrackEntry::get_track_end); + ClassDB::bind_method(D_METHOD("set_track_end", "v"), &SpineTrackEntry::set_track_end); + + ClassDB::bind_method(D_METHOD("get_animation_start"), &SpineTrackEntry::get_animation_start); + ClassDB::bind_method(D_METHOD("set_animation_start", "v"), &SpineTrackEntry::set_animation_start); + + ClassDB::bind_method(D_METHOD("get_animation_last"), &SpineTrackEntry::get_animation_last); + ClassDB::bind_method(D_METHOD("set_animation_last", "v"), &SpineTrackEntry::set_animation_last); + + ClassDB::bind_method(D_METHOD("get_animation_time"), &SpineTrackEntry::get_animation_time); + + ClassDB::bind_method(D_METHOD("get_time_scale"), &SpineTrackEntry::get_time_scale); + ClassDB::bind_method(D_METHOD("set_time_scale", "v"), &SpineTrackEntry::set_time_scale); + + ClassDB::bind_method(D_METHOD("get_alpha"), &SpineTrackEntry::get_alpha); + ClassDB::bind_method(D_METHOD("set_alpha", "v"), &SpineTrackEntry::set_alpha); + + ClassDB::bind_method(D_METHOD("get_event_threshold"), &SpineTrackEntry::get_event_threshold); + ClassDB::bind_method(D_METHOD("set_event_threshold", "v"), &SpineTrackEntry::set_event_threshold); + + ClassDB::bind_method(D_METHOD("get_attachment_threshold"), &SpineTrackEntry::get_attachment_threshold); + ClassDB::bind_method(D_METHOD("set_attachment_threshold", "v"), &SpineTrackEntry::set_attachment_threshold); + + ClassDB::bind_method(D_METHOD("get_draw_order_threshold"), &SpineTrackEntry::get_draw_order_threshold); + ClassDB::bind_method(D_METHOD("set_draw_order_threshold", "v"), &SpineTrackEntry::set_draw_order_threshold); + + ClassDB::bind_method(D_METHOD("get_next"), &SpineTrackEntry::get_next); + + ClassDB::bind_method(D_METHOD("is_complete"), &SpineTrackEntry::is_complete); + + ClassDB::bind_method(D_METHOD("get_mix_time"), &SpineTrackEntry::get_mix_time); + ClassDB::bind_method(D_METHOD("set_mix_time", "v"), &SpineTrackEntry::set_mix_time); + + ClassDB::bind_method(D_METHOD("get_mix_duration"), &SpineTrackEntry::get_mix_duration); + ClassDB::bind_method(D_METHOD("set_mix_duration", "v"), &SpineTrackEntry::set_mix_duration); + + ClassDB::bind_method(D_METHOD("get_mix_blend"), &SpineTrackEntry::get_mix_blend); + ClassDB::bind_method(D_METHOD("set_mix_blend", "v"), &SpineTrackEntry::set_mix_blend); + + ClassDB::bind_method(D_METHOD("get_mixing_from"), &SpineTrackEntry::get_mixing_from); + ClassDB::bind_method(D_METHOD("get_mixing_to"), &SpineTrackEntry::get_mixing_to); + + ClassDB::bind_method(D_METHOD("reset_rotation_directions"), &SpineTrackEntry::reset_rotation_directions); + + BIND_ENUM_CONSTANT(MIXBLEND_SETUP); + BIND_ENUM_CONSTANT(MIXBLEND_FIRST); + BIND_ENUM_CONSTANT(MIXBLEND_REPLACE); + BIND_ENUM_CONSTANT(MIXBLEND_ADD); +} + +SpineTrackEntry::SpineTrackEntry() : track_entry(NULL) {} +SpineTrackEntry::~SpineTrackEntry() {} + +int SpineTrackEntry::get_track_index() { + return track_entry->getTrackIndex(); +} + +Ref SpineTrackEntry::get_animation() { + Ref gd_anim(memnew(SpineAnimation)); + auto anim = track_entry->getAnimation(); + if (anim == NULL) return NULL; + gd_anim->set_spine_object(anim); + return gd_anim; +} + +bool SpineTrackEntry::get_loop() { + return track_entry->getLoop(); +} +void SpineTrackEntry::set_loop(bool v) { + track_entry->setLoop(v); +} + +bool SpineTrackEntry::get_hold_previous() { + return track_entry->getHoldPrevious(); +} +void SpineTrackEntry::set_hold_previous(bool v) { + track_entry->setHoldPrevious(v); +} + +float SpineTrackEntry::get_delay() { + return track_entry->getDelay(); +} +void SpineTrackEntry::set_delay(float v) { + track_entry->setDelay(v); +} + +float SpineTrackEntry::get_track_time() { + return track_entry->getTrackTime(); +} +void SpineTrackEntry::set_track_time(float v) { + track_entry->setTrackTime(v); +} + +float SpineTrackEntry::get_track_end() { + return track_entry->getTrackEnd(); +} +void SpineTrackEntry::set_track_end(float v) { + track_entry->setTrackEnd(v); +} + +float SpineTrackEntry::get_animation_start() { + return track_entry->getAnimationStart(); +} +void SpineTrackEntry::set_animation_start(float v) { + track_entry->setAnimationStart(v); +} + +float SpineTrackEntry::get_animation_last() { + return track_entry->getAnimationLast(); +} +void SpineTrackEntry::set_animation_last(float v) { + track_entry->setAnimationLast(v); +} + +float SpineTrackEntry::get_animation_time() { + return track_entry->getAnimationTime(); +} + +float SpineTrackEntry::get_time_scale() { + return track_entry->getTimeScale(); +} +void SpineTrackEntry::set_time_scale(float v) { + track_entry->setTimeScale(v); +} + +float SpineTrackEntry::get_alpha() { + return track_entry->getAlpha(); +} +void SpineTrackEntry::set_alpha(float v) { + track_entry->setAlpha(v); +} + +float SpineTrackEntry::get_event_threshold() { + return track_entry->getEventThreshold(); +} +void SpineTrackEntry::set_event_threshold(float v) { + track_entry->setEventThreshold(v); +} + +float SpineTrackEntry::get_attachment_threshold() { + return track_entry->getAttachmentThreshold(); +} +void SpineTrackEntry::set_attachment_threshold(float v) { + track_entry->setAttachmentThreshold(v); +} + +float SpineTrackEntry::get_draw_order_threshold() { + return track_entry->getDrawOrderThreshold(); +} +void SpineTrackEntry::set_draw_order_threshold(float v) { + track_entry->setDrawOrderThreshold(v); +} + +Ref SpineTrackEntry::get_next() { + Ref gd_entry(memnew(SpineTrackEntry)); + auto entry = track_entry->getNext(); + if (entry == NULL) return NULL; + gd_entry->set_spine_object(entry); + return gd_entry; +} + +bool SpineTrackEntry::is_complete() { + return track_entry->isComplete(); +} + +float SpineTrackEntry::get_mix_time() { + return track_entry->getMixTime(); +} +void SpineTrackEntry::set_mix_time(float v) { + track_entry->setMixTime(v); +} + +float SpineTrackEntry::get_mix_duration() { + return track_entry->getMixDuration(); +} +void SpineTrackEntry::set_mix_duration(float v) { + track_entry->setMixDuration(v); +} + +SpineTrackEntry::MixBlend SpineTrackEntry::get_mix_blend() { + int mb = track_entry->getMixBlend(); + return (MixBlend) mb; +} +void SpineTrackEntry::set_mix_blend(SpineTrackEntry::MixBlend v) { + int mb = (int) v; + track_entry->setMixBlend((spine::MixBlend) mb); +} + +Ref SpineTrackEntry::get_mixing_from() { + Ref gd_entry(memnew(SpineTrackEntry)); + auto entry = track_entry->getMixingFrom(); + if (entry == NULL) return NULL; + gd_entry->set_spine_object(entry); + return gd_entry; +} +Ref SpineTrackEntry::get_mixing_to() { + Ref gd_entry(memnew(SpineTrackEntry)); + auto entry = track_entry->getMixingTo(); + if (entry == NULL) return NULL; + gd_entry->set_spine_object(entry); + return gd_entry; +} + +void SpineTrackEntry::reset_rotation_directions() { + track_entry->resetRotationDirections(); +} + +bool SpineTrackEntry::get_reverse() { + return track_entry->getReverse(); +} + +void SpineTrackEntry::set_reverse(bool v) { + track_entry->setReverse(v); +} diff --git a/spine-godot/spine_godot/SpineTrackEntry.h b/spine-godot/spine_godot/SpineTrackEntry.h new file mode 100644 index 000000000..25c4b785f --- /dev/null +++ b/spine-godot/spine_godot/SpineTrackEntry.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 GODOT_SPINETRACKENTRY_H +#define GODOT_SPINETRACKENTRY_H + +#include "core/variant_parser.h" + +#include + +#include "SpineAnimation.h" + +class SpineTrackEntry : public Reference { + GDCLASS(SpineTrackEntry, Reference); + +protected: + static void _bind_methods(); + +private: + spine::TrackEntry *track_entry; + +public: + SpineTrackEntry(); + ~SpineTrackEntry(); + + inline void set_spine_object(spine::TrackEntry *t) { + track_entry = t; + } + inline spine::TrackEntry *get_spine_object() { + return track_entry; + } + + enum MixBlend { + MIXBLEND_SETUP = 0, + MIXBLEND_FIRST, + MIXBLEND_REPLACE, + MIXBLEND_ADD + }; + + int get_track_index(); + + Ref get_animation(); + + bool get_loop(); + void set_loop(bool v); + + bool get_hold_previous(); + void set_hold_previous(bool v); + + bool get_reverse(); + void set_reverse(bool v); + + float get_delay(); + void set_delay(float v); + + float get_track_time(); + void set_track_time(float v); + + float get_track_end(); + void set_track_end(float v); + + float get_animation_start(); + void set_animation_start(float v); + + float get_animation_last(); + void set_animation_last(float v); + + float get_animation_time(); + + float get_time_scale(); + void set_time_scale(float v); + + float get_alpha(); + void set_alpha(float v); + + float get_event_threshold(); + void set_event_threshold(float v); + + float get_attachment_threshold(); + void set_attachment_threshold(float v); + + float get_draw_order_threshold(); + void set_draw_order_threshold(float v); + + Ref get_next(); + + bool is_complete(); + + float get_mix_time(); + void set_mix_time(float v); + + float get_mix_duration(); + void set_mix_duration(float v); + + MixBlend get_mix_blend(); + void set_mix_blend(MixBlend v); + + Ref get_mixing_from(); + Ref get_mixing_to(); + + void reset_rotation_directions(); +}; + +VARIANT_ENUM_CAST(SpineTrackEntry::MixBlend); +#endif//GODOT_SPINETRACKENTRY_H diff --git a/spine-godot/spine_godot/SpineTransformConstraint.cpp b/spine-godot/spine_godot/SpineTransformConstraint.cpp new file mode 100644 index 000000000..2166a5917 --- /dev/null +++ b/spine-godot/spine_godot/SpineTransformConstraint.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. + *****************************************************************************/ + +#include "SpineTransformConstraint.h" + +void SpineTransformConstraint::_bind_methods() { + ClassDB::bind_method(D_METHOD("update"), &SpineTransformConstraint::update); + ClassDB::bind_method(D_METHOD("get_data"), &SpineTransformConstraint::get_data); + ClassDB::bind_method(D_METHOD("get_bones"), &SpineTransformConstraint::get_bones); + ClassDB::bind_method(D_METHOD("get_target"), &SpineTransformConstraint::get_target); + ClassDB::bind_method(D_METHOD("set_target", "v"), &SpineTransformConstraint::set_target); + ClassDB::bind_method(D_METHOD("get_mix_rotate"), &SpineTransformConstraint::get_mix_rotate); + ClassDB::bind_method(D_METHOD("set_mix_rotate", "v"), &SpineTransformConstraint::set_mix_rotate); + ClassDB::bind_method(D_METHOD("get_mix_x"), &SpineTransformConstraint::get_mix_x); + ClassDB::bind_method(D_METHOD("set_mix_x", "v"), &SpineTransformConstraint::set_mix_x); + ClassDB::bind_method(D_METHOD("get_mix_y"), &SpineTransformConstraint::get_mix_y); + ClassDB::bind_method(D_METHOD("set_mix_y", "v"), &SpineTransformConstraint::set_mix_y); + ClassDB::bind_method(D_METHOD("get_mix_scale_x"), &SpineTransformConstraint::get_mix_scale_x); + ClassDB::bind_method(D_METHOD("set_mix_scale_x", "v"), &SpineTransformConstraint::set_mix_scale_x); + ClassDB::bind_method(D_METHOD("get_mix_scale_y"), &SpineTransformConstraint::get_mix_scale_y); + ClassDB::bind_method(D_METHOD("set_mix_scale_y", "v"), &SpineTransformConstraint::set_mix_scale_y); + ClassDB::bind_method(D_METHOD("get_mix_shear_y"), &SpineTransformConstraint::get_mix_shear_y); + ClassDB::bind_method(D_METHOD("set_mix_shear_y", "v"), &SpineTransformConstraint::set_mix_shear_y); + ClassDB::bind_method(D_METHOD("is_active"), &SpineTransformConstraint::is_active); + ClassDB::bind_method(D_METHOD("set_active", "v"), &SpineTransformConstraint::set_active); +} + +SpineTransformConstraint::SpineTransformConstraint() : transform_constraint(NULL) {} +SpineTransformConstraint::~SpineTransformConstraint() {} + +void SpineTransformConstraint::update() { + transform_constraint->update(); +} + +int SpineTransformConstraint::get_order() { + return transform_constraint->getOrder(); +} + +Ref SpineTransformConstraint::get_data() { + auto &d = transform_constraint->getData(); + Ref gd_d(memnew(SpineTransformConstraintData)); + gd_d->set_spine_object(&d); + return gd_d; +} + +Array SpineTransformConstraint::get_bones() { + auto &bs = transform_constraint->getBones(); + Array gd_bs; + gd_bs.resize(bs.size()); + for (size_t i = 0; i < bs.size(); ++i) { + auto b = bs[i]; + if (b == NULL) gd_bs[i] = Ref(NULL); + Ref gd_b(memnew(SpineBone)); + gd_b->set_spine_object(b); + gd_bs[i] = gd_b; + } + return gd_bs; +} + +Ref SpineTransformConstraint::get_target() { + auto b = transform_constraint->getTarget(); + if (b == NULL) return NULL; + Ref gd_b(memnew(SpineBone)); + gd_b->set_spine_object(b); + return gd_b; +} +void SpineTransformConstraint::set_target(Ref v) { + if (v.is_valid()) { + transform_constraint->setTarget(v->get_spine_object()); + } else { + transform_constraint->setTarget(NULL); + } +} + +float SpineTransformConstraint::get_mix_rotate() { + return transform_constraint->getMixRotate(); +} +void SpineTransformConstraint::set_mix_rotate(float v) { + transform_constraint->setMixRotate(v); +} + +float SpineTransformConstraint::get_mix_x() { + return transform_constraint->getMixX(); +} +void SpineTransformConstraint::set_mix_x(float v) { + transform_constraint->setMixX(v); +} + +float SpineTransformConstraint::get_mix_y() { + return transform_constraint->getMixY(); +} +void SpineTransformConstraint::set_mix_y(float v) { + transform_constraint->setMixY(v); +} + +float SpineTransformConstraint::get_mix_scale_x() { + return transform_constraint->getMixScaleX(); +} +void SpineTransformConstraint::set_mix_scale_x(float v) { + transform_constraint->setMixScaleX(v); +} + +float SpineTransformConstraint::get_mix_scale_y() { + return transform_constraint->getMixScaleY(); +} +void SpineTransformConstraint::set_mix_scale_y(float v) { + transform_constraint->setMixScaleY(v); +} + +float SpineTransformConstraint::get_mix_shear_y() { + return transform_constraint->getMixShearY(); +} +void SpineTransformConstraint::set_mix_shear_y(float v) { + transform_constraint->setMixShearY(v); +} + +bool SpineTransformConstraint::is_active() { + return transform_constraint->isActive(); +} +void SpineTransformConstraint::set_active(bool v) { + transform_constraint->setActive(v); +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineTransformConstraint.h b/spine-godot/spine_godot/SpineTransformConstraint.h new file mode 100644 index 000000000..6430f05fb --- /dev/null +++ b/spine-godot/spine_godot/SpineTransformConstraint.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 GODOT_SPINETRANSFORMCONSTRAINT_H +#define GODOT_SPINETRANSFORMCONSTRAINT_H + +#include "core/variant_parser.h" + +#include + +#include "SpineTransformConstraintData.h" +#include "SpineBone.h" + +class SpineTransformConstraint : public Reference { + GDCLASS(SpineTransformConstraint, Reference); + +protected: + static void _bind_methods(); + +private: + spine::TransformConstraint *transform_constraint; + +public: + SpineTransformConstraint(); + ~SpineTransformConstraint(); + + inline void set_spine_object(spine::TransformConstraint *tc) { + transform_constraint = tc; + } + inline spine::TransformConstraint *get_spine_object() { + return transform_constraint; + } + + void update(); + + int get_order(); + + Ref get_data(); + + Array get_bones(); + + Ref get_target(); + void set_target(Ref v); + + float get_mix_rotate(); + void set_mix_rotate(float v); + + float get_mix_x(); + void set_mix_x(float v); + + float get_mix_y(); + void set_mix_y(float v); + + float get_mix_scale_x(); + void set_mix_scale_x(float v); + + float get_mix_scale_y(); + void set_mix_scale_y(float v); + + float get_mix_shear_y(); + void set_mix_shear_y(float v); + + bool is_active(); + void set_active(bool v); +}; + +#endif//GODOT_SPINETRANSFORMCONSTRAINT_H diff --git a/spine-godot/spine_godot/SpineTransformConstraintData.cpp b/spine-godot/spine_godot/SpineTransformConstraintData.cpp new file mode 100644 index 000000000..c7534cafb --- /dev/null +++ b/spine-godot/spine_godot/SpineTransformConstraintData.cpp @@ -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. + *****************************************************************************/ + +#include "SpineTransformConstraintData.h" + +void SpineTransformConstraintData::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_all_bone_data"), &SpineTransformConstraintData::get_bones); + ClassDB::bind_method(D_METHOD("get_target"), &SpineTransformConstraintData::get_target); + ClassDB::bind_method(D_METHOD("get_mix_rotate"), &SpineTransformConstraintData::get_mix_rotate); + ClassDB::bind_method(D_METHOD("get_mix_x"), &SpineTransformConstraintData::get_mix_x); + ClassDB::bind_method(D_METHOD("get_mix_y"), &SpineTransformConstraintData::get_mix_y); + ClassDB::bind_method(D_METHOD("get_mix_scale_x"), &SpineTransformConstraintData::get_mix_scale_x); + ClassDB::bind_method(D_METHOD("get_mix_scale_y"), &SpineTransformConstraintData::get_mix_scale_y); + ClassDB::bind_method(D_METHOD("get_mix_shear_y"), &SpineTransformConstraintData::get_mix_shear_y); + ClassDB::bind_method(D_METHOD("get_offset_rotation"), &SpineTransformConstraintData::get_offset_rotation); + ClassDB::bind_method(D_METHOD("get_offset_x"), &SpineTransformConstraintData::get_offset_x); + ClassDB::bind_method(D_METHOD("get_offset_y"), &SpineTransformConstraintData::get_offset_y); + ClassDB::bind_method(D_METHOD("get_offset_scale_x"), &SpineTransformConstraintData::get_offset_scale_x); + ClassDB::bind_method(D_METHOD("get_offset_scale_y"), &SpineTransformConstraintData::get_offset_scale_y); + ClassDB::bind_method(D_METHOD("get_offset_shear_y"), &SpineTransformConstraintData::get_offset_shear_y); + ClassDB::bind_method(D_METHOD("is_relative"), &SpineTransformConstraintData::is_relative); + ClassDB::bind_method(D_METHOD("is_local"), &SpineTransformConstraintData::is_local); +} + +SpineTransformConstraintData::SpineTransformConstraintData() {} +SpineTransformConstraintData::~SpineTransformConstraintData() {} + +Array SpineTransformConstraintData::get_bones() { + auto bs = get_spine_data()->getBones(); + Array gd_bs; + gd_bs.resize(bs.size()); + for (size_t i = 0; i < bs.size(); ++i) { + if (bs[i] == NULL) gd_bs[i] = Ref(NULL); + else { + Ref gd_b(memnew(SpineBoneData)); + gd_b->set_spine_object(bs[i]); + gd_bs[i] = gd_b; + } + } + return gd_bs; +} +Ref SpineTransformConstraintData::get_target() { + auto b = get_spine_data()->getTarget(); + if (b == NULL) return NULL; + Ref gd_b(memnew(SpineBoneData)); + gd_b->set_spine_object(b); + return gd_b; +} +float SpineTransformConstraintData::get_mix_rotate() { + return get_spine_data()->getMixRotate(); +} +float SpineTransformConstraintData::get_mix_x() { + return get_spine_data()->getMixX(); +} +float SpineTransformConstraintData::get_mix_y() { + return get_spine_data()->getMixY(); +} +float SpineTransformConstraintData::get_mix_scale_x() { + return get_spine_data()->getMixScaleX(); +} +float SpineTransformConstraintData::get_mix_scale_y() { + return get_spine_data()->getMixScaleY(); +} +float SpineTransformConstraintData::get_mix_shear_y() { + return get_spine_data()->getMixShearY(); +} + +float SpineTransformConstraintData::get_offset_rotation() { + return get_spine_data()->getOffsetRotation(); +} +float SpineTransformConstraintData::get_offset_x() { + return get_spine_data()->getOffsetX(); +} +float SpineTransformConstraintData::get_offset_y() { + return get_spine_data()->getOffsetY(); +} +float SpineTransformConstraintData::get_offset_scale_x() { + return get_spine_data()->getOffsetScaleX(); +} +float SpineTransformConstraintData::get_offset_scale_y() { + return get_spine_data()->getOffsetScaleY(); +} +float SpineTransformConstraintData::get_offset_shear_y() { + return get_spine_data()->getOffsetShearY(); +} + +bool SpineTransformConstraintData::is_relative() { + return get_spine_data()->isRelative(); +} +bool SpineTransformConstraintData::is_local() { + return get_spine_data()->isLocal(); +} \ No newline at end of file diff --git a/spine-godot/spine_godot/SpineTransformConstraintData.h b/spine-godot/spine_godot/SpineTransformConstraintData.h new file mode 100644 index 000000000..6c1b21569 --- /dev/null +++ b/spine-godot/spine_godot/SpineTransformConstraintData.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 GODOT_SPINETRANSFORMCONSTRAINTDATA_H +#define GODOT_SPINETRANSFORMCONSTRAINTDATA_H + +#include "core/variant_parser.h" + +#include + +#include "SpineConstraintData.h" +#include "SpineBoneData.h" + +class SpineTransformConstraintData : public SpineConstraintData { + GDCLASS(SpineTransformConstraintData, SpineConstraintData); + +protected: + static void _bind_methods(); + +public: + SpineTransformConstraintData(); + ~SpineTransformConstraintData(); + + virtual inline spine::TransformConstraintData *get_spine_data() { + return (spine::TransformConstraintData *) SpineConstraintData::get_spine_object(); + } + + Array get_bones(); + Ref get_target(); + float get_mix_rotate(); + float get_mix_x(); + float get_mix_y(); + float get_mix_scale_x(); + float get_mix_scale_y(); + float get_mix_shear_y(); + + float get_offset_rotation(); + float get_offset_x(); + float get_offset_y(); + float get_offset_scale_x(); + float get_offset_scale_y(); + float get_offset_shear_y(); + + bool is_relative(); + bool is_local(); +}; + +#endif//GODOT_SPINETRANSFORMCONSTRAINTDATA_H diff --git a/spine-godot/spine_godot/config.py b/spine-godot/spine_godot/config.py new file mode 100644 index 000000000..827e2c435 --- /dev/null +++ b/spine-godot/spine_godot/config.py @@ -0,0 +1,5 @@ +def can_build(env, platform): + return True + +def configure(env): + pass \ No newline at end of file diff --git a/spine-godot/spine_godot/register_types.cpp b/spine-godot/spine_godot/register_types.cpp new file mode 100644 index 000000000..1fd9ad626 --- /dev/null +++ b/spine-godot/spine_godot/register_types.cpp @@ -0,0 +1,144 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING 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 "register_types.h" + +#include "core/class_db.h" + +#include "SpineAtlasResource.h" +#include "SpineSkeletonDataResource.h" +#include "ResourceFormatLoaderSpineSkeletonJsonData.h" +#include "ResourceFormatSaverSpineSkeletonJsonData.h" +#include "SpineSprite.h" +#include "SpineAnimationStateDataResource.h" +#include "SpineSkeleton.h" +#include "SpineAnimationState.h" +#include "SpineEventData.h" +#include "SpineEvent.h" +#include "SpineTrackEntry.h" +#include "SpineBoneData.h" +#include "SpineSlotData.h" +#include "SpineAttachment.h" +#include "SpineSkinAttachmentMapEntries.h" +#include "SpineConstraintData.h" +#include "SpineSkin.h" +#include "SpineIkConstraintData.h" +#include "SpineTransformConstraintData.h" +#include "SpinePathConstraintData.h" +#include "SpineSpriteMeshInstance2D.h" +#include "SpineTimeline.h" +#include "SpineConstant.h" +#include "SpineCollisionShapeProxy.h" +#include "SpineSpriteAnimateDialog.h" + + +static Ref atlas_loader; +static Ref atlas_saver; +static Ref json_skeleton_loader; +static Ref json_skeleton_saver; + +// editor plugin +#ifdef TOOLS_ENABLED +#include "editor/editor_export.h" +#include "editor/editor_node.h" + +#include "SpineRuntimeEditorPlugin.h" + +static void editor_init_callback() { + EditorNode::get_singleton()->add_editor_plugin(memnew(SpineRuntimeEditorPlugin(EditorNode::get_singleton()))); +} + + +#endif + +void register_spine_godot_types() { +#ifdef TOOLS_ENABLED + ClassDB::register_class(); + + EditorNode::add_init_callback(editor_init_callback); + +#endif + + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + + atlas_loader.instance(); + ResourceLoader::add_resource_format_loader(atlas_loader); + + atlas_saver.instance(); + ResourceSaver::add_resource_format_saver(atlas_saver); + + json_skeleton_loader.instance(); + ResourceLoader::add_resource_format_loader(json_skeleton_loader); + + json_skeleton_saver.instance(); + ResourceSaver::add_resource_format_saver(json_skeleton_saver); +} + +void unregister_spine_godot_types() { + ResourceLoader::remove_resource_format_loader(atlas_loader); + atlas_loader.unref(); + + ResourceSaver::remove_resource_format_saver(atlas_saver); + atlas_saver.unref(); + + ResourceLoader::remove_resource_format_loader(json_skeleton_loader); + json_skeleton_loader.unref(); + + ResourceSaver::remove_resource_format_saver(json_skeleton_saver); + json_skeleton_saver.unref(); +} \ No newline at end of file diff --git a/spine-godot/spine_godot/register_types.h b/spine-godot/spine_godot/register_types.h new file mode 100644 index 000000000..59ef9515f --- /dev/null +++ b/spine-godot/spine_godot/register_types.h @@ -0,0 +1,31 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +void register_spine_godot_types(); +void unregister_spine_godot_types(); From b409fcb067c50a93c4927dd2f0115aa91a26037f Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Mon, 4 Apr 2022 12:23:00 +0200 Subject: [PATCH 14/18] [godot] Fix gitignore again. --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index dc09502da..b1b0e9d8d 100644 --- a/.gitignore +++ b/.gitignore @@ -165,4 +165,5 @@ spine-cocos2dx/example/build-ios spine-cocos2dx/example/proj.android/app/.cxx spine-cocos2dx/example/build-win spine-godot/godot -spine-godot/spine_godot +spine-godot/spine_godot/__pycache__ +spine-godot/spine_godot/spine-cpp From 1a51078c1996f428cc13ce6ef4565215b4cd4d30 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Mon, 4 Apr 2022 13:41:56 +0200 Subject: [PATCH 15/18] [godot] Get rid of symlink --- .gitignore | 1 + spine-godot/{ => godot}/custom.py | 0 .../modules}/spine_godot/GodotSpineExtension.cpp | 0 .../modules}/spine_godot/GodotSpineExtension.h | 0 .../ResourceFormatLoaderSpineSkeletonJsonData.cpp | 0 .../ResourceFormatLoaderSpineSkeletonJsonData.h | 0 .../ResourceFormatSaverSpineSkeletonJsonData.cpp | 0 .../ResourceFormatSaverSpineSkeletonJsonData.h | 0 spine-godot/{ => godot/modules}/spine_godot/SCsub | 0 .../{ => godot/modules}/spine_godot/SpineAnimation.cpp | 0 .../{ => godot/modules}/spine_godot/SpineAnimation.h | 0 .../modules}/spine_godot/SpineAnimationState.cpp | 0 .../modules}/spine_godot/SpineAnimationState.h | 0 .../spine_godot/SpineAnimationStateDataResource.cpp | 0 .../spine_godot/SpineAnimationStateDataResource.h | 0 .../modules}/spine_godot/SpineAtlasResource.cpp | 0 .../{ => godot/modules}/spine_godot/SpineAtlasResource.h | 0 .../{ => godot/modules}/spine_godot/SpineAttachment.cpp | 0 .../{ => godot/modules}/spine_godot/SpineAttachment.h | 0 .../{ => godot/modules}/spine_godot/SpineBone.cpp | 0 spine-godot/{ => godot/modules}/spine_godot/SpineBone.h | 0 .../{ => godot/modules}/spine_godot/SpineBoneData.cpp | 0 .../{ => godot/modules}/spine_godot/SpineBoneData.h | 0 .../modules}/spine_godot/SpineCollisionShapeProxy.cpp | 0 .../modules}/spine_godot/SpineCollisionShapeProxy.h | 0 .../{ => godot/modules}/spine_godot/SpineConstant.cpp | 0 .../{ => godot/modules}/spine_godot/SpineConstant.h | 0 .../modules}/spine_godot/SpineConstraintData.cpp | 0 .../modules}/spine_godot/SpineConstraintData.h | 0 .../{ => godot/modules}/spine_godot/SpineEvent.cpp | 0 spine-godot/{ => godot/modules}/spine_godot/SpineEvent.h | 0 .../{ => godot/modules}/spine_godot/SpineEventData.cpp | 0 .../{ => godot/modules}/spine_godot/SpineEventData.h | 0 .../modules}/spine_godot/SpineIkConstraint.cpp | 0 .../{ => godot/modules}/spine_godot/SpineIkConstraint.h | 0 .../modules}/spine_godot/SpineIkConstraintData.cpp | 0 .../modules}/spine_godot/SpineIkConstraintData.h | 0 .../modules}/spine_godot/SpinePathConstraint.cpp | 0 .../modules}/spine_godot/SpinePathConstraint.h | 0 .../modules}/spine_godot/SpinePathConstraintData.cpp | 0 .../modules}/spine_godot/SpinePathConstraintData.h | 0 .../modules}/spine_godot/SpineRendererObject.h | 0 .../modules}/spine_godot/SpineRuntimeEditorPlugin.cpp | 0 .../modules}/spine_godot/SpineRuntimeEditorPlugin.h | 0 .../{ => godot/modules}/spine_godot/SpineSkeleton.cpp | 0 .../{ => godot/modules}/spine_godot/SpineSkeleton.h | 0 .../modules}/spine_godot/SpineSkeletonDataResource.cpp | 0 .../modules}/spine_godot/SpineSkeletonDataResource.h | 0 .../spine_godot/SpineSkeletonJsonDataResource.cpp | 0 .../modules}/spine_godot/SpineSkeletonJsonDataResource.h | 0 .../{ => godot/modules}/spine_godot/SpineSkin.cpp | 0 spine-godot/{ => godot/modules}/spine_godot/SpineSkin.h | 0 .../spine_godot/SpineSkinAttachmentMapEntries.cpp | 0 .../modules}/spine_godot/SpineSkinAttachmentMapEntries.h | 0 .../{ => godot/modules}/spine_godot/SpineSlot.cpp | 0 spine-godot/{ => godot/modules}/spine_godot/SpineSlot.h | 0 .../{ => godot/modules}/spine_godot/SpineSlotData.cpp | 0 .../{ => godot/modules}/spine_godot/SpineSlotData.h | 0 .../{ => godot/modules}/spine_godot/SpineSprite.cpp | 0 .../{ => godot/modules}/spine_godot/SpineSprite.h | 0 .../modules}/spine_godot/SpineSpriteAnimateDialog.cpp | 0 .../modules}/spine_godot/SpineSpriteAnimateDialog.h | 0 .../modules}/spine_godot/SpineSpriteMeshInstance2D.cpp | 0 .../modules}/spine_godot/SpineSpriteMeshInstance2D.h | 0 .../{ => godot/modules}/spine_godot/SpineTimeline.cpp | 0 .../{ => godot/modules}/spine_godot/SpineTimeline.h | 0 .../{ => godot/modules}/spine_godot/SpineTrackEntry.cpp | 0 .../{ => godot/modules}/spine_godot/SpineTrackEntry.h | 0 .../modules}/spine_godot/SpineTransformConstraint.cpp | 0 .../modules}/spine_godot/SpineTransformConstraint.h | 0 .../spine_godot/SpineTransformConstraintData.cpp | 0 .../modules}/spine_godot/SpineTransformConstraintData.h | 0 spine-godot/{ => godot/modules}/spine_godot/config.py | 0 .../{ => godot/modules}/spine_godot/register_types.cpp | 0 .../{ => godot/modules}/spine_godot/register_types.h | 0 spine-godot/setup.sh | 9 ++++----- 76 files changed, 5 insertions(+), 5 deletions(-) rename spine-godot/{ => godot}/custom.py (100%) rename spine-godot/{ => godot/modules}/spine_godot/GodotSpineExtension.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/GodotSpineExtension.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SCsub (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineAnimation.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineAnimation.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineAnimationState.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineAnimationState.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineAnimationStateDataResource.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineAnimationStateDataResource.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineAtlasResource.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineAtlasResource.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineAttachment.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineAttachment.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineBone.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineBone.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineBoneData.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineBoneData.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineCollisionShapeProxy.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineCollisionShapeProxy.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineConstant.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineConstant.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineConstraintData.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineConstraintData.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineEvent.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineEvent.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineEventData.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineEventData.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineIkConstraint.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineIkConstraint.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineIkConstraintData.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineIkConstraintData.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpinePathConstraint.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpinePathConstraint.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpinePathConstraintData.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpinePathConstraintData.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineRendererObject.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineRuntimeEditorPlugin.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineRuntimeEditorPlugin.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineSkeleton.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineSkeleton.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineSkeletonDataResource.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineSkeletonDataResource.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineSkeletonJsonDataResource.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineSkeletonJsonDataResource.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineSkin.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineSkin.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineSkinAttachmentMapEntries.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineSkinAttachmentMapEntries.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineSlot.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineSlot.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineSlotData.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineSlotData.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineSprite.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineSprite.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineSpriteAnimateDialog.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineSpriteAnimateDialog.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineSpriteMeshInstance2D.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineSpriteMeshInstance2D.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineTimeline.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineTimeline.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineTrackEntry.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineTrackEntry.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineTransformConstraint.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineTransformConstraint.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineTransformConstraintData.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/SpineTransformConstraintData.h (100%) rename spine-godot/{ => godot/modules}/spine_godot/config.py (100%) rename spine-godot/{ => godot/modules}/spine_godot/register_types.cpp (100%) rename spine-godot/{ => godot/modules}/spine_godot/register_types.h (100%) diff --git a/.gitignore b/.gitignore index b1b0e9d8d..8de21a3f3 100644 --- a/.gitignore +++ b/.gitignore @@ -167,3 +167,4 @@ spine-cocos2dx/example/build-win spine-godot/godot spine-godot/spine_godot/__pycache__ spine-godot/spine_godot/spine-cpp +spine-godot/godot-copy diff --git a/spine-godot/custom.py b/spine-godot/godot/custom.py similarity index 100% rename from spine-godot/custom.py rename to spine-godot/godot/custom.py diff --git a/spine-godot/spine_godot/GodotSpineExtension.cpp b/spine-godot/godot/modules/spine_godot/GodotSpineExtension.cpp similarity index 100% rename from spine-godot/spine_godot/GodotSpineExtension.cpp rename to spine-godot/godot/modules/spine_godot/GodotSpineExtension.cpp diff --git a/spine-godot/spine_godot/GodotSpineExtension.h b/spine-godot/godot/modules/spine_godot/GodotSpineExtension.h similarity index 100% rename from spine-godot/spine_godot/GodotSpineExtension.h rename to spine-godot/godot/modules/spine_godot/GodotSpineExtension.h diff --git a/spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.cpp b/spine-godot/godot/modules/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.cpp similarity index 100% rename from spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.cpp rename to spine-godot/godot/modules/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.cpp diff --git a/spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.h b/spine-godot/godot/modules/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.h similarity index 100% rename from spine-godot/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.h rename to spine-godot/godot/modules/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.h diff --git a/spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.cpp b/spine-godot/godot/modules/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.cpp similarity index 100% rename from spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.cpp rename to spine-godot/godot/modules/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.cpp diff --git a/spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.h b/spine-godot/godot/modules/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.h similarity index 100% rename from spine-godot/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.h rename to spine-godot/godot/modules/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.h diff --git a/spine-godot/spine_godot/SCsub b/spine-godot/godot/modules/spine_godot/SCsub similarity index 100% rename from spine-godot/spine_godot/SCsub rename to spine-godot/godot/modules/spine_godot/SCsub diff --git a/spine-godot/spine_godot/SpineAnimation.cpp b/spine-godot/godot/modules/spine_godot/SpineAnimation.cpp similarity index 100% rename from spine-godot/spine_godot/SpineAnimation.cpp rename to spine-godot/godot/modules/spine_godot/SpineAnimation.cpp diff --git a/spine-godot/spine_godot/SpineAnimation.h b/spine-godot/godot/modules/spine_godot/SpineAnimation.h similarity index 100% rename from spine-godot/spine_godot/SpineAnimation.h rename to spine-godot/godot/modules/spine_godot/SpineAnimation.h diff --git a/spine-godot/spine_godot/SpineAnimationState.cpp b/spine-godot/godot/modules/spine_godot/SpineAnimationState.cpp similarity index 100% rename from spine-godot/spine_godot/SpineAnimationState.cpp rename to spine-godot/godot/modules/spine_godot/SpineAnimationState.cpp diff --git a/spine-godot/spine_godot/SpineAnimationState.h b/spine-godot/godot/modules/spine_godot/SpineAnimationState.h similarity index 100% rename from spine-godot/spine_godot/SpineAnimationState.h rename to spine-godot/godot/modules/spine_godot/SpineAnimationState.h diff --git a/spine-godot/spine_godot/SpineAnimationStateDataResource.cpp b/spine-godot/godot/modules/spine_godot/SpineAnimationStateDataResource.cpp similarity index 100% rename from spine-godot/spine_godot/SpineAnimationStateDataResource.cpp rename to spine-godot/godot/modules/spine_godot/SpineAnimationStateDataResource.cpp diff --git a/spine-godot/spine_godot/SpineAnimationStateDataResource.h b/spine-godot/godot/modules/spine_godot/SpineAnimationStateDataResource.h similarity index 100% rename from spine-godot/spine_godot/SpineAnimationStateDataResource.h rename to spine-godot/godot/modules/spine_godot/SpineAnimationStateDataResource.h diff --git a/spine-godot/spine_godot/SpineAtlasResource.cpp b/spine-godot/godot/modules/spine_godot/SpineAtlasResource.cpp similarity index 100% rename from spine-godot/spine_godot/SpineAtlasResource.cpp rename to spine-godot/godot/modules/spine_godot/SpineAtlasResource.cpp diff --git a/spine-godot/spine_godot/SpineAtlasResource.h b/spine-godot/godot/modules/spine_godot/SpineAtlasResource.h similarity index 100% rename from spine-godot/spine_godot/SpineAtlasResource.h rename to spine-godot/godot/modules/spine_godot/SpineAtlasResource.h diff --git a/spine-godot/spine_godot/SpineAttachment.cpp b/spine-godot/godot/modules/spine_godot/SpineAttachment.cpp similarity index 100% rename from spine-godot/spine_godot/SpineAttachment.cpp rename to spine-godot/godot/modules/spine_godot/SpineAttachment.cpp diff --git a/spine-godot/spine_godot/SpineAttachment.h b/spine-godot/godot/modules/spine_godot/SpineAttachment.h similarity index 100% rename from spine-godot/spine_godot/SpineAttachment.h rename to spine-godot/godot/modules/spine_godot/SpineAttachment.h diff --git a/spine-godot/spine_godot/SpineBone.cpp b/spine-godot/godot/modules/spine_godot/SpineBone.cpp similarity index 100% rename from spine-godot/spine_godot/SpineBone.cpp rename to spine-godot/godot/modules/spine_godot/SpineBone.cpp diff --git a/spine-godot/spine_godot/SpineBone.h b/spine-godot/godot/modules/spine_godot/SpineBone.h similarity index 100% rename from spine-godot/spine_godot/SpineBone.h rename to spine-godot/godot/modules/spine_godot/SpineBone.h diff --git a/spine-godot/spine_godot/SpineBoneData.cpp b/spine-godot/godot/modules/spine_godot/SpineBoneData.cpp similarity index 100% rename from spine-godot/spine_godot/SpineBoneData.cpp rename to spine-godot/godot/modules/spine_godot/SpineBoneData.cpp diff --git a/spine-godot/spine_godot/SpineBoneData.h b/spine-godot/godot/modules/spine_godot/SpineBoneData.h similarity index 100% rename from spine-godot/spine_godot/SpineBoneData.h rename to spine-godot/godot/modules/spine_godot/SpineBoneData.h diff --git a/spine-godot/spine_godot/SpineCollisionShapeProxy.cpp b/spine-godot/godot/modules/spine_godot/SpineCollisionShapeProxy.cpp similarity index 100% rename from spine-godot/spine_godot/SpineCollisionShapeProxy.cpp rename to spine-godot/godot/modules/spine_godot/SpineCollisionShapeProxy.cpp diff --git a/spine-godot/spine_godot/SpineCollisionShapeProxy.h b/spine-godot/godot/modules/spine_godot/SpineCollisionShapeProxy.h similarity index 100% rename from spine-godot/spine_godot/SpineCollisionShapeProxy.h rename to spine-godot/godot/modules/spine_godot/SpineCollisionShapeProxy.h diff --git a/spine-godot/spine_godot/SpineConstant.cpp b/spine-godot/godot/modules/spine_godot/SpineConstant.cpp similarity index 100% rename from spine-godot/spine_godot/SpineConstant.cpp rename to spine-godot/godot/modules/spine_godot/SpineConstant.cpp diff --git a/spine-godot/spine_godot/SpineConstant.h b/spine-godot/godot/modules/spine_godot/SpineConstant.h similarity index 100% rename from spine-godot/spine_godot/SpineConstant.h rename to spine-godot/godot/modules/spine_godot/SpineConstant.h diff --git a/spine-godot/spine_godot/SpineConstraintData.cpp b/spine-godot/godot/modules/spine_godot/SpineConstraintData.cpp similarity index 100% rename from spine-godot/spine_godot/SpineConstraintData.cpp rename to spine-godot/godot/modules/spine_godot/SpineConstraintData.cpp diff --git a/spine-godot/spine_godot/SpineConstraintData.h b/spine-godot/godot/modules/spine_godot/SpineConstraintData.h similarity index 100% rename from spine-godot/spine_godot/SpineConstraintData.h rename to spine-godot/godot/modules/spine_godot/SpineConstraintData.h diff --git a/spine-godot/spine_godot/SpineEvent.cpp b/spine-godot/godot/modules/spine_godot/SpineEvent.cpp similarity index 100% rename from spine-godot/spine_godot/SpineEvent.cpp rename to spine-godot/godot/modules/spine_godot/SpineEvent.cpp diff --git a/spine-godot/spine_godot/SpineEvent.h b/spine-godot/godot/modules/spine_godot/SpineEvent.h similarity index 100% rename from spine-godot/spine_godot/SpineEvent.h rename to spine-godot/godot/modules/spine_godot/SpineEvent.h diff --git a/spine-godot/spine_godot/SpineEventData.cpp b/spine-godot/godot/modules/spine_godot/SpineEventData.cpp similarity index 100% rename from spine-godot/spine_godot/SpineEventData.cpp rename to spine-godot/godot/modules/spine_godot/SpineEventData.cpp diff --git a/spine-godot/spine_godot/SpineEventData.h b/spine-godot/godot/modules/spine_godot/SpineEventData.h similarity index 100% rename from spine-godot/spine_godot/SpineEventData.h rename to spine-godot/godot/modules/spine_godot/SpineEventData.h diff --git a/spine-godot/spine_godot/SpineIkConstraint.cpp b/spine-godot/godot/modules/spine_godot/SpineIkConstraint.cpp similarity index 100% rename from spine-godot/spine_godot/SpineIkConstraint.cpp rename to spine-godot/godot/modules/spine_godot/SpineIkConstraint.cpp diff --git a/spine-godot/spine_godot/SpineIkConstraint.h b/spine-godot/godot/modules/spine_godot/SpineIkConstraint.h similarity index 100% rename from spine-godot/spine_godot/SpineIkConstraint.h rename to spine-godot/godot/modules/spine_godot/SpineIkConstraint.h diff --git a/spine-godot/spine_godot/SpineIkConstraintData.cpp b/spine-godot/godot/modules/spine_godot/SpineIkConstraintData.cpp similarity index 100% rename from spine-godot/spine_godot/SpineIkConstraintData.cpp rename to spine-godot/godot/modules/spine_godot/SpineIkConstraintData.cpp diff --git a/spine-godot/spine_godot/SpineIkConstraintData.h b/spine-godot/godot/modules/spine_godot/SpineIkConstraintData.h similarity index 100% rename from spine-godot/spine_godot/SpineIkConstraintData.h rename to spine-godot/godot/modules/spine_godot/SpineIkConstraintData.h diff --git a/spine-godot/spine_godot/SpinePathConstraint.cpp b/spine-godot/godot/modules/spine_godot/SpinePathConstraint.cpp similarity index 100% rename from spine-godot/spine_godot/SpinePathConstraint.cpp rename to spine-godot/godot/modules/spine_godot/SpinePathConstraint.cpp diff --git a/spine-godot/spine_godot/SpinePathConstraint.h b/spine-godot/godot/modules/spine_godot/SpinePathConstraint.h similarity index 100% rename from spine-godot/spine_godot/SpinePathConstraint.h rename to spine-godot/godot/modules/spine_godot/SpinePathConstraint.h diff --git a/spine-godot/spine_godot/SpinePathConstraintData.cpp b/spine-godot/godot/modules/spine_godot/SpinePathConstraintData.cpp similarity index 100% rename from spine-godot/spine_godot/SpinePathConstraintData.cpp rename to spine-godot/godot/modules/spine_godot/SpinePathConstraintData.cpp diff --git a/spine-godot/spine_godot/SpinePathConstraintData.h b/spine-godot/godot/modules/spine_godot/SpinePathConstraintData.h similarity index 100% rename from spine-godot/spine_godot/SpinePathConstraintData.h rename to spine-godot/godot/modules/spine_godot/SpinePathConstraintData.h diff --git a/spine-godot/spine_godot/SpineRendererObject.h b/spine-godot/godot/modules/spine_godot/SpineRendererObject.h similarity index 100% rename from spine-godot/spine_godot/SpineRendererObject.h rename to spine-godot/godot/modules/spine_godot/SpineRendererObject.h diff --git a/spine-godot/spine_godot/SpineRuntimeEditorPlugin.cpp b/spine-godot/godot/modules/spine_godot/SpineRuntimeEditorPlugin.cpp similarity index 100% rename from spine-godot/spine_godot/SpineRuntimeEditorPlugin.cpp rename to spine-godot/godot/modules/spine_godot/SpineRuntimeEditorPlugin.cpp diff --git a/spine-godot/spine_godot/SpineRuntimeEditorPlugin.h b/spine-godot/godot/modules/spine_godot/SpineRuntimeEditorPlugin.h similarity index 100% rename from spine-godot/spine_godot/SpineRuntimeEditorPlugin.h rename to spine-godot/godot/modules/spine_godot/SpineRuntimeEditorPlugin.h diff --git a/spine-godot/spine_godot/SpineSkeleton.cpp b/spine-godot/godot/modules/spine_godot/SpineSkeleton.cpp similarity index 100% rename from spine-godot/spine_godot/SpineSkeleton.cpp rename to spine-godot/godot/modules/spine_godot/SpineSkeleton.cpp diff --git a/spine-godot/spine_godot/SpineSkeleton.h b/spine-godot/godot/modules/spine_godot/SpineSkeleton.h similarity index 100% rename from spine-godot/spine_godot/SpineSkeleton.h rename to spine-godot/godot/modules/spine_godot/SpineSkeleton.h diff --git a/spine-godot/spine_godot/SpineSkeletonDataResource.cpp b/spine-godot/godot/modules/spine_godot/SpineSkeletonDataResource.cpp similarity index 100% rename from spine-godot/spine_godot/SpineSkeletonDataResource.cpp rename to spine-godot/godot/modules/spine_godot/SpineSkeletonDataResource.cpp diff --git a/spine-godot/spine_godot/SpineSkeletonDataResource.h b/spine-godot/godot/modules/spine_godot/SpineSkeletonDataResource.h similarity index 100% rename from spine-godot/spine_godot/SpineSkeletonDataResource.h rename to spine-godot/godot/modules/spine_godot/SpineSkeletonDataResource.h diff --git a/spine-godot/spine_godot/SpineSkeletonJsonDataResource.cpp b/spine-godot/godot/modules/spine_godot/SpineSkeletonJsonDataResource.cpp similarity index 100% rename from spine-godot/spine_godot/SpineSkeletonJsonDataResource.cpp rename to spine-godot/godot/modules/spine_godot/SpineSkeletonJsonDataResource.cpp diff --git a/spine-godot/spine_godot/SpineSkeletonJsonDataResource.h b/spine-godot/godot/modules/spine_godot/SpineSkeletonJsonDataResource.h similarity index 100% rename from spine-godot/spine_godot/SpineSkeletonJsonDataResource.h rename to spine-godot/godot/modules/spine_godot/SpineSkeletonJsonDataResource.h diff --git a/spine-godot/spine_godot/SpineSkin.cpp b/spine-godot/godot/modules/spine_godot/SpineSkin.cpp similarity index 100% rename from spine-godot/spine_godot/SpineSkin.cpp rename to spine-godot/godot/modules/spine_godot/SpineSkin.cpp diff --git a/spine-godot/spine_godot/SpineSkin.h b/spine-godot/godot/modules/spine_godot/SpineSkin.h similarity index 100% rename from spine-godot/spine_godot/SpineSkin.h rename to spine-godot/godot/modules/spine_godot/SpineSkin.h diff --git a/spine-godot/spine_godot/SpineSkinAttachmentMapEntries.cpp b/spine-godot/godot/modules/spine_godot/SpineSkinAttachmentMapEntries.cpp similarity index 100% rename from spine-godot/spine_godot/SpineSkinAttachmentMapEntries.cpp rename to spine-godot/godot/modules/spine_godot/SpineSkinAttachmentMapEntries.cpp diff --git a/spine-godot/spine_godot/SpineSkinAttachmentMapEntries.h b/spine-godot/godot/modules/spine_godot/SpineSkinAttachmentMapEntries.h similarity index 100% rename from spine-godot/spine_godot/SpineSkinAttachmentMapEntries.h rename to spine-godot/godot/modules/spine_godot/SpineSkinAttachmentMapEntries.h diff --git a/spine-godot/spine_godot/SpineSlot.cpp b/spine-godot/godot/modules/spine_godot/SpineSlot.cpp similarity index 100% rename from spine-godot/spine_godot/SpineSlot.cpp rename to spine-godot/godot/modules/spine_godot/SpineSlot.cpp diff --git a/spine-godot/spine_godot/SpineSlot.h b/spine-godot/godot/modules/spine_godot/SpineSlot.h similarity index 100% rename from spine-godot/spine_godot/SpineSlot.h rename to spine-godot/godot/modules/spine_godot/SpineSlot.h diff --git a/spine-godot/spine_godot/SpineSlotData.cpp b/spine-godot/godot/modules/spine_godot/SpineSlotData.cpp similarity index 100% rename from spine-godot/spine_godot/SpineSlotData.cpp rename to spine-godot/godot/modules/spine_godot/SpineSlotData.cpp diff --git a/spine-godot/spine_godot/SpineSlotData.h b/spine-godot/godot/modules/spine_godot/SpineSlotData.h similarity index 100% rename from spine-godot/spine_godot/SpineSlotData.h rename to spine-godot/godot/modules/spine_godot/SpineSlotData.h diff --git a/spine-godot/spine_godot/SpineSprite.cpp b/spine-godot/godot/modules/spine_godot/SpineSprite.cpp similarity index 100% rename from spine-godot/spine_godot/SpineSprite.cpp rename to spine-godot/godot/modules/spine_godot/SpineSprite.cpp diff --git a/spine-godot/spine_godot/SpineSprite.h b/spine-godot/godot/modules/spine_godot/SpineSprite.h similarity index 100% rename from spine-godot/spine_godot/SpineSprite.h rename to spine-godot/godot/modules/spine_godot/SpineSprite.h diff --git a/spine-godot/spine_godot/SpineSpriteAnimateDialog.cpp b/spine-godot/godot/modules/spine_godot/SpineSpriteAnimateDialog.cpp similarity index 100% rename from spine-godot/spine_godot/SpineSpriteAnimateDialog.cpp rename to spine-godot/godot/modules/spine_godot/SpineSpriteAnimateDialog.cpp diff --git a/spine-godot/spine_godot/SpineSpriteAnimateDialog.h b/spine-godot/godot/modules/spine_godot/SpineSpriteAnimateDialog.h similarity index 100% rename from spine-godot/spine_godot/SpineSpriteAnimateDialog.h rename to spine-godot/godot/modules/spine_godot/SpineSpriteAnimateDialog.h diff --git a/spine-godot/spine_godot/SpineSpriteMeshInstance2D.cpp b/spine-godot/godot/modules/spine_godot/SpineSpriteMeshInstance2D.cpp similarity index 100% rename from spine-godot/spine_godot/SpineSpriteMeshInstance2D.cpp rename to spine-godot/godot/modules/spine_godot/SpineSpriteMeshInstance2D.cpp diff --git a/spine-godot/spine_godot/SpineSpriteMeshInstance2D.h b/spine-godot/godot/modules/spine_godot/SpineSpriteMeshInstance2D.h similarity index 100% rename from spine-godot/spine_godot/SpineSpriteMeshInstance2D.h rename to spine-godot/godot/modules/spine_godot/SpineSpriteMeshInstance2D.h diff --git a/spine-godot/spine_godot/SpineTimeline.cpp b/spine-godot/godot/modules/spine_godot/SpineTimeline.cpp similarity index 100% rename from spine-godot/spine_godot/SpineTimeline.cpp rename to spine-godot/godot/modules/spine_godot/SpineTimeline.cpp diff --git a/spine-godot/spine_godot/SpineTimeline.h b/spine-godot/godot/modules/spine_godot/SpineTimeline.h similarity index 100% rename from spine-godot/spine_godot/SpineTimeline.h rename to spine-godot/godot/modules/spine_godot/SpineTimeline.h diff --git a/spine-godot/spine_godot/SpineTrackEntry.cpp b/spine-godot/godot/modules/spine_godot/SpineTrackEntry.cpp similarity index 100% rename from spine-godot/spine_godot/SpineTrackEntry.cpp rename to spine-godot/godot/modules/spine_godot/SpineTrackEntry.cpp diff --git a/spine-godot/spine_godot/SpineTrackEntry.h b/spine-godot/godot/modules/spine_godot/SpineTrackEntry.h similarity index 100% rename from spine-godot/spine_godot/SpineTrackEntry.h rename to spine-godot/godot/modules/spine_godot/SpineTrackEntry.h diff --git a/spine-godot/spine_godot/SpineTransformConstraint.cpp b/spine-godot/godot/modules/spine_godot/SpineTransformConstraint.cpp similarity index 100% rename from spine-godot/spine_godot/SpineTransformConstraint.cpp rename to spine-godot/godot/modules/spine_godot/SpineTransformConstraint.cpp diff --git a/spine-godot/spine_godot/SpineTransformConstraint.h b/spine-godot/godot/modules/spine_godot/SpineTransformConstraint.h similarity index 100% rename from spine-godot/spine_godot/SpineTransformConstraint.h rename to spine-godot/godot/modules/spine_godot/SpineTransformConstraint.h diff --git a/spine-godot/spine_godot/SpineTransformConstraintData.cpp b/spine-godot/godot/modules/spine_godot/SpineTransformConstraintData.cpp similarity index 100% rename from spine-godot/spine_godot/SpineTransformConstraintData.cpp rename to spine-godot/godot/modules/spine_godot/SpineTransformConstraintData.cpp diff --git a/spine-godot/spine_godot/SpineTransformConstraintData.h b/spine-godot/godot/modules/spine_godot/SpineTransformConstraintData.h similarity index 100% rename from spine-godot/spine_godot/SpineTransformConstraintData.h rename to spine-godot/godot/modules/spine_godot/SpineTransformConstraintData.h diff --git a/spine-godot/spine_godot/config.py b/spine-godot/godot/modules/spine_godot/config.py similarity index 100% rename from spine-godot/spine_godot/config.py rename to spine-godot/godot/modules/spine_godot/config.py diff --git a/spine-godot/spine_godot/register_types.cpp b/spine-godot/godot/modules/spine_godot/register_types.cpp similarity index 100% rename from spine-godot/spine_godot/register_types.cpp rename to spine-godot/godot/modules/spine_godot/register_types.cpp diff --git a/spine-godot/spine_godot/register_types.h b/spine-godot/godot/modules/spine_godot/register_types.h similarity index 100% rename from spine-godot/spine_godot/register_types.h rename to spine-godot/godot/modules/spine_godot/register_types.h diff --git a/spine-godot/setup.sh b/spine-godot/setup.sh index e78c64151..539910b31 100755 --- a/spine-godot/setup.sh +++ b/spine-godot/setup.sh @@ -1,11 +1,10 @@ #!/bin/bash set -e -rm -rf godot -cp -r ../spine-cpp/spine-cpp spine_godot -git clone --depth 1 https://github.com/godotengine/godot.git -b 3.4.4-stable -cp custom.py godot +cp -r ../spine-cpp/spine-cpp godot/modules/spine_godot +git clone --depth 1 https://github.com/godotengine/godot.git -b 3.4.4-stable godot-copy +rm -rf godot-copy/.git +cp -r godot-copy/* godot cp -r .idea godot -ln -s $(pwd)/spine_godot godot/modules/spine_godot pushd godot scons target=debug --jobs=$(sysctl -n hw.logicalcpu) popd \ No newline at end of file From 85227351eef492a5b930ae196bd42540dc70f9ee Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Mon, 4 Apr 2022 13:44:29 +0200 Subject: [PATCH 16/18] [godot] Setup script cleans up. --- spine-godot/setup.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/spine-godot/setup.sh b/spine-godot/setup.sh index 539910b31..9f0bc593c 100755 --- a/spine-godot/setup.sh +++ b/spine-godot/setup.sh @@ -1,10 +1,13 @@ #!/bin/bash set -e +git clean -x -f -d cp -r ../spine-cpp/spine-cpp godot/modules/spine_godot git clone --depth 1 https://github.com/godotengine/godot.git -b 3.4.4-stable godot-copy rm -rf godot-copy/.git cp -r godot-copy/* godot +rm -rf godot-copy cp -r .idea godot pushd godot +scons -Q compiledb scons target=debug --jobs=$(sysctl -n hw.logicalcpu) popd \ No newline at end of file From 437f88922d65cdf28007851ee036e9c0034cd7f6 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Mon, 4 Apr 2022 14:38:04 +0200 Subject: [PATCH 17/18] [godot] Fix examples/export/runtime.sh for godot, fix MeshAttachment, fix Godot example --- .gitignore | 1 + examples/export/runtimes.sh | 33 +--- .../spine-cpp/include/spine/MeshAttachment.h | 2 + spine-godot/example/Spineboy.gd | 4 + spine-godot/example/icon.png.import | 1 + spine-godot/example/spineboy.tscn | 17 +- .../example/spineboy/spineboy-data.tres | 10 ++ .../example/spineboy/spineboy-pro.json | 148 +++++++++--------- .../example/spineboy/spineboy-pro.skel | Bin 0 -> 67568 bytes spine-godot/example/spineboy/spineboy.png | Bin 249068 -> 243396 bytes .../example/spineboy/spineboy.png.import | 1 + .../godot/modules/spine_godot/SpineSprite.cpp | 5 +- 12 files changed, 112 insertions(+), 110 deletions(-) create mode 100644 spine-godot/example/Spineboy.gd create mode 100644 spine-godot/example/spineboy/spineboy-data.tres create mode 100644 spine-godot/example/spineboy/spineboy-pro.skel diff --git a/.gitignore b/.gitignore index 8de21a3f3..5135e5475 100644 --- a/.gitignore +++ b/.gitignore @@ -168,3 +168,4 @@ spine-godot/godot spine-godot/spine_godot/__pycache__ spine-godot/spine_godot/spine-cpp spine-godot/godot-copy +spine-godot/example/.import diff --git a/examples/export/runtimes.sh b/examples/export/runtimes.sh index aa315dc5d..252a8d6fd 100755 --- a/examples/export/runtimes.sh +++ b/examples/export/runtimes.sh @@ -85,31 +85,14 @@ cp -f ../mix-and-match/export/mix-and-match-pro.skel "$ROOT/spine-cocos2dx/examp cp -f ../mix-and-match/export/mix-and-match.atlas "$ROOT/spine-cocos2dx/example/Resources/common/" cp -f ../mix-and-match/export/mix-and-match.png "$ROOT/spine-cocos2dx/example/Resources/common/" -rm "$ROOT/spine-cocos2dx/example-v4/Resources/common/"* - -cp -f ../coin/export/coin-pro.skel "$ROOT/spine-cocos2dx/example-v4/Resources/common/" -cp -f ../coin/export/coin.atlas "$ROOT/spine-cocos2dx/example-v4/Resources/common/" -cp -f ../coin/export/coin.png "$ROOT/spine-cocos2dx/example-v4/Resources/common/" - -cp -f ../goblins/export/goblins-pro.json "$ROOT/spine-cocos2dx/example-v4/Resources/common/" -cp -f ../goblins/export/goblins.atlas "$ROOT/spine-cocos2dx/example-v4/Resources/common/" -cp -f ../goblins/export/goblins.png "$ROOT/spine-cocos2dx/example-v4/Resources/common/" - -cp -f ../raptor/export/raptor-pro.json "$ROOT/spine-cocos2dx/example-v4/Resources/common/" -cp -f ../raptor/export/raptor.atlas "$ROOT/spine-cocos2dx/example-v4/Resources/common/" -cp -f ../raptor/export/raptor.png "$ROOT/spine-cocos2dx/example-v4/Resources/common/" - -cp -f ../spineboy/export/spineboy-pro.json "$ROOT/spine-cocos2dx/example-v4/Resources/common/" -cp -f ../spineboy/export/spineboy.atlas "$ROOT/spine-cocos2dx/example-v4/Resources/common/" -cp -f ../spineboy/export/spineboy.png "$ROOT/spine-cocos2dx/example-v4/Resources/common/" - -cp -f ../tank/export/tank-pro.skel "$ROOT/spine-cocos2dx/example-v4/Resources/common/" -cp -f ../tank/export/tank.atlas "$ROOT/spine-cocos2dx/example-v4/Resources/common/" -cp -f ../tank/export/tank.png "$ROOT/spine-cocos2dx/example-v4/Resources/common/" - -cp -f ../mix-and-match/export/mix-and-match-pro.skel "$ROOT/spine-cocos2dx/example-v4/Resources/common/" -cp -f ../mix-and-match/export/mix-and-match.atlas "$ROOT/spine-cocos2dx/example-v4/Resources/common/" -cp -f ../mix-and-match/export/mix-and-match.png "$ROOT/spine-cocos2dx/example-v4/Resources/common/" +echo "spine-godot" +rm "$ROOT"/spine-godot/example/spineboy/*.atlas +rm "$ROOT"/spine-godot/example/spineboy/*.json +rm "$ROOT"/spine-godot/example/spineboy/*.skel +cp -f ../spineboy/export/spineboy-pro.json "$ROOT/spine-godot/example/spineboy/" +cp -f ../spineboy/export/spineboy-pro.skel "$ROOT/spine-godot/example/spineboy/" +cp -f ../spineboy/export/spineboy.atlas "$ROOT/spine-godot/example/spineboy/" +cp -f ../spineboy/export/spineboy.png "$ROOT/spine-godot/example/spineboy/" echo "spine-sfml-c" rm "$ROOT/spine-sfml/c/data/"* diff --git a/spine-cpp/spine-cpp/include/spine/MeshAttachment.h b/spine-cpp/spine-cpp/include/spine/MeshAttachment.h index 78ec8a709..6961a2dd3 100644 --- a/spine-cpp/spine-cpp/include/spine/MeshAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/MeshAttachment.h @@ -53,6 +53,8 @@ namespace spine { 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); diff --git a/spine-godot/example/Spineboy.gd b/spine-godot/example/Spineboy.gd new file mode 100644 index 000000000..6a7de1c43 --- /dev/null +++ b/spine-godot/example/Spineboy.gd @@ -0,0 +1,4 @@ +extends SpineSprite + +func _ready(): + get_animation_state().set_animation("walk", true, 0); diff --git a/spine-godot/example/icon.png.import b/spine-godot/example/icon.png.import index 96cbf4629..a4c02e6e2 100644 --- a/spine-godot/example/icon.png.import +++ b/spine-godot/example/icon.png.import @@ -28,6 +28,7 @@ process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false +process/normal_map_invert_y=false stream=false size_limit=0 detect_3d=true diff --git a/spine-godot/example/spineboy.tscn b/spine-godot/example/spineboy.tscn index 8a99d91f3..7a9e8947f 100644 --- a/spine-godot/example/spineboy.tscn +++ b/spine-godot/example/spineboy.tscn @@ -1,20 +1,15 @@ -[gd_scene load_steps=5 format=2] +[gd_scene load_steps=4 format=2] -[ext_resource path="res://spineboy/spineboy-pro.json" type="SpineSkeletonJsonDataResource" id=1] -[ext_resource path="res://spineboy/spineboy.atlas" type="SpineAtlasResource" id=2] - -[sub_resource type="SpineSkeletonDataResource" id=1] -atlas_res = ExtResource( 2 ) -skeleton_json_res = ExtResource( 1 ) -animations = null -skins = null +[ext_resource path="res://Spineboy.gd" type="Script" id=1] +[ext_resource path="res://spineboy/spineboy-data.tres" type="SpineSkeletonDataResource" id=2] [sub_resource type="SpineAnimationStateDataResource" id=2] -skeleton = SubResource( 1 ) +skeleton = ExtResource( 2 ) [node name="Node2D" type="Node2D"] -[node name="SpineSprite" type="SpineSprite" parent="."] +[node name="Spineboy" type="SpineSprite" parent="."] position = Vector2( 504, 622 ) animation_state_data_res = SubResource( 2 ) current_animations = [ "walk" ] +script = ExtResource( 1 ) diff --git a/spine-godot/example/spineboy/spineboy-data.tres b/spine-godot/example/spineboy/spineboy-data.tres new file mode 100644 index 000000000..8ba6dc0b1 --- /dev/null +++ b/spine-godot/example/spineboy/spineboy-data.tres @@ -0,0 +1,10 @@ +[gd_resource type="SpineSkeletonDataResource" load_steps=3 format=2] + +[ext_resource path="res://spineboy/spineboy.atlas" type="SpineAtlasResource" id=1] +[ext_resource path="res://spineboy/spineboy-pro.json" type="SpineSkeletonJsonDataResource" id=2] + +[resource] +atlas_res = ExtResource( 1 ) +skeleton_json_res = ExtResource( 2 ) +animations = null +skins = null diff --git a/spine-godot/example/spineboy/spineboy-pro.json b/spine-godot/example/spineboy/spineboy-pro.json index 4d8c7c2cf..b4dd8b40f 100644 --- a/spine-godot/example/spineboy/spineboy-pro.json +++ b/spine-godot/example/spineboy/spineboy-pro.json @@ -1,7 +1,7 @@ { "skeleton": { - "hash": "IQgkYFQG8ng", - "spine": "4.0.31", + "hash": "itfFESDjM1c", + "spine": "4.1.23-beta", "x": -188.63, "y": -7.94, "width": 418.45, @@ -2427,19 +2427,19 @@ "side-glow1": { "attachment": [ { "name": "hoverglow-small" }, - { "time": 0.9667, "name": null } + { "time": 0.9667 } ] }, "side-glow2": { "attachment": [ { "time": 0.0667, "name": "hoverglow-small" }, - { "time": 1, "name": null } + { "time": 1 } ] }, "side-glow3": { "attachment": [ { "name": "hoverglow-small" }, - { "time": 0.9667, "name": null } + { "time": 0.9667 } ] } }, @@ -3479,60 +3479,68 @@ { "mixX": 0, "mixScaleX": 0, "mixShearY": 0 } ] }, - "deform": { + "attachments": { "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-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": [ - { - "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 ] - } - ] + "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": [ - { - "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 } - ] + "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": [ - { - "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 ] - } - ] + "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 ] + } + ] + } } } } @@ -5203,7 +5211,7 @@ "portal-bg": { "attachment": [ { "name": "portal-bg" }, - { "time": 3, "name": null } + { "time": 3 } ] }, "portal-flare1": { @@ -5214,7 +5222,7 @@ { "time": 1.2, "name": "portal-flare1" }, { "time": 1.2333, "name": "portal-flare2" }, { "time": 1.2667, "name": "portal-flare1" }, - { "time": 1.3333, "name": null } + { "time": 1.3333 } ] }, "portal-flare2": { @@ -5224,14 +5232,14 @@ { "time": 1.1667, "name": "portal-flare1" }, { "time": 1.2, "name": "portal-flare2" }, { "time": 1.2333, "name": "portal-flare3" }, - { "time": 1.2667, "name": null } + { "time": 1.2667 } ] }, "portal-flare3": { "attachment": [ { "time": 1.2, "name": "portal-flare3" }, { "time": 1.2333, "name": "portal-flare2" }, - { "time": 1.2667, "name": null } + { "time": 1.2667 } ] }, "portal-flare4": { @@ -5239,33 +5247,33 @@ { "time": 1.2, "name": "portal-flare2" }, { "time": 1.2333, "name": "portal-flare1" }, { "time": 1.2667, "name": "portal-flare2" }, - { "time": 1.3333, "name": null } + { "time": 1.3333 } ] }, "portal-flare5": { "attachment": [ { "time": 1.2333, "name": "portal-flare3" }, { "time": 1.2667, "name": "portal-flare1" }, - { "time": 1.3333, "name": null } + { "time": 1.3333 } ] }, "portal-flare6": { "attachment": [ { "time": 1.2667, "name": "portal-flare3" }, - { "time": 1.3333, "name": null } + { "time": 1.3333 } ] }, "portal-flare7": { "attachment": [ { "time": 1.1333, "name": "portal-flare2" }, - { "time": 1.1667, "name": null } + { "time": 1.1667 } ] }, "portal-flare8": { "attachment": [ { "time": 1.2, "name": "portal-flare3" }, { "time": 1.2333, "name": "portal-flare2" }, - { "time": 1.2667, "name": null } + { "time": 1.2667 } ] }, "portal-flare9": { @@ -5273,7 +5281,7 @@ { "time": 1.2, "name": "portal-flare2" }, { "time": 1.2333, "name": "portal-flare3" }, { "time": 1.2667, "name": "portal-flare1" }, - { "time": 1.3, "name": null } + { "time": 1.3 } ] }, "portal-flare10": { @@ -5281,25 +5289,25 @@ { "time": 1.2, "name": "portal-flare2" }, { "time": 1.2333, "name": "portal-flare1" }, { "time": 1.2667, "name": "portal-flare3" }, - { "time": 1.3, "name": null } + { "time": 1.3 } ] }, "portal-shade": { "attachment": [ { "name": "portal-shade" }, - { "time": 3, "name": null } + { "time": 3 } ] }, "portal-streaks1": { "attachment": [ { "name": "portal-streaks1" }, - { "time": 3, "name": null } + { "time": 3 } ] }, "portal-streaks2": { "attachment": [ { "name": "portal-streaks2" }, - { "time": 3, "name": null } + { "time": 3 } ] } }, @@ -7696,7 +7704,7 @@ { "time": 0.1, "name": "muzzle03" }, { "time": 0.1333, "name": "muzzle04" }, { "time": 0.1667, "name": "muzzle05" }, - { "time": 0.2, "name": null } + { "time": 0.2 } ] }, "muzzle-glow": { @@ -7725,7 +7733,7 @@ ], "attachment": [ { "time": 0.0333, "name": "muzzle-ring" }, - { "time": 0.2333, "name": null } + { "time": 0.2333 } ] }, "muzzle-ring2": { @@ -7739,7 +7747,7 @@ ], "attachment": [ { "time": 0.0333, "name": "muzzle-ring" }, - { "time": 0.2, "name": null } + { "time": 0.2 } ] }, "muzzle-ring3": { @@ -7753,7 +7761,7 @@ ], "attachment": [ { "time": 0.0333, "name": "muzzle-ring" }, - { "time": 0.2, "name": null } + { "time": 0.2 } ] }, "muzzle-ring4": { @@ -7767,7 +7775,7 @@ ], "attachment": [ { "time": 0.0333, "name": "muzzle-ring" }, - { "time": 0.2, "name": null } + { "time": 0.2 } ] } }, diff --git a/spine-godot/example/spineboy/spineboy-pro.skel b/spine-godot/example/spineboy/spineboy-pro.skel new file mode 100644 index 0000000000000000000000000000000000000000..199839b499688be6c2aed175b683a2ee93f1a64e GIT binary patch literal 67568 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