diff --git a/.gitignore b/.gitignore index 81d8a4436..5135e5475 100644 --- a/.gitignore +++ b/.gitignore @@ -164,3 +164,8 @@ 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/__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/.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/README.md b/spine-godot/README.md new file mode 100644 index 000000000..ee9038925 --- /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/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/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/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 000000000..c98fbb601 Binary files /dev/null and b/spine-godot/example/icon.png differ diff --git a/spine-godot/example/icon.png.import b/spine-godot/example/icon.png.import new file mode 100644 index 000000000..a4c02e6e2 --- /dev/null +++ b/spine-godot/example/icon.png.import @@ -0,0 +1,35 @@ +[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 +process/normal_map_invert_y=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..c7fc9bd26 --- /dev/null +++ b/spine-godot/example/project.godot @@ -0,0 +1,26 @@ +; 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" +run/main_scene="res://spineboy.tscn" +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/example/spineboy.tscn b/spine-godot/example/spineboy.tscn new file mode 100644 index 000000000..7a9e8947f --- /dev/null +++ b/spine-godot/example/spineboy.tscn @@ -0,0 +1,15 @@ +[gd_scene load_steps=4 format=2] + +[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 = ExtResource( 2 ) + +[node name="Node2D" type="Node2D"] + +[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 new file mode 100644 index 000000000..b4dd8b40f --- /dev/null +++ b/spine-godot/example/spineboy/spineboy-pro.json @@ -0,0 +1,8707 @@ +{ +"skeleton": { + "hash": "itfFESDjM1c", + "spine": "4.1.23-beta", + "x": -188.63, + "y": -7.94, + "width": 418.45, + "height": 686.2, + "images": "./images/", + "audio": "" +}, +"bones": [ + { "name": "root", "rotation": 0.05 }, + { "name": "hip", "parent": "root", "y": 247.27 }, + { "name": "crosshair", "parent": "root", "x": 302.83, "y": 569.45, "color": "ff3f00ff" }, + { + "name": "aim-constraint-target", + "parent": "hip", + "length": 26.24, + "rotation": 19.61, + "x": 1.02, + "y": 5.62, + "color": "abe323ff" + }, + { "name": "rear-foot-target", "parent": "root", "x": 61.91, "y": 0.42, "color": "ff3f00ff" }, + { "name": "rear-leg-target", "parent": "rear-foot-target", "x": -33.91, "y": 37.34, "color": "ff3f00ff" }, + { + "name": "rear-thigh", + "parent": "hip", + "length": 85.72, + "rotation": -72.54, + "x": 8.91, + "y": -5.63, + "color": "ff000dff" + }, + { + "name": "rear-shin", + "parent": "rear-thigh", + "length": 121.88, + "rotation": -19.83, + "x": 86.1, + "y": -1.33, + "color": "ff000dff" + }, + { + "name": "rear-foot", + "parent": "rear-shin", + "length": 51.58, + "rotation": 45.78, + "x": 121.46, + "y": -0.76, + "color": "ff000dff" + }, + { + "name": "back-foot-tip", + "parent": "rear-foot", + "length": 50.3, + "rotation": -0.85, + "x": 51.17, + "y": 0.24, + "transform": "noRotationOrReflection", + "color": "ff000dff" + }, + { "name": "board-ik", "parent": "root", "x": -131.78, "y": 69.09, "color": "4c56ffff" }, + { "name": "clipping", "parent": "root" }, + { "name": "hoverboard-controller", "parent": "root", "rotation": -0.28, "x": -329.69, "y": 69.82, "color": "ff0004ff" }, + { "name": "exhaust1", "parent": "hoverboard-controller", "rotation": 3.02, "x": -249.68, "y": 53.39 }, + { "name": "exhaust2", "parent": "hoverboard-controller", "rotation": 26.34, "x": -191.6, "y": -22.92 }, + { + "name": "exhaust3", + "parent": "hoverboard-controller", + "rotation": -12.34, + "x": -236.03, + "y": 80.54, + "scaleX": 0.7847, + "scaleY": 0.7847 + }, + { "name": "portal-root", "parent": "root", "x": 12.9, "y": 328.54, "scaleX": 2.0334, "scaleY": 2.0334 }, + { "name": "flare1", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare10", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare2", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare3", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare4", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare5", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare6", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare7", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare8", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { "name": "flare9", "parent": "portal-root", "x": -6.34, "y": -161.57 }, + { + "name": "torso", + "parent": "hip", + "length": 42.52, + "rotation": 103.82, + "x": -1.62, + "y": 4.9, + "color": "e0da19ff" + }, + { "name": "torso2", "parent": "torso", "length": 42.52, "x": 42.52, "color": "e0da19ff" }, + { "name": "torso3", "parent": "torso2", "length": 42.52, "x": 42.52, "color": "e0da19ff" }, + { "name": "front-shoulder", "parent": "torso3", "rotation": 255.89, "x": 18.72, "y": 19.33, "color": "00ff04ff" }, + { "name": "front-upper-arm", "parent": "front-shoulder", "length": 69.45, "rotation": -87.51, "color": "00ff04ff" }, + { + "name": "front-bracer", + "parent": "front-upper-arm", + "length": 40.57, + "rotation": 18.3, + "x": 68.8, + "y": -0.68, + "color": "00ff04ff" + }, + { + "name": "front-fist", + "parent": "front-bracer", + "length": 65.39, + "rotation": 12.43, + "x": 40.57, + "y": 0.2, + "color": "00ff04ff" + }, + { "name": "front-foot-target", "parent": "root", "x": -13.53, "y": 0.04, "color": "ff3f00ff" }, + { "name": "front-leg-target", "parent": "front-foot-target", "x": -28.4, "y": 29.06, "color": "ff3f00ff" }, + { + "name": "front-thigh", + "parent": "hip", + "length": 74.81, + "rotation": -95.51, + "x": -17.46, + "y": -11.64, + "color": "00ff04ff" + }, + { + "name": "front-shin", + "parent": "front-thigh", + "length": 128.77, + "rotation": -2.21, + "x": 78.69, + "y": 1.6, + "color": "00ff04ff" + }, + { + "name": "front-foot", + "parent": "front-shin", + "length": 41.01, + "rotation": 51.27, + "x": 128.76, + "y": -0.34, + "color": "00ff04ff" + }, + { + "name": "front-foot-tip", + "parent": "front-foot", + "length": 56.03, + "rotation": -1.68, + "x": 41.42, + "y": -0.09, + "transform": "noRotationOrReflection", + "color": "00ff04ff" + }, + { "name": "back-shoulder", "parent": "torso3", "rotation": -104.11, "x": 7.32, "y": -19.22, "color": "ff000dff" }, + { "name": "rear-upper-arm", "parent": "back-shoulder", "length": 51.94, "rotation": -65.45, "color": "ff000dff" }, + { "name": "rear-bracer", "parent": "rear-upper-arm", "length": 34.56, "rotation": 23.15, "x": 51.36, "color": "ff000dff" }, + { + "name": "gun", + "parent": "rear-bracer", + "length": 43.11, + "rotation": -5.43, + "x": 34.42, + "y": -0.45, + "color": "ff000dff" + }, + { "name": "gun-tip", "parent": "gun", "rotation": 7.1, "x": 200.78, "y": 52.5, "color": "ff0000ff" }, + { + "name": "neck", + "parent": "torso3", + "length": 25.45, + "rotation": -31.54, + "x": 42.46, + "y": -0.31, + "color": "e0da19ff" + }, + { + "name": "head", + "parent": "neck", + "length": 131.79, + "rotation": 26.1, + "x": 27.66, + "y": -0.26, + "color": "e0da19ff" + }, + { + "name": "hair1", + "parent": "head", + "length": 47.23, + "rotation": -49.1, + "x": 149.83, + "y": -59.77, + "color": "e0da19ff" + }, + { + "name": "hair2", + "parent": "hair1", + "length": 55.57, + "rotation": 50.42, + "x": 47.23, + "y": 0.19, + "color": "e0da19ff" + }, + { + "name": "hair3", + "parent": "head", + "length": 62.22, + "rotation": -32.17, + "x": 164.14, + "y": 3.68, + "color": "e0da19ff" + }, + { + "name": "hair4", + "parent": "hair3", + "length": 80.28, + "rotation": 83.71, + "x": 62.22, + "y": -0.04, + "color": "e0da19ff" + }, + { "name": "hoverboard-thruster-front", "parent": "hoverboard-controller", "rotation": -29.2, "x": 95.77, "y": -2.99, "transform": "noRotationOrReflection" }, + { "name": "hoverboard-thruster-rear", "parent": "hoverboard-controller", "rotation": -29.2, "x": -76.47, "y": -4.88, "transform": "noRotationOrReflection" }, + { "name": "hoverglow-front", "parent": "hoverboard-thruster-front", "rotation": 0.17, "x": -1.78, "y": -37.79 }, + { "name": "hoverglow-rear", "parent": "hoverboard-thruster-rear", "rotation": 0.17, "x": 1.06, "y": -35.66 }, + { "name": "muzzle", "parent": "rear-bracer", "rotation": 3.06, "x": 242.34, "y": 34.26, "color": "ffb900ff" }, + { "name": "muzzle-ring", "parent": "muzzle", "color": "ffb900ff" }, + { "name": "muzzle-ring2", "parent": "muzzle", "color": "ffb900ff" }, + { "name": "muzzle-ring3", "parent": "muzzle", "color": "ffb900ff" }, + { "name": "muzzle-ring4", "parent": "muzzle", "color": "ffb900ff" }, + { "name": "portal", "parent": "portal-root" }, + { "name": "portal-shade", "parent": "portal-root" }, + { "name": "portal-streaks1", "parent": "portal-root" }, + { "name": "portal-streaks2", "parent": "portal-root" }, + { "name": "side-glow1", "parent": "hoverboard-controller", "x": -110.56, "y": 2.62, "color": "000effff" }, + { + "name": "side-glow2", + "parent": "hoverboard-controller", + "x": -110.56, + "y": 2.62, + "scaleX": 0.738, + "scaleY": 0.738, + "color": "000effff" + }, + { "name": "head-control", "parent": "head", "x": 110.21, "color": "00a220ff" } +], +"slots": [ + { "name": "portal-bg", "bone": "portal" }, + { "name": "portal-shade", "bone": "portal-shade" }, + { "name": "portal-streaks2", "bone": "portal-streaks2", "blend": "additive" }, + { "name": "portal-streaks1", "bone": "portal-streaks1", "blend": "additive" }, + { "name": "portal-flare8", "bone": "flare8", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare9", "bone": "flare9", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare10", "bone": "flare10", "color": "c3cbffff", "blend": "additive" }, + { "name": "clipping", "bone": "clipping" }, + { "name": "exhaust3", "bone": "exhaust3", "color": "5eb4ffff", "blend": "additive" }, + { "name": "hoverboard-thruster-rear", "bone": "hoverboard-thruster-rear" }, + { "name": "hoverboard-thruster-front", "bone": "hoverboard-thruster-front" }, + { "name": "hoverboard-board", "bone": "hoverboard-controller" }, + { "name": "side-glow1", "bone": "side-glow1", "color": "ff8686ff", "blend": "additive" }, + { "name": "side-glow3", "bone": "side-glow1", "color": "ff8686ff", "blend": "additive" }, + { "name": "side-glow2", "bone": "side-glow2", "color": "ff8686ff", "blend": "additive" }, + { "name": "hoverglow-front", "bone": "hoverglow-front", "color": "5eb4ffff", "blend": "additive" }, + { "name": "hoverglow-rear", "bone": "hoverglow-rear", "color": "5eb4ffff", "blend": "additive" }, + { "name": "exhaust1", "bone": "exhaust2", "color": "5eb4ffff", "blend": "additive" }, + { "name": "exhaust2", "bone": "exhaust1", "color": "5eb4ffff", "blend": "additive" }, + { "name": "rear-upper-arm", "bone": "rear-upper-arm", "attachment": "rear-upper-arm" }, + { "name": "rear-bracer", "bone": "rear-bracer", "attachment": "rear-bracer" }, + { "name": "gun", "bone": "gun", "attachment": "gun" }, + { "name": "rear-foot", "bone": "rear-foot", "attachment": "rear-foot" }, + { "name": "rear-thigh", "bone": "rear-thigh", "attachment": "rear-thigh" }, + { "name": "rear-shin", "bone": "rear-shin", "attachment": "rear-shin" }, + { "name": "neck", "bone": "neck", "attachment": "neck" }, + { "name": "torso", "bone": "torso", "attachment": "torso" }, + { "name": "front-upper-arm", "bone": "front-upper-arm", "attachment": "front-upper-arm" }, + { "name": "head", "bone": "head", "attachment": "head" }, + { "name": "eye", "bone": "head", "attachment": "eye-indifferent" }, + { "name": "front-thigh", "bone": "front-thigh", "attachment": "front-thigh" }, + { "name": "front-foot", "bone": "front-foot", "attachment": "front-foot" }, + { "name": "front-shin", "bone": "front-shin", "attachment": "front-shin" }, + { "name": "mouth", "bone": "head", "attachment": "mouth-smile" }, + { "name": "goggles", "bone": "head", "attachment": "goggles" }, + { "name": "front-bracer", "bone": "front-bracer", "attachment": "front-bracer" }, + { "name": "front-fist", "bone": "front-fist", "attachment": "front-fist-closed" }, + { "name": "muzzle", "bone": "muzzle" }, + { "name": "head-bb", "bone": "head" }, + { "name": "portal-flare1", "bone": "flare1", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare2", "bone": "flare2", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare3", "bone": "flare3", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare4", "bone": "flare4", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare5", "bone": "flare5", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare6", "bone": "flare6", "color": "c3cbffff", "blend": "additive" }, + { "name": "portal-flare7", "bone": "flare7", "color": "c3cbffff", "blend": "additive" }, + { "name": "crosshair", "bone": "crosshair" }, + { "name": "muzzle-glow", "bone": "gun-tip", "color": "ffffff00", "blend": "additive" }, + { "name": "muzzle-ring", "bone": "muzzle-ring", "color": "d8baffff", "blend": "additive" }, + { "name": "muzzle-ring2", "bone": "muzzle-ring2", "color": "d8baffff", "blend": "additive" }, + { "name": "muzzle-ring3", "bone": "muzzle-ring3", "color": "d8baffff", "blend": "additive" }, + { "name": "muzzle-ring4", "bone": "muzzle-ring4", "color": "d8baffff", "blend": "additive" } +], +"ik": [ + { + "name": "aim-ik", + "order": 13, + "bones": [ "rear-upper-arm" ], + "target": "crosshair", + "mix": 0 + }, + { + "name": "aim-torso-ik", + "order": 8, + "bones": [ "aim-constraint-target" ], + "target": "crosshair" + }, + { + "name": "board-ik", + "order": 1, + "bones": [ "hoverboard-controller" ], + "target": "board-ik" + }, + { + "name": "front-foot-ik", + "order": 6, + "bones": [ "front-foot" ], + "target": "front-foot-target" + }, + { + "name": "front-leg-ik", + "order": 4, + "bones": [ "front-thigh", "front-shin" ], + "target": "front-leg-target", + "bendPositive": false + }, + { + "name": "rear-foot-ik", + "order": 7, + "bones": [ "rear-foot" ], + "target": "rear-foot-target" + }, + { + "name": "rear-leg-ik", + "order": 5, + "bones": [ "rear-thigh", "rear-shin" ], + "target": "rear-leg-target", + "bendPositive": false + } +], +"transform": [ + { + "name": "aim-front-arm-transform", + "order": 11, + "bones": [ "front-upper-arm" ], + "target": "aim-constraint-target", + "rotation": -180, + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "aim-head-transform", + "order": 10, + "bones": [ "head" ], + "target": "aim-constraint-target", + "rotation": 84.3, + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "aim-rear-arm-transform", + "order": 12, + "bones": [ "rear-upper-arm" ], + "target": "aim-constraint-target", + "x": 57.7, + "y": 56.4, + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "aim-torso-transform", + "order": 9, + "bones": [ "torso" ], + "target": "aim-constraint-target", + "rotation": 69.5, + "shearY": -36, + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "front-foot-board-transform", + "order": 2, + "bones": [ "front-foot-target" ], + "target": "hoverboard-controller", + "x": -69.8, + "y": 20.7, + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "rear-foot-board-transform", + "order": 3, + "bones": [ "rear-foot-target" ], + "target": "hoverboard-controller", + "x": 86.6, + "y": 21.3, + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "shoulder", + "bones": [ "back-shoulder" ], + "target": "front-shoulder", + "x": 40.17, + "y": -1.66, + "mixRotate": 0, + "mixX": -1, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "toes-board", + "order": 14, + "bones": [ "front-foot-tip", "back-foot-tip" ], + "target": "hoverboard-controller", + "mixRotate": 0, + "mixX": 0, + "mixScaleX": 0, + "mixShearY": 0 + } +], +"skins": [ + { + "name": "default", + "attachments": { + "clipping": { + "clipping": { + "type": "clipping", + "end": "head-bb", + "vertexCount": 9, + "vertices": [ 66.76, 509.48, 19.98, 434.54, 5.34, 336.28, 22.19, 247.93, 77.98, 159.54, 182.21, -97.56, 1452.26, -99.8, 1454.33, 843.61, 166.57, 841.02 ], + "color": "ce3a3aff" + } + }, + "crosshair": { + "crosshair": { "width": 89, "height": 89 } + }, + "exhaust1": { + "hoverglow-small": { "scaleX": 0.4629, "scaleY": 0.8129, "rotation": -83.07, "width": 274, "height": 75 } + }, + "exhaust2": { + "hoverglow-small": { + "x": 0.01, + "y": -0.76, + "scaleX": 0.4208, + "scaleY": 0.8403, + "rotation": -89.25, + "width": 274, + "height": 75 + } + }, + "exhaust3": { + "hoverglow-small": { "scaleX": 0.4629, "scaleY": 0.8129, "rotation": -83.07, "width": 274, "height": 75 } + }, + "eye": { + "eye-indifferent": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 2, 66, -36.8, -91.35, 0.3, 46, 73.41, -91.35, 0.7, 2, 66, -87.05, -13.11, 0.70968, 46, 23.16, -13.11, 0.29032, 2, 66, -12.18, 34.99, 0.82818, 46, 98.03, 34.99, 0.17182, 2, 66, 38.07, -43.25, 0.59781, 46, 148.28, -43.25, 0.40219 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 93, + "height": 89 + }, + "eye-surprised": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 2, 3, 1, 3, 0 ], + "vertices": [ 2, 66, -46.74, -89.7, 0.3, 46, 63.47, -89.7, 0.7, 2, 66, -77.58, -1.97, 0.71, 46, 32.63, -1.97, 0.29, 2, 66, 6.38, 27.55, 0.83, 46, 116.59, 27.55, 0.17, 2, 66, 37.22, -60.19, 0.6, 46, 147.44, -60.19, 0.4 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 93, + "height": 89 + } + }, + "front-bracer": { + "front-bracer": { "x": 12.03, "y": -1.68, "rotation": 79.6, "width": 58, "height": 80 } + }, + "front-fist": { + "front-fist-closed": { "x": 35.5, "y": 6, "rotation": 67.16, "width": 75, "height": 82 }, + "front-fist-open": { "x": 39.57, "y": 7.76, "rotation": 67.16, "width": 86, "height": 87 } + }, + "front-foot": { + "front-foot": { + "type": "mesh", + "uvs": [ 0.59417, 0.23422, 0.62257, 0.30336, 0.6501, 0.37036, 0.67637, 0.38404, 0.72068, 0.4071, 0.76264, 0.42894, 1, 0.70375, 1, 1, 0.65517, 1, 0.46923, 0.99999, 0, 1, 0, 0.39197, 0.17846, 0, 0.49796, 0 ], + "triangles": [ 8, 9, 3, 4, 8, 3, 5, 8, 4, 6, 8, 5, 8, 6, 7, 11, 1, 10, 0, 12, 13, 0, 11, 12, 0, 1, 11, 9, 2, 3, 1, 2, 10, 9, 10, 2 ], + "vertices": [ 2, 38, 18.17, 41.57, 0.7896, 39, 12.46, 46.05, 0.2104, 2, 38, 24.08, 40.76, 0.71228, 39, 16.12, 41.34, 0.28772, 2, 38, 29.81, 39.98, 0.55344, 39, 19.67, 36.78, 0.44656, 2, 38, 32.81, 41.67, 0.38554, 39, 23, 35.89, 0.61446, 2, 38, 37.86, 44.52, 0.25567, 39, 28.61, 34.4, 0.74433, 2, 38, 42.65, 47.22, 0.17384, 39, 33.92, 32.99, 0.82616, 1, 39, 64.15, 14.56, 1, 1, 39, 64.51, -5.87, 1, 1, 39, 21.08, -6.64, 1, 2, 38, 44.67, -6.77, 0.5684, 39, -2.34, -6.97, 0.4316, 1, 38, 3.1, -48.81, 1, 1, 38, -26.73, -19.31, 1, 1, 38, -30.15, 15.69, 1, 1, 38, -1.84, 44.32, 1 ], + "hull": 14, + "edges": [ 14, 16, 16, 18, 18, 20, 4, 18, 20, 22, 24, 26, 22, 24, 12, 14, 10, 12, 2, 4, 2, 20, 4, 6, 6, 16, 2, 0, 0, 26, 6, 8, 8, 10 ], + "width": 126, + "height": 69 + } + }, + "front-shin": { + "front-shin": { + "type": "mesh", + "uvs": [ 0.90031, 0.05785, 1, 0.12828, 1, 0.21619, 0.9025, 0.31002, 0.78736, 0.35684, 0.78081, 0.39874, 0.77215, 0.45415, 0.77098, 0.51572, 0.84094, 0.63751, 0.93095, 0.7491, 0.95531, 0.7793, 0.78126, 0.87679, 0.5613, 1, 0.2687, 1, 0, 1, 0.00279, 0.96112, 0.01358, 0.81038, 0.02822, 0.60605, 0.08324, 0.45142, 0.18908, 0.31882, 0.29577, 0.2398, 0.30236, 0.14941, 0.37875, 0.05902, 0.53284, 0, 0.70538, 0, 0.41094, 0.71968, 0.40743, 0.54751, 0.41094, 0.4536, 0.4724, 0.35186, 0.33367, 0.27829, 0.50226, 0.31664, 0.65328, 0.67507, 0.60762, 0.52716, 0.6006, 0.45125, 0.62747, 0.37543, 0.6573, 0.3385, 0.27843, 0.32924, 0.18967, 0.45203, 0.16509, 0.58586, 0.18265, 0.7682, 0.50532, 0.24634, 0.59473, 0.17967, 0.60161, 0.10611, 0.51392, 0.04327, 0.72198, 0.28849, 0.82343, 0.20266, 0.86814, 0.11377, 0.79592, 0.04634, 0.44858, 0.15515, 0.25466, 0.96219, 0.53169, 0.9448, 0.7531, 0.8324 ], + "triangles": [ 24, 0, 47, 43, 23, 24, 47, 43, 24, 43, 22, 23, 42, 43, 47, 46, 47, 0, 42, 47, 46, 46, 0, 1, 48, 22, 43, 48, 43, 42, 21, 22, 48, 41, 48, 42, 45, 42, 46, 41, 42, 45, 46, 1, 2, 45, 46, 2, 40, 48, 41, 48, 20, 21, 29, 48, 40, 29, 20, 48, 44, 41, 45, 40, 41, 44, 3, 45, 2, 44, 45, 3, 30, 29, 40, 35, 30, 40, 36, 19, 20, 36, 20, 29, 44, 35, 40, 28, 29, 30, 4, 44, 3, 35, 44, 4, 34, 30, 35, 5, 35, 4, 34, 28, 30, 33, 28, 34, 37, 19, 36, 18, 19, 37, 27, 29, 28, 27, 28, 33, 36, 29, 27, 37, 36, 27, 5, 34, 35, 6, 34, 5, 33, 34, 6, 6, 32, 33, 7, 32, 6, 26, 37, 27, 38, 18, 37, 38, 37, 26, 17, 18, 38, 31, 32, 7, 31, 7, 8, 32, 25, 26, 38, 26, 25, 27, 33, 32, 32, 26, 27, 39, 38, 25, 17, 38, 39, 16, 17, 39, 51, 31, 8, 51, 8, 9, 11, 51, 9, 11, 9, 10, 31, 50, 25, 31, 25, 32, 50, 31, 51, 49, 39, 25, 49, 25, 50, 15, 16, 39, 49, 15, 39, 13, 49, 50, 14, 15, 49, 13, 14, 49, 12, 50, 51, 12, 51, 11, 13, 50, 12 ], + "vertices": [ -23.66, 19.37, -11.73, 28.98, 4.34, 30.83, 22.41, 24.87, 32.05, 16.48, 39.77, 16.83, 49.98, 17.3, 61.25, 18.5, 82.85, 26.78, 102.4, 36.46, 107.69, 39.09, 127.15, 26.97, 151.74, 11.65, 154.49, -12.18, 157.02, -34.07, 149.89, -34.66, 122.23, -36.97, 84.75, -40.09, 55.97, -38.88, 30.73, -33.05, 15.29, -26.03, -1.3, -27.41, -18.54, -23.09, -30.78, -11.79, -32.4, 2.27, 101.92, -6.52, 70.48, -10.44, 53.28, -12.14, 34.11, -9.28, 21.96, -22.13, 27.39, -7.59, 91.48, 12.28, 64.88, 5.44, 51.07, 3.26, 36.95, 3.85, 29.92, 5.5, 31.8, -25.56, 55.08, -30.19, 79.77, -29.37, 112.93, -24.09, 14.51, -8.83, 1.48, -2.95, -12.03, -3.94, -22.69, -12.41, 20.17, 9.71, 3.53, 16.16, -13.14, 17.93, -24.78, 10.62, -1.62, -15.37, 147.71, -14.13, 141.93, 8.07, 119.3, 23.74 ], + "hull": 25, + "edges": [ 8, 6, 6, 4, 4, 2, 2, 0, 0, 48, 46, 48, 46, 44, 44, 42, 42, 40, 40, 38, 38, 36, 36, 34, 32, 34, 50, 52, 52, 54, 54, 56, 40, 58, 58, 60, 8, 10, 20, 22, 22, 24, 62, 64, 64, 66, 66, 68, 8, 70, 70, 60, 68, 70, 58, 72, 72, 74, 74, 76, 76, 78, 24, 26, 26, 28, 58, 80, 80, 82, 82, 84, 84, 86, 86, 44, 70, 88, 88, 90, 90, 92, 92, 94, 94, 48, 80, 88, 88, 6, 82, 90, 90, 4, 84, 92, 92, 2, 86, 94, 94, 0, 56, 60, 10, 12, 12, 14, 14, 16, 28, 30, 30, 32, 26, 98, 98, 78, 30, 98, 24, 100, 100, 50, 98, 100, 22, 102, 102, 62, 100, 102, 16, 18, 18, 20, 102, 18 ], + "width": 82, + "height": 184 + } + }, + "front-thigh": { + "front-thigh": { "x": 42.48, "y": 4.45, "rotation": 84.87, "width": 45, "height": 112 } + }, + "front-upper-arm": { + "front-upper-arm": { "x": 28.31, "y": 7.37, "rotation": 97.9, "width": 46, "height": 97 } + }, + "goggles": { + "goggles": { + "type": "mesh", + "uvs": [ 0.53653, 0.04114, 0.72922, 0.16036, 0.91667, 0.33223, 0.97046, 0.31329, 1, 0.48053, 0.95756, 0.5733, 0.88825, 0.6328, 0.86878, 0.78962, 0.77404, 0.8675, 0.72628, 1, 0.60714, 0.93863, 0.49601, 0.88138, 0.41558, 0.75027, 0.32547, 0.70084, 0.2782, 0.58257, 0.1721, 0.63281, 0.17229, 0.75071, 0.10781, 0.79898, 0, 0.32304, 0, 0.12476, 0.07373, 0.07344, 0.15423, 0.10734, 0.23165, 0.13994, 0.30313, 0.02256, 0.34802, 0, 0.42979, 0.69183, 0.39476, 0.51042, 0.39488, 0.31512, 0.45878, 0.23198, 0.56501, 0.28109, 0.69961, 0.39216, 0.82039, 0.54204, 0.85738, 0.62343, 0.91107, 0.51407, 0.72639, 0.32147, 0.58764, 0.19609, 0.48075, 0.11269, 0.37823, 0.05501, 0.3287, 0.17866, 0.319, 0.305, 0.36036, 0.53799, 0.40327, 0.70072, 0.30059, 0.55838, 0.21957, 0.2815, 0.09963, 0.28943, 0.56863, 0.4368, 0.4911, 0.37156, 0.51185, 0.52093, 0.67018, 0.59304, 0.7619, 0.68575, 0.73296, 0.43355 ], + "triangles": [ 18, 44, 15, 21, 19, 20, 17, 18, 15, 44, 19, 21, 2, 3, 4, 18, 19, 44, 2, 33, 34, 33, 2, 4, 5, 33, 4, 5, 6, 33, 7, 32, 6, 31, 50, 33, 32, 31, 33, 6, 32, 33, 31, 49, 50, 49, 31, 32, 49, 32, 7, 8, 49, 7, 33, 50, 34, 17, 15, 16, 9, 48, 8, 49, 48, 50, 50, 48, 45, 47, 45, 48, 50, 45, 30, 45, 47, 46, 45, 46, 29, 30, 45, 29, 30, 29, 34, 30, 34, 50, 47, 26, 46, 25, 10, 11, 12, 25, 11, 41, 12, 42, 42, 44, 43, 43, 21, 22, 41, 40, 25, 41, 42, 40, 29, 35, 34, 40, 26, 25, 25, 26, 47, 37, 24, 0, 36, 37, 0, 42, 43, 39, 42, 39, 40, 28, 38, 36, 40, 39, 26, 28, 27, 38, 26, 39, 27, 37, 38, 23, 39, 43, 38, 38, 37, 36, 27, 39, 38, 43, 22, 38, 37, 23, 24, 22, 23, 38, 36, 0, 35, 28, 36, 35, 29, 28, 35, 27, 28, 46, 26, 27, 46, 35, 0, 1, 34, 35, 1, 12, 41, 25, 47, 10, 25, 44, 21, 43, 42, 14, 44, 14, 15, 44, 13, 14, 42, 12, 13, 42, 46, 28, 29, 47, 48, 10, 48, 9, 10, 49, 8, 48, 2, 34, 1 ], + "vertices": [ 2, 66, 61.88, 22.81, 0.832, 46, 172.09, 22.81, 0.168, 2, 66, 59.89, -31.19, 0.6855, 46, 170.1, -31.19, 0.3145, 2, 66, 49.2, -86.8, 0.32635, 46, 159.41, -86.8, 0.67365, 2, 66, 56.82, -99.01, 0.01217, 46, 167.03, -99.01, 0.98783, 1, 46, 143.4, -115.48, 1, 2, 66, 15, -110.14, 0.0041, 46, 125.21, -110.14, 0.9959, 2, 66, -0.32, -96.36, 0.07948, 46, 109.89, -96.36, 0.92052, 2, 66, -26.56, -100.19, 0.01905, 46, 83.65, -100.19, 0.98095, 2, 66, -46.96, -81.16, 0.4921, 46, 63.26, -81.16, 0.50791, 2, 66, -71.84, -76.69, 0.56923, 46, 38.37, -76.69, 0.43077, 2, 66, -72.54, -43.98, 0.74145, 46, 37.67, -43.98, 0.25855, 2, 66, -73.2, -13.47, 0.87929, 46, 37.01, -13.47, 0.12071, 2, 66, -59.63, 13.55, 0.864, 46, 50.58, 13.55, 0.136, 2, 66, -59.69, 38.45, 0.85289, 46, 50.52, 38.45, 0.14711, 2, 66, -45.26, 56.6, 0.74392, 46, 64.95, 56.6, 0.25608, 2, 66, -62.31, 79.96, 0.624, 46, 47.9, 79.96, 0.376, 2, 66, -80.76, 73.42, 0.616, 46, 29.45, 73.42, 0.384, 2, 66, -93.9, 86.64, 0.288, 46, 16.31, 86.64, 0.712, 1, 46, 81.51, 139.38, 1, 1, 46, 112.56, 150.3, 1, 2, 66, 16.76, 134.97, 0.02942, 46, 126.97, 134.97, 0.97058, 2, 66, 18.42, 113.28, 0.36147, 46, 128.63, 113.28, 0.63853, 2, 66, 20.02, 92.43, 0.7135, 46, 130.23, 92.43, 0.2865, 2, 66, 44.58, 81.29, 0.69603, 46, 154.79, 81.29, 0.30397, 2, 66, 52, 71.48, 0.848, 46, 162.21, 71.48, 0.152, 2, 66, -49.25, 13.27, 0.8, 46, 60.96, 13.27, 0.2, 2, 66, -23.88, 31.88, 0.896, 46, 86.33, 31.88, 0.104, 2, 66, 6.72, 42.6, 0.928, 46, 116.93, 42.6, 0.072, 2, 66, 25.26, 31.44, 0.8, 46, 135.47, 31.44, 0.2, 2, 66, 26.77, 2.59, 0.75, 46, 136.98, 2.59, 0.25, 2, 66, 21.02, -36.66, 0.54887, 46, 131.23, -36.66, 0.45113, 2, 66, 8.01, -74.65, 0.36029, 46, 118.22, -74.65, 0.63971, 2, 66, -1.52, -88.24, 0.1253, 46, 108.69, -88.24, 0.8747, 2, 66, 20.25, -95.44, 0.08687, 46, 130.46, -95.44, 0.91313, 2, 66, 34.42, -39.36, 0.72613, 46, 144.63, -39.36, 0.27387, 2, 66, 42.03, 1.7, 0.824, 46, 152.25, 1.7, 0.176, 2, 66, 45.85, 32.6, 0.856, 46, 156.06, 32.6, 0.144, 1, 66, 46.01, 61.02, 1, 1, 66, 22.35, 66.41, 1, 1, 66, 1.73, 61.84, 1, 2, 66, -31.17, 38.83, 0.928, 46, 79.04, 38.83, 0.072, 2, 66, -52.94, 19.31, 0.79073, 46, 57.27, 19.31, 0.20927, 2, 66, -39.54, 52.42, 0.912, 46, 70.67, 52.42, 0.088, 2, 66, -3.2, 87.61, 0.744, 46, 107.02, 87.61, 0.256, 2, 66, -14.82, 116.7, 0.6368, 46, 95.4, 116.7, 0.3632, 2, 66, 2.7, -6.87, 0.856, 46, 112.91, -6.87, 0.144, 2, 66, 6.21, 15.8, 0.744, 46, 116.42, 15.8, 0.256, 2, 66, -15.39, 2.47, 0.856, 46, 94.82, 2.47, 0.144, 2, 66, -12.98, -40.48, 0.72102, 46, 97.24, -40.48, 0.27898, 2, 66, -19.55, -68.16, 0.59162, 46, 90.66, -68.16, 0.40838, 2, 66, 17.44, -47.15, 0.53452, 46, 127.65, -47.15, 0.46548 ], + "hull": 25, + "edges": [ 36, 34, 34, 32, 32, 30, 30, 28, 28, 26, 26, 24, 24, 22, 18, 16, 16, 14, 14, 12, 12, 10, 10, 8, 8, 6, 6, 4, 4, 2, 2, 0, 0, 48, 48, 46, 46, 44, 36, 38, 40, 38, 24, 50, 50, 52, 52, 54, 54, 56, 56, 58, 58, 60, 62, 64, 64, 12, 8, 66, 66, 68, 68, 70, 70, 72, 72, 74, 74, 76, 76, 78, 78, 80, 80, 82, 82, 24, 24, 84, 84, 86, 86, 44, 40, 42, 42, 44, 42, 88, 88, 30, 58, 90, 90, 92, 92, 94, 18, 20, 20, 22, 94, 20, 18, 96, 96, 98, 60, 100, 100, 62, 98, 100 ], + "width": 261, + "height": 166 + } + }, + "gun": { + "gun": { "x": 77.3, "y": 16.4, "rotation": 60.83, "width": 210, "height": 203 } + }, + "head": { + "head": { + "type": "mesh", + "uvs": [ 0.75919, 0.06107, 0.88392, 0.17893, 0.90174, 0.30856, 0.94224, 0.1966, 1, 0.26584, 1, 0.422, 0.95864, 0.46993, 0.92118, 0.51333, 0.85957, 0.5347, 0.78388, 0.65605, 0.74384, 0.74838, 0.85116, 0.75151, 0.84828, 0.82564, 0.81781, 0.85367, 0.75599, 0.85906, 0.76237, 0.90468, 0.65875, 1, 0.38337, 1, 0.1858, 0.85404, 0.12742, 0.81091, 0.06025, 0.69209, 0, 0.58552, 0, 0.41021, 0.0853, 0.20692, 0.24243, 0.14504, 0.5, 0.1421, 0.50324, 0.07433, 0.41738, 0, 0.57614, 0, 0.85059, 0.36087, 0.73431, 0.43206, 0.68481, 0.31271, 0.72165, 0.16718, 0.55931, 0.04154, 0.44764, 0.22895, 0.23926, 0.26559, 0.71272, 0.44036, 0.56993, 0.383, 0.41678, 0.33511, 0.293, 0.31497, 0.70802, 0.44502, 0.56676, 0.38976, 0.41521, 0.34416, 0.28754, 0.33017, 0.88988, 0.50177, 0.30389, 0.73463, 0.2646, 0.65675, 0.21414, 0.61584, 0.14613, 0.62194, 0.10316, 0.66636, 0.10358, 0.72557, 0.14505, 0.79164, 0.20263, 0.81355, 0.27873, 0.80159, 0.34947, 0.7376, 0.23073, 0.57073, 0.08878, 0.60707, 0.29461, 0.8129, 0.73006, 0.87883, 0.69805, 0.87348, 0.66166, 0.79681, 0.22468, 0.69824, 0.14552, 0.67405 ], + "triangles": [ 50, 49, 62, 34, 25, 31, 39, 35, 34, 38, 39, 34, 37, 38, 34, 42, 39, 38, 43, 39, 42, 32, 2, 31, 31, 37, 34, 42, 38, 37, 41, 42, 37, 43, 22, 39, 30, 31, 29, 36, 37, 31, 30, 36, 31, 40, 41, 37, 36, 40, 37, 36, 30, 44, 55, 22, 43, 55, 48, 56, 47, 48, 55, 46, 55, 54, 42, 55, 43, 47, 55, 46, 62, 49, 48, 61, 47, 46, 62, 48, 47, 61, 62, 47, 46, 54, 45, 42, 41, 55, 61, 46, 45, 55, 41, 54, 61, 51, 50, 61, 50, 62, 60, 41, 40, 54, 41, 60, 53, 61, 45, 52, 51, 61, 57, 53, 45, 57, 45, 54, 53, 52, 61, 52, 19, 51, 57, 18, 52, 57, 52, 53, 17, 54, 60, 57, 54, 17, 18, 57, 17, 19, 50, 51, 33, 27, 28, 26, 27, 33, 0, 33, 28, 32, 33, 0, 32, 0, 1, 33, 25, 26, 33, 32, 25, 31, 25, 32, 2, 32, 1, 2, 3, 4, 29, 31, 2, 2, 4, 5, 29, 2, 5, 6, 29, 5, 30, 29, 6, 44, 30, 6, 18, 19, 52, 49, 56, 48, 34, 24, 25, 35, 23, 24, 35, 24, 34, 39, 22, 35, 22, 23, 35, 7, 44, 6, 8, 36, 44, 40, 36, 8, 8, 44, 7, 56, 21, 22, 55, 56, 22, 9, 40, 8, 20, 21, 56, 20, 56, 49, 9, 60, 40, 10, 60, 9, 20, 50, 19, 12, 10, 11, 13, 10, 12, 14, 60, 10, 13, 14, 10, 59, 60, 14, 58, 59, 14, 58, 14, 15, 16, 17, 60, 59, 16, 60, 15, 16, 59, 15, 59, 58, 20, 49, 50 ], + "vertices": [ 2, 50, 41.97, -41.8, 0.94074, 66, 165.41, -22.6, 0.05926, 4, 48, 73.47, 27.54, 0.26795, 50, -5.75, -51.71, 0.4738, 49, 112.99, -11.41, 0.12255, 66, 143.5, -66.13, 0.1357, 4, 48, 38.23, 10.99, 0.6831, 50, -41.01, -35.22, 0.07866, 49, 92.73, -44.66, 0.04872, 66, 108.65, -83.49, 0.18952, 2, 48, 73.35, 10.89, 0.8455, 66, 143.77, -82.78, 0.1545, 2, 48, 58.59, -10.38, 0.91607, 66, 129.5, -104.39, 0.08393, 3, 46, 195.82, -119.82, 0.104, 47, 75.49, -4.55, 0.09191, 48, 14.36, -24.8, 0.80409, 4, 46, 178.62, -113.98, 0.19022, 47, 59.82, -13.72, 0.33409, 48, -2.7, -18.57, 0.46643, 66, 68.41, -113.98, 0.00926, 4, 46, 163.06, -108.69, 0.18724, 47, 45.64, -22.03, 0.3133, 48, -18.14, -12.93, 0.47469, 66, 52.84, -108.69, 0.02477, 2, 46, 151.52, -95.05, 0.91122, 66, 41.31, -95.05, 0.08878, 2, 46, 110.61, -87.69, 0.70564, 66, 0.4, -87.69, 0.29436, 2, 46, 81.05, -86.58, 0.63951, 66, -29.16, -86.58, 0.36049, 2, 46, 89.82, -114.32, 0.57, 66, -20.39, -114.32, 0.43, 2, 46, 68.72, -120.91, 0.57, 66, -41.49, -120.91, 0.43, 2, 46, 58.1, -115.9, 0.57, 66, -52.11, -115.9, 0.43, 2, 46, 51.03, -100.63, 0.64242, 66, -59.18, -100.63, 0.35758, 2, 46, 38.79, -106.76, 0.81659, 66, -71.43, -106.76, 0.18341, 2, 46, 2.68, -89.7, 0.77801, 66, -107.53, -89.7, 0.22199, 2, 46, -22.07, -19.3, 0.823, 66, -132.28, -19.3, 0.177, 2, 46, 1.2, 45.63, 0.51204, 66, -109.01, 45.63, 0.48796, 2, 46, 8.07, 64.81, 0.60869, 66, -102.14, 64.81, 0.39131, 2, 46, 35.44, 93.73, 0.80009, 66, -74.77, 93.73, 0.19991, 2, 46, 59.98, 119.66, 0.93554, 66, -50.23, 119.66, 0.06446, 2, 46, 109.26, 136.99, 0.99895, 66, -0.95, 136.99, 0.00105, 1, 46, 174.07, 135.27, 1, 3, 46, 205.59, 101.22, 0.80778, 49, -16.84, 104.63, 0.15658, 66, 95.38, 101.22, 0.03564, 3, 50, 58.94, 30.5, 0.43491, 49, 38.36, 61.89, 0.28116, 66, 119.35, 35.65, 0.28393, 2, 50, 75.56, 19.01, 0.92164, 66, 138.68, 41.52, 0.07836, 1, 50, 106.7, 26.9, 1, 1, 50, 83.79, -9.51, 1, 5, 47, 44.51, 27.24, 0.15139, 48, 19.12, 19.33, 0.44847, 50, -46.82, -15.19, 0.05757, 49, 72.19, -48.24, 0.1149, 66, 89.35, -75.58, 0.22767, 3, 47, 7.42, 19.08, 0.37772, 49, 34.32, -45.24, 0.09918, 66, 58.9, -52.89, 0.52311, 2, 49, 45.94, -9.07, 0.4826, 66, 87.99, -28.45, 0.5174, 2, 50, 20.62, -16.35, 0.7435, 66, 132.21, -23.49, 0.2565, 2, 50, 75.74, 0.94, 0.97172, 66, 152.95, 30.42, 0.02828, 4, 46, 200.45, 40.46, 0.18809, 50, 44.6, 56.29, 0.05831, 49, 11.15, 50.46, 0.14366, 66, 90.24, 40.46, 0.60994, 2, 46, 171.41, 90.12, 0.48644, 66, 61.2, 90.12, 0.51356, 2, 46, 164.84, -48.18, 0.43217, 66, 54.62, -48.18, 0.56783, 4, 46, 168.13, -6.02, 0.01949, 47, -28.65, 49.02, 0.02229, 49, 8.54, -6.09, 0.12791, 66, 57.92, -6.02, 0.83031, 2, 46, 167.84, 37.87, 0.15, 66, 57.63, 37.87, 0.85, 2, 46, 162.36, 71.5, 0.24107, 66, 52.15, 71.5, 0.75893, 2, 46, 163.11, -47.44, 0.41951, 66, 52.9, -47.44, 0.58049, 2, 46, 165.94, -5.87, 0.16355, 66, 55.73, -5.87, 0.83645, 2, 46, 165.14, 37.38, 0.15, 66, 54.93, 37.38, 0.85, 2, 46, 157.6, 71.4, 0.21735, 66, 47.39, 71.4, 0.78265, 3, 46, 163.5, -99.54, 0.61812, 47, 39.01, -15.71, 0.30445, 66, 53.29, -99.54, 0.07744, 2, 46, 45.38, 27.24, 0.16741, 66, -64.83, 27.24, 0.83259, 2, 46, 63.74, 44.98, 0.15, 66, -46.47, 44.98, 0.85, 2, 46, 70.7, 61.92, 0.22175, 66, -39.51, 61.92, 0.77825, 2, 46, 62.88, 78.71, 0.38, 66, -47.34, 78.71, 0.62, 2, 46, 46.53, 85.3, 0.51, 66, -63.68, 85.3, 0.49, 2, 46, 29.92, 79.34, 0.388, 66, -80.29, 79.34, 0.612, 2, 46, 15.08, 62.21, 0.38, 66, -95.13, 62.21, 0.62, 2, 46, 14.09, 45.32, 0.41, 66, -96.12, 45.32, 0.59, 2, 46, 24.3, 27.06, 0.192, 66, -85.91, 27.06, 0.808, 1, 66, -61.57, 15.3, 1, 2, 46, 84.87, 62.14, 0.16757, 66, -25.34, 62.14, 0.83243, 2, 46, 61.9, 94.84, 0.68145, 66, -48.31, 94.84, 0.31855, 2, 46, 22.54, 21.88, 0.16, 66, -87.67, 21.88, 0.84, 2, 46, 43.15, -95.95, 0.73445, 66, -67.06, -95.95, 0.26555, 2, 46, 41.77, -87.24, 0.67858, 66, -68.44, -87.24, 0.32142, 2, 46, 60.05, -70.36, 0.50195, 66, -50.16, -70.36, 0.49805, 2, 46, 48.49, 51.09, 0.25, 66, -61.72, 51.09, 0.75, 2, 46, 48.17, 73.71, 0.15634, 66, -62.04, 73.71, 0.84366 ], + "hull": 29, + "edges": [ 10, 8, 8, 6, 6, 4, 4, 2, 2, 0, 0, 56, 54, 56, 54, 52, 52, 50, 50, 48, 48, 46, 46, 44, 42, 44, 32, 34, 4, 58, 58, 60, 62, 64, 64, 66, 66, 54, 50, 68, 68, 70, 70, 44, 60, 72, 62, 74, 72, 74, 74, 76, 76, 78, 78, 44, 16, 80, 80, 82, 82, 84, 84, 86, 86, 44, 14, 88, 88, 72, 14, 16, 10, 12, 12, 14, 12, 60, 90, 92, 92, 94, 94, 96, 96, 98, 98, 100, 100, 102, 102, 104, 104, 106, 106, 90, 108, 110, 110, 112, 38, 40, 40, 42, 112, 40, 34, 36, 36, 38, 36, 114, 114, 108, 30, 32, 30, 28, 24, 26, 28, 26, 22, 24, 22, 20, 20, 18, 18, 16, 28, 116, 116, 118, 118, 120, 120, 20 ], + "width": 271, + "height": 298 + } + }, + "head-bb": { + "head": { + "type": "boundingbox", + "vertexCount": 6, + "vertices": [ -19.14, -70.3, 40.8, -118.08, 257.78, -115.62, 285.17, 57.18, 120.77, 164.95, -5.07, 76.95 ] + } + }, + "hoverboard-board": { + "hoverboard-board": { + "type": "mesh", + "uvs": [ 0.13865, 0.56624, 0.11428, 0.51461, 0.07619, 0.52107, 0.02364, 0.52998, 0.01281, 0.53182, 0, 0.37979, 0, 0.2206, 0.00519, 0.10825, 0.01038, 0.10726, 0.03834, 0.10194, 0.05091, 0, 0.08326, 0, 0.10933, 0.04206, 0.1382, 0.08865, 0.18916, 0.24067, 0.22234, 0.4063, 0.23886, 0.44063, 0.83412, 0.44034, 0.88444, 0.38296, 0.92591, 0.32639, 0.95996, 0.28841, 0.98612, 0.28542, 1, 0.38675, 0.99494, 0.47104, 0.97883, 0.53251, 0.94409, 0.62135, 0.90206, 0.69492, 0.86569, 0.71094, 0.82822, 0.70791, 0.81286, 0.77127, 0.62931, 0.77266, 0.61364, 0.70645, 0.47166, 0.70664, 0.45901, 0.77827, 0.27747, 0.76986, 0.2658, 0.70372, 0.24976, 0.71381, 0.24601, 0.77827, 0.23042, 0.84931, 0.20926, 0.90956, 0.17299, 1, 0.15077, 0.99967, 0.12906, 0.90192, 0.10369, 0.73693, 0.10198, 0.62482, 0.09131, 0.47272, 0.09133, 0.41325, 0.15082, 0.41868, 0.21991, 0.51856, 0.06331, 0.10816, 0.08383, 0.21696, 0.08905, 0.37532, 0.15903, 0.58726, 0.17538, 0.65706, 0.20118, 0.8029, 0.17918, 0.55644, 0.22166, 0.5802, 0.86259, 0.57962, 0.92346, 0.48534, 0.96691, 0.36881, 0.0945, 0.13259, 0.12688, 0.17831, 0.15986, 0.24682, 0.18036, 0.31268, 0.20607, 0.4235, 0.16074, 0.85403, 0.13624, 0.70122, 0.12096, 0.64049, 0.02396, 0.21811, 0.02732, 0.37839, 0.02557, 0.4972, 0.14476, 0.45736, 0.18019, 0.51689, 0.19692, 0.56636 ], + "triangles": [ 10, 11, 12, 9, 10, 12, 49, 9, 12, 60, 49, 12, 13, 60, 12, 61, 60, 13, 50, 49, 60, 50, 60, 61, 68, 8, 9, 68, 9, 49, 68, 49, 50, 7, 8, 68, 6, 7, 68, 61, 13, 14, 62, 61, 14, 50, 61, 62, 63, 62, 14, 59, 20, 21, 19, 20, 59, 51, 50, 62, 51, 62, 63, 51, 69, 68, 51, 68, 50, 6, 68, 69, 5, 6, 69, 18, 19, 59, 15, 63, 14, 59, 21, 22, 47, 51, 63, 47, 46, 51, 47, 63, 64, 15, 64, 63, 64, 15, 16, 71, 46, 47, 23, 59, 22, 69, 51, 70, 45, 46, 71, 70, 51, 2, 58, 18, 59, 58, 59, 23, 17, 18, 58, 70, 5, 69, 2, 51, 46, 1, 45, 71, 47, 48, 71, 47, 64, 48, 48, 72, 71, 1, 71, 72, 16, 48, 64, 45, 2, 46, 2, 45, 1, 70, 4, 5, 3, 70, 2, 3, 4, 70, 24, 58, 23, 72, 0, 1, 73, 55, 72, 55, 0, 72, 48, 73, 72, 57, 17, 58, 25, 57, 58, 56, 48, 16, 73, 48, 56, 56, 16, 17, 56, 17, 57, 52, 0, 55, 24, 25, 58, 44, 0, 52, 67, 44, 52, 52, 56, 53, 73, 52, 55, 56, 52, 73, 67, 52, 53, 26, 57, 25, 66, 67, 53, 56, 32, 35, 53, 56, 35, 56, 57, 32, 28, 31, 57, 57, 31, 32, 57, 27, 28, 26, 27, 57, 36, 53, 35, 43, 44, 67, 43, 67, 66, 34, 35, 32, 29, 31, 28, 30, 31, 29, 53, 54, 66, 53, 36, 54, 33, 34, 32, 37, 54, 36, 65, 43, 66, 38, 54, 37, 54, 65, 66, 39, 65, 54, 42, 43, 65, 38, 39, 54, 40, 42, 65, 40, 41, 42, 65, 39, 40 ], + "vertices": [ -189.36, 15.62, -201.35, 23.47, -220.09, 22.49, -245.95, 21.13, -251.28, 20.86, -257.58, 43.96, -257.57, 68.16, -255.02, 85.24, -252.47, 85.39, -238.71, 86.2, -232.52, 101.69, -216.61, 101.69, -203.78, 95.3, -189.58, 88.21, -164.51, 65.1, -148.19, 39.93, -140.06, 34.71, 152.82, 34.73, 177.57, 43.45, 197.97, 52.05, 214.72, 57.82, 227.6, 58.27, 234.42, 42.87, 231.94, 30.06, 224.01, 20.72, 206.91, 7.21, 186.23, -3.97, 168.34, -6.4, 149.9, -5.94, 142.35, -15.57, 52.04, -15.77, 44.33, -5.71, -25.52, -5.73, -31.75, -16.62, -121.07, -15.34, -126.81, -5.28, -134.7, -6.81, -136.54, -16.61, -144.22, -27.41, -154.63, -36.57, -172.47, -50.31, -183.41, -50.26, -194.09, -35.4, -206.56, -10.32, -207.4, 6.72, -212.65, 29.84, -212.64, 38.88, -183.37, 38.05, -149.38, 22.86, -226.43, 85.25, -216.33, 68.71, -213.76, 44.64, -179.34, 12.42, -171.29, 1.81, -158.6, -20.36, -169.42, 17.11, -148.52, 13.49, 166.82, 13.56, 196.76, 27.89, 218.14, 45.6, -211.08, 81.54, -195.15, 74.59, -178.93, 64.17, -168.84, 54.16, -156.19, 37.31, -178.5, -28.13, -190.55, -4.9, -198.07, 4.33, -245.79, 68.54, -244.14, 44.18, -245, 26.12, -186.36, 32.17, -168.92, 23.12, -160.69, 15.6 ], + "hull": 45, + "edges": [ 0, 2, 8, 10, 10, 12, 12, 14, 18, 20, 20, 22, 26, 28, 28, 30, 30, 32, 32, 34, 34, 36, 36, 38, 38, 40, 40, 42, 42, 44, 44, 46, 46, 48, 48, 50, 50, 52, 52, 54, 54, 56, 56, 58, 58, 60, 60, 62, 62, 64, 64, 66, 66, 68, 68, 70, 70, 72, 72, 74, 80, 82, 82, 84, 84, 86, 86, 88, 0, 88, 2, 90, 90, 92, 92, 94, 94, 96, 96, 32, 18, 98, 98, 100, 100, 102, 2, 4, 102, 4, 92, 102, 0, 104, 104, 106, 106, 108, 78, 80, 108, 78, 74, 76, 76, 78, 62, 56, 64, 70, 0, 110, 112, 114, 114, 116, 116, 118, 118, 42, 50, 116, 114, 34, 98, 120, 120, 122, 22, 24, 24, 26, 120, 24, 122, 124, 124, 126, 126, 128, 128, 96, 80, 130, 130, 132, 132, 134, 134, 88, 14, 16, 16, 18, 136, 16, 136, 138, 138, 140, 4, 6, 6, 8, 140, 6, 96, 112, 92, 142, 142, 144, 110, 146, 146, 112, 144, 146 ], + "width": 492, + "height": 152 + } + }, + "hoverboard-thruster-front": { + "hoverboard-thruster": { "x": 0.02, "y": -7.08, "rotation": 0.17, "width": 60, "height": 64 } + }, + "hoverboard-thruster-rear": { + "hoverboard-thruster": { "x": 1.1, "y": -6.29, "rotation": 0.17, "width": 60, "height": 64 } + }, + "hoverglow-front": { + "hoverglow-small": { + "x": 2.13, + "y": -2, + "scaleX": 0.303, + "scaleY": 0.495, + "rotation": 0.15, + "width": 274, + "height": 75 + } + }, + "hoverglow-rear": { + "hoverglow-small": { + "x": 1.39, + "y": -2.09, + "scaleX": 0.303, + "scaleY": 0.495, + "rotation": 0.61, + "width": 274, + "height": 75 + } + }, + "mouth": { + "mouth-grind": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 2, 66, -98.93, -85.88, 0.22, 46, 11.28, -85.88, 0.78, 2, 66, -129.77, 1.84, 0.6, 46, -19.56, 1.84, 0.4, 2, 66, -74.12, 21.41, 0.6, 46, 36.09, 21.41, 0.4, 2, 66, -43.28, -66.32, 0.4, 46, 66.93, -66.32, 0.6 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 93, + "height": 59 + }, + "mouth-oooo": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 2, 46, 11.28, -85.89, 0.22, 66, -98.93, -85.89, 0.78, 2, 46, -19.56, 1.85, 0.6, 66, -129.78, 1.85, 0.4, 2, 46, 36.1, 21.42, 0.6, 66, -74.12, 21.42, 0.4, 2, 46, 66.94, -66.32, 0.4, 66, -43.27, -66.32, 0.6 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 93, + "height": 59 + }, + "mouth-smile": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 2, 66, -98.93, -85.89, 0.21075, 46, 11.28, -85.89, 0.78925, 2, 66, -129.77, 1.85, 0.6, 46, -19.56, 1.85, 0.4, 2, 66, -74.11, 21.42, 0.6, 46, 36.1, 21.42, 0.4, 2, 66, -43.27, -66.32, 0.40772, 46, 66.94, -66.32, 0.59228 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 93, + "height": 59 + } + }, + "muzzle": { + "muzzle01": { + "x": 151.97, + "y": 5.81, + "scaleX": 3.7361, + "scaleY": 3.7361, + "rotation": 0.15, + "width": 133, + "height": 79 + }, + "muzzle02": { + "x": 187.25, + "y": 5.9, + "scaleX": 4.0623, + "scaleY": 4.0623, + "rotation": 0.15, + "width": 135, + "height": 84 + }, + "muzzle03": { + "x": 231.96, + "y": 6.02, + "scaleX": 4.1325, + "scaleY": 4.1325, + "rotation": 0.15, + "width": 166, + "height": 106 + }, + "muzzle04": { + "x": 231.96, + "y": 6.02, + "scaleX": 4.0046, + "scaleY": 4.0046, + "rotation": 0.15, + "width": 149, + "height": 90 + }, + "muzzle05": { + "x": 293.8, + "y": 6.19, + "scaleX": 4.4673, + "scaleY": 4.4673, + "rotation": 0.15, + "width": 135, + "height": 75 + } + }, + "muzzle-glow": { + "muzzle-glow": { "width": 50, "height": 50 } + }, + "muzzle-ring": { + "muzzle-ring": { "x": -1.3, "y": 0.32, "scaleX": 0.3147, "scaleY": 0.3147, "width": 49, "height": 209 } + }, + "muzzle-ring2": { + "muzzle-ring": { "x": -1.3, "y": 0.32, "scaleX": 0.3147, "scaleY": 0.3147, "width": 49, "height": 209 } + }, + "muzzle-ring3": { + "muzzle-ring": { "x": -1.3, "y": 0.32, "scaleX": 0.3147, "scaleY": 0.3147, "width": 49, "height": 209 } + }, + "muzzle-ring4": { + "muzzle-ring": { "x": -1.3, "y": 0.32, "scaleX": 0.3147, "scaleY": 0.3147, "width": 49, "height": 209 } + }, + "neck": { + "neck": { "x": 9.77, "y": -3.01, "rotation": -55.22, "width": 36, "height": 41 } + }, + "portal-bg": { + "portal-bg": { "x": -3.1, "y": 7.25, "scaleX": 1.0492, "scaleY": 1.0492, "width": 266, "height": 266 } + }, + "portal-flare1": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare2": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare3": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare4": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare5": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare6": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare7": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare8": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare9": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-flare10": { + "portal-flare1": { "width": 111, "height": 60 }, + "portal-flare2": { "width": 114, "height": 61 }, + "portal-flare3": { "width": 115, "height": 59 } + }, + "portal-shade": { + "portal-shade": { "width": 266, "height": 266 } + }, + "portal-streaks1": { + "portal-streaks1": { "scaleX": 0.9774, "scaleY": 0.9774, "width": 252, "height": 256 } + }, + "portal-streaks2": { + "portal-streaks2": { "x": -1.64, "y": 2.79, "width": 250, "height": 249 } + }, + "rear-bracer": { + "rear-bracer": { "x": 11.15, "y": -2.2, "rotation": 66.17, "width": 56, "height": 72 } + }, + "rear-foot": { + "rear-foot": { + "type": "mesh", + "uvs": [ 0.48368, 0.1387, 0.51991, 0.21424, 0.551, 0.27907, 0.58838, 0.29816, 0.63489, 0.32191, 0.77342, 0.39267, 1, 0.73347, 1, 1, 0.54831, 0.99883, 0.31161, 1, 0, 1, 0, 0.41397, 0.13631, 0, 0.41717, 0 ], + "triangles": [ 8, 3, 4, 8, 4, 5, 8, 5, 6, 8, 6, 7, 11, 1, 10, 3, 9, 2, 2, 10, 1, 12, 13, 0, 0, 11, 12, 1, 11, 0, 2, 9, 10, 3, 8, 9 ], + "vertices": [ 2, 8, 10.45, 29.41, 0.90802, 9, -6.74, 49.62, 0.09198, 2, 8, 16.56, 29.27, 0.84259, 9, -2.65, 45.09, 0.15741, 2, 8, 21.8, 29.15, 0.69807, 9, 0.85, 41.2, 0.30193, 2, 8, 25.53, 31.43, 0.52955, 9, 5.08, 40.05, 0.47045, 2, 8, 30.18, 34.27, 0.39303, 9, 10.33, 38.62, 0.60697, 2, 8, 44.02, 42.73, 0.27525, 9, 25.98, 34.36, 0.72475, 2, 8, 76.47, 47.28, 0.21597, 9, 51.56, 13.9, 0.78403, 2, 8, 88.09, 36.29, 0.28719, 9, 51.55, -2.09, 0.71281, 2, 8, 52.94, -0.73, 0.47576, 9, 0.52, -1.98, 0.52424, 2, 8, 34.63, -20.23, 0.68757, 9, -26.23, -2.03, 0.31243, 2, 8, 10.44, -45.81, 0.84141, 9, -61.43, -2, 0.15859, 2, 8, -15.11, -21.64, 0.93283, 9, -61.4, 33.15, 0.06717, 1, 8, -22.57, 6.61, 1, 1, 8, -0.76, 29.67, 1 ], + "hull": 14, + "edges": [ 14, 12, 10, 12, 14, 16, 16, 18, 18, 20, 4, 18, 20, 22, 24, 26, 22, 24, 4, 2, 2, 20, 4, 6, 6, 16, 6, 8, 8, 10, 2, 0, 0, 26 ], + "width": 113, + "height": 60 + } + }, + "rear-shin": { + "rear-shin": { "x": 58.29, "y": -2.75, "rotation": 92.37, "width": 75, "height": 178 } + }, + "rear-thigh": { + "rear-thigh": { "x": 33.11, "y": -4.11, "rotation": 72.54, "width": 55, "height": 94 } + }, + "rear-upper-arm": { + "rear-upper-arm": { "x": 21.13, "y": 4.09, "rotation": 89.33, "width": 40, "height": 87 } + }, + "side-glow1": { + "hoverglow-small": { "x": 2.09, "scaleX": 0.2353, "scaleY": 0.4132, "width": 274, "height": 75 } + }, + "side-glow2": { + "hoverglow-small": { "x": 2.09, "scaleX": 0.2353, "scaleY": 0.4132, "width": 274, "height": 75 } + }, + "side-glow3": { + "hoverglow-small": { "x": 2.09, "scaleX": 0.3586, "scaleY": 0.6297, "width": 274, "height": 75 } + }, + "torso": { + "torso": { + "type": "mesh", + "uvs": [ 0.6251, 0.12672, 1, 0.26361, 1, 0.28871, 1, 0.66021, 1, 0.68245, 0.92324, 0.69259, 0.95116, 0.84965, 0.77124, 1, 0.49655, 1, 0.27181, 1, 0.13842, 0.77196, 0.09886, 0.6817, 0.05635, 0.58471, 0, 0.45614, 0, 0.33778, 0, 0.19436, 0.14463, 0, 0.27802, 0, 0.72525, 0.27835, 0.76091, 0.46216, 0.84888, 0.67963, 0.68257, 0.63249, 0.53986, 0.3847, 0.25443, 0.3217, 0.30063, 0.55174, 0.39553, 0.79507, 0.26389, 0.17007, 0.5241, 0.18674, 0.71492, 0.76655, 0.82151, 0.72956, 0.27626, 0.4304, 0.62327, 0.52952, 0.3455, 0.66679, 0.53243, 0.2914 ], + "triangles": [ 18, 1, 2, 19, 2, 3, 18, 0, 1, 23, 15, 26, 27, 26, 16, 14, 15, 23, 15, 16, 26, 17, 27, 16, 13, 14, 23, 0, 27, 17, 13, 23, 30, 11, 12, 24, 21, 31, 19, 12, 13, 30, 24, 22, 31, 31, 22, 19, 12, 30, 24, 32, 24, 31, 24, 30, 22, 3, 20, 19, 32, 31, 21, 11, 24, 32, 4, 5, 3, 8, 28, 7, 7, 29, 6, 7, 28, 29, 9, 25, 8, 8, 25, 28, 9, 10, 25, 29, 5, 6, 10, 32, 25, 25, 21, 28, 25, 32, 21, 10, 11, 32, 28, 21, 29, 29, 20, 5, 29, 21, 20, 5, 20, 3, 20, 21, 19, 33, 26, 27, 22, 18, 19, 19, 18, 2, 33, 27, 18, 30, 23, 22, 22, 33, 18, 23, 33, 22, 33, 23, 26, 27, 0, 18 ], + "vertices": [ 2, 29, 44.59, -10.39, 0.88, 40, -17.65, 33.99, 0.12, 3, 28, 59.65, -45.08, 0.12189, 29, 17.13, -45.08, 0.26811, 40, 22.68, 15.82, 0.61, 3, 28, 55.15, -44.72, 0.1345, 29, 12.63, -44.72, 0.2555, 40, 23.43, 11.37, 0.61, 3, 27, 31.01, -39.45, 0.51133, 28, -11.51, -39.45, 0.30867, 40, 34.58, -54.57, 0.18, 3, 27, 27.01, -39.14, 0.53492, 28, -15.5, -39.14, 0.28508, 40, 35.25, -58.52, 0.18, 2, 27, 25.79, -31.5, 0.75532, 28, -16.73, -31.5, 0.24468, 1, 27, -2.61, -32, 1, 1, 27, -28.2, -12.29, 1, 1, 27, -26.08, 14.55, 1, 1, 27, -24.35, 36.5, 1, 2, 27, 17.6, 46.3, 0.8332, 28, -24.92, 46.3, 0.1668, 2, 27, 34.1, 48.89, 0.59943, 28, -8.42, 48.89, 0.40058, 3, 27, 51.83, 51.67, 0.29262, 28, 9.32, 51.67, 0.63181, 29, -33.2, 51.67, 0.07557, 3, 27, 75.34, 55.35, 0.06656, 28, 32.82, 55.35, 0.62298, 29, -9.7, 55.35, 0.31046, 2, 28, 54.06, 53.67, 0.37296, 29, 11.54, 53.67, 0.62704, 2, 28, 79.79, 51.64, 0.10373, 29, 37.27, 51.64, 0.89627, 1, 29, 71.04, 34.76, 1, 1, 29, 70.01, 21.72, 1, 1, 30, 36.74, 7.06, 1, 3, 30, 45.7, -24.98, 0.67, 28, 25.87, -18.9, 0.3012, 29, -16.65, -18.9, 0.0288, 2, 27, 28.69, -24.42, 0.77602, 28, -13.83, -24.42, 0.22398, 3, 30, 43.24, -56.49, 0.064, 27, 38.43, -8.84, 0.67897, 28, -4.09, -8.84, 0.25703, 3, 30, 22.02, -14.85, 0.29, 28, 41.48, 1.59, 0.53368, 29, -1.04, 1.59, 0.17632, 3, 30, -7.45, -8.33, 0.76, 28, 54.98, 28.59, 0.06693, 29, 12.46, 28.59, 0.17307, 3, 30, 3.91, -48.4, 0.25, 27, 55.87, 27.33, 0.15843, 28, 13.35, 27.33, 0.59157, 1, 27, 11.47, 21.51, 1, 2, 30, -11.09, 18.74, 0.416, 29, 39.6, 25.51, 0.584, 2, 30, 14.56, 20.03, 0.53, 29, 34.6, 0.33, 0.47, 1, 27, 14.12, -10.1, 1, 2, 27, 19.94, -21.03, 0.92029, 28, -22.58, -21.03, 0.07971, 3, 30, -2.08, -27.26, 0.29, 28, 35.31, 27.99, 0.49582, 29, -7.21, 27.99, 0.21418, 2, 30, 34.42, -39.19, 0.25, 28, 14.84, -4.5, 0.75, 2, 27, 34.87, 24.58, 0.67349, 28, -7.64, 24.58, 0.32651, 2, 30, 18.5, 1.59, 0.76, 29, 15.76, 1, 0.24 ], + "hull": 18, + "edges": [ 14, 12, 12, 10, 10, 8, 18, 20, 32, 34, 30, 32, 2, 4, 36, 4, 36, 38, 38, 40, 4, 6, 6, 8, 40, 6, 40, 42, 14, 16, 16, 18, 50, 16, 46, 52, 54, 36, 2, 0, 0, 34, 54, 0, 54, 32, 20, 50, 14, 56, 56, 42, 50, 56, 56, 58, 58, 40, 58, 10, 46, 60, 60, 48, 26, 60, 60, 44, 24, 26, 24, 48, 42, 62, 62, 44, 48, 62, 48, 64, 64, 50, 42, 64, 20, 22, 22, 24, 64, 22, 26, 28, 28, 30, 28, 46, 44, 66, 66, 54, 46, 66, 66, 36, 62, 38 ], + "width": 98, + "height": 180 + } + } + } + } +], +"events": { + "footstep": {} +}, +"animations": { + "aim": { + "slots": { + "crosshair": { + "attachment": [ + { "name": "crosshair" } + ] + } + }, + "bones": { + "front-fist": { + "rotate": [ + { "value": 36.08 } + ] + }, + "rear-bracer": { + "rotate": [ + { "value": -26.55 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { "value": 62.31 } + ] + }, + "front-bracer": { + "rotate": [ + { "value": 9.11 } + ] + }, + "gun": { + "rotate": [ + { "value": -0.31 } + ] + } + }, + "ik": { + "aim-ik": [ + { "mix": 0.995 } + ] + }, + "transform": { + "aim-front-arm-transform": [ + { "mixRotate": 0.784, "mixX": 0, "mixScaleX": 0, "mixShearY": 0 } + ], + "aim-head-transform": [ + { "mixRotate": 0.659, "mixX": 0, "mixScaleX": 0, "mixShearY": 0 } + ], + "aim-torso-transform": [ + { "mixRotate": 0.423, "mixX": 0, "mixScaleX": 0, "mixShearY": 0 } + ] + } + }, + "death": { + "slots": { + "eye": { + "attachment": [ + { "name": "eye-surprised" }, + { "time": 0.5333, "name": "eye-indifferent" }, + { "time": 2.2, "name": "eye-surprised" }, + { "time": 4.6, "name": "eye-indifferent" } + ] + }, + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + }, + "mouth": { + "attachment": [ + { "name": "mouth-oooo" }, + { "time": 0.5333, "name": "mouth-grind" }, + { "time": 1.4, "name": "mouth-oooo" }, + { "time": 2.1667, "name": "mouth-grind" }, + { "time": 4.5333, "name": "mouth-oooo" } + ] + } + }, + "bones": { + "head": { + "rotate": [ + { + "value": -2.83, + "curve": [ 0.015, -2.83, 0.036, 12.72 ] + }, + { + "time": 0.0667, + "value": 12.19, + "curve": [ 0.096, 11.68, 0.119, -1.14 ] + }, + { + "time": 0.1333, + "value": -6.86, + "curve": [ 0.149, -13.27, 0.21, -37.28 ] + }, + { + "time": 0.3, + "value": -36.86, + "curve": [ 0.354, -36.61, 0.412, -32.35 ] + }, + { + "time": 0.4667, + "value": -23.49, + "curve": [ 0.49, -19.87, 0.512, -3.29 ] + }, + { + "time": 0.5333, + "value": -3.24, + "curve": [ 0.56, -3.39, 0.614, -67.25 ] + }, + { + "time": 0.6333, + "value": -74.4, + "curve": [ 0.652, -81.58, 0.702, -88.94 ] + }, + { + "time": 0.7333, + "value": -88.93, + "curve": [ 0.805, -88.91, 0.838, -80.87 ] + }, + { + "time": 0.8667, + "value": -81.03, + "curve": [ 0.922, -81.32, 0.976, -85.29 ] + }, + { "time": 1, "value": -85.29, "curve": "stepped" }, + { + "time": 2.2333, + "value": -85.29, + "curve": [ 2.314, -85.29, 2.382, -68.06 ] + }, + { + "time": 2.4667, + "value": -63.48, + "curve": [ 2.57, -57.87, 2.916, -55.24 ] + }, + { + "time": 3.2, + "value": -55.1, + "curve": [ 3.447, -54.98, 4.135, -56.61 ] + }, + { + "time": 4.2667, + "value": -58.23, + "curve": [ 4.672, -63.24, 4.646, -82.69 ] + }, + { "time": 4.9333, "value": -85.29 } + ], + "scale": [ + { + "time": 0.4667, + "curve": [ 0.469, 1.005, 0.492, 1.065, 0.475, 1.018, 0.492, 0.94 ] + }, + { + "time": 0.5, + "x": 1.065, + "y": 0.94, + "curve": [ 0.517, 1.065, 0.541, 0.991, 0.517, 0.94, 0.542, 1.026 ] + }, + { + "time": 0.5667, + "x": 0.99, + "y": 1.025, + "curve": [ 0.593, 0.988, 0.609, 1.002, 0.595, 1.024, 0.607, 1.001 ] + }, + { "time": 0.6333 } + ] + }, + "neck": { + "rotate": [ + { + "value": -2.83, + "curve": [ 0.114, 1.33, 0.195, 4.13 ] + }, + { + "time": 0.2667, + "value": 4.13, + "curve": [ 0.351, 4.14, 0.444, -24.5 ] + }, + { + "time": 0.5, + "value": -24.69, + "curve": [ 0.571, -23.89, 0.55, 34.22 ] + }, + { + "time": 0.6667, + "value": 35.13, + "curve": [ 0.713, 34.81, 0.756, 22.76 ] + }, + { + "time": 0.8333, + "value": 22.82, + "curve": [ 0.868, 22.84, 0.916, 47.95 ] + }, + { "time": 0.9667, "value": 47.95, "curve": "stepped" }, + { + "time": 2.2333, + "value": 47.95, + "curve": [ 2.3, 47.95, 2.617, 18.72 ] + }, + { + "time": 2.6667, + "value": 18.51, + "curve": [ 3.172, 16.58, 4.06, 16.79 ] + }, + { + "time": 4.5333, + "value": 18.51, + "curve": [ 4.707, 19.13, 4.776, 41.11 ] + }, + { "time": 4.8, "value": 47.95 } + ] + }, + "torso": { + "rotate": [ + { + "value": -8.62, + "curve": [ 0.01, -16.71, 0.032, -33.6 ] + }, + { + "time": 0.0667, + "value": -33.37, + "curve": [ 0.182, -32.61, 0.298, 123.07 ] + }, + { + "time": 0.4667, + "value": 122.77, + "curve": [ 0.511, 122.69, 0.52, 100.2 ] + }, + { + "time": 0.5667, + "value": 88.96, + "curve": [ 0.588, 83.89, 0.667, 75.34 ] + }, + { + "time": 0.7, + "value": 75.34, + "curve": [ 0.767, 75.34, 0.9, 76.03 ] + }, + { "time": 0.9667, "value": 76.03 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -38.86, + "curve": [ 0.022, -40.38, 0.096, -41.92 ] + }, + { + "time": 0.1333, + "value": -41.92, + "curve": [ 0.176, -41.92, 0.216, -16.92 ] + }, + { + "time": 0.2333, + "value": -4.35, + "curve": [ 0.258, 13.69, 0.308, 60.35 ] + }, + { + "time": 0.4, + "value": 60.17, + "curve": [ 0.496, 59.98, 0.539, 33.63 ] + }, + { + "time": 0.5667, + "value": 23.06, + "curve": [ 0.595, 32.71, 0.675, 53.71 ] + }, + { + "time": 0.7333, + "value": 53.61, + "curve": [ 0.797, 53.51, 0.926, 30.98 ] + }, + { "time": 0.9333, "value": 19.57, "curve": "stepped" }, + { + "time": 1.9667, + "value": 19.57, + "curve": [ 2.245, 19.57, 2.702, 77.03 ] + }, + { + "time": 3.0667, + "value": 77.06, + "curve": [ 3.209, 77.33, 3.291, 67.99 ] + }, + { + "time": 3.4333, + "value": 67.96, + "curve": [ 3.608, 68.34, 3.729, 73.88 ] + }, + { + "time": 3.8333, + "value": 73.42, + "curve": [ 4.152, 73.91, 4.46, 71.98 ] + }, + { + "time": 4.6333, + "value": 64.77, + "curve": [ 4.688, 62.5, 4.847, 26.42 ] + }, + { "time": 4.8667, "value": 10.94 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": -44.7, + "curve": [ 0.033, -44.7, 0.12, 54.89 ] + }, + { + "time": 0.1333, + "value": 64.62, + "curve": [ 0.154, 79.18, 0.214, 79.42 ] + }, + { + "time": 0.2667, + "value": 63.4, + "curve": [ 0.293, 55.19, 0.332, 30.13 ] + }, + { + "time": 0.3667, + "value": 30.13, + "curve": [ 0.4, 30.13, 0.441, 39.87 ] + }, + { + "time": 0.4667, + "value": 55.13, + "curve": [ 0.488, 68.18, 0.52, 100.72 ] + }, + { + "time": 0.5333, + "value": 111.96, + "curve": [ 0.551, 126.88, 0.627, 185.97 ] + }, + { + "time": 0.6667, + "value": 185.97, + "curve": [ 0.692, 185.97, 0.736, 162.43 ] + }, + { + "time": 0.8, + "value": 158.01, + "curve": [ 0.9, 151.12, 1.017, 144.01 ] + }, + { "time": 1.1, "value": 144.01, "curve": "stepped" }, + { + "time": 2.3667, + "value": 144.01, + "curve": [ 2.492, 144.01, 2.742, 138.63 ] + }, + { + "time": 2.8667, + "value": 138.63, + "curve": [ 3.067, 138.63, 3.467, 138.63 ] + }, + { + "time": 3.6667, + "value": 138.63, + "curve": [ 3.883, 138.63, 4.317, 135.18 ] + }, + { + "time": 4.5333, + "value": 135.18, + "curve": [ 4.575, 135.18, 4.692, 131.59 ] + }, + { + "time": 4.7333, + "value": 131.59, + "curve": [ 4.758, 131.59, 4.517, 144.01 ] + }, + { "time": 4.8333, "value": 144.01 } + ], + "translate": [ + { + "time": 0.4667, + "curve": [ 0.517, 0, 0.617, -34.96, 0.517, 0, 0.617, -16.59 ] + }, + { "time": 0.6667, "x": -35.02, "y": -16.62 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 21.88, + "curve": [ 0.033, 21.88, 0.099, 20.44 ] + }, + { + "time": 0.1333, + "value": 9.43, + "curve": [ 0.164, -0.29, 0.162, -38.26 ] + }, + { + "time": 0.2, + "value": -38.05, + "curve": [ 0.24, -37.96, 0.228, -17.82 ] + }, + { + "time": 0.3333, + "value": -9.73, + "curve": [ 0.372, -6.76, 0.431, -0.74 ] + }, + { + "time": 0.4667, + "value": 6.47, + "curve": [ 0.489, 11.05, 0.503, 19.09 ] + }, + { + "time": 0.5333, + "value": 19.09, + "curve": [ 0.571, 19.09, 0.554, -42.67 ] + }, + { + "time": 0.6, + "value": -42.67, + "curve": [ 0.653, -42.67, 0.691, -13.8 ] + }, + { + "time": 0.7, + "value": -3.54, + "curve": [ 0.707, 3.8, 0.719, 24.94 ] + }, + { + "time": 0.8, + "value": 25.31, + "curve": [ 0.902, 24.75, 0.992, -0.34 ] + }, + { "time": 1, "value": -32.16, "curve": "stepped" }, + { + "time": 2.2333, + "value": -32.16, + "curve": [ 2.6, -32.16, 2.638, -5.3 ] + }, + { + "time": 2.7, + "value": -1.96, + "curve": [ 2.707, -1.56, 2.775, 1.67 ] + }, + { + "time": 2.8, + "value": 1.67, + "curve": [ 2.825, 1.67, 2.875, -0.39 ] + }, + { + "time": 2.9, + "value": -0.39, + "curve": [ 2.925, -0.39, 2.975, 0.26 ] + }, + { + "time": 3, + "value": 0.26, + "curve": [ 3.025, 0.26, 3.075, -1.81 ] + }, + { + "time": 3.1, + "value": -1.81, + "curve": [ 3.125, -1.81, 3.175, -0.52 ] + }, + { + "time": 3.2, + "value": -0.52, + "curve": [ 3.225, -0.52, 3.275, -2.41 ] + }, + { + "time": 3.3, + "value": -2.41, + "curve": [ 3.333, -2.41, 3.4, -0.38 ] + }, + { + "time": 3.4333, + "value": -0.38, + "curve": [ 3.467, -0.38, 3.533, -2.25 ] + }, + { + "time": 3.5667, + "value": -2.25, + "curve": [ 3.592, -2.25, 3.642, -0.33 ] + }, + { + "time": 3.6667, + "value": -0.33, + "curve": [ 3.7, -0.33, 3.767, -1.34 ] + }, + { + "time": 3.8, + "value": -1.34, + "curve": [ 3.825, -1.34, 3.862, -0.77 ] + }, + { + "time": 3.9, + "value": -0.77, + "curve": [ 3.942, -0.77, 3.991, -1.48 ] + }, + { + "time": 4, + "value": -1.87, + "curve": [ 4.167, -1.87, 4.5, -1.96 ] + }, + { + "time": 4.6667, + "value": -1.96, + "curve": [ 4.709, 18.05, 4.767, 34.55 ] + }, + { + "time": 4.8, + "value": 34.55, + "curve": [ 4.84, 34.24, 4.902, 12.03 ] + }, + { "time": 4.9333, "value": -18.75 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -2.33, + "curve": [ 0.019, 4.43, 0.069, 10.82 ] + }, + { + "time": 0.1, + "value": 10.6, + "curve": [ 0.148, 10.6, 0.123, -15.24 ] + }, + { + "time": 0.2, + "value": -15.35, + "curve": [ 0.266, -15.44, 0.316, -6.48 ] + }, + { + "time": 0.3333, + "value": -3.9, + "curve": [ 0.362, 0.43, 0.479, 22.36 ] + }, + { + "time": 0.5667, + "value": 22.01, + "curve": [ 0.61, 21.84, 0.627, 12.85 ] + }, + { + "time": 0.6333, + "value": 9.05, + "curve": [ 0.643, 2.77, 0.622, -39.43 ] + }, + { + "time": 0.7, + "value": -39.5, + "curve": [ 0.773, -39.57, 0.814, 14.77 ] + }, + { + "time": 0.8667, + "value": 14.81, + "curve": [ 0.965, 14.88, 1.1, 5.64 ] + }, + { "time": 1.1, "value": -6.08, "curve": "stepped" }, + { + "time": 2.2333, + "value": -6.08, + "curve": [ 2.307, -6.08, 2.427, -25.89 ] + }, + { + "time": 2.5333, + "value": -22.42, + "curve": [ 2.598, -20.38, 2.657, 5.73 ] + }, + { + "time": 2.7, + "value": 5.73, + "curve": [ 2.77, 5.73, 2.851, -5.38 ] + }, + { + "time": 2.9333, + "value": -5.38, + "curve": [ 3.008, -5.38, 3.087, -4.54 ] + }, + { + "time": 3.1667, + "value": -4.17, + "curve": [ 3.223, -3.91, 4.486, 5.73 ] + }, + { + "time": 4.6667, + "value": 5.73, + "curve": [ 4.733, 5.73, 4.886, -2.47 ] + }, + { "time": 4.9333, "value": -6.52 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 10.36, + "curve": [ 0.033, 10.36, 0.1, -32.89 ] + }, + { + "time": 0.1333, + "value": -32.89, + "curve": [ 0.183, -32.89, 0.283, -4.45 ] + }, + { + "time": 0.3333, + "value": -4.45, + "curve": [ 0.367, -4.45, 0.438, -6.86 ] + }, + { + "time": 0.4667, + "value": -8.99, + "curve": [ 0.529, -13.62, 0.605, -20.58 ] + }, + { + "time": 0.6333, + "value": -23.2, + "curve": [ 0.708, -30.18, 0.758, -35.56 ] + }, + { + "time": 0.8, + "value": -35.56, + "curve": [ 0.875, -35.56, 1.025, -23.2 ] + }, + { "time": 1.1, "value": -23.2 } + ] + }, + "gun": { + "rotate": [ + { + "value": -2.79, + "curve": [ 0.033, -2.79, 0.12, -7.22 ] + }, + { + "time": 0.1333, + "value": -8.52, + "curve": [ 0.168, -11.87, 0.29, -23.71 ] + }, + { + "time": 0.3333, + "value": -26.24, + "curve": [ 0.369, -28.31, 0.436, -29.75 ] + }, + { + "time": 0.5, + "value": -29.66, + "curve": [ 0.552, -29.58, 0.611, -25.47 ] + }, + { + "time": 0.6333, + "value": -22.68, + "curve": [ 0.656, -19.76, 0.68, -10.02 ] + }, + { + "time": 0.7, + "value": -6.49, + "curve": [ 0.722, -2.6, 0.75, -1.22 ] + }, + { + "time": 0.7667, + "value": -1.35, + "curve": [ 0.792, -1.55, 0.842, -19.74 ] + }, + { "time": 0.8667, "value": -19.8 } + ] + }, + "hip": { + "translate": [ + { + "curve": [ 0.098, -42.62, 0.166, -79.85, 0.029, 84.97, 0.109, 155.93 ] + }, + { + "time": 0.2667, + "x": -133.79, + "y": 152.44, + "curve": [ 0.361, -184.63, 0.392, -203.69, 0.42, 149.12, 0.467, -15.7 ] + }, + { + "time": 0.4667, + "x": -230.02, + "y": -113.87, + "curve": [ 0.523, -249.86, 0.565, -261.7, 0.473, -133.1, 0.583, -203.43 ] + }, + { + "time": 0.6, + "x": -268.57, + "y": -203.43, + "curve": [ 0.663, -280.98, 0.816, -290.05, 0.708, -203.43, 0.892, -203.5 ] + }, + { "time": 1, "x": -290.42, "y": -203.5 } + ] + }, + "front-thigh": { + "rotate": [ + { + "curve": [ 0.06, 1.02, 0.151, 45.23 ] + }, + { + "time": 0.1667, + "value": 54.01, + "curve": [ 0.19, 66.85, 0.358, 169.85 ] + }, + { + "time": 0.5, + "value": 169.51, + "curve": [ 0.628, 169.85, 0.692, 108.85 ] + }, + { + "time": 0.7, + "value": 97.74, + "curve": [ 0.723, 102.6, 0.805, 111.6 ] + }, + { + "time": 0.8667, + "value": 111.69, + "curve": [ 0.899, 111.83, 1.015, 109.15 ] + }, + { "time": 1.0667, "value": 95.8 } + ] + }, + "front-shin": { + "rotate": [ + { + "curve": [ 0.086, -0.02, 0.191, -24.25 ] + }, + { + "time": 0.2, + "value": -26.5, + "curve": [ 0.214, -29.92, 0.249, -40.51 ] + }, + { + "time": 0.3333, + "value": -40.57, + "curve": [ 0.431, -40.7, 0.459, -11.34 ] + }, + { + "time": 0.4667, + "value": -8.71, + "curve": [ 0.477, -5.16, 0.524, 17.13 ] + }, + { + "time": 0.6, + "value": 16.98, + "curve": [ 0.632, 17.09, 0.625, 2.76 ] + }, + { + "time": 0.6333, + "value": 2.76, + "curve": [ 0.648, 2.76, 0.653, 2.75 ] + }, + { + "time": 0.6667, + "value": 2.59, + "curve": [ 0.678, 2.39, 0.733, 2.53 ] + }, + { + "time": 0.7333, + "value": -9.43, + "curve": [ 0.745, -2.48, 0.782, 3.12 ] + }, + { + "time": 0.8, + "value": 4.28, + "curve": [ 0.832, 6.32, 0.895, 8.46 ] + }, + { + "time": 0.9333, + "value": 8.49, + "curve": [ 0.986, 8.53, 1.051, 6.38 ] + }, + { + "time": 1.0667, + "value": 2.28, + "curve": [ 1.078, 4.17, 1.103, 5.86 ] + }, + { + "time": 1.1333, + "value": 5.88, + "curve": [ 1.191, 5.93, 1.209, 4.56 ] + }, + { "time": 1.2333, "value": 2.52 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "curve": [ 0.033, 0, 0.12, 50.26 ] + }, + { + "time": 0.1333, + "value": 57.3, + "curve": [ 0.164, 73.34, 0.274, 147.18 ] + }, + { + "time": 0.3333, + "value": 147.1, + "curve": [ 0.475, 146.45, 0.583, 95.72 ] + }, + { + "time": 0.6, + "value": 79.66, + "curve": [ 0.62, 94.74, 0.732, 103.15 ] + }, + { + "time": 0.7667, + "value": 103.02, + "curve": [ 0.812, 102.85, 0.897, 95.75 ] + }, + { "time": 0.9333, "value": 83.01 } + ] + }, + "rear-shin": { + "rotate": [ + { + "curve": [ 0.021, -16.65, 0.091, -54.82 ] + }, + { + "time": 0.1667, + "value": -55.29, + "curve": [ 0.187, -55.42, 0.213, -52.52 ] + }, + { + "time": 0.2333, + "value": -45.98, + "curve": [ 0.242, -43.1, 0.311, -12.73 ] + }, + { + "time": 0.3333, + "value": -6.32, + "curve": [ 0.356, 0.13, 0.467, 24.5 ] + }, + { + "time": 0.5, + "value": 24.5, + "curve": [ 0.543, 24.5, 0.56, 3.78 ] + }, + { + "time": 0.5667, + "value": -3.53, + "curve": [ 0.585, 3.86, 0.659, 16.63 ] + }, + { + "time": 0.7, + "value": 16.56, + "curve": [ 0.782, 16.43, 0.896, 8.44 ] + }, + { + "time": 0.9333, + "value": 4.04, + "curve": [ 0.956, 6.84, 1.008, 8.41 ] + }, + { + "time": 1.0333, + "value": 8.41, + "curve": [ 1.067, 8.41, 1.122, 8.14 ] + }, + { "time": 1.1667, "value": 5.8 } + ] + }, + "rear-foot": { + "rotate": [ + { + "value": -0.28, + "curve": [ 0.033, -0.28, 0.256, -66.71 ] + }, + { + "time": 0.3667, + "value": -66.84, + "curve": [ 0.418, -66.91, 0.499, -21.79 ] + }, + { + "time": 0.6, + "value": -21.52, + "curve": [ 0.652, -21.38, 0.665, -53.96 ] + }, + { + "time": 0.7, + "value": -54.26, + "curve": [ 0.757, -53.96, 0.843, -2.07 ] + }, + { + "time": 0.9333, + "value": -1.47, + "curve": [ 0.968, -2.07, 0.975, -19.96 ] + }, + { + "time": 1, + "value": -19.96, + "curve": [ 1.025, -19.96, 1.075, -12.42 ] + }, + { + "time": 1.1, + "value": -12.42, + "curve": [ 1.133, -12.42, 1.2, -18.34 ] + }, + { "time": 1.2333, "value": -18.34 } + ] + }, + "front-foot": { + "rotate": [ + { + "curve": [ 0.008, -11.33, 0.108, -57.71 ] + }, + { + "time": 0.1333, + "value": -57.71, + "curve": [ 0.175, -57.71, 0.229, 19.73 ] + }, + { + "time": 0.3, + "value": 19.34, + "curve": [ 0.354, 19.34, 0.4, -57.76 ] + }, + { + "time": 0.4333, + "value": -57.76, + "curve": [ 0.458, -57.76, 0.511, -3.56 ] + }, + { + "time": 0.5333, + "value": 3.7, + "curve": [ 0.563, 13.29, 0.633, 15.79 ] + }, + { + "time": 0.6667, + "value": 15.79, + "curve": [ 0.7, 15.79, 0.767, -48.75 ] + }, + { + "time": 0.8, + "value": -48.75, + "curve": [ 0.842, -48.75, 0.925, 4.7 ] + }, + { + "time": 0.9667, + "value": 4.7, + "curve": [ 1, 4.7, 1.067, -22.9 ] + }, + { + "time": 1.1, + "value": -22.9, + "curve": [ 1.142, -22.9, 1.225, -13.28 ] + }, + { "time": 1.2667, "value": -13.28 } + ] + }, + "rear-foot-target": { + "rotate": [ + { "value": -0.28 } + ] + }, + "front-foot-tip": { + "rotate": [ + { + "value": -0.28, + "curve": [ 0.008, -0.28, 0.003, -66.62 ] + }, + { + "time": 0.0667, + "value": -65.75, + "curve": [ 0.166, -64.42, 0.234, 14.35 ] + }, + { + "time": 0.2667, + "value": 38.25, + "curve": [ 0.294, 57.91, 0.392, 89.79 ] + }, + { + "time": 0.4667, + "value": 90.73, + "curve": [ 0.483, 90.73, 0.55, 177.66 ] + }, + { + "time": 0.5667, + "value": 177.66, + "curve": [ 0.733, 176.24, 0.75, 11.35 ] + }, + { + "time": 0.8, + "value": 11.35, + "curve": [ 0.886, 12.29, 0.911, 47.88 ] + }, + { + "time": 0.9333, + "value": 56.77, + "curve": [ 0.967, 70.59, 1.05, 86.46 ] + }, + { + "time": 1.1, + "value": 86.46, + "curve": [ 1.187, 86.46, 1.214, 66.44 ] + }, + { "time": 1.3333, "value": 64.55 } + ] + }, + "back-foot-tip": { + "rotate": [ + { + "value": -0.28, + "curve": [ 0, -7.97, 0.027, -18.69 ] + }, + { + "time": 0.0667, + "value": -19, + "curve": [ 0.166, -19.3, 0.208, 15.58 ] + }, + { + "time": 0.2667, + "value": 45.95, + "curve": [ 0.306, 66.24, 0.378, 99.08 ] + }, + { + "time": 0.4333, + "value": 99.08, + "curve": [ 0.497, 98.62, 0.488, -1.2 ] + }, + { + "time": 0.5667, + "value": -1.32, + "curve": [ 0.637, -0.84, 0.687, 94.41 ] + }, + { + "time": 0.7333, + "value": 94.33, + "curve": [ 0.832, 94.16, 0.895, 29.6 ] + }, + { + "time": 0.9667, + "value": 28.67, + "curve": [ 1.026, 28.67, 1.045, 53.14 ] + }, + { "time": 1.1, "value": 53.38 } + ] + }, + "hair4": { + "rotate": [ + { + "curve": [ 0.011, 4.5, 0.05, 11.42 ] + }, + { + "time": 0.0667, + "value": 11.42, + "curve": [ 0.1, 11.42, 0.136, -5.92 ] + }, + { + "time": 0.1667, + "value": -10.54, + "curve": [ 0.206, -16.51, 0.327, -22 ] + }, + { + "time": 0.3667, + "value": -24.47, + "curve": [ 0.413, -27.37, 0.467, -43.99 ] + }, + { + "time": 0.5, + "value": -43.99, + "curve": [ 0.533, -43.99, 0.552, 12.12 ] + }, + { + "time": 0.6333, + "value": 11.85, + "curve": [ 0.714, 11.59, 0.758, -34.13 ] + }, + { + "time": 0.8, + "value": -34.13, + "curve": [ 0.858, -34.13, 1.015, -12.47 ] + }, + { + "time": 1.0667, + "value": -8.85, + "curve": [ 1.121, -5.07, 1.219, -0.02 ] + }, + { + "time": 1.3333, + "value": 1.29, + "curve": [ 1.509, 3.3, 1.763, 2.75 ] + }, + { + "time": 1.8667, + "value": 2.78, + "curve": [ 1.974, 2.81, 2.108, 2.81 ] + }, + { + "time": 2.2, + "value": 2.78, + "curve": [ 2.315, 2.74, 2.374, 1.22 ] + }, + { + "time": 2.4667, + "value": 1.18, + "curve": [ 2.525, 1.18, 2.608, 10.79 ] + }, + { + "time": 2.6667, + "value": 10.79, + "curve": [ 2.725, 10.79, 2.893, 4.72 ] + }, + { + "time": 3.0333, + "value": 4.72, + "curve": [ 3.117, 4.72, 3.283, 7.93 ] + }, + { + "time": 3.3667, + "value": 7.93, + "curve": [ 3.492, 7.93, 3.775, 6.93 ] + }, + { + "time": 3.9, + "value": 6.93, + "curve": [ 3.981, 6.93, 4.094, 6.9 ] + }, + { + "time": 4.2, + "value": 8.44, + "curve": [ 4.267, 9.42, 4.401, 16.61 ] + }, + { + "time": 4.5, + "value": 16.33, + "curve": [ 4.582, 16.12, 4.709, 9.94 ] + }, + { + "time": 4.7333, + "value": 6.51, + "curve": [ 4.747, 4.57, 4.779, -1.76 ] + }, + { + "time": 4.8, + "value": -1.75, + "curve": [ 4.823, -1.73, 4.82, 4.47 ] + }, + { + "time": 4.8667, + "value": 6.04, + "curve": [ 4.899, 7.14, 4.913, 6.93 ] + }, + { "time": 4.9333, "value": 6.93 } + ] + }, + "hair2": { + "rotate": [ + { + "value": 10.61, + "curve": [ 0.075, 10.61, 0.05, 12.67 ] + }, + { + "time": 0.0667, + "value": 12.67, + "curve": [ 0.123, 12.67, 0.194, -16.51 ] + }, + { + "time": 0.2, + "value": -19.87, + "curve": [ 0.207, -23.48, 0.236, -31.68 ] + }, + { + "time": 0.3, + "value": -31.8, + "curve": [ 0.356, -31.9, 0.437, -25.61 ] + }, + { + "time": 0.4667, + "value": -19.29, + "curve": [ 0.485, -15.33, 0.529, 6.48 ] + }, + { + "time": 0.5667, + "value": 6.67, + "curve": [ 0.628, 6.97, 0.65, -46.39 ] + }, + { + "time": 0.7333, + "value": -46.3, + "curve": [ 0.843, -46.17, 0.941, -33.37 ] + }, + { + "time": 0.9667, + "value": -23.17, + "curve": [ 0.972, -20.98, 1.047, 15.21 ] + }, + { + "time": 1.1, + "value": 15.21, + "curve": [ 1.142, 15.21, 1.183, 10.73 ] + }, + { + "time": 1.2667, + "value": 10.61, + "curve": [ 1.45, 10.34, 1.817, 10.61 ] + }, + { + "time": 2, + "value": 10.61, + "curve": [ 2.075, 10.61, 2.225, 16.9 ] + }, + { + "time": 2.3, + "value": 16.9, + "curve": [ 2.327, 16.9, 2.347, 6.81 ] + }, + { + "time": 2.4, + "value": 6.83, + "curve": [ 2.492, 6.87, 2.602, 17.39 ] + }, + { + "time": 2.6667, + "value": 17.39, + "curve": [ 2.742, 17.39, 2.892, 10.67 ] + }, + { + "time": 2.9667, + "value": 10.64, + "curve": [ 3.187, 10.57, 3.344, 10.73 ] + }, + { + "time": 3.6, + "value": 11.4, + "curve": [ 3.766, 11.83, 3.874, 14.87 ] + }, + { + "time": 3.9333, + "value": 14.83, + "curve": [ 4.022, 14.76, 4.208, 9.49 ] + }, + { + "time": 4.3, + "value": 9.54, + "curve": [ 4.391, 9.58, 4.441, 14.82 ] + }, + { + "time": 4.5333, + "value": 14.84, + "curve": [ 4.642, 14.88, 4.692, 1.17 ] + }, + { + "time": 4.7667, + "value": 1.24, + "curve": [ 4.823, 1.3, 4.818, 18.35 ] + }, + { + "time": 4.8667, + "value": 18.38, + "curve": [ 4.905, 18.41, 4.901, 10.61 ] + }, + { "time": 4.9333, "value": 10.61 } + ] + }, + "torso2": { + "rotate": [ + { + "curve": [ 0.048, 0, 0.129, -12.73 ] + }, + { + "time": 0.1667, + "value": -15.95, + "curve": [ 0.221, -20.66, 0.254, -21.62 ] + }, + { + "time": 0.3, + "value": -21.59, + "curve": [ 0.458, -21.46, 0.46, -1.67 ] + }, + { + "time": 0.6333, + "value": -1.71, + "curve": [ 0.71, -1.73, 0.715, -4 ] + }, + { + "time": 0.7667, + "value": -3.97, + "curve": [ 0.866, -3.92, 0.84, 0.02 ] + }, + { "time": 1, "curve": "stepped" }, + { + "time": 2, + "curve": [ 2.275, 0, 2.867, -5.8 ] + }, + { + "time": 3.1, + "value": -6.44, + "curve": [ 3.327, -7.06, 3.71, -6.23 ] + }, + { + "time": 3.9333, + "value": -5.41, + "curve": [ 4.168, -4.53, 4.488, -2.83 ] + }, + { "time": 4.8 } + ] + }, + "torso3": { + "rotate": [ + { + "curve": [ 0.025, 0, 0.09, -3.66 ] + }, + { + "time": 0.1, + "value": -4.55, + "curve": [ 0.143, -8.4, 0.223, -17.07 ] + }, + { + "time": 0.2333, + "value": -18.31, + "curve": [ 0.282, -24.44, 0.35, -29 ] + }, + { + "time": 0.3667, + "value": -30.07, + "curve": [ 0.405, -32.58, 0.442, -33.03 ] + }, + { + "time": 0.4667, + "value": -32.99, + "curve": [ 0.491, -33.04, 0.505, -23.56 ] + }, + { + "time": 0.5333, + "value": -23.55, + "curve": [ 0.571, -23.67, 0.599, -27.21 ] + }, + { + "time": 0.6333, + "value": -27.21, + "curve": [ 0.669, -27.2, 0.742, -10.43 ] + }, + { + "time": 0.7667, + "value": -7.79, + "curve": [ 0.788, -5.53, 0.796, -4.42 ] + }, + { + "time": 0.8333, + "value": -2.9, + "curve": [ 0.875, -1.21, 0.933, 0 ] + }, + { "time": 0.9667, "curve": "stepped" }, + { + "time": 2.4333, + "curve": [ 2.517, 0, 2.683, 4.63 ] + }, + { + "time": 2.7667, + "value": 4.66, + "curve": [ 3.084, 4.76, 3.248, 4.37 ] + }, + { + "time": 3.4, + "value": 3.74, + "curve": [ 3.596, 2.92, 3.755, 2.18 ] + }, + { + "time": 3.8667, + "value": 1.72, + "curve": [ 4.136, 0.59, 4.471, 0 ] + }, + { "time": 4.8 } + ] + }, + "hair3": { + "rotate": [ + { + "curve": [ 0, 0, 0.041, 10.74 ] + }, + { + "time": 0.0667, + "value": 14.16, + "curve": [ 0.075, 15.22, 0.148, 18.04 ] + }, + { + "time": 0.2, + "value": 18.13, + "curve": [ 0.251, 18.23, 0.307, -4.75 ] + }, + { + "time": 0.3667, + "value": -5.06, + "curve": [ 0.412, -5.3, 0.47, -0.96 ] + }, + { + "time": 0.5, + "value": 2.21, + "curve": [ 0.512, 3.48, 0.595, 20.31 ] + }, + { + "time": 0.6333, + "value": 24.87, + "curve": [ 0.647, 26.53, 0.719, 29.33 ] + }, + { + "time": 0.8, + "value": 29.22, + "curve": [ 0.859, 29.14, 0.9, 28.48 ] + }, + { + "time": 0.9333, + "value": 26.11, + "curve": [ 0.981, 22.72, 0.998, 2.06 ] + }, + { "time": 1.1, "value": 2.21 } + ] + }, + "hair1": { + "rotate": [ + { + "curve": [ 0.047, -0.21, 0.048, 7.86 ] + }, + { + "time": 0.0667, + "value": 13.27, + "curve": [ 0.083, 18.05, 0.135, 24.44 ] + }, + { + "time": 0.2, + "value": 24.02, + "curve": [ 0.225, 24.02, 0.28, 6.32 ] + }, + { + "time": 0.3, + "value": 3.1, + "curve": [ 0.323, -0.58, 0.382, -7.12 ] + }, + { + "time": 0.4667, + "value": -7.45, + "curve": [ 0.512, -7.66, 0.538, 12.13 ] + }, + { + "time": 0.5667, + "value": 16.46, + "curve": [ 0.609, 22.72, 0.672, 27.4 ] + }, + { + "time": 0.7333, + "value": 27.55, + "curve": [ 0.827, 27.4, 0.933, 23.23 ] + }, + { + "time": 0.9667, + "value": 19.11, + "curve": [ 0.998, 15.27, 1.092, -2.53 ] + }, + { + "time": 1.1333, + "value": -2.53, + "curve": [ 1.158, -2.53, 1.208, 0 ] + }, + { "time": 1.2333, "curve": "stepped" }, + { + "time": 2, + "curve": [ 2.075, 0, 2.248, 0.35 ] + }, + { + "time": 2.3333, + "value": 0.78, + "curve": [ 2.585, 2.06, 2.805, 3.46 ] + }, + { + "time": 3.2, + "value": 3.5, + "curve": [ 3.593, 3.54, 3.979, 2.36 ] + }, + { + "time": 4.1667, + "value": 1.55, + "curve": [ 4.391, 0.59, 4.447, 0.04 ] + }, + { + "time": 4.6, + "value": 0.04, + "curve": [ 4.642, 0.04, 4.742, 0 ] + }, + { "time": 4.9333 } + ] + }, + "head-control": { + "translate": [ + { + "curve": [ 0.025, 0, 0.09, 1.43, 0.025, 0, 0.075, -34.76 ] + }, + { + "time": 0.1, + "x": 1.59, + "y": -34.76, + "curve": [ 0.214, 3.33, 0.375, 5.34, 0.192, -34.76, 0.441, -21.17 ] + }, + { + "time": 0.4667, + "x": 5.34, + "y": -12.57, + "curve": [ 0.492, 5.34, 0.55, 5.24, 0.482, -7.36, 0.504, 4.03 ] + }, + { + "time": 0.5667, + "x": 5.11, + "y": 4.01, + "curve": [ 0.658, 4.45, 0.679, 3.19, 0.649, 3.98, 0.642, -16.84 ] + }, + { + "time": 0.7, + "x": 2.8, + "y": -16.74, + "curve": [ 0.787, 1.15, 0.881, -1.29, 0.772, -16.62, 0.82, 8.95 ] + }, + { + "time": 0.9, + "x": -1.72, + "y": 8.91, + "curve": [ 0.961, -3.06, 1.025, -3.58, 0.975, 8.87, 0.951, -1.37 ] + }, + { + "time": 1.1, + "x": -3.58, + "y": -1.45, + "curve": [ 1.292, -3.58, 2.002, -2.4, 1.292, -1.56, 1.975, -1.45 ] + }, + { + "time": 2.1667, + "x": -1.39, + "y": -1.45, + "curve": [ 2.25, -0.88, 2.503, 1.38, 2.283, -1.45, 2.603, -12.44 ] + }, + { + "time": 2.6667, + "x": 2.13, + "y": -14.45, + "curve": [ 2.766, 2.59, 2.999, 2.81, 2.835, -19.73, 3.003, -25.2 ] + }, + { + "time": 3.1333, + "x": 2.91, + "y": -26.08, + "curve": [ 3.392, 3.1, 4.199, 4.05, 3.483, -28.44, 4.129, -27.23 ] + }, + { + "time": 4.3667, + "x": 4.81, + "y": -19.59, + "curve": [ 4.429, 5.1, 4.594, 8.54, 4.538, -14.08, 4.583, -7.88 ] + }, + { + "time": 4.6667, + "x": 8.65, + "y": -4.56, + "curve": [ 4.794, 8.86, 4.806, 5.93, 4.691, -3.59, 4.8, -1.61 ] + }, + { "time": 4.9333, "x": 5.8, "y": -1.99 } + ] + } + }, + "ik": { + "front-foot-ik": [ + { "mix": 0 } + ], + "front-leg-ik": [ + { "mix": 0, "bendPositive": false } + ], + "rear-foot-ik": [ + { "mix": 0.005 } + ], + "rear-leg-ik": [ + { "mix": 0.005, "bendPositive": false } + ] + } + }, + "hoverboard": { + "slots": { + "exhaust1": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "exhaust2": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "exhaust3": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + }, + "hoverboard-board": { + "attachment": [ + { "name": "hoverboard-board" } + ] + }, + "hoverboard-thruster-front": { + "attachment": [ + { "name": "hoverboard-thruster" } + ] + }, + "hoverboard-thruster-rear": { + "attachment": [ + { "name": "hoverboard-thruster" } + ] + }, + "hoverglow-front": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "hoverglow-rear": { + "attachment": [ + { "name": "hoverglow-small" } + ] + }, + "side-glow1": { + "attachment": [ + { "name": "hoverglow-small" }, + { "time": 0.9667 } + ] + }, + "side-glow2": { + "attachment": [ + { "time": 0.0667, "name": "hoverglow-small" }, + { "time": 1 } + ] + }, + "side-glow3": { + "attachment": [ + { "name": "hoverglow-small" }, + { "time": 0.9667 } + ] + } + }, + "bones": { + "hoverboard-controller": { + "translate": [ + { + "x": 319.55, + "y": -1.59, + "curve": [ 0.064, 319.55, 0.2, 347.85, 0.058, -1.2, 0.2, 23.11 ] + }, + { + "time": 0.2667, + "x": 347.66, + "y": 39.62, + "curve": [ 0.35, 347.41, 0.476, 341.47, 0.323, 53.58, 0.44, 85.82 ] + }, + { + "time": 0.5333, + "x": 338.47, + "y": 85.72, + "curve": [ 0.603, 334.83, 0.913, 319.65, 0.621, 85.62, 0.88, -1.53 ] + }, + { "time": 1, "x": 319.55, "y": -1.59 } + ] + }, + "hip": { + "translate": [ + { + "x": -53.49, + "y": 32.14, + "curve": [ 0.061, -53.77, 0.093, -51.81, 0.044, 16.34, 0.063, 9.67 ] + }, + { + "time": 0.1333, + "x": -49.31, + "y": 7.01, + "curve": [ 0.3, -35.27, 0.461, -20.06, 0.314, 9.52, 0.408, 121.09 ] + }, + { + "time": 0.5667, + "x": -20.06, + "y": 122.72, + "curve": [ 0.716, -20.09, 0.912, -53.29, 0.753, 121.8, 0.946, 51.85 ] + }, + { "time": 1, "x": -53.49, "y": 32.14 } + ] + }, + "exhaust1": { + "scale": [ + { + "x": 1.593, + "y": 0.964, + "curve": [ 0.033, 1.593, 0.1, 1, 0.033, 0.964, 0.1, 0.713 ] + }, + { + "time": 0.1333, + "y": 0.713, + "curve": [ 0.15, 1, 0.183, 1.774, 0.15, 0.713, 0.183, 0.883 ] + }, + { + "time": 0.2, + "x": 1.774, + "y": 0.883, + "curve": [ 0.242, 1.774, 0.325, 1.181, 0.242, 0.883, 0.325, 0.649 ] + }, + { + "time": 0.3667, + "x": 1.181, + "y": 0.649, + "curve": [ 0.408, 1.181, 0.492, 1.893, 0.408, 0.649, 0.492, 0.819 ] + }, + { + "time": 0.5333, + "x": 1.893, + "y": 0.819, + "curve": [ 0.558, 1.893, 0.608, 1.18, 0.558, 0.819, 0.608, 0.686 ] + }, + { + "time": 0.6333, + "x": 1.18, + "y": 0.686, + "curve": [ 0.658, 1.18, 0.708, 1.903, 0.658, 0.686, 0.708, 0.855 ] + }, + { + "time": 0.7333, + "x": 1.903, + "y": 0.855, + "curve": [ 0.767, 1.903, 0.833, 1.311, 0.767, 0.855, 0.833, 0.622 ] + }, + { + "time": 0.8667, + "x": 1.311, + "y": 0.622, + "curve": [ 0.9, 1.311, 0.967, 1.593, 0.9, 0.622, 0.967, 0.964 ] + }, + { "time": 1, "x": 1.593, "y": 0.964 } + ] + }, + "exhaust2": { + "scale": [ + { + "x": 1.88, + "y": 0.832, + "curve": [ 0.025, 1.88, 0.075, 1.311, 0.025, 0.832, 0.075, 0.686 ] + }, + { + "time": 0.1, + "x": 1.311, + "y": 0.686, + "curve": [ 0.133, 1.311, 0.2, 2.01, 0.133, 0.686, 0.208, 0.736 ] + }, + { + "time": 0.2333, + "x": 2.01, + "y": 0.769, + "curve": [ 0.267, 2.01, 0.333, 1, 0.282, 0.831, 0.333, 0.91 ] + }, + { + "time": 0.3667, + "y": 0.91, + "curve": [ 0.4, 1, 0.467, 1.699, 0.4, 0.91, 0.474, 0.891 ] + }, + { + "time": 0.5, + "x": 1.699, + "y": 0.86, + "curve": [ 0.517, 1.699, 0.55, 1.181, 0.54, 0.813, 0.55, 0.713 ] + }, + { + "time": 0.5667, + "x": 1.181, + "y": 0.713, + "curve": [ 0.617, 1.181, 0.717, 1.881, 0.617, 0.713, 0.717, 0.796 ] + }, + { + "time": 0.7667, + "x": 1.881, + "y": 0.796, + "curve": [ 0.8, 1.881, 0.867, 1.3, 0.8, 0.796, 0.867, 0.649 ] + }, + { + "time": 0.9, + "x": 1.3, + "y": 0.649, + "curve": [ 0.925, 1.3, 0.975, 1.88, 0.925, 0.649, 0.975, 0.832 ] + }, + { "time": 1, "x": 1.88, "y": 0.832 } + ] + }, + "hoverboard-thruster-front": { + "rotate": [ + { + "curve": [ 0.125, 0, 0.375, 24.06 ] + }, + { + "time": 0.5, + "value": 24.06, + "curve": [ 0.625, 24.06, 0.875, 0 ] + }, + { "time": 1 } + ] + }, + "hoverglow-front": { + "scale": [ + { + "x": 0.849, + "y": 1.764, + "curve": [ 0.017, 0.849, 0.05, 0.835, 0.017, 1.764, 0.05, 2.033 ] + }, + { + "time": 0.0667, + "x": 0.835, + "y": 2.033, + "curve": [ 0.092, 0.835, 0.142, 0.752, 0.092, 2.033, 0.142, 1.584 ] + }, + { + "time": 0.1667, + "x": 0.752, + "y": 1.584, + "curve": [ 0.183, 0.752, 0.217, 0.809, 0.183, 1.584, 0.217, 1.71 ] + }, + { + "time": 0.2333, + "x": 0.809, + "y": 1.71, + "curve": [ 0.25, 0.809, 0.283, 0.717, 0.25, 1.71, 0.283, 1.45 ] + }, + { + "time": 0.3, + "x": 0.717, + "y": 1.45, + "curve": [ 0.317, 0.717, 0.35, 0.777, 0.317, 1.45, 0.35, 1.698 ] + }, + { + "time": 0.3667, + "x": 0.777, + "y": 1.698, + "curve": [ 0.4, 0.781, 0.45, 0.685, 0.375, 1.698, 0.45, 1.173 ] + }, + { + "time": 0.4667, + "x": 0.685, + "y": 1.173, + "curve": [ 0.492, 0.685, 0.542, 0.825, 0.492, 1.173, 0.542, 1.572 ] + }, + { + "time": 0.5667, + "x": 0.825, + "y": 1.572, + "curve": [ 0.611, 0.816, 0.63, 0.727, 0.611, 1.577, 0.606, 1.255 ] + }, + { + "time": 0.6667, + "x": 0.725, + "y": 1.241, + "curve": [ 0.692, 0.725, 0.742, 0.895, 0.692, 1.241, 0.749, 1.799 ] + }, + { + "time": 0.7667, + "x": 0.895, + "y": 1.857, + "curve": [ 0.783, 0.895, 0.796, 0.892, 0.796, 1.955, 0.817, 1.962 ] + }, + { + "time": 0.8333, + "x": 0.845, + "y": 1.962, + "curve": [ 0.845, 0.831, 0.883, 0.802, 0.85, 1.962, 0.872, 1.704 ] + }, + { + "time": 0.9, + "x": 0.802, + "y": 1.491, + "curve": [ 0.917, 0.802, 0.95, 0.845, 0.907, 1.441, 0.936, 1.508 ] + }, + { + "time": 0.9667, + "x": 0.845, + "y": 1.627, + "curve": [ 0.975, 0.845, 0.992, 0.849, 0.973, 1.652, 0.992, 1.764 ] + }, + { "time": 1, "x": 0.849, "y": 1.764 } + ] + }, + "hoverboard-thruster-rear": { + "rotate": [ + { + "curve": [ 0.125, 0, 0.375, 24.06 ] + }, + { + "time": 0.5, + "value": 24.06, + "curve": [ 0.625, 24.06, 0.875, 0 ] + }, + { "time": 1 } + ] + }, + "hoverglow-rear": { + "scale": [ + { + "x": 0.845, + "y": 1.31, + "curve": [ 0.017, 0.845, 0.117, 0.899, 0.017, 1.31, 0.117, 2.033 ] + }, + { + "time": 0.1333, + "x": 0.899, + "y": 2.033, + "curve": [ 0.15, 0.899, 0.183, 0.752, 0.15, 2.033, 0.183, 1.574 ] + }, + { + "time": 0.2, + "x": 0.752, + "y": 1.574, + "curve": [ 0.225, 0.752, 0.275, 0.809, 0.225, 1.574, 0.275, 1.71 ] + }, + { + "time": 0.3, + "x": 0.809, + "y": 1.71, + "curve": [ 0.317, 0.809, 0.35, 0.717, 0.317, 1.71, 0.35, 1.397 ] + }, + { + "time": 0.3667, + "x": 0.717, + "y": 1.397, + "curve": [ 0.383, 0.717, 0.417, 0.777, 0.383, 1.397, 0.417, 1.45 ] + }, + { + "time": 0.4333, + "x": 0.777, + "y": 1.45, + "curve": [ 0.45, 0.777, 0.496, 0.689, 0.45, 1.45, 0.481, 1.168 ] + }, + { + "time": 0.5333, + "x": 0.685, + "y": 1.173, + "curve": [ 0.565, 0.682, 0.617, 0.758, 0.575, 1.177, 0.617, 1.297 ] + }, + { + "time": 0.6333, + "x": 0.758, + "y": 1.297, + "curve": [ 0.658, 0.758, 0.708, 0.725, 0.658, 1.297, 0.708, 1.241 ] + }, + { + "time": 0.7333, + "x": 0.725, + "y": 1.241, + "curve": [ 0.772, 0.732, 0.796, 0.893, 0.782, 1.238, 0.778, 1.854 ] + }, + { + "time": 0.8333, + "x": 0.895, + "y": 1.857, + "curve": [ 0.878, 0.9, 0.992, 0.845, 0.88, 1.86, 0.992, 1.31 ] + }, + { "time": 1, "x": 0.845, "y": 1.31 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -85.92, + "curve": [ 0.08, -85.59, 0.284, -62.7 ] + }, + { + "time": 0.3667, + "value": -55.14, + "curve": [ 0.438, -48.65, 0.551, -43.21 ] + }, + { + "time": 0.6333, + "value": -43.21, + "curve": [ 0.716, -43.22, 0.908, -85.92 ] + }, + { "time": 1, "value": -85.92 } + ], + "translate": [ + { + "x": -0.59, + "y": -2.94, + "curve": [ 0.1, -1.21, 0.275, -1.74, 0.092, -2.94, 0.275, -6.39 ] + }, + { + "time": 0.3667, + "x": -1.74, + "y": -6.39, + "curve": [ 0.433, -1.74, 0.567, 0.72, 0.433, -6.39, 0.587, -4.48 ] + }, + { + "time": 0.6333, + "x": 0.72, + "y": -4.21, + "curve": [ 0.725, 0.72, 0.908, -0.08, 0.743, -3.57, 0.908, -2.94 ] + }, + { "time": 1, "x": -0.59, "y": -2.94 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": 7.61, + "curve": [ 0.143, 7.62, 0.247, -23.17 ] + }, + { + "time": 0.2667, + "value": -26.56, + "curve": [ 0.281, -29.08, 0.351, -37.36 ] + }, + { + "time": 0.4333, + "value": -37.2, + "curve": [ 0.513, -37.05, 0.562, -29.88 ] + }, + { + "time": 0.6, + "value": -25.18, + "curve": [ 0.621, -22.58, 0.694, -3.98 ] + }, + { + "time": 0.8, + "value": 3.63, + "curve": [ 0.861, 8.03, 0.946, 7.57 ] + }, + { "time": 1, "value": 7.61 } + ], + "translate": [ + { + "curve": [ 0.117, 0, 0.35, 0.52, 0.117, 0, 0.35, -3.27 ] + }, + { + "time": 0.4667, + "x": 0.52, + "y": -3.27, + "curve": [ 0.6, 0.52, 0.867, 0, 0.6, -3.27, 0.867, 0 ] + }, + { "time": 1 } + ], + "shear": [ + { + "y": 19.83, + "curve": [ 0.117, 0, 0.35, 15.28, 0.117, 19.83, 0.35, 28.31 ] + }, + { + "time": 0.4667, + "x": 15.28, + "y": 28.31, + "curve": [ 0.6, 15.28, 0.867, 0, 0.6, 28.31, 0.867, 19.83 ] + }, + { "time": 1, "y": 19.83 } + ] + }, + "board-ik": { + "translate": [ + { + "x": 393.62, + "curve": [ 0.083, 393.62, 0.25, 393.48, 0.083, 0, 0.25, 117.69 ] + }, + { + "time": 0.3333, + "x": 393.48, + "y": 117.69, + "curve": [ 0.375, 393.48, 0.458, 393.62, 0.375, 117.69, 0.458, 83.82 ] + }, + { "time": 0.5, "x": 393.62, "y": 83.82 }, + { "time": 0.6667, "x": 393.62, "y": 30.15 }, + { "time": 1, "x": 393.62 } + ] + }, + "front-thigh": { + "translate": [ + { "x": -7.49, "y": 8.51 } + ] + }, + "front-leg-target": { + "translate": [ + { + "time": 0.3667, + "curve": [ 0.428, 10.83, 0.567, 12.78, 0.414, 7.29, 0.567, 8.79 ] + }, + { + "time": 0.6, + "x": 12.78, + "y": 8.79, + "curve": [ 0.692, 12.78, 0.772, 11.27, 0.692, 8.79, 0.766, 8.62 ] + }, + { "time": 0.8667 } + ] + }, + "rear-leg-target": { + "translate": [ + { + "time": 0.4667, + "curve": [ 0.492, 0, 0.534, 4.47, 0.492, 0, 0.542, 1.63 ] + }, + { + "time": 0.5667, + "x": 4.53, + "y": 1.77, + "curve": [ 0.622, 4.64, 0.717, 3.31, 0.615, 2.06, 0.71, 2.1 ] + }, + { "time": 0.8 } + ] + }, + "exhaust3": { + "scale": [ + { + "x": 1.882, + "y": 0.81, + "curve": [ 0.017, 1.882, 0.167, 1.3, 0.017, 0.81, 0.167, 0.649 ] + }, + { + "time": 0.2, + "x": 1.3, + "y": 0.649, + "curve": [ 0.225, 1.3, 0.275, 2.051, 0.225, 0.649, 0.275, 0.984 ] + }, + { + "time": 0.3, + "x": 2.051, + "y": 0.984, + "curve": [ 0.325, 2.051, 0.375, 1.311, 0.325, 0.984, 0.384, 0.715 ] + }, + { + "time": 0.4, + "x": 1.311, + "y": 0.686, + "curve": [ 0.433, 1.311, 0.5, 1.86, 0.426, 0.638, 0.5, 0.537 ] + }, + { + "time": 0.5333, + "x": 1.86, + "y": 0.537, + "curve": [ 0.567, 1.86, 0.633, 1.187, 0.567, 0.537, 0.604, 0.854 ] + }, + { + "time": 0.6667, + "x": 1.187, + "y": 0.854, + "curve": [ 0.7, 1.187, 0.767, 1.549, 0.707, 0.854, 0.774, 0.775 ] + }, + { + "time": 0.8, + "x": 1.549, + "y": 0.746, + "curve": [ 0.817, 1.549, 0.85, 1.181, 0.815, 0.729, 0.85, 0.713 ] + }, + { + "time": 0.8667, + "x": 1.181, + "y": 0.713, + "curve": [ 0.9, 1.181, 0.967, 1.882, 0.9, 0.713, 0.967, 0.81 ] + }, + { "time": 1, "x": 1.882, "y": 0.81 } + ] + }, + "side-glow1": { + "rotate": [ + { "value": 51.12, "curve": "stepped" }, + { "time": 0.0667, "value": 43.82, "curve": "stepped" }, + { "time": 0.1, "value": 40.95, "curve": "stepped" }, + { "time": 0.1667, "value": 27.78, "curve": "stepped" }, + { "time": 0.2, "value": 10.24, "curve": "stepped" }, + { "time": 0.2667, "curve": "stepped" }, + { "time": 0.8, "value": -25.81 } + ], + "translate": [ + { "x": 338.28, "y": 40.22, "curve": "stepped" }, + { "time": 0.0667, "x": 331.2, "y": 30.39, "curve": "stepped" }, + { "time": 0.1, "x": 318.63, "y": 20.59, "curve": "stepped" }, + { "time": 0.1667, "x": 302.45, "y": 9.64, "curve": "stepped" }, + { "time": 0.2, "x": 276.87, "y": 1.13, "curve": "stepped" }, + { "time": 0.2667, "x": 248.16, "curve": "stepped" }, + { "time": 0.3, "x": 221.36, "curve": "stepped" }, + { "time": 0.3667, "x": 195.69, "curve": "stepped" }, + { "time": 0.4, "x": 171.08, "curve": "stepped" }, + { "time": 0.4667, "x": 144.84, "curve": "stepped" }, + { "time": 0.5, "x": 121.22, "curve": "stepped" }, + { "time": 0.5667, "x": 91.98, "curve": "stepped" }, + { "time": 0.6, "x": 62.63, "curve": "stepped" }, + { "time": 0.6667, "x": 30.78, "curve": "stepped" }, + { "time": 0.7, "curve": "stepped" }, + { "time": 0.7667, "x": -28.45, "curve": "stepped" }, + { "time": 0.8, "x": -67.49, "y": 16.82, "curve": "stepped" }, + { "time": 0.8667, "x": -83.07, "y": 24.36, "curve": "stepped" }, + { "time": 0.9, "x": -93.81, "y": 29.55 } + ], + "scale": [ + { "x": 0.535, "curve": "stepped" }, + { "time": 0.0667, "x": 0.594, "curve": "stepped" }, + { "time": 0.1, "x": 0.844, "curve": "stepped" }, + { "time": 0.1667, "curve": "stepped" }, + { "time": 0.8, "x": 0.534, "curve": "stepped" }, + { "time": 0.8667, "x": 0.428, "y": 0.801, "curve": "stepped" }, + { "time": 0.9, "x": 0.349, "y": 0.654 } + ] + }, + "side-glow2": { + "rotate": [ + { "time": 0.0667, "value": 51.12, "curve": "stepped" }, + { "time": 0.1, "value": 43.82, "curve": "stepped" }, + { "time": 0.1667, "value": 40.95, "curve": "stepped" }, + { "time": 0.2, "value": 27.78, "curve": "stepped" }, + { "time": 0.2667, "value": 10.24, "curve": "stepped" }, + { "time": 0.3, "curve": "stepped" }, + { "time": 0.8667, "value": -25.81 } + ], + "translate": [ + { "time": 0.0667, "x": 338.28, "y": 40.22, "curve": "stepped" }, + { "time": 0.1, "x": 331.2, "y": 30.39, "curve": "stepped" }, + { "time": 0.1667, "x": 318.63, "y": 20.59, "curve": "stepped" }, + { "time": 0.2, "x": 302.45, "y": 9.64, "curve": "stepped" }, + { "time": 0.2667, "x": 276.87, "y": 1.13, "curve": "stepped" }, + { "time": 0.3, "x": 248.16, "curve": "stepped" }, + { "time": 0.3667, "x": 221.36, "curve": "stepped" }, + { "time": 0.4, "x": 195.69, "curve": "stepped" }, + { "time": 0.4667, "x": 171.08, "curve": "stepped" }, + { "time": 0.5, "x": 144.84, "curve": "stepped" }, + { "time": 0.5667, "x": 121.22, "curve": "stepped" }, + { "time": 0.6, "x": 91.98, "curve": "stepped" }, + { "time": 0.6667, "x": 62.63, "curve": "stepped" }, + { "time": 0.7, "x": 30.78, "curve": "stepped" }, + { "time": 0.7667, "curve": "stepped" }, + { "time": 0.8, "x": -28.45, "curve": "stepped" }, + { "time": 0.8667, "x": -67.49, "y": 16.82, "curve": "stepped" }, + { "time": 0.9, "x": -83.07, "y": 24.36, "curve": "stepped" }, + { "time": 0.9667, "x": -93.81, "y": 29.55 } + ], + "scale": [ + { "time": 0.0667, "x": 0.535, "curve": "stepped" }, + { "time": 0.1, "x": 0.594, "curve": "stepped" }, + { "time": 0.1667, "x": 0.844, "curve": "stepped" }, + { "time": 0.2, "curve": "stepped" }, + { "time": 0.8667, "x": 0.534, "curve": "stepped" }, + { "time": 0.9, "x": 0.428, "y": 0.801, "curve": "stepped" }, + { "time": 0.9667, "x": 0.349, "y": 0.654 } + ] + }, + "torso": { + "rotate": [ + { + "value": -34.73, + "curve": [ 0.034, -36.31, 0.162, -39.33 ] + }, + { + "time": 0.2667, + "value": -39.37, + "curve": [ 0.384, -39.37, 0.491, -29.52 ] + }, + { + "time": 0.5, + "value": -28.86, + "curve": [ 0.525, -26.95, 0.571, -21.01 ] + }, + { + "time": 0.6333, + "value": -21.01, + "curve": [ 0.725, -21.01, 0.969, -33.35 ] + }, + { "time": 1, "value": -34.73 } + ] + }, + "neck": { + "rotate": [ + { + "value": 10.2, + "curve": [ 0.07, 12.09, 0.189, 16.03 ] + }, + { + "time": 0.2667, + "value": 16.14, + "curve": [ 0.333, 16.14, 0.449, 8.03 ] + }, + { + "time": 0.5, + "value": 5.83, + "curve": [ 0.542, 4.02, 0.6, 2.68 ] + }, + { + "time": 0.6333, + "value": 2.68, + "curve": [ 0.725, 2.68, 0.943, 8.57 ] + }, + { "time": 1, "value": 10.2 } + ] + }, + "head": { + "rotate": [ + { + "value": 10.2, + "curve": [ 0.044, 11.52, 0.2, 16.12 ] + }, + { + "time": 0.2667, + "value": 16.14, + "curve": [ 0.375, 16.17, 0.492, 2.65 ] + }, + { + "time": 0.6333, + "value": 2.68, + "curve": [ 0.725, 2.7, 0.963, 9.26 ] + }, + { "time": 1, "value": 10.2 } + ], + "translate": [ + { + "curve": [ 0.03, -0.24, 0.2, -4.22, 0.051, -1.06, 0.2, -3.62 ] + }, + { + "time": 0.2667, + "x": -4.22, + "y": -3.62, + "curve": [ 0.358, -4.22, 0.542, 0.84, 0.358, -3.62, 0.542, 6.01 ] + }, + { + "time": 0.6333, + "x": 0.84, + "y": 6.01, + "curve": [ 0.725, 0.84, 0.939, 0.32, 0.725, 6.01, 0.945, 1.14 ] + }, + { "time": 1 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": -11.18, + "curve": [ 0.064, -14.82, 0.25, -20.01 ] + }, + { + "time": 0.3333, + "value": -20.01, + "curve": [ 0.429, -20.12, 0.58, 5.12 ] + }, + { + "time": 0.6, + "value": 8.67, + "curve": [ 0.617, 11.72, 0.687, 20.52 ] + }, + { + "time": 0.7667, + "value": 20.55, + "curve": [ 0.848, 20.7, 0.963, -9.43 ] + }, + { "time": 1, "value": -11.18 } + ] + }, + "hair3": { + "rotate": [ + { + "value": 9.61, + "curve": [ 0.014, 8.51, 0.075, 2.63 ] + }, + { + "time": 0.1, + "value": 2.63, + "curve": [ 0.15, 2.63, 0.25, 13.52 ] + }, + { + "time": 0.3, + "value": 13.52, + "curve": [ 0.35, 13.52, 0.45, 11.28 ] + }, + { + "time": 0.5, + "value": 11.28, + "curve": [ 0.575, 11.28, 0.725, 18.13 ] + }, + { + "time": 0.8, + "value": 18.13, + "curve": [ 0.85, 18.13, 0.978, 11.07 ] + }, + { "time": 1, "value": 9.61 } + ] + }, + "hair4": { + "rotate": [ + { + "value": -17.7, + "curve": [ 0.008, -17.7, 0.025, -23.73 ] + }, + { + "time": 0.0333, + "value": -23.73, + "curve": [ 0.067, -23.73, 0.154, -4.4 ] + }, + { + "time": 0.1667, + "value": -1.92, + "curve": [ 0.197, 4.09, 0.236, 12.91 ] + }, + { + "time": 0.2667, + "value": 17.56, + "curve": [ 0.301, 22.68, 0.342, 27.97 ] + }, + { + "time": 0.3667, + "value": 27.97, + "curve": [ 0.4, 27.97, 0.467, -1.45 ] + }, + { + "time": 0.5, + "value": -1.45, + "curve": [ 0.517, -1.45, 0.55, 3.16 ] + }, + { + "time": 0.5667, + "value": 3.16, + "curve": [ 0.583, 3.16, 0.617, -8.9 ] + }, + { + "time": 0.6333, + "value": -8.9, + "curve": [ 0.642, -8.9, 0.658, -5.4 ] + }, + { + "time": 0.6667, + "value": -5.4, + "curve": [ 0.683, -5.4, 0.717, -15.32 ] + }, + { + "time": 0.7333, + "value": -15.32, + "curve": [ 0.75, -15.32, 0.783, -9.19 ] + }, + { + "time": 0.8, + "value": -9.19, + "curve": [ 0.817, -9.19, 0.85, -23.6 ] + }, + { + "time": 0.8667, + "value": -23.6, + "curve": [ 0.883, -23.6, 0.917, -17.38 ] + }, + { + "time": 0.9333, + "value": -17.38, + "curve": [ 0.942, -17.38, 0.958, -20.46 ] + }, + { + "time": 0.9667, + "value": -20.46, + "curve": [ 0.975, -20.46, 0.992, -17.7 ] + }, + { "time": 1, "value": -17.7 } + ] + }, + "hair1": { + "rotate": [ + { + "value": 9.61, + "curve": [ 0.06, 9.04, 0.25, 8.9 ] + }, + { + "time": 0.3333, + "value": 8.9, + "curve": [ 0.392, 8.9, 0.508, 14.58 ] + }, + { + "time": 0.5667, + "value": 14.58, + "curve": [ 0.675, 14.58, 0.956, 10.28 ] + }, + { "time": 1, "value": 9.61 } + ] + }, + "hair2": { + "rotate": [ + { + "value": -3.82, + "curve": [ 0.017, -3.82, 0.064, -9.16 ] + }, + { + "time": 0.1333, + "value": -9.09, + "curve": [ 0.178, -9.04, 0.234, 1.29 ] + }, + { + "time": 0.2667, + "value": 5.98, + "curve": [ 0.276, 7.27, 0.336, 17.1 ] + }, + { + "time": 0.3667, + "value": 17.1, + "curve": [ 0.413, 17.1, 0.467, 1.59 ] + }, + { + "time": 0.5, + "value": 1.59, + "curve": [ 0.533, 1.59, 0.567, 13.63 ] + }, + { + "time": 0.6, + "value": 13.63, + "curve": [ 0.617, 13.63, 0.683, 0.78 ] + }, + { + "time": 0.7, + "value": 0.78, + "curve": [ 0.717, 0.78, 0.75, 12.01 ] + }, + { + "time": 0.7667, + "value": 11.9, + "curve": [ 0.792, 11.73, 0.817, -0.85 ] + }, + { + "time": 0.8333, + "value": -0.85, + "curve": [ 0.85, -0.85, 0.88, 1.99 ] + }, + { + "time": 0.9, + "value": 1.82, + "curve": [ 0.916, 1.68, 0.95, -6.9 ] + }, + { + "time": 0.9667, + "value": -6.9, + "curve": [ 0.975, -6.9, 0.992, -3.82 ] + }, + { "time": 1, "value": -3.82 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 31.65, + "curve": [ 0.108, 31.65, 0.325, 13.01 ] + }, + { + "time": 0.4333, + "value": 13.01, + "curve": [ 0.71, 13.01, 0.917, 31.65 ] + }, + { "time": 1, "value": 31.65 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 31, + "curve": [ 0.108, 31, 0.325, 12.76 ] + }, + { + "time": 0.4333, + "value": 12.79, + "curve": [ 0.587, 12.82, 0.917, 31 ] + }, + { "time": 1, "value": 31 } + ] + }, + "gun": { + "rotate": [ + { + "value": 1.95, + "curve": [ 0.083, 1.95, 0.245, 36.73 ] + }, + { + "time": 0.3333, + "value": 36.71, + "curve": [ 0.439, 36.69, 0.589, 10.68 ] + }, + { + "time": 0.6333, + "value": 8.75, + "curve": [ 0.701, 5.81, 0.917, 1.95 ] + }, + { "time": 1, "value": 1.95 } + ] + }, + "torso2": { + "rotate": [ + { + "curve": [ 0.033, 0, 0.1, 2.35 ] + }, + { + "time": 0.1333, + "value": 2.35, + "curve": [ 0.225, 2.35, 0.408, -2.4 ] + }, + { + "time": 0.5, + "value": -2.4, + "curve": [ 0.567, -2.4, 0.7, 1.44 ] + }, + { + "time": 0.7667, + "value": 1.44, + "curve": [ 0.825, 1.44, 0.942, 0 ] + }, + { "time": 1 } + ] + }, + "torso3": { + "rotate": [ + { + "curve": [ 0.063, 0.77, 0.106, 1.42 ] + }, + { + "time": 0.1667, + "value": 1.42, + "curve": [ 0.259, 1.42, 0.344, -1.25 ] + }, + { + "time": 0.4667, + "value": -1.26, + "curve": [ 0.656, -1.26, 0.917, -0.78 ] + }, + { "time": 1 } + ] + }, + "head-control": { + "translate": [ + { + "x": 0.37, + "y": -11.17, + "curve": [ 0.133, 0.37, 0.335, -10.23, 0.133, -11.17, 0.335, 3.15 ] + }, + { + "time": 0.5333, + "x": -10.23, + "y": 3.15, + "curve": [ 0.71, -10.23, 0.883, 0.37, 0.71, 3.15, 0.883, -11.17 ] + }, + { "time": 1, "x": 0.37, "y": -11.17 } + ] + }, + "front-shoulder": { + "translate": [ + { + "x": 1.46, + "y": 10.15, + "curve": [ 0.103, 1.46, 0.249, 1.36, 0.103, 10.15, 0.249, -4.39 ] + }, + { + "time": 0.4, + "x": 1.36, + "y": -4.39, + "curve": [ 0.621, 1.36, 0.85, 1.46, 0.621, -4.39, 0.85, 10.15 ] + }, + { "time": 1, "x": 1.46, "y": 10.15 } + ] + }, + "back-shoulder": { + "translate": [ + { + "x": 1.4, + "y": 0.44, + "curve": [ 0.088, 1.4, 0.208, -2.47, 0.088, 0.44, 0.208, 8.61 ] + }, + { + "time": 0.3333, + "x": -2.47, + "y": 8.61, + "curve": [ 0.572, -2.47, 0.833, 1.4, 0.572, 8.61, 0.833, 0.44 ] + }, + { "time": 1, "x": 1.4, "y": 0.44 } + ] + } + }, + "transform": { + "front-foot-board-transform": [ + { "mixRotate": 0.997 } + ], + "rear-foot-board-transform": [ + {} + ], + "toes-board": [ + { "mixX": 0, "mixScaleX": 0, "mixShearY": 0 } + ] + }, + "attachments": { + "default": { + "front-foot": { + "front-foot": { + "deform": [ + { + "offset": 26, + "vertices": [ -0.02832, -5.37024, -0.02832, -5.37024, 3.8188, -3.7757, -0.02832, -5.37024, -3.82159, 3.77847 ] + } + ] + } + }, + "front-shin": { + "front-shin": { + "deform": [ + { + "offset": 14, + "vertices": [ 0.5298, -1.12677, -0.85507, -4.20587, -11.35158, -10.19225, -10.79865, -8.43765, -6.06447, -6.89757, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.54892, -3.06021, 1.48463, -2.29663, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4.80437, -7.01817 ] + }, + { + "time": 0.3667, + "offset": 14, + "vertices": [ 0.5298, -1.12677, -11.66571, -9.07211, -25.65866, -17.53735, -25.53217, -16.50978, -11.78232, -11.26097, 0, 0, 0.60487, -1.63589, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.60487, -1.63589, 0, 0, -2.64522, -7.35739, 1.48463, -2.29663, 0, 0, 0, 0, 0, 0, 0.60487, -1.63589, 0.60487, -1.63589, 0.60487, -1.63589, 0.60487, -1.63589, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.60487, -1.63589, 0, 0, -10.06873, -12.0999 ] + }, + { + "time": 0.5333, + "offset": 14, + "vertices": [ 0.5298, -1.12677, -0.85507, -4.20587, -7.00775, -8.24771, -6.45482, -6.49312, -6.06447, -6.89757, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.54892, -3.06021, 1.48463, -2.29663, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4.80437, -7.01817 ] + }, + { + "time": 1, + "offset": 14, + "vertices": [ 0.5298, -1.12677, -0.85507, -4.20587, -11.35158, -10.19225, -10.79865, -8.43765, -6.06447, -6.89757, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.54892, -3.06021, 1.48463, -2.29663, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4.80437, -7.01817 ] + } + ] + } + }, + "hoverboard-board": { + "hoverboard-board": { + "deform": [ + { + "curve": [ 0.067, 0, 0.2, 1 ] + }, + { + "time": 0.2667, + "offset": 1, + "vertices": [ 2.45856, 0, 0, 0, 0, 0, 0, 0, 0, 3.55673, -3.0E-4, 3.55673, -3.0E-4, 0, 0, 0, 0, 0, 0, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, 0, 0, 0, 0, 0, 0, 0, 0, -4.90558, 0.11214, -9.40706, 6.2E-4, -6.34871, 4.3E-4, -6.34925, -6.57018, -6.34925, -6.57018, -6.34871, 4.3E-4, -2.3308, 1.7E-4, -2.33133, -6.57045, -2.33133, -6.57045, -2.3308, 1.7E-4, 0, 0, 1.2E-4, 2.45856, 1.2E-4, 2.45856, 1.2E-4, 2.45856, 1.2E-4, 2.45856, 3.3297, 4.44005, 3.3297, 4.44005, 3.3297, 4.44005, 1.2E-4, 2.45856, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.46227, 1.7E-4, -2.46227, 1.7E-4, -2.52316, 1.1313, -2.52316, 1.1313, -2.52316, 1.1313, 1.2E-4, 2.45856, 1.2E-4, 2.45856, -9.40694, 2.45918, 1.88063, 0.44197, -2.9E-4, -3.54808, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.52316, 1.1313, -2.52316, 1.1313, -2.52316, 1.1313, -2.46227, 1.7E-4, -2.46227, 1.7E-4, -2.46227, 1.7E-4, 0, 0, 0, 0, 1.2E-4, 2.45856 ], + "curve": [ 0.45, 0, 0.817, 1 ] + }, + { "time": 1 } + ] + } + }, + "rear-foot": { + "rear-foot": { + "deform": [ + { + "offset": 28, + "vertices": [ -1.93078, 1.34782, -0.31417, 2.33363, 3.05122, 0.33946, 2.31472, -2.01678, 2.17583, -2.05795, -0.04277, -2.99459, 1.15429, 0.26328, 0.97501, -0.67169 ] + } + ] + } + } + } + } + }, + "idle": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + } + }, + "bones": { + "front-foot-target": { + "translate": [ + { "x": -69.06 } + ] + }, + "hip": { + "rotate": [ + { + "curve": [ 0.073, 0.35, 0.303, 1.27 ] + }, + { + "time": 0.4, + "value": 1.28, + "curve": [ 0.615, 1.3, 0.847, -1.41 ] + }, + { + "time": 1.2, + "value": -1.38, + "curve": [ 1.344, -1.37, 1.602, -0.28 ] + }, + { "time": 1.6667 } + ], + "translate": [ + { + "x": -11.97, + "y": -23.15, + "curve": [ 0.059, -12.96, 0.258, -15.19, 0.142, -23.15, 0.341, -24.89 ] + }, + { + "time": 0.4667, + "x": -15.14, + "y": -26.74, + "curve": [ 0.62, -15.1, 0.788, -13.28, 0.597, -28.66, 0.75, -30.01 ] + }, + { + "time": 0.9, + "x": -12.02, + "y": -30.01, + "curve": [ 0.978, -11.13, 1.175, -9.05, 1.036, -29.94, 1.234, -28.08 ] + }, + { + "time": 1.3333, + "x": -9.06, + "y": -26.64, + "curve": [ 1.501, -9.06, 1.614, -10.95, 1.454, -24.89, 1.609, -23.15 ] + }, + { "time": 1.6667, "x": -11.97, "y": -23.15 } + ] + }, + "rear-foot-target": { + "translate": [ + { "x": 48.87 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -60.87, + "curve": [ 0.154, -60.85, 0.452, -68.65 ] + }, + { + "time": 0.8333, + "value": -68.65, + "curve": [ 1.221, -68.65, 1.542, -60.87 ] + }, + { "time": 1.6667, "value": -60.87 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 42.46, + "curve": [ 0.029, 42.97, 0.134, 45.28 ] + }, + { + "time": 0.3333, + "value": 45.27, + "curve": [ 0.578, 45.26, 0.798, 40.07 ] + }, + { + "time": 0.8333, + "value": 39.74, + "curve": [ 0.878, 39.32, 1.019, 38.23 ] + }, + { + "time": 1.2, + "value": 38.22, + "curve": [ 1.377, 38.22, 1.619, 41.68 ] + }, + { "time": 1.6667, "value": 42.46 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 39.2, + "curve": [ 0.185, 39.22, 0.5, 29.37 ] + }, + { + "time": 0.6667, + "value": 29.37, + "curve": [ 0.917, 29.37, 1.417, 39.2 ] + }, + { "time": 1.6667, "value": 39.2 } + ] + }, + "head": { + "rotate": [ + { + "value": -6.75, + "curve": [ 0.176, -7.88, 0.349, -8.95 ] + }, + { + "time": 0.4667, + "value": -8.95, + "curve": [ 0.55, -8.95, 0.697, -6.77 ] + }, + { + "time": 0.8333, + "value": -5.44, + "curve": [ 0.88, -4.98, 1.05, -4.12 ] + }, + { + "time": 1.1333, + "value": -4.12, + "curve": [ 1.266, -4.12, 1.469, -5.48 ] + }, + { "time": 1.6667, "value": -6.75 } + ] + }, + "front-fist": { + "rotate": [ + { + "curve": [ 0.086, 0, 0.233, 2.48 ] + }, + { + "time": 0.3333, + "value": 4.13, + "curve": [ 0.429, 5.7, 0.711, 10.06 ] + }, + { + "time": 0.8333, + "value": 10.06, + "curve": [ 0.926, 10.06, 1.092, 4.21 ] + }, + { + "time": 1.2, + "value": 2.78, + "curve": [ 1.349, 0.8, 1.551, 0 ] + }, + { "time": 1.6667 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "curve": [ 0.063, 0.54, 0.367, 3.39 ] + }, + { + "time": 0.5333, + "value": 3.39, + "curve": [ 0.696, 3.39, 0.939, -1.63 ] + }, + { + "time": 1.2, + "value": -1.61, + "curve": [ 1.42, -1.59, 1.574, -0.67 ] + }, + { "time": 1.6667 } + ] + }, + "gun": { + "rotate": [ + { + "curve": [ 0.099, 0.27, 0.367, 1.23 ] + }, + { + "time": 0.5333, + "value": 1.23, + "curve": [ 0.665, 1.23, 0.937, -0.56 ] + }, + { + "time": 1.1333, + "value": -0.55, + "curve": [ 1.316, -0.55, 1.582, -0.21 ] + }, + { "time": 1.6667 } + ] + }, + "torso": { + "rotate": [ + { + "value": -22.88, + "curve": [ 0.099, -23.45, 0.363, -24.74 ] + }, + { + "time": 0.5333, + "value": -24.74, + "curve": [ 0.706, -24.74, 0.961, -20.97 ] + }, + { + "time": 1.1333, + "value": -20.97, + "curve": [ 1.355, -20.97, 1.567, -22.28 ] + }, + { "time": 1.6667, "value": -22.88 } + ] + }, + "neck": { + "rotate": [ + { + "value": 3.78, + "curve": [ 0.167, 3.78, 0.5, 5.45 ] + }, + { + "time": 0.6667, + "value": 5.45, + "curve": [ 0.917, 5.45, 1.417, 3.78 ] + }, + { "time": 1.6667, "value": 3.78 } + ] + }, + "torso2": { + "rotate": [ + { + "curve": [ 0.067, 0.33, 0.341, 2.54 ] + }, + { + "time": 0.5333, + "value": 2.54, + "curve": [ 0.734, 2.55, 0.982, -0.94 ] + }, + { + "time": 1.1333, + "value": -0.93, + "curve": [ 1.365, -0.91, 1.549, -0.56 ] + }, + { "time": 1.6667 } + ] + }, + "torso3": { + "rotate": [ + { + "value": -2.15, + "curve": [ 0.052, -1.9, 0.384, -0.15 ] + }, + { + "time": 0.5333, + "value": -0.14, + "curve": [ 0.762, -0.13, 0.895, -3.1 ] + }, + { + "time": 1.1333, + "value": -3.1, + "curve": [ 1.348, -3.1, 1.592, -2.46 ] + }, + { "time": 1.6667, "value": -2.15 } + ] + }, + "hair1": { + "rotate": [ + { + "curve": [ 0.067, 0, 0.213, 2.86 ] + }, + { + "time": 0.2667, + "value": 3.65, + "curve": [ 0.358, 4.99, 0.535, 7.92 ] + }, + { + "time": 0.6667, + "value": 7.92, + "curve": [ 0.809, 7.92, 1.067, 5.49 ] + }, + { + "time": 1.1333, + "value": 4.7, + "curve": [ 1.245, 3.34, 1.525, 0 ] + }, + { "time": 1.6667 } + ] + }, + "hair2": { + "rotate": [ + { + "curve": [ 0.067, 0, 0.225, -7.97 ] + }, + { + "time": 0.2667, + "value": -9.75, + "curve": [ 0.316, -11.84, 0.519, -16.66 ] + }, + { + "time": 0.6667, + "value": -16.66, + "curve": [ 0.817, -16.66, 1.029, -11.43 ] + }, + { + "time": 1.1333, + "value": -9.14, + "curve": [ 1.25, -6.56, 1.525, 0 ] + }, + { "time": 1.6667 } + ] + }, + "hair3": { + "rotate": [ + { + "curve": [ 0.1, 0, 0.3, 1.32 ] + }, + { + "time": 0.4, + "value": 1.32, + "curve": [ 0.55, 1.32, 0.866, 0.93 ] + }, + { + "time": 1, + "value": 0.73, + "curve": [ 1.189, 0.46, 1.5, 0 ] + }, + { "time": 1.6667 } + ] + }, + "hair4": { + "rotate": [ + { + "curve": [ 0.118, -0.44, 0.3, -8.52 ] + }, + { + "time": 0.4, + "value": -8.52, + "curve": [ 0.55, -8.52, 0.85, 1.96 ] + }, + { + "time": 1, + "value": 1.96, + "curve": [ 1.167, 1.96, 1.577, 0.38 ] + }, + { "time": 1.6667 } + ] + }, + "head-control": { + "translate": [ + { + "curve": [ 0.098, 1.46, 0.3, 4.49, 0.17, 0.13, 0.316, -3.28 ] + }, + { + "time": 0.4, + "x": 4.55, + "y": -5.95, + "curve": [ 0.53, 4.64, 0.776, 2.59, 0.492, -8.89, 0.668, -14.21 ] + }, + { + "time": 0.8667, + "x": 1.42, + "y": -14.26, + "curve": [ 0.966, 0.15, 1.109, -2.91, 0.994, -14.26, 1.144, -10.58 ] + }, + { + "time": 1.2333, + "x": -3.02, + "y": -8.26, + "curve": [ 1.342, -3.02, 1.568, -1.48, 1.317, -6.1, 1.558, 0 ] + }, + { "time": 1.6667 } + ] + }, + "front-shoulder": { + "translate": [ + { + "curve": [ 0.21, 0, 0.525, -1.72, 0.21, 0, 0.525, 4.08 ] + }, + { + "time": 0.8333, + "x": -1.72, + "y": 4.08, + "curve": [ 1.15, -1.72, 1.46, 0, 1.15, 4.08, 1.46, 0 ] + }, + { "time": 1.6667 } + ] + } + } + }, + "idle-turn": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + } + }, + "bones": { + "front-upper-arm": { + "rotate": [ + { + "value": -302.77, + "curve": [ 0, -406.9, 0.125, -420.87 ] + }, + { "time": 0.2667, "value": -420.87 } + ], + "translate": [ + { + "x": 2.24, + "y": -4.98, + "curve": [ 0.067, 2.24, 0.111, 0, 0.067, -4.98, 0.111, 0 ] + }, + { "time": 0.2667 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 248.56, + "curve": [ 0, 371.28, 0.062, 399.2 ] + }, + { "time": 0.1333, "value": 399.2 } + ], + "translate": [ + { + "x": -2.84, + "y": 37.28, + "curve": [ 0.033, -2.84, 0.069, 0, 0.033, 37.28, 0.069, 0 ] + }, + { "time": 0.1333 } + ] + }, + "gun": { + "rotate": [ + { + "value": -3.95, + "curve": [ 0, -10.4, 0.019, -20.43 ] + }, + { + "time": 0.0333, + "value": -20.45, + "curve": [ 0.044, -20.47, 0.125, 0 ] + }, + { "time": 0.2 } + ] + }, + "neck": { + "rotate": [ + { + "value": 17.2, + "curve": [ 0, 6.27, 0.125, 3.78 ] + }, + { "time": 0.2667, "value": 3.78 } + ] + }, + "hip": { + "translate": [ + { + "x": -2.69, + "y": -6.79, + "curve": [ 0.067, -2.69, 0.2, -11.97, 0.067, -6.79, 0.2, -23.15 ] + }, + { "time": 0.2667, "x": -11.97, "y": -23.15 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -15.54, + "curve": [ 0, -3.08, 0.034, 18.44 ] + }, + { + "time": 0.0667, + "value": 19.02, + "curve": [ 0.108, 19.75, 0.169, 0 ] + }, + { "time": 0.2667 } + ], + "scale": [ + { + "x": 0.94, + "curve": [ 0, 0.962, 0.024, 1.237, 0, 1, 0.026, 0.947 ] + }, + { + "time": 0.0667, + "x": 1.236, + "y": 0.947, + "curve": [ 0.117, 1.235, 0.189, 1, 0.117, 0.947, 0.189, 1 ] + }, + { "time": 0.2667 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 11.75, + "curve": [ 0, -7.97, 0.017, -33.4 ] + }, + { + "time": 0.0333, + "value": -33.39, + "curve": [ 0.049, -33.37, 0.131, 0 ] + }, + { "time": 0.2 } + ] + }, + "torso": { + "rotate": [ + { + "value": -18.25, + "curve": [ 0, -10.59, 0.125, -22.88 ] + }, + { "time": 0.2667, "value": -22.88 } + ], + "scale": [ + { + "y": 1.03, + "curve": [ 0.067, 1, 0.132, 1, 0.067, 1.03, 0.132, 1 ] + }, + { "time": 0.2667 } + ] + }, + "head": { + "rotate": [ + { + "value": 5.12, + "curve": [ 0, -6.34, 0.125, -6.75 ] + }, + { "time": 0.2667, "value": -6.75 } + ], + "scale": [ + { + "y": 1.03, + "curve": [ 0.067, 1, 0.107, 1, 0.067, 1.03, 0.107, 1 ] + }, + { "time": 0.2667 } + ] + }, + "rear-foot-target": { + "translate": [ + { + "x": -58.39, + "y": 30.48, + "curve": [ 0, -7.15, 0.047, 16.62, 0, 12.71, 0.039, 0.22 ] + }, + { + "time": 0.1, + "x": 34.14, + "y": -0.19, + "curve": [ 0.136, 45.79, 0.163, 48.87, 0.133, -0.41, 0.163, 0 ] + }, + { "time": 0.2, "x": 48.87 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 6.69, + "curve": [ 0, 19.76, 0.039, 56.53 ] + }, + { + "time": 0.0667, + "value": 56.63, + "curve": [ 0.114, 56.79, 0.189, 42.46 ] + }, + { "time": 0.2667, "value": 42.46 } + ] + }, + "front-foot-target": { + "rotate": [ + { + "value": -1.85, + "curve": [ 0.014, -8.91, 0.047, -28.4 ] + }, + { + "time": 0.1, + "value": -28.89, + "curve": [ 0.144, -29.29, 0.262, -21.77 ] + }, + { "time": 0.2667 } + ], + "translate": [ + { + "x": 9.97, + "y": 0.82, + "curve": [ 0, -54.41, 0.078, -69.06, 0, 0.15, 0.078, 0 ] + }, + { "time": 0.1667, "x": -69.06 } + ] + }, + "hair3": { + "rotate": [ + { + "value": -9.01, + "curve": [ 0.044, -9.01, 0.072, 7.41 ] + }, + { + "time": 0.1333, + "value": 10.08, + "curve": [ 0.166, 11.47, 0.208, 0 ] + }, + { "time": 0.2667 } + ] + }, + "hair4": { + "rotate": [ + { + "value": -16.49, + "curve": [ 0.044, -16.49, 0.101, -5.98 ] + }, + { + "time": 0.1333, + "value": -2.95, + "curve": [ 0.162, -0.34, 0.208, 0 ] + }, + { "time": 0.2667 } + ] + }, + "hair1": { + "rotate": [ + { + "value": -3.85, + "curve": [ 0.044, -3.85, 0.072, 6.91 ] + }, + { + "time": 0.1333, + "value": 8.05, + "curve": [ 0.166, 8.65, 0.208, 0 ] + }, + { "time": 0.2667 } + ] + }, + "hair2": { + "rotate": [ + { + "value": 1.25, + "curve": [ 0.044, 1.25, 0.072, 8.97 ] + }, + { + "time": 0.1333, + "value": 8.6, + "curve": [ 0.166, 8.4, 0.208, 0 ] + }, + { "time": 0.2667 } + ] + }, + "front-thigh": { + "translate": [ + { + "x": 12.21, + "y": 1.89, + "curve": [ 0.033, 12.21, 0.1, 0, 0.033, 1.89, 0.1, 0 ] + }, + { "time": 0.1333 } + ] + }, + "rear-thigh": { + "translate": [ + { + "x": -16.11, + "y": -1.38, + "curve": [ 0.033, -16.11, 0.1, 0, 0.033, -1.38, 0.1, 0 ] + }, + { "time": 0.1333 } + ] + }, + "torso3": { + "rotate": [ + { "time": 0.2667, "value": -2.15 } + ] + }, + "head-control": { + "translate": [ + { + "x": -13.72, + "y": -34.7, + "curve": [ 0.067, -13.72, 0.2, 0, 0.067, -34.7, 0.2, 0 ] + }, + { "time": 0.2667 } + ] + }, + "front-shoulder": { + "translate": [ + { + "x": 1.13, + "y": -14.31, + "curve": [ 0.067, 1.13, 0.2, 0, 0.067, -14.31, 0.2, 0 ] + }, + { "time": 0.2667 } + ] + } + } + }, + "jump": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" }, + { "time": 0.1, "name": "front-fist-closed" }, + { "time": 0.8333, "name": "front-fist-open" } + ] + } + }, + "bones": { + "front-thigh": { + "rotate": [ + { + "value": 55.08, + "curve": [ 0.007, 46.66, 0.043, 26.3 ] + }, + { + "time": 0.0667, + "value": 22.84, + "curve": [ 0.1, 17.99, 0.165, 15.78 ] + }, + { + "time": 0.2333, + "value": 15.71, + "curve": [ 0.309, 15.63, 0.408, 46.67 ] + }, + { + "time": 0.5, + "value": 63.6, + "curve": [ 0.56, 74.72, 0.762, 91.48 ] + }, + { + "time": 0.9667, + "value": 91.81, + "curve": [ 1.068, 92.01, 1.096, 22.05 ] + }, + { + "time": 1.1667, + "value": 22.25, + "curve": [ 1.18, 22.29, 1.176, 56.17 ] + }, + { + "time": 1.2, + "value": 56.16, + "curve": [ 1.246, 56.15, 1.263, 54.94 ] + }, + { "time": 1.3333, "value": 55.08 } + ], + "translate": [ + { "x": -5.13, "y": 11.55 } + ] + }, + "torso": { + "rotate": [ + { + "value": -45.57, + "curve": [ 0.022, -44.61, 0.03, -39.06 ] + }, + { + "time": 0.0667, + "value": -35.29, + "curve": [ 0.12, -29.77, 0.28, -19.95 ] + }, + { + "time": 0.4333, + "value": -19.95, + "curve": [ 0.673, -19.95, 0.871, -22.38 ] + }, + { + "time": 0.9667, + "value": -27.08, + "curve": [ 1.094, -33.33, 1.176, -44.93 ] + }, + { "time": 1.3333, "value": -45.57 } + ], + "translate": [ + { "x": -3.79, "y": -0.77 } + ] + }, + "rear-thigh": { + "rotate": [ + { + "value": 12.81, + "curve": [ 0.067, 12.81, 0.242, 67.88 ] + }, + { + "time": 0.2667, + "value": 74.11, + "curve": [ 0.314, 86.02, 0.454, 92.23 ] + }, + { + "time": 0.5667, + "value": 92.24, + "curve": [ 0.753, 92.26, 0.966, 67.94 ] + }, + { + "time": 1, + "value": 61.32, + "curve": [ 1.039, 53.75, 1.218, 12.68 ] + }, + { "time": 1.3333, "value": 12.81 } + ] + }, + "rear-shin": { + "rotate": [ + { + "value": -115.64, + "curve": [ 0.067, -117.17, 0.125, -117.15 ] + }, + { + "time": 0.1667, + "value": -117.15, + "curve": [ 0.225, -117.15, 0.332, -108.76 ] + }, + { + "time": 0.4, + "value": -107.15, + "curve": [ 0.48, -105.26, 0.685, -103.49 ] + }, + { + "time": 0.7667, + "value": -101.97, + "curve": [ 0.826, -100.87, 0.919, -92.3 ] + }, + { + "time": 1, + "value": -92.28, + "curve": [ 1.113, -92.26, 1.297, -114.22 ] + }, + { "time": 1.3333, "value": -115.64 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -40.21, + "curve": [ 0.054, -35.46, 0.15, -31.12 ] + }, + { + "time": 0.2, + "value": -31.12, + "curve": [ 0.308, -31.12, 0.547, -80.12 ] + }, + { + "time": 0.6333, + "value": -96.56, + "curve": [ 0.697, -108.56, 0.797, -112.54 ] + }, + { + "time": 0.8667, + "value": -112.6, + "curve": [ 1.137, -112.84, 1.274, -49.19 ] + }, + { "time": 1.3333, "value": -40.21 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 20.54, + "curve": [ 0.054, 32.23, 0.192, 55.84 ] + }, + { + "time": 0.2333, + "value": 62.58, + "curve": [ 0.29, 71.87, 0.375, 79.28 ] + }, + { + "time": 0.4333, + "value": 79.18, + "curve": [ 0.555, 78.98, 0.684, 27.54 ] + }, + { + "time": 0.7333, + "value": 13.28, + "curve": [ 0.786, -1.85, 0.874, -24.76 ] + }, + { + "time": 1, + "value": -25.45, + "curve": [ 1.165, -26.36, 1.303, 9.1 ] + }, + { "time": 1.3333, "value": 20.54 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -36.16, + "curve": [ 0.114, -39.59, 0.3, -45.61 ] + }, + { + "time": 0.4, + "value": -45.61, + "curve": [ 0.442, -45.61, 0.537, -21.54 ] + }, + { + "time": 0.5667, + "value": -15.4, + "curve": [ 0.592, -10.23, 0.692, 11.89 ] + }, + { + "time": 0.7333, + "value": 11.73, + "curve": [ 0.783, 11.54, 0.831, 1.8 ] + }, + { + "time": 0.8667, + "value": -5.78, + "curve": [ 0.897, -12.22, 0.901, -14.22 ] + }, + { + "time": 0.9333, + "value": -14.51, + "curve": [ 0.974, -14.89, 0.976, 10.38 ] + }, + { + "time": 1, + "value": 10.55, + "curve": [ 1.027, 10.74, 1.023, -8.44 ] + }, + { + "time": 1.0333, + "value": -8.42, + "curve": [ 1.059, -8.36, 1.074, 10.12 ] + }, + { + "time": 1.1, + "value": 10.22, + "curve": [ 1.168, 10.48, 1.27, -36.07 ] + }, + { "time": 1.3333, "value": -36.16 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 40.5, + "curve": [ 0.048, 36.1, 0.168, 20.45 ] + }, + { + "time": 0.3, + "value": 20.45, + "curve": [ 0.476, 20.45, 0.571, 33.76 ] + }, + { + "time": 0.6, + "value": 38.67, + "curve": [ 0.642, 45.8, 0.681, 57.44 ] + }, + { + "time": 0.7333, + "value": 62.91, + "curve": [ 0.829, 72.8, 0.996, 77.61 ] + }, + { + "time": 1.0333, + "value": 80.37, + "curve": [ 1.082, 83.94, 1.148, 90.6 ] + }, + { + "time": 1.2, + "value": 90.6, + "curve": [ 1.248, 90.46, 1.317, 53.07 ] + }, + { "time": 1.3333, "value": 49.06 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 28.28, + "curve": [ 0.022, 25.12, 0.187, -0.89 ] + }, + { + "time": 0.2, + "value": -2.52, + "curve": [ 0.257, -9.92, 0.372, -17.38 ] + }, + { + "time": 0.4333, + "value": -17.41, + "curve": [ 0.54, -17.47, 0.659, -16.91 ] + }, + { + "time": 0.7667, + "value": -12.1, + "curve": [ 0.907, -5.79, 1.025, 14.58 ] + }, + { + "time": 1.1, + "value": 20.58, + "curve": [ 1.191, 27.85, 1.283, 29.67 ] + }, + { "time": 1.3333, "value": 29.67 } + ] + }, + "neck": { + "rotate": [ + { + "value": 11.88, + "curve": [ 0.104, 11.82, 0.179, 11.15 ] + }, + { + "time": 0.2, + "value": 10.08, + "curve": [ 0.255, 7.29, 0.405, -8.15 ] + }, + { + "time": 0.4333, + "value": -9.35, + "curve": [ 0.508, -12.48, 0.595, -13.14 ] + }, + { + "time": 0.6667, + "value": -12.61, + "curve": [ 0.714, -12.26, 0.815, -5.57 ] + }, + { + "time": 0.8333, + "value": -4.08, + "curve": [ 0.883, -0.07, 1.045, 12.77 ] + }, + { + "time": 1.1, + "value": 15.06, + "curve": [ 1.208, 19.6, 1.279, 20.64 ] + }, + { "time": 1.3333, "value": 20.73 } + ] + }, + "head": { + "rotate": [ + { + "value": 13.14, + "curve": [ 0.008, 12.19, 0.197, -23.53 ] + }, + { + "time": 0.3333, + "value": -23.95, + "curve": [ 0.509, -23.95, 0.667, -2.66 ] + }, + { + "time": 0.7333, + "value": -2.66, + "curve": [ 0.792, -2.66, 0.908, -13.32 ] + }, + { + "time": 0.9667, + "value": -13.32, + "curve": [ 1.158, -13.11, 1.241, -1.58 ] + }, + { "time": 1.3333, "value": -1.58 } + ], + "scale": [ + { + "curve": [ 0.041, 1, 0.052, 0.962, 0.041, 1, 0.052, 1.137 ] + }, + { + "time": 0.1, + "x": 0.954, + "y": 1.137, + "curve": [ 0.202, 0.962, 0.318, 1, 0.202, 1.137, 0.252, 1.002 ] + }, + { "time": 0.4667 }, + { + "time": 1.0667, + "x": 1.002, + "curve": [ 1.092, 1.002, 1.126, 1.143, 1.092, 1, 1.128, 0.975 ] + }, + { + "time": 1.1667, + "x": 1.144, + "y": 0.973, + "curve": [ 1.204, 1.145, 1.233, 0.959, 1.206, 0.972, 1.227, 1.062 ] + }, + { + "time": 1.2667, + "x": 0.958, + "y": 1.063, + "curve": [ 1.284, 0.958, 1.292, 1.001, 1.288, 1.063, 1.288, 1.001 ] + }, + { "time": 1.3333 } + ] + }, + "hip": { + "translate": [ + { + "y": -45.46, + "curve": [ 0.042, -0.09, 0.15, 15.22, 0.031, 44.98, 0.123, 289.73 ] + }, + { + "time": 0.2, + "x": 15.22, + "y": 415.85, + "curve": [ 0.332, 15.22, 0.539, -34.52, 0.271, 532.93, 0.483, 720.5 ] + }, + { + "time": 0.7667, + "x": -34.52, + "y": 721.6, + "curve": [ 0.888, -34.52, 1.057, -21.95, 1.049, 721.17, 1.098, 379.84 ] + }, + { + "time": 1.1333, + "x": -15.67, + "y": 266.77, + "curve": [ 1.144, -14.77, 1.188, -10.53, 1.15, 213.72, 1.172, -61.32 ] + }, + { + "time": 1.2333, + "x": -6.53, + "y": -61.34, + "curve": [ 1.272, -3.22, 1.311, 0.05, 1.291, -61.36, 1.296, -44.8 ] + }, + { "time": 1.3333, "y": -45.46 } + ] + }, + "front-shin": { + "rotate": [ + { + "value": -74.19, + "curve": [ 0, -51.14, 0.042, -12.54 ] + }, + { + "time": 0.1667, + "value": -12.28, + "curve": [ 0.285, -12.32, 0.37, -74.44 ] + }, + { + "time": 0.4333, + "value": -92.92, + "curve": [ 0.498, -111.86, 0.617, -140.28 ] + }, + { + "time": 0.9, + "value": -140.84, + "curve": [ 1.004, -141.04, 1.09, -47.87 ] + }, + { + "time": 1.1, + "value": -37.44, + "curve": [ 1.108, -29.83, 1.14, -21.18 ] + }, + { + "time": 1.1667, + "value": -21.08, + "curve": [ 1.18, -21.03, 1.191, -50.65 ] + }, + { + "time": 1.2, + "value": -53.17, + "curve": [ 1.22, -58.53, 1.271, -73.38 ] + }, + { "time": 1.3333, "value": -74.19 } + ] + }, + "front-foot": { + "rotate": [ + { + "value": 7.35, + "curve": [ 0, 4.8, 0.05, -26.64 ] + }, + { + "time": 0.0667, + "value": -26.64, + "curve": [ 0.192, -26.64, 0.442, -11.77 ] + }, + { + "time": 0.5667, + "value": -11.77, + "curve": [ 0.692, -11.77, 0.942, -19.36 ] + }, + { + "time": 1.0667, + "value": -19.36, + "curve": [ 1.133, -19.36, 1.32, 3.82 ] + }, + { "time": 1.3333, "value": 7.35 } + ] + }, + "rear-foot": { + "rotate": [ + { "value": -7.14 } + ] + }, + "gun": { + "rotate": [ + { + "value": 12.36, + "curve": [ 0.022, 16.28, 0.15, 30.81 ] + }, + { + "time": 0.2, + "value": 30.81, + "curve": [ 0.258, 30.81, 0.375, 13.26 ] + }, + { + "time": 0.4333, + "value": 13.26, + "curve": [ 0.508, 13.26, 0.658, 15.05 ] + }, + { + "time": 0.7333, + "value": 14.98, + "curve": [ 0.789, 14.94, 0.828, 13.62 ] + }, + { + "time": 0.8667, + "value": 12.72, + "curve": [ 0.887, 12.25, 0.984, 9.83 ] + }, + { + "time": 1.0333, + "value": 8.6, + "curve": [ 1.045, 8.31, 1.083, 7.55 ] + }, + { + "time": 1.1333, + "value": 7.13, + "curve": [ 1.175, 6.78, 1.283, 6.18 ] + }, + { "time": 1.3333, "value": 6.18 } + ] + }, + "front-leg-target": { + "translate": [ + { "x": -13.95, "y": -30.34 } + ] + }, + "rear-leg-target": { + "rotate": [ + { "value": -38.43 } + ], + "translate": [ + { "x": 85, "y": -33.59 } + ] + }, + "front-foot-target": { + "rotate": [ + { "value": -62.54 } + ], + "translate": [ + { "x": 16.34, "y": 0.18 } + ] + }, + "rear-foot-target": { + "rotate": [ + { "value": 18.55 } + ], + "translate": [ + { "x": -176.39, "y": 134.12 } + ] + }, + "back-foot-tip": { + "rotate": [ + { + "value": -143.73, + "curve": [ 0.083, -144.24, 0.167, -74.26 ] + }, + { + "time": 0.2667, + "value": -52.76, + "curve": [ 0.342, -36.57, 0.513, -36.57 ] + }, + { + "time": 0.6333, + "value": -30.97, + "curve": [ 0.724, -26.78, 0.848, -17.06 ] + }, + { + "time": 0.9667, + "value": -16.74, + "curve": [ 1.167, -16.2, 1.272, -144.17 ] + }, + { "time": 1.3333, "value": -143.73 } + ] + }, + "front-foot-tip": { + "rotate": [ + { + "value": -1.57, + "curve": [ 0, -24.71, 0.162, -60.88 ] + }, + { + "time": 0.2667, + "value": -60.83, + "curve": [ 0.342, -60.8, 0.582, -43.5 ] + }, + { + "time": 0.7, + "value": -39.45, + "curve": [ 0.773, -36.94, 0.832, -36.78 ] + }, + { + "time": 0.9667, + "value": -36.6, + "curve": [ 1.054, -36.49, 1.092, -37.37 ] + }, + { + "time": 1.1667, + "value": -33.26, + "curve": [ 1.237, -29.37, 1.147, -1.41 ] + }, + { "time": 1.2, "value": -1.57 } + ] + }, + "hair3": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0, 13.59, 0.117, 18.21 ] + }, + { + "time": 0.1333, + "value": 18.21, + "curve": [ 0.167, 18.21, 0.26, 12.95 ] + }, + { + "time": 0.3, + "value": 11.56, + "curve": [ 0.382, 8.7, 0.55, 9.43 ] + }, + { + "time": 0.6667, + "value": 9.32, + "curve": [ 0.843, 9.15, 0.918, -7.34 ] + }, + { "time": 1.3333, "value": -6.81 } + ], + "translate": [ + { + "time": 0.6667, + "curve": [ 0.781, 0, 0.972, 16.03, 0.781, 0, 0.972, 0.92 ] + }, + { + "time": 1.1333, + "x": 16.03, + "y": 0.92, + "curve": [ 1.211, 16.03, 1.281, 0, 1.211, 0.92, 1.281, 0 ] + }, + { "time": 1.3333 } + ] + }, + "hair4": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0.001, -3.88, 0.063, 16.18 ] + }, + { + "time": 0.1667, + "value": 16.14, + "curve": [ 0.242, 16.1, 0.249, 16.07 ] + }, + { + "time": 0.3333, + "value": 13.46, + "curve": [ 0.442, 10.09, 0.573, -2.2 ] + }, + { + "time": 0.6, + "value": -6.04, + "curve": [ 0.614, -8.05, 0.717, -33.44 ] + }, + { + "time": 0.7667, + "value": -33.44, + "curve": [ 0.809, -33.44, 0.835, -31.32 ] + }, + { + "time": 0.8667, + "value": -27.36, + "curve": [ 0.874, -26.47, 0.903, -14.28 ] + }, + { + "time": 0.9333, + "value": -14.47, + "curve": [ 0.956, -14.62, 0.944, -25.91 ] + }, + { + "time": 1, + "value": -25.96, + "curve": [ 1.062, -26.02, 1.051, -1.87 ] + }, + { + "time": 1.0667, + "value": -1.87, + "curve": [ 1.096, -1.87, 1.096, -16.09 ] + }, + { + "time": 1.1333, + "value": -16.08, + "curve": [ 1.169, -16.08, 1.153, -3.38 ] + }, + { + "time": 1.2, + "value": -3.38, + "curve": [ 1.234, -3.38, 1.271, -6.07 ] + }, + { "time": 1.3333, "value": -6.07 } + ] + }, + "hair2": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0, -3.17, 0.042, 16.33 ] + }, + { + "time": 0.0667, + "value": 16.33, + "curve": [ 0.21, 15.74, 0.208, -12.06 ] + }, + { + "time": 0.3333, + "value": -12.21, + "curve": [ 0.417, -12.3, 0.552, -3.98 ] + }, + { + "time": 0.6667, + "value": 1.52, + "curve": [ 0.726, 4.35, 0.817, 4.99 ] + }, + { + "time": 0.8667, + "value": 4.99, + "curve": [ 0.901, 4.99, 0.912, -29.05 ] + }, + { + "time": 0.9667, + "value": -27.45, + "curve": [ 0.987, -26.83, 1.018, -5.42 ] + }, + { + "time": 1.0667, + "value": -5.46, + "curve": [ 1.107, -5.22, 1.095, -33.51 ] + }, + { + "time": 1.1333, + "value": -33.28, + "curve": [ 1.162, -33.57, 1.192, 8.04 ] + }, + { + "time": 1.2667, + "value": 7.86, + "curve": [ 1.302, 7.77, 1.313, 2.7 ] + }, + { "time": 1.3333, "value": 2.7 } + ] + }, + "hair1": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0.001, -3.12, 0.074, 14.66 ] + }, + { + "time": 0.1333, + "value": 14.66, + "curve": [ 0.188, 14.8, 0.293, 9.56 ] + }, + { + "time": 0.3333, + "value": 5.99, + "curve": [ 0.381, 1.72, 0.55, -11.11 ] + }, + { + "time": 0.6667, + "value": -11.11, + "curve": [ 0.833, -11.11, 0.933, 22.54 ] + }, + { + "time": 1.1, + "value": 22.54, + "curve": [ 1.158, 22.54, 1.275, -6.81 ] + }, + { "time": 1.3333, "value": -6.81 } + ] + }, + "torso2": { + "rotate": [ + { + "value": 4.52, + "curve": [ 0.013, 2.33, 0.092, -9.75 ] + }, + { + "time": 0.1333, + "value": -9.75, + "curve": [ 0.175, -9.75, 0.291, -1.26 ] + }, + { + "time": 0.3333, + "value": 0.96, + "curve": [ 0.359, 2.3, 0.543, 4.25 ] + }, + { + "time": 0.6, + "value": 4.68, + "curve": [ 0.683, 5.3, 0.771, 5.92 ] + }, + { + "time": 0.8333, + "value": 6.48, + "curve": [ 0.871, 6.82, 1.083, 11.37 ] + }, + { + "time": 1.1667, + "value": 11.37, + "curve": [ 1.208, 11.37, 1.317, 6.18 ] + }, + { "time": 1.3333, "value": 4.52 } + ], + "translate": [ + { + "curve": [ 0, 0, 0.082, -2.24, 0, 0, 0.082, -0.42 ] + }, + { + "time": 0.1667, + "x": -2.98, + "y": -0.56, + "curve": [ 0.232, -2.24, 0.298, 0, 0.232, -0.42, 0.298, 0 ] + }, + { "time": 0.3333, "curve": "stepped" }, + { + "time": 0.8667, + "curve": [ 0.889, 0, 0.912, 0.26, 0.889, 0, 0.912, 0.06 ] + }, + { + "time": 0.9333, + "x": 0.68, + "y": 0.23, + "curve": [ 1.016, 2.22, 1.095, 5.9, 1.023, 0.97, 1.095, 1.99 ] + }, + { + "time": 1.1667, + "x": 6.47, + "y": 2.18, + "curve": [ 1.23, 5.75, 1.286, 0, 1.23, 1.94, 1.286, 0 ] + }, + { "time": 1.3333 } + ] + }, + "torso3": { + "rotate": [ + { + "value": 4.52, + "curve": [ 0.025, 4.52, 0.075, -6.17 ] + }, + { + "time": 0.1, + "value": -6.17, + "curve": [ 0.175, -6.17, 0.381, -0.71 ] + }, + { + "time": 0.4, + "value": -0.25, + "curve": [ 0.447, 0.87, 0.775, 4.84 ] + }, + { + "time": 0.9, + "value": 4.84, + "curve": [ 1.008, 4.84, 1.225, 4.52 ] + }, + { "time": 1.3333, "value": 4.52 } + ] + }, + "head-control": { + "translate": [ + { + "curve": [ 0.138, -2.4, 0.227, -10.44, 0.123, 1.05, 0.227, 2.7 ] + }, + { + "time": 0.3667, + "x": -10.44, + "y": 2.7, + "curve": [ 0.484, -10.44, 0.585, -5.63, 0.484, 2.7, 0.629, -23.62 ] + }, + { + "time": 0.7333, + "x": -2.29, + "y": -26.61, + "curve": [ 0.818, -0.39, 0.962, 1.21, 0.858, -30.17, 0.972, -28.75 ] + }, + { + "time": 1.1, + "x": 1.25, + "y": -28.75, + "curve": [ 1.192, 1.28, 1.234, 0.98, 1.224, -28.75, 1.235, -2.15 ] + }, + { "time": 1.3333 } + ] + }, + "front-shoulder": { + "translate": [ + { + "curve": [ 0.031, -2.22, 0.065, -3.73, 0.02, -3.25, 0.065, -14.74 ] + }, + { + "time": 0.1, + "x": -3.73, + "y": -14.74, + "curve": [ 0.216, -3.73, 0.384, -0.17, 0.216, -14.74, 0.402, -12.51 ] + }, + { + "time": 0.5, + "x": 1.63, + "y": -9.51, + "curve": [ 0.632, 3.69, 0.935, 7.41, 0.585, -6.91, 0.909, 10.86 ] + }, + { + "time": 1.1, + "x": 7.45, + "y": 10.99, + "curve": [ 1.18, 7.46, 1.265, 2.86, 1.193, 11.05, 1.294, 3.38 ] + }, + { "time": 1.3333 } + ] + } + }, + "ik": { + "front-foot-ik": [ + { + "mix": 0, + "curve": [ 0.3, 0, 0.9, 1, 0.3, 0, 0.9, 0 ] + }, + { "time": 1.2 } + ], + "front-leg-ik": [ + { + "mix": 0, + "bendPositive": false, + "curve": [ 0.3, 0, 0.9, 1, 0.3, 0, 0.9, 0 ] + }, + { "time": 1.2, "bendPositive": false } + ], + "rear-foot-ik": [ + { "mix": 0 } + ], + "rear-leg-ik": [ + { "mix": 0, "bendPositive": false } + ] + }, + "events": [ + { "time": 1.2, "name": "footstep" } + ] + }, + "portal": { + "slots": { + "clipping": { + "attachment": [ + { "name": "clipping" } + ] + }, + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + }, + "mouth": { + "attachment": [ + { "time": 0.9, "name": "mouth-grind" }, + { "time": 2.2667, "name": "mouth-smile" } + ] + }, + "portal-bg": { + "attachment": [ + { "name": "portal-bg" }, + { "time": 3 } + ] + }, + "portal-flare1": { + "attachment": [ + { "time": 1.1, "name": "portal-flare1" }, + { "time": 1.1333, "name": "portal-flare2" }, + { "time": 1.1667, "name": "portal-flare3" }, + { "time": 1.2, "name": "portal-flare1" }, + { "time": 1.2333, "name": "portal-flare2" }, + { "time": 1.2667, "name": "portal-flare1" }, + { "time": 1.3333 } + ] + }, + "portal-flare2": { + "attachment": [ + { "time": 1.1, "name": "portal-flare2" }, + { "time": 1.1333, "name": "portal-flare3" }, + { "time": 1.1667, "name": "portal-flare1" }, + { "time": 1.2, "name": "portal-flare2" }, + { "time": 1.2333, "name": "portal-flare3" }, + { "time": 1.2667 } + ] + }, + "portal-flare3": { + "attachment": [ + { "time": 1.2, "name": "portal-flare3" }, + { "time": 1.2333, "name": "portal-flare2" }, + { "time": 1.2667 } + ] + }, + "portal-flare4": { + "attachment": [ + { "time": 1.2, "name": "portal-flare2" }, + { "time": 1.2333, "name": "portal-flare1" }, + { "time": 1.2667, "name": "portal-flare2" }, + { "time": 1.3333 } + ] + }, + "portal-flare5": { + "attachment": [ + { "time": 1.2333, "name": "portal-flare3" }, + { "time": 1.2667, "name": "portal-flare1" }, + { "time": 1.3333 } + ] + }, + "portal-flare6": { + "attachment": [ + { "time": 1.2667, "name": "portal-flare3" }, + { "time": 1.3333 } + ] + }, + "portal-flare7": { + "attachment": [ + { "time": 1.1333, "name": "portal-flare2" }, + { "time": 1.1667 } + ] + }, + "portal-flare8": { + "attachment": [ + { "time": 1.2, "name": "portal-flare3" }, + { "time": 1.2333, "name": "portal-flare2" }, + { "time": 1.2667 } + ] + }, + "portal-flare9": { + "attachment": [ + { "time": 1.2, "name": "portal-flare2" }, + { "time": 1.2333, "name": "portal-flare3" }, + { "time": 1.2667, "name": "portal-flare1" }, + { "time": 1.3 } + ] + }, + "portal-flare10": { + "attachment": [ + { "time": 1.2, "name": "portal-flare2" }, + { "time": 1.2333, "name": "portal-flare1" }, + { "time": 1.2667, "name": "portal-flare3" }, + { "time": 1.3 } + ] + }, + "portal-shade": { + "attachment": [ + { "name": "portal-shade" }, + { "time": 3 } + ] + }, + "portal-streaks1": { + "attachment": [ + { "name": "portal-streaks1" }, + { "time": 3 } + ] + }, + "portal-streaks2": { + "attachment": [ + { "name": "portal-streaks2" }, + { "time": 3 } + ] + } + }, + "bones": { + "portal-root": { + "translate": [ + { + "x": -458.35, + "y": 105.19, + "curve": [ 0.333, -458.22, 0.669, -457.86, 0.934, 105.19, 0.671, 105.19 ] + }, + { + "time": 1, + "x": -456.02, + "y": 105.19, + "curve": [ 1.339, -454.14, 2.208, -447.28, 1.35, 105.19, 2.05, 105.19 ] + }, + { + "time": 2.4, + "x": -439.12, + "y": 105.19, + "curve": [ 2.463, -436.44, 2.502, -432.92, 2.487, 105.19, 2.512, 105.09 ] + }, + { + "time": 2.6, + "x": -432.58, + "y": 105.09, + "curve": [ 2.784, -431.94, 2.978, -446.6, 2.772, 105.09, 2.933, 105.19 ] + }, + { "time": 3.0333, "x": -457.42, "y": 105.19 } + ], + "scale": [ + { + "x": 0.003, + "y": 0.006, + "curve": [ 0.329, 0.044, 0.347, 0.117, 0.329, 0.097, 0.37, 0.249 ] + }, + { + "time": 0.4, + "x": 0.175, + "y": 0.387, + "curve": [ 0.63, 0.619, 0.663, 0.723, 0.609, 1.338, 0.645, 1.524 ] + }, + { + "time": 0.7333, + "x": 0.724, + "y": 1.52, + "curve": [ 0.798, 0.725, 0.907, 0.647, 0.797, 1.517, 0.895, 1.424 ] + }, + { + "time": 1, + "x": 0.645, + "y": 1.426, + "curve": [ 1.095, 0.643, 1.139, 0.688, 1.089, 1.428, 1.115, 1.513 ] + }, + { + "time": 1.2333, + "x": 0.685, + "y": 1.516, + "curve": [ 1.325, 0.683, 1.508, 0.636, 1.343, 1.518, 1.467, 1.4 ] + }, + { + "time": 1.6, + "x": 0.634, + "y": 1.401, + "curve": [ 1.728, 0.631, 1.946, 0.687, 1.722, 1.402, 1.924, 1.522 ] + }, + { + "time": 2.0667, + "x": 0.688, + "y": 1.522, + "curve": [ 2.189, 0.69, 2.289, 0.649, 2.142, 1.522, 2.265, 1.417 ] + }, + { + "time": 2.4, + "x": 0.65, + "y": 1.426, + "curve": [ 2.494, 0.651, 2.504, 0.766, 2.508, 1.434, 2.543, 1.566 ] + }, + { + "time": 2.6, + "x": 0.766, + "y": 1.568, + "curve": [ 2.73, 0.765, 3.006, 0.098, 2.767, 1.564, 2.997, 0.1 ] + }, + { "time": 3.0333, "x": 0.007, "y": 0.015 } + ] + }, + "portal-streaks1": { + "rotate": [ + {}, + { "time": 3.1667, "value": 1200 } + ], + "translate": [ + { + "x": 15.15, + "curve": [ 0.162, 15.15, 0.432, 12.6, 0.162, 0, 0.432, -3.86 ] + }, + { + "time": 0.6667, + "x": 10.9, + "y": -6.44, + "curve": [ 0.794, 9.93, 0.912, 9.21, 0.794, -7.71, 0.912, -8.66 ] + }, + { + "time": 1, + "x": 9.21, + "y": -8.66, + "curve": [ 1.083, 9.21, 1.25, 21.53, 1.083, -8.66, 1.265, -4.9 ] + }, + { + "time": 1.3333, + "x": 21.53, + "y": -3.19, + "curve": [ 1.5, 21.53, 1.939, 12.3, 1.446, -0.37, 1.9, 6.26 ] + }, + { + "time": 2.0667, + "x": 11.26, + "y": 6.26, + "curve": [ 2.239, 9.85, 2.389, 9.68, 2.208, 6.26, 2.523, 0.51 ] + }, + { + "time": 2.5667, + "x": 9.39, + "y": -0.8, + "curve": [ 2.657, 9.24, 2.842, 9.21, 2.646, -3.2, 2.842, -8.91 ] + }, + { "time": 2.9333, "x": 9.21, "y": -8.91 } + ], + "scale": [ + { + "curve": [ 0.167, 1, 0.5, 1.053, 0.167, 1, 0.5, 1.053 ] + }, + { + "time": 0.6667, + "x": 1.053, + "y": 1.053, + "curve": [ 0.833, 1.053, 1.167, 0.986, 0.833, 1.053, 1.167, 0.986 ] + }, + { + "time": 1.3333, + "x": 0.986, + "y": 0.986, + "curve": [ 1.5, 0.986, 1.833, 1.053, 1.5, 0.986, 1.833, 1.053 ] + }, + { "time": 2, "x": 1.053, "y": 1.053 } + ] + }, + "portal-streaks2": { + "rotate": [ + {}, + { "time": 3.1667, "value": 600 } + ], + "translate": [ + { "x": -2.11 }, + { "time": 1, "x": -2.11, "y": 6.63 }, + { "time": 1.9333, "x": -2.11 } + ], + "scale": [ + { + "x": 1.014, + "y": 1.014, + "curve": [ 0.229, 0.909, 0.501, 0.755, 0.242, 0.892, 0.502, 0.768 ] + }, + { + "time": 0.8667, + "x": 0.745, + "y": 0.745, + "curve": [ 1.282, 0.733, 2.021, 0.699, 1.27, 0.719, 2.071, 0.709 ] + }, + { + "time": 2.2, + "x": 0.7, + "y": 0.704, + "curve": [ 2.315, 0.7, 2.421, 0.794, 2.311, 0.701, 2.485, 0.797 ] + }, + { + "time": 2.5667, + "x": 0.794, + "y": 0.794, + "curve": [ 2.734, 0.794, 2.99, 0.323, 2.714, 0.789, 3.019, 0.341 ] + }, + { "time": 3.1667, "x": 0, "y": 0 } + ] + }, + "portal-shade": { + "translate": [ + { "x": -29.68 } + ], + "scale": [ + { "x": 0.714, "y": 0.714 } + ] + }, + "portal": { + "rotate": [ + {}, + { "time": 3.1667, "value": 600 } + ] + }, + "clipping": { + "translate": [ + { "x": -476.55, "y": 2.27 } + ], + "scale": [ + { "x": 0.983, "y": 1.197 } + ] + }, + "hip": { + "rotate": [ + { + "time": 1.0667, + "value": 22.74, + "curve": [ 1.163, 18.84, 1.77, 8.77 ] + }, + { + "time": 1.9, + "value": 7.82, + "curve": [ 2.271, 5.1, 2.89, 0 ] + }, + { "time": 3.1667 } + ], + "translate": [ + { "x": -899.41, "y": 4.47, "curve": "stepped" }, + { + "time": 1.0667, + "x": -694.16, + "y": 183.28, + "curve": [ 1.091, -602.08, 1.138, -427.59, 1.115, 185.6, 1.171, 133.18 ] + }, + { + "time": 1.2333, + "x": -316.97, + "y": 55.29, + "curve": [ 1.317, -220.27, 1.512, -123.21, 1.271, 8.68, 1.461, -83.18 ] + }, + { + "time": 1.6, + "x": -95.53, + "y": -112.23, + "curve": [ 1.718, -58.25, 2.037, -22.54, 1.858, -166.17, 2.109, -31.4 ] + }, + { + "time": 2.1667, + "x": -14.82, + "y": -31.12, + "curve": [ 2.294, -7.28, 2.442, -7.2, 2.274, -30.6, 2.393, -36.76 ] + }, + { + "time": 2.6, + "x": -7.2, + "y": -36.96, + "curve": [ 2.854, -7.2, 3.071, -11.87, 2.786, -36.27, 3.082, -22.98 ] + }, + { "time": 3.1667, "x": -11.97, "y": -23.15 } + ] + }, + "rear-foot-target": { + "rotate": [ + { "time": 1.0667, "value": 41.6, "curve": "stepped" }, + { + "time": 1.2333, + "value": 41.6, + "curve": [ 1.258, 41.6, 1.379, 35.46 ] + }, + { + "time": 1.4, + "value": 30.09, + "curve": [ 1.412, 27.04, 1.433, 10.65 ] + }, + { "time": 1.4333, "value": -0.28 }, + { "time": 1.6, "value": 2.44 } + ], + "translate": [ + { "x": -899.41, "y": 4.47, "curve": "stepped" }, + { + "time": 1.0667, + "x": -591.13, + "y": 438.46, + "curve": [ 1.076, -539.77, 1.206, -268.1, 1.117, 418.44, 1.21, 333.18 ] + }, + { + "time": 1.2333, + "x": -225.28, + "y": 304.53, + "curve": [ 1.265, -175.22, 1.393, -74.21, 1.296, 226.52, 1.401, 49.61 ] + }, + { + "time": 1.4333, + "x": -52.32, + "y": 0.2, + "curve": [ 1.454, -40.85, 1.616, 40.87, 1.466, 0.17, 1.614, 0.04 ] + }, + { "time": 1.6667, "x": 45.87, "y": 0.01 }, + { "time": 1.9333, "x": 48.87 } + ] + }, + "front-foot-target": { + "rotate": [ + { + "time": 1.0667, + "value": 32.08, + "curve": [ 1.108, 32.08, 1.192, 35.16 ] + }, + { + "time": 1.2333, + "value": 35.16, + "curve": [ 1.258, 35.16, 1.317, 2.23 ] + }, + { + "time": 1.3333, + "value": -4.74, + "curve": [ 1.351, -12.14, 1.429, -34.96 ] + }, + { + "time": 1.6, + "value": -34.77, + "curve": [ 1.765, -34.58, 1.897, -17.25 ] + }, + { "time": 1.9333 } + ], + "translate": [ + { "x": -899.41, "y": 4.47, "curve": "stepped" }, + { + "time": 1.0667, + "x": -533.93, + "y": 363.75, + "curve": [ 1.074, -480.85, 1.18, -261.31, 1.094, 362.3, 1.195, 267.77 ] + }, + { + "time": 1.2333, + "x": -201.23, + "y": 199.93, + "curve": [ 1.269, -161.38, 1.294, -140.32, 1.274, 126.67, 1.308, 77.12 ] + }, + { + "time": 1.3333, + "x": -124.08, + "y": 0.2, + "curve": [ 1.426, -85.6, 1.633, -69.06, 1.45, 0.48, 1.633, 0 ] + }, + { "time": 1.7333, "x": -69.06 } + ] + }, + "torso": { + "rotate": [ + { + "time": 1.0667, + "value": 27.02, + "curve": [ 1.187, 26.86, 1.291, 7.81 ] + }, + { + "time": 1.3333, + "value": -2.62, + "curve": [ 1.402, -19.72, 1.429, -48.64 ] + }, + { + "time": 1.4667, + "value": -56.31, + "curve": [ 1.509, -64.87, 1.62, -77.14 ] + }, + { + "time": 1.7333, + "value": -77.34, + "curve": [ 1.837, -76.89, 1.895, -71.32 ] + }, + { + "time": 2, + "value": -57.52, + "curve": [ 2.104, -43.83, 2.189, -28.59 ] + }, + { + "time": 2.3, + "value": -29.03, + "curve": [ 2.413, -29.48, 2.513, -36.79 ] + }, + { + "time": 2.6667, + "value": -36.79, + "curve": [ 2.814, -36.95, 2.947, -22.88 ] + }, + { "time": 3.1667, "value": -22.88 } + ] + }, + "neck": { + "rotate": [ + { + "time": 1.0667, + "value": -3.57, + "curve": [ 1.146, -3.66, 1.15, -13.5 ] + }, + { + "time": 1.2333, + "value": -13.5, + "curve": [ 1.428, -13.5, 1.443, 11.58 ] + }, + { + "time": 1.5667, + "value": 11.42, + "curve": [ 1.658, 11.3, 1.775, 3.78 ] + }, + { + "time": 1.8667, + "value": 3.78, + "curve": [ 1.92, 3.78, 2.036, 8.01 ] + }, + { + "time": 2.1, + "value": 7.93, + "curve": [ 2.266, 7.72, 2.42, 3.86 ] + }, + { + "time": 2.5333, + "value": 3.86, + "curve": [ 2.783, 3.86, 3.004, 3.78 ] + }, + { "time": 3.1667, "value": 3.78 } + ] + }, + "head": { + "rotate": [ + { + "time": 1.0667, + "value": 16.4, + "curve": [ 1.133, 9.9, 1.207, 1.87 ] + }, + { + "time": 1.3333, + "value": 1.67, + "curve": [ 1.46, 1.56, 1.547, 47.54 ] + }, + { + "time": 1.7333, + "value": 47.55, + "curve": [ 1.897, 47.56, 2.042, 5.68 ] + }, + { + "time": 2.0667, + "value": 0.86, + "curve": [ 2.074, -0.61, 2.086, -2.81 ] + }, + { + "time": 2.1, + "value": -5.31, + "curve": [ 2.145, -13.07, 2.216, -23.65 ] + }, + { + "time": 2.2667, + "value": -23.71, + "curve": [ 2.334, -23.79, 2.426, -13.43 ] + }, + { + "time": 2.4667, + "value": -9.18, + "curve": [ 2.498, -5.91, 2.604, 2.53 ] + }, + { + "time": 2.6667, + "value": 2.52, + "curve": [ 2.738, 2.24, 2.85, -8.76 ] + }, + { + "time": 2.9333, + "value": -8.67, + "curve": [ 3.036, -8.55, 3.09, -7.09 ] + }, + { "time": 3.1667, "value": -6.75 } + ], + "scale": [ + { + "time": 1.3333, + "curve": [ 1.392, 1, 1.526, 1, 1.392, 1, 1.508, 1.043 ] + }, + { + "time": 1.5667, + "x": 0.992, + "y": 1.043, + "curve": [ 1.598, 0.985, 1.676, 0.955, 1.584, 1.043, 1.672, 1.04 ] + }, + { + "time": 1.7333, + "x": 0.954, + "y": 1.029, + "curve": [ 1.843, 0.954, 1.933, 1, 1.825, 1.013, 1.933, 1 ] + }, + { "time": 2 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "time": 0.9, + "value": 39.24, + "curve": [ 0.968, 39.93, 1.267, 85.31 ] + }, + { + "time": 1.4667, + "value": 112.27, + "curve": [ 1.555, 124.24, 1.576, 126.44 ] + }, + { + "time": 1.6333, + "value": 126.44, + "curve": [ 1.782, 126.44, 1.992, 94.55 ] + }, + { + "time": 2.1, + "value": 79.96, + "curve": [ 2.216, 64.26, 2.407, 34.36 ] + }, + { + "time": 2.5667, + "value": 33.38, + "curve": [ 2.815, 31.87, 3.1, 39.2 ] + }, + { "time": 3.1667, "value": 39.2 } + ] + }, + "back-foot-tip": { + "rotate": [ + { + "time": 1.0667, + "value": 56.07, + "curve": [ 1.138, 59.21, 1.192, 59.65 ] + }, + { + "time": 1.2333, + "value": 59.46, + "curve": [ 1.295, 59.17, 1.45, 22.54 ] + }, + { "time": 1.4667, "value": -0.84 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "time": 1.0667, + "value": 118.03, + "curve": [ 1.075, 93.64, 1.358, -34.03 ] + }, + { + "time": 1.6667, + "value": -33.94, + "curve": [ 1.808, -33.89, 1.879, -25 ] + }, + { + "time": 1.9667, + "value": -25.19, + "curve": [ 2.09, -25.46, 2.312, -34.58 ] + }, + { + "time": 2.3667, + "value": -38.36, + "curve": [ 2.465, -45.18, 2.557, -60.1 ] + }, + { + "time": 2.8333, + "value": -61.1, + "curve": [ 2.843, -61.06, 3.16, -60.87 ] + }, + { "time": 3.1667, "value": -60.87 } + ] + }, + "front-bracer": { + "rotate": [ + { + "time": 1.0667, + "value": 0.66, + "curve": [ 1.108, 0.66, 1.221, 44.95 ] + }, + { + "time": 1.2333, + "value": 49.25, + "curve": [ 1.263, 59.42, 1.342, 68.06 ] + }, + { + "time": 1.3667, + "value": 68.34, + "curve": [ 1.409, 68.8, 1.476, 4.9 ] + }, + { + "time": 1.5, + "value": -2.05, + "curve": [ 1.529, -10.3, 1.695, -15.95 ] + }, + { + "time": 1.7333, + "value": -17.38, + "curve": [ 1.807, -20.1, 1.878, -21.19 ] + }, + { + "time": 1.9333, + "value": -21.08, + "curve": [ 2.073, -20.8, 2.146, -7.63 ] + }, + { + "time": 2.1667, + "value": -3.64, + "curve": [ 2.186, 0.12, 2.275, 15.28 ] + }, + { + "time": 2.3333, + "value": 21.78, + "curve": [ 2.392, 28.31, 2.575, 37.66 ] + }, + { + "time": 2.7, + "value": 39.43, + "curve": [ 2.947, 42.93, 3.02, 42.46 ] + }, + { "time": 3.1667, "value": 42.46 } + ] + }, + "front-thigh": { + "translate": [ + { "time": 1.1, "x": -6.41, "y": 18.23, "curve": "stepped" }, + { "time": 1.1333, "x": -6.41, "y": 18.23 }, + { "time": 1.2, "x": 1.61, "y": 3.66 }, + { "time": 1.2333, "x": 4.5, "y": -3.15 }, + { "time": 1.3667, "x": -3.79, "y": 2.94 }, + { "time": 1.4, "x": -8.37, "y": 8.72 }, + { "time": 1.4333, "x": -11.26, "y": 16.99 }, + { "time": 1.4667, "x": -9.89, "y": 24.73, "curve": "stepped" }, + { "time": 1.8667, "x": -9.89, "y": 24.73 }, + { "time": 2.1 } + ] + }, + "front-foot-tip": { + "rotate": [ + { "time": 1.0667, "value": 42.55, "curve": "stepped" }, + { "time": 1.1333, "value": 42.55 }, + { "time": 1.2333, "value": 17.71 }, + { "time": 1.3667, "value": 3.63 }, + { "time": 1.4333 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "time": 1.0667, + "value": 108.71, + "curve": [ 1.082, 108.29, 1.437, 50.73 ] + }, + { + "time": 1.5667, + "value": 24.87, + "curve": [ 1.62, 14.2, 1.66, -11.74 ] + }, + { + "time": 1.7333, + "value": -11.74, + "curve": [ 1.961, -11.73, 2.172, 1.66 ] + }, + { + "time": 2.2667, + "value": 7.88, + "curve": [ 2.331, 12.13, 2.439, 18.65 ] + }, + { + "time": 2.5333, + "value": 18.72, + "curve": [ 2.788, 18.91, 3.145, -0.3 ] + }, + { "time": 3.1667 } + ] + }, + "front-fist": { + "rotate": [ + { + "time": 1.1, + "value": 6.32, + "curve": [ 1.11, 3.31, 1.153, -5.07 ] + }, + { + "time": 1.2333, + "value": -5.13, + "curve": [ 1.311, -5.19, 1.364, 34.65 ] + }, + { + "time": 1.4667, + "value": 34.53, + "curve": [ 1.574, 34.41, 1.547, -55.78 ] + }, + { + "time": 1.8667, + "value": -54.7, + "curve": [ 1.947, -54.7, 2.03, -53.94 ] + }, + { + "time": 2.1333, + "value": -42.44, + "curve": [ 2.215, -33.42, 2.358, -4.43 ] + }, + { + "time": 2.4, + "value": 0.03, + "curve": [ 2.444, 4.66, 2.536, 8.2 ] + }, + { + "time": 2.6333, + "value": 8.2, + "curve": [ 2.733, 8.19, 2.804, -0.67 ] + }, + { + "time": 2.9, + "value": -0.82, + "curve": [ 3.127, -1.16, 3.093, 0 ] + }, + { "time": 3.1667 } + ] + }, + "gun": { + "rotate": [ + { + "time": 1.2667, + "curve": [ 1.35, 0, 1.549, 7.49 ] + }, + { + "time": 1.6, + "value": 9.5, + "curve": [ 1.663, 12.02, 1.846, 19.58 ] + }, + { + "time": 1.9333, + "value": 19.43, + "curve": [ 1.985, 19.4, 2.057, 2.98 ] + }, + { + "time": 2.2, + "value": 2.95, + "curve": [ 2.304, 3.55, 2.458, 10.8 ] + }, + { + "time": 2.5, + "value": 10.8, + "curve": [ 2.642, 10.8, 2.873, -2.54 ] + }, + { + "time": 2.9333, + "value": -2.55, + "curve": [ 3.09, -2.57, 3.08, 0 ] + }, + { "time": 3.1667 } + ] + }, + "hair2": { + "rotate": [ + { + "time": 1.0667, + "value": 26.19, + "curve": [ 1.158, 26.19, 1.368, 26 ] + }, + { + "time": 1.4333, + "value": 24.43, + "curve": [ 1.534, 22.03, 2, -29.14 ] + }, + { + "time": 2.2, + "value": -29.14, + "curve": [ 2.292, -29.14, 2.475, 6.71 ] + }, + { + "time": 2.5667, + "value": 6.71, + "curve": [ 2.675, 6.71, 2.814, -5.06 ] + }, + { + "time": 2.9, + "value": -5.06, + "curve": [ 2.973, -5.06, 3.123, 0 ] + }, + { "time": 3.1667 } + ] + }, + "hair4": { + "rotate": [ + { + "time": 1.0667, + "value": 5.21, + "curve": [ 1.108, 5.21, 1.192, 26.19 ] + }, + { + "time": 1.2333, + "value": 26.19, + "curve": [ 1.317, 26.19, 1.483, 10.63 ] + }, + { + "time": 1.5667, + "value": 10.63, + "curve": [ 1.627, 10.63, 1.642, 17.91 ] + }, + { + "time": 1.7, + "value": 17.94, + "curve": [ 1.761, 17.97, 1.774, 8.22 ] + }, + { + "time": 1.8, + "value": 3.33, + "curve": [ 1.839, -4.21, 1.95, -22.67 ] + }, + { + "time": 2, + "value": -22.67, + "curve": [ 2.025, -22.67, 2.123, -21.86 ] + }, + { + "time": 2.1667, + "value": -18.71, + "curve": [ 2.228, -14.31, 2.294, -0.3 ] + }, + { + "time": 2.3667, + "value": 6.36, + "curve": [ 2.433, 12.45, 2.494, 19.21 ] + }, + { + "time": 2.6, + "value": 19.21, + "curve": [ 2.729, 19.21, 2.854, 6.75 ] + }, + { + "time": 2.9333, + "value": 4.62, + "curve": [ 3.09, 0.45, 3.062, 0 ] + }, + { "time": 3.1667 } + ] + }, + "hair3": { + "rotate": [ + { + "time": 1.4333, + "curve": [ 1.45, 0, 1.452, 11.29 ] + }, + { + "time": 1.5, + "value": 11.21, + "curve": [ 1.596, 11.06, 1.573, -14.17 ] + }, + { + "time": 1.7333, + "value": -20.4, + "curve": [ 1.851, -24.98, 1.943, -28.45 ] + }, + { + "time": 2.2, + "value": -28.75, + "curve": [ 2.317, -28.75, 2.55, 7.04 ] + }, + { + "time": 2.6667, + "value": 7.04, + "curve": [ 2.792, 7.04, 2.885, -5.19 ] + }, + { + "time": 2.9667, + "value": -5.19, + "curve": [ 3.037, -5.19, 3.096, 0 ] + }, + { "time": 3.1667 } + ] + }, + "hair1": { + "rotate": [ + { + "time": 1.2333, + "curve": [ 1.283, 0, 1.349, 3.99 ] + }, + { + "time": 1.4333, + "value": 6.58, + "curve": [ 1.497, 8.54, 1.683, 9.35 ] + }, + { + "time": 1.7667, + "value": 9.35, + "curve": [ 1.825, 9.35, 1.945, -8.71 ] + }, + { + "time": 2, + "value": -11.15, + "curve": [ 2.058, -13.71, 2.2, -14.97 ] + }, + { + "time": 2.2667, + "value": -14.97, + "curve": [ 2.367, -14.97, 2.567, 18.77 ] + }, + { + "time": 2.6667, + "value": 18.77, + "curve": [ 2.733, 18.77, 2.817, 8.29 ] + }, + { + "time": 2.8667, + "value": 6.51, + "curve": [ 2.988, 2.17, 3.058, 0 ] + }, + { "time": 3.1667 } + ] + }, + "flare1": { + "rotate": [ + { "time": 1.1, "value": 8.2 } + ], + "translate": [ + { "time": 1.1, "x": -19.97, "y": 149.68 }, + { "time": 1.2, "x": 3.85, "y": 152.43 }, + { "time": 1.2333, "x": -15.42, "y": 152.29 } + ], + "scale": [ + { + "time": 1.1, + "x": 0.805, + "y": 0.805, + "curve": [ 1.119, 0.763, 1.16, 1.162, 1.117, 0.805, 1.15, 0.605 ] + }, + { + "time": 1.1667, + "x": 1.279, + "y": 0.605, + "curve": [ 1.177, 1.47, 1.192, 2.151, 1.175, 0.605, 1.192, 0.911 ] + }, + { + "time": 1.2, + "x": 2.151, + "y": 0.911, + "curve": [ 1.208, 2.151, 1.231, 1.668, 1.208, 0.911, 1.227, 0.844 ] + }, + { + "time": 1.2333, + "x": 1.608, + "y": 0.805, + "curve": [ 1.249, 1.205, 1.283, 0.547, 1.254, 0.685, 1.283, 0.416 ] + }, + { "time": 1.3, "x": 0.547, "y": 0.416 } + ], + "shear": [ + { "time": 1.1, "y": 4.63 }, + { "time": 1.2333, "x": -5.74, "y": 4.63 } + ] + }, + "flare2": { + "rotate": [ + { "time": 1.1, "value": 12.29 } + ], + "translate": [ + { "time": 1.1, "x": -8.63, "y": 132.96 }, + { "time": 1.2, "x": 4.35, "y": 132.93 } + ], + "scale": [ + { "time": 1.1, "x": 0.864, "y": 0.864 }, + { "time": 1.1667, "x": 0.945, "y": 0.945 }, + { "time": 1.2, "x": 1.511, "y": 1.081 } + ], + "shear": [ + { "time": 1.1, "y": 24.03 } + ] + }, + "flare3": { + "rotate": [ + { "time": 1.1667, "value": 2.88 } + ], + "translate": [ + { "time": 1.1667, "x": 3.24, "y": 114.81 } + ], + "scale": [ + { "time": 1.1667, "x": 0.668, "y": 0.668 } + ], + "shear": [ + { "time": 1.1667, "y": 38.59 } + ] + }, + "flare4": { + "rotate": [ + { "time": 1.1667, "value": -8.64 } + ], + "translate": [ + { "time": 1.1667, "x": -3.82, "y": 194.06 }, + { "time": 1.2667, "x": -1.82, "y": 198.47, "curve": "stepped" }, + { "time": 1.3, "x": -1.94, "y": 187.81 } + ], + "scale": [ + { "time": 1.1667, "x": 0.545, "y": 0.545 }, + { "time": 1.2667, "x": 0.757, "y": 0.757 } + ], + "shear": [ + { "time": 1.1667, "x": 7.42, "y": -22.04 } + ] + }, + "flare5": { + "translate": [ + { "time": 1.2, "x": -11.17, "y": 176.42 }, + { "time": 1.2333, "x": -8.56, "y": 179.04, "curve": "stepped" }, + { "time": 1.3, "x": -14.57, "y": 168.69 } + ], + "scale": [ + { "time": 1.2333, "x": 1.146 }, + { "time": 1.3, "x": 0.703, "y": 0.61 } + ], + "shear": [ + { "time": 1.2, "x": 6.9 } + ] + }, + "flare6": { + "rotate": [ + { "time": 1.2333, "value": -5.36 }, + { "time": 1.2667, "value": -0.54 } + ], + "translate": [ + { "time": 1.2333, "x": 14.52, "y": 204.67 }, + { "time": 1.2667, "x": 19.16, "y": 212.9, "curve": "stepped" }, + { "time": 1.3, "x": 9.23, "y": 202.85 } + ], + "scale": [ + { "time": 1.2333, "x": 0.777, "y": 0.49 }, + { "time": 1.2667, "x": 0.777, "y": 0.657 }, + { "time": 1.3, "x": 0.475, "y": 0.401 } + ] + }, + "flare7": { + "rotate": [ + { "time": 1.1, "value": 5.98 }, + { "time": 1.1333, "value": 32.82 } + ], + "translate": [ + { "time": 1.1, "x": -6.34, "y": 112.98 }, + { "time": 1.1333, "x": 2.66, "y": 111.6 } + ], + "scale": [ + { "time": 1.1, "x": 0.588, "y": 0.588 } + ], + "shear": [ + { "time": 1.1333, "x": -19.93 } + ] + }, + "flare8": { + "rotate": [ + { "time": 1.2333, "value": -6.85 } + ], + "translate": [ + { "time": 1.1667, "x": 66.67, "y": 125.52, "curve": "stepped" }, + { "time": 1.2, "x": 58.24, "y": 113.53, "curve": "stepped" }, + { "time": 1.2333, "x": 40.15, "y": 114.69 } + ], + "scale": [ + { "time": 1.1667, "x": 1.313, "y": 1.203 }, + { "time": 1.2333, "x": 1.038, "y": 0.95 } + ], + "shear": [ + { "time": 1.2, "y": -13.01 } + ] + }, + "flare9": { + "rotate": [ + { "time": 1.1667, "value": 2.9 } + ], + "translate": [ + { "time": 1.1667, "x": 28.45, "y": 151.35, "curve": "stepped" }, + { "time": 1.2, "x": 48.8, "y": 191.09, "curve": "stepped" }, + { "time": 1.2333, "x": 52, "y": 182.52, "curve": "stepped" }, + { "time": 1.2667, "x": 77.01, "y": 195.96 } + ], + "scale": [ + { "time": 1.1667, "x": 0.871, "y": 1.073 }, + { "time": 1.2, "x": 0.927, "y": 0.944 }, + { "time": 1.2333, "x": 1.165, "y": 1.336 } + ], + "shear": [ + { "time": 1.1667, "x": 7.95, "y": 25.48 } + ] + }, + "flare10": { + "rotate": [ + { "time": 1.1667, "value": 2.18 } + ], + "translate": [ + { "time": 1.1667, "x": 55.64, "y": 137.64, "curve": "stepped" }, + { "time": 1.2, "x": 90.49, "y": 151.07, "curve": "stepped" }, + { "time": 1.2333, "x": 114.06, "y": 153.05, "curve": "stepped" }, + { "time": 1.2667, "x": 90.44, "y": 164.61 } + ], + "scale": [ + { "time": 1.1667, "x": 2.657, "y": 0.891 }, + { "time": 1.2, "x": 3.314, "y": 1.425 }, + { "time": 1.2333, "x": 2.871, "y": 0.924 }, + { "time": 1.2667, "x": 2.317, "y": 0.775 } + ], + "shear": [ + { "time": 1.1667, "x": -1.35 } + ] + }, + "torso2": { + "rotate": [ + { + "time": 1, + "curve": [ 1.117, 0, 1.255, 24.94 ] + }, + { + "time": 1.4, + "value": 24.94, + "curve": [ 1.477, 24.94, 1.59, -17.62 ] + }, + { + "time": 1.6333, + "value": -19.48, + "curve": [ 1.717, -23.1, 1.784, -26.12 ] + }, + { + "time": 1.9333, + "value": -26.14, + "curve": [ 2.067, -26.15, 2.158, 4.3 ] + }, + { + "time": 2.3, + "value": 4.22, + "curve": [ 2.45, 4.13, 2.579, -1.76 ] + }, + { + "time": 2.7333, + "value": -1.8, + "curve": [ 2.816, -1.82, 2.857, -2.94 ] + }, + { + "time": 2.9333, + "value": -2.99, + "curve": [ 3.056, -3.08, 3.09, 0 ] + }, + { "time": 3.1667 } + ] + }, + "torso3": { + "rotate": [ + { + "time": 1.3, + "curve": [ 1.352, 0, 1.408, 6.47 ] + }, + { + "time": 1.4667, + "value": 6.43, + "curve": [ 1.55, 6.39, 1.723, -5.05 ] + }, + { + "time": 1.7333, + "value": -5.53, + "curve": [ 1.782, -7.72, 1.843, -16.94 ] + }, + { + "time": 1.9667, + "value": -16.86, + "curve": [ 2.111, -16.78, 2.259, -3.97 ] + }, + { + "time": 2.4, + "value": -2.43, + "curve": [ 2.525, -1.12, 2.639, -0.5 ] + }, + { + "time": 2.7333, + "value": -0.49, + "curve": [ 2.931, -0.47, 2.999, -2.15 ] + }, + { "time": 3.1667, "value": -2.15 } + ] + }, + "head-control": { + "translate": [ + { + "time": 1.2333, + "curve": [ 1.25, 0, 1.474, 6.89, 1.25, 0, 1.496, 0.98 ] + }, + { + "time": 1.6667, + "x": 11.99, + "y": -6.42, + "curve": [ 1.743, 14.01, 1.86, 14.33, 1.785, -11.55, 1.86, -27.1 ] + }, + { + "time": 1.9667, + "x": 13.91, + "y": -26.88, + "curve": [ 2.074, 13.49, 2.244, 8.13, 2.074, -26.65, 2.215, -21.78 ] + }, + { + "time": 2.3, + "x": 6.07, + "y": -16.64, + "curve": [ 2.416, 1.84, 2.497, -1.41, 2.417, -9.57, 2.526, -1.72 ] + }, + { + "time": 2.5667, + "x": -3.78, + "y": -1.71, + "curve": [ 2.661, -6.98, 2.76, -8.76, 2.692, -1.68, 2.821, -15.75 ] + }, + { + "time": 2.9, + "x": -8.32, + "y": -16.7, + "curve": [ 2.962, -8.12, 3.082, -0.04, 2.958, -17.39, 3.089, 0 ] + }, + { "time": 3.1667 } + ] + }, + "front-shoulder": { + "translate": [ + { + "time": 1.3333, + "curve": [ 1.488, 0, 1.717, 0.21, 1.488, 0, 1.688, -30.29 ] + }, + { + "time": 1.9, + "x": 0.83, + "y": -30.29, + "curve": [ 2.078, 1.43, 2.274, 2.88, 2.071, -30.29, 2.289, 4.48 ] + }, + { + "time": 2.4333, + "x": 2.89, + "y": 4.59, + "curve": [ 2.604, 2.89, 2.677, -0.68, 2.57, 4.7, 2.694, -2.43 ] + }, + { + "time": 2.7667, + "x": -0.67, + "y": -2.47, + "curve": [ 2.866, -0.67, 2.986, -0.07, 2.882, -2.47, 3.036, -0.06 ] + }, + { "time": 3.1667 } + ] + } + }, + "ik": { + "rear-leg-ik": [ + { "time": 3.1667, "softness": 10, "bendPositive": false } + ] + } + }, + "run": { + "slots": { + "mouth": { + "attachment": [ + { "name": "mouth-grind" } + ] + } + }, + "bones": { + "front-thigh": { + "translate": [ + { + "x": -5.14, + "y": 11.13, + "curve": [ 0.033, -7.77, 0.112, -9.03, 0.034, 11.13, 0.108, 9.74 ] + }, + { + "time": 0.1667, + "x": -9.03, + "y": 7.99, + "curve": [ 0.23, -9.05, 0.314, -1.34, 0.236, 5.93, 0.28, 3.22 ] + }, + { + "time": 0.3333, + "x": 0.41, + "y": 3.19, + "curve": [ 0.352, 2.09, 0.449, 11.16, 0.384, 3.16, 0.449, 4.98 ] + }, + { + "time": 0.5, + "x": 11.17, + "y": 6.76, + "curve": [ 0.571, 10.79, 0.621, -1.83, 0.542, 8.21, 0.625, 11.13 ] + }, + { "time": 0.6667, "x": -5.14, "y": 11.13 } + ] + }, + "torso": { + "rotate": [ + { + "value": -37.66, + "curve": [ 0.034, -37.14, 0.107, -36.21 ] + }, + { + "time": 0.1333, + "value": -36.21, + "curve": [ 0.158, -36.21, 0.209, -38.8 ] + }, + { + "time": 0.2333, + "value": -38.79, + "curve": [ 0.259, -38.78, 0.313, -38.03 ] + }, + { + "time": 0.3333, + "value": -37.66, + "curve": [ 0.357, -37.21, 0.4, -36.21 ] + }, + { + "time": 0.4333, + "value": -36.21, + "curve": [ 0.458, -36.21, 0.539, -38.8 ] + }, + { + "time": 0.5667, + "value": -38.8, + "curve": [ 0.592, -38.8, 0.645, -38 ] + }, + { "time": 0.6667, "value": -37.66 } + ] + }, + "rear-thigh": { + "translate": [ + { + "x": -16.41, + "y": 1.55, + "curve": [ 0.013, -15.67, 0.183, -8.55, 0.03, 2.39, 0.183, 6.17 ] + }, + { + "time": 0.2333, + "x": -8.55, + "y": 6.17, + "curve": [ 0.308, -8.55, 0.492, -19.75, 0.308, 6.17, 0.492, 0.61 ] + }, + { + "time": 0.5667, + "x": -19.75, + "y": 0.61, + "curve": [ 0.592, -19.75, 0.641, -18.06, 0.592, 0.61, 0.632, 0.78 ] + }, + { "time": 0.6667, "x": -16.41, "y": 1.55 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -39.03, + "curve": [ 0.051, -0.1, 0.145, 88.36 ] + }, + { + "time": 0.2333, + "value": 88.36, + "curve": [ 0.28, 88.76, 0.324, 59.52 ] + }, + { + "time": 0.3333, + "value": 51.13, + "curve": [ 0.358, 30.2, 0.445, -74.91 ] + }, + { + "time": 0.5667, + "value": -75.82, + "curve": [ 0.599, -76.06, 0.642, -55.72 ] + }, + { "time": 0.6667, "value": -39.03 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 20.54, + "curve": [ 0.052, 11.42, 0.089, 0.13 ] + }, + { + "time": 0.1333, + "value": 0.15, + "curve": [ 0.186, 0.17, 0.221, 26.29 ] + }, + { + "time": 0.2333, + "value": 32.37, + "curve": [ 0.247, 39.19, 0.286, 61.45 ] + }, + { + "time": 0.3333, + "value": 61.58, + "curve": [ 0.371, 61.69, 0.42, 55.79 ] + }, + { "time": 0.4667, "value": 49.68 }, + { "time": 0.6667, "value": 20.54 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -36.16, + "curve": [ 0.014, -38.8, 0.036, -43.27 ] + }, + { + "time": 0.0667, + "value": -43.37, + "curve": [ 0.102, -43.49, 0.182, -28.46 ] + }, + { + "time": 0.2, + "value": -23.04, + "curve": [ 0.23, -13.87, 0.264, 3.86 ] + }, + { + "time": 0.3333, + "value": 3.7, + "curve": [ 0.38, 3.64, 0.535, -16.22 ] + }, + { "time": 0.5667, "value": -21.29 }, + { "time": 0.6667, "value": -36.16 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 40.5, + "curve": [ 0.028, 23.74, 0.128, -79.86 ] + }, + { + "time": 0.2333, + "value": -79.87, + "curve": [ 0.38, -79.88, 0.403, 63.25 ] + }, + { + "time": 0.5667, + "value": 64.13, + "curve": [ 0.607, 64.35, 0.644, 53.1 ] + }, + { "time": 0.6667, "value": 40.5 } + ], + "translate": [ + { + "x": -3.79, + "y": -0.77, + "curve": [ 0.044, -4.58, 0.169, -5.48, 0.044, 0.93, 0.169, 2.85 ] + }, + { + "time": 0.2333, + "x": -5.48, + "y": 2.85, + "curve": [ 0.346, -5.48, 0.475, -2.68, 0.346, 2.85, 0.475, -3.13 ] + }, + { + "time": 0.5667, + "x": -2.68, + "y": -3.13, + "curve": [ 0.611, -2.68, 0.642, -3.34, 0.611, -3.13, 0.642, -1.73 ] + }, + { "time": 0.6667, "x": -3.79, "y": -0.77 } + ] + }, + "rear-bracer": { + "rotate": [ + { "value": 28.28 }, + { + "time": 0.2333, + "value": -11.12, + "curve": [ 0.252, -14.12, 0.297, -19.37 ] + }, + { + "time": 0.3333, + "value": -19.38, + "curve": [ 0.435, -19.41, 0.522, 38.96 ] + }, + { + "time": 0.5667, + "value": 38.87, + "curve": [ 0.619, 38.76, 0.644, 32.01 ] + }, + { "time": 0.6667, "value": 28.28 } + ] + }, + "neck": { + "rotate": [ + { + "value": 11.88, + "curve": [ 0.024, 11.4, 0.075, 9.74 ] + }, + { + "time": 0.1, + "value": 9.74, + "curve": [ 0.125, 9.74, 0.208, 13.36 ] + }, + { + "time": 0.2333, + "value": 13.36, + "curve": [ 0.258, 13.36, 0.321, 12.2 ] + }, + { + "time": 0.3333, + "value": 11.88, + "curve": [ 0.365, 11.06, 0.408, 9.72 ] + }, + { + "time": 0.4333, + "value": 9.72, + "curve": [ 0.458, 9.72, 0.542, 13.36 ] + }, + { + "time": 0.5667, + "value": 13.36, + "curve": [ 0.592, 13.36, 0.636, 12.48 ] + }, + { "time": 0.6667, "value": 11.88 } + ] + }, + "head": { + "rotate": [ + { + "value": 13.14, + "curve": [ 0.02, 11.99, 0.039, 8.94 ] + }, + { + "time": 0.0667, + "value": 8.93, + "curve": [ 0.122, 8.9, 0.232, 15.8 ] + }, + { + "time": 0.2667, + "value": 15.81, + "curve": [ 0.325, 15.82, 0.357, 8.95 ] + }, + { + "time": 0.4, + "value": 8.93, + "curve": [ 0.444, 8.91, 0.568, 15.8 ] + }, + { + "time": 0.6, + "value": 15.77, + "curve": [ 0.632, 15.74, 0.649, 14.05 ] + }, + { "time": 0.6667, "value": 13.14 } + ], + "scale": [ + { + "curve": [ 0.014, 0.996, 0.068, 0.991, 0.027, 1.005, 0.083, 1.012 ] + }, + { + "time": 0.1, + "x": 0.991, + "y": 1.012, + "curve": [ 0.128, 0.991, 0.205, 1.018, 0.128, 1.012, 0.197, 0.988 ] + }, + { + "time": 0.2333, + "x": 1.018, + "y": 0.988, + "curve": [ 0.272, 1.018, 0.305, 1.008, 0.262, 0.988, 0.311, 0.995 ] + }, + { + "time": 0.3333, + "curve": [ 0.351, 0.995, 0.417, 0.987, 0.359, 1.006, 0.417, 1.013 ] + }, + { + "time": 0.4333, + "x": 0.987, + "y": 1.013, + "curve": [ 0.467, 0.987, 0.533, 1.02, 0.467, 1.013, 0.533, 0.989 ] + }, + { + "time": 0.5667, + "x": 1.02, + "y": 0.989, + "curve": [ 0.592, 1.02, 0.652, 1.004, 0.592, 0.989, 0.644, 0.996 ] + }, + { "time": 0.6667 } + ] + }, + "gun": { + "rotate": [ + { + "value": 12.36, + "curve": [ 0.022, 16.28, 0.087, 20.25 ] + }, + { + "time": 0.1333, + "value": 20.19, + "curve": [ 0.168, 20.32, 0.254, -8.82 ] + }, + { + "time": 0.2667, + "value": -11.88, + "curve": [ 0.291, -17.91, 0.344, -24.11 ] + }, + { + "time": 0.4, + "value": -23.88, + "curve": [ 0.448, -23.69, 0.533, -15.47 ] + }, + { "time": 0.5667, "value": -8.69 }, + { "time": 0.6667, "value": 12.36 } + ] + }, + "hip": { + "rotate": [ + { "value": -8.24 } + ], + "translate": [ + { + "x": -3.6, + "y": -34.1, + "curve": [ 0.042, -3.84, 0.118, 7.62, 0.042, -33.74, 0.112, 20.55 ] + }, + { + "time": 0.1667, + "x": 7.61, + "y": 20.36, + "curve": [ 0.194, 7.6, 0.21, 5.06, 0.204, 20.65, 0.217, -8.69 ] + }, + { + "time": 0.2333, + "x": 1.68, + "y": -18.48, + "curve": [ 0.279, -4.99, 0.297, -5.64, 0.254, -31.08, 0.292, -34.55 ] + }, + { + "time": 0.3333, + "x": -5.76, + "y": -35, + "curve": [ 0.379, -5.9, 0.451, 6.8, 0.384, -35.56, 0.428, 17.6 ] + }, + { + "time": 0.5, + "x": 6.61, + "y": 17.01, + "curve": [ 0.536, 6.47, 0.545, 3.56, 0.533, 16.75, 0.548, -8.71 ] + }, + { + "time": 0.5667, + "x": 0.35, + "y": -18.81, + "curve": [ 0.597, -4.07, 0.642, -3.45, 0.584, -28.58, 0.642, -34.32 ] + }, + { "time": 0.6667, "x": -3.6, "y": -34.1 } + ] + }, + "front-foot-target": { + "rotate": [ + { + "value": -62.54, + "curve": [ 0.015, -74.19, 0.056, -103.19 ] + }, + { + "time": 0.0667, + "value": -111.08, + "curve": [ 0.092, -129.44, 0.189, -146.55 ] + }, + { + "time": 0.2333, + "value": -146.32, + "curve": [ 0.285, -146.06, 0.32, -125.1 ] + }, + { "time": 0.3333, "value": -117.24 }, + { + "time": 0.5, + "value": -35.07, + "curve": [ 0.522, -28.64, 0.546, -24.84 ] + }, + { + "time": 0.5667, + "value": -24.9, + "curve": [ 0.595, -25, 0.623, -40.82 ] + }, + { "time": 0.6667, "value": -62.54 } + ], + "translate": [ + { "x": 16.34, "y": 0.18 }, + { + "time": 0.0667, + "x": -101.43, + "y": 8.04, + "curve": [ 0.085, -131.35, 0.129, -207.69, 0.08, 14.9, 0.124, 113.28 ] + }, + { + "time": 0.1667, + "x": -207.92, + "y": 145.81, + "curve": [ 0.196, -208.13, 0.21, -202.91, 0.186, 160.26, 0.206, 163.48 ] + }, + { + "time": 0.2333, + "x": -189.94, + "y": 163.85, + "curve": [ 0.27, -169.94, 0.31, -126.19, 0.269, 164.35, 0.316, 85.97 ] + }, + { + "time": 0.3333, + "x": -90.56, + "y": 78.57, + "curve": [ 0.355, -57.99, 0.376, -29.14, 0.35, 71.55, 0.376, 66.4 ] + }, + { + "time": 0.4, + "x": 2.87, + "y": 66.38, + "curve": [ 0.412, 19.24, 0.469, 90.73, 0.429, 66.37, 0.469, 70.66 ] + }, + { + "time": 0.5, + "x": 117.18, + "y": 70.46, + "curve": [ 0.522, 136.24, 0.542, 151.33, 0.539, 70.2, 0.555, 38.25 ] + }, + { + "time": 0.5667, + "x": 151.49, + "y": 25.29, + "curve": [ 0.578, 146.76, 0.586, 133.13, 0.572, 19.7, 0.582, 12.23 ] + }, + { "time": 0.6, "x": 115.02, "y": 0.1 }, + { "time": 0.6667, "x": 16.34, "y": 0.18 } + ] + }, + "front-leg-target": { + "translate": [ + { "x": -13.95, "y": -30.34 } + ] + }, + "rear-foot-target": { + "rotate": [ + { "value": 18.55 }, + { + "time": 0.2333, + "value": 167.84, + "curve": [ 0.246, 153.66, 0.256, 129.74 ] + }, + { + "time": 0.2667, + "value": 124.32, + "curve": [ 0.296, 124.43, 0.313, 129.93 ] + }, + { + "time": 0.3667, + "value": 129.87, + "curve": [ 0.421, 128.32, 0.519, 0.98 ] + }, + { + "time": 0.5667, + "curve": [ 0.6, 0.27, 0.642, 4.73 ] + }, + { "time": 0.6667, "value": 18.55 } + ], + "translate": [ + { + "x": -176.39, + "y": 134.12, + "curve": [ 0.018, -142.26, 0.054, -94.41, 0.01, 120.96, 0.044, 84.08 ] + }, + { + "time": 0.0667, + "x": -73.56, + "y": 76.68, + "curve": [ 0.086, -42.82, 0.194, 101.2, 0.098, 66.73, 0.198, 60.88 ] + }, + { "time": 0.2333, "x": 98.32, "y": 32.17 }, + { "time": 0.2667, "x": 49.13, "y": -0.63 }, + { + "time": 0.4, + "x": -147.9, + "y": 0.32, + "curve": [ 0.414, -168.78, 0.478, -284.76, 0.43, 30.09, 0.478, 129.14 ] + }, + { + "time": 0.5, + "x": -283.37, + "y": 167.12, + "curve": [ 0.526, -285.66, 0.548, -280.54, 0.516, 194.84, 0.55, 216.53 ] + }, + { + "time": 0.5667, + "x": -266.98, + "y": 216.12, + "curve": [ 0.581, -256.27, 0.643, -206.54, 0.61, 214.82, 0.65, 145.33 ] + }, + { "time": 0.6667, "x": -176.39, "y": 134.12 } + ] + }, + "rear-leg-target": { + "translate": [ + { "x": 85, "y": -33.59 } + ] + }, + "back-foot-tip": { + "rotate": [ + { + "value": -147.04, + "curve": [ 0.033, -113.4, 0.161, 44.34 ] + }, + { + "time": 0.2333, + "value": 43.48, + "curve": [ 0.24, 43.41, 0.282, 35.72 ] + }, + { + "time": 0.3, + "value": 0.29, + "curve": [ 0.347, 0.28, 0.396, 4.27 ] + }, + { + "time": 0.4, + "curve": [ 0.424, -23.8, 0.525, -181.39 ] + }, + { + "time": 0.5667, + "value": -181.39, + "curve": [ 0.592, -181.39, 0.642, -169.09 ] + }, + { "time": 0.6667, "value": -147.04 } + ] + }, + "front-foot-tip": { + "rotate": [ + { + "value": -0.25, + "curve": [ 0.008, -0.25, 0.056, 1.73 ] + }, + { + "time": 0.0667, + "value": -7.68, + "curve": [ 0.075, -43.13, 0.15, -130.44 ] + }, + { + "time": 0.2, + "value": -130.08, + "curve": [ 0.239, -129.79, 0.272, -126.8 ] + }, + { + "time": 0.3, + "value": -116.24, + "curve": [ 0.333, -103.91, 0.348, -86.1 ] + }, + { + "time": 0.3667, + "value": -71.08, + "curve": [ 0.386, -55.25, 0.415, -32.44 ] + }, + { + "time": 0.4333, + "value": -21.63, + "curve": [ 0.47, -0.01, 0.542, 33.42 ] + }, + { + "time": 0.5667, + "value": 33.2, + "curve": [ 0.622, 32.7, 0.569, 0.64 ] + }, + { "time": 0.6667, "value": -0.25 } + ] + }, + "hair1": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0.087, -6.81, 0.143, -5.75 ] + }, + { + "time": 0.1667, + "value": -4.3, + "curve": [ 0.183, -3.28, 0.209, 2.79 ] + }, + { + "time": 0.2333, + "value": 2.78, + "curve": [ 0.262, 2.77, 0.305, -6.63 ] + }, + { + "time": 0.3333, + "value": -6.64, + "curve": [ 0.419, -6.68, 0.49, -4.84 ] + }, + { + "time": 0.5, + "value": -4.38, + "curve": [ 0.518, -3.56, 0.574, 2.32 ] + }, + { + "time": 0.6, + "value": 2.33, + "curve": [ 0.643, 2.35, 0.633, -6.81 ] + }, + { "time": 0.6667, "value": -6.81 } + ] + }, + "hair2": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0.014, -3.17, 0.109, 43.93 ] + }, + { + "time": 0.1333, + "value": 43.95, + "curve": [ 0.177, 43.97, 0.192, -13.76 ] + }, + { + "time": 0.2667, + "value": -13.83, + "curve": [ 0.302, -13.72, 0.322, -8.86 ] + }, + { + "time": 0.3333, + "value": -6.6, + "curve": [ 0.349, -3.5, 0.436, 41.1 ] + }, + { + "time": 0.4667, + "value": 41.05, + "curve": [ 0.51, 40.99, 0.549, -14.06 ] + }, + { + "time": 0.6, + "value": -14.18, + "curve": [ 0.63, -14.26, 0.656, -9.04 ] + }, + { "time": 0.6667, "value": -6.81 } + ] + }, + "hair3": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0.079, -6.83, 0.108, 0.3 ] + }, + { + "time": 0.1333, + "value": 1.96, + "curve": [ 0.177, 4.89, 0.208, 6.28 ] + }, + { + "time": 0.2333, + "value": 6.29, + "curve": [ 0.313, 6.31, 0.383, 3.49 ] + }, + { + "time": 0.4, + "value": 2.58, + "curve": [ 0.442, 0.28, 0.523, -6.81 ] + }, + { "time": 0.6, "value": -6.81 } + ] + }, + "hair4": { + "rotate": [ + { + "value": -6.81, + "curve": [ 0.011, -4.06, 0.108, 24.92 ] + }, + { + "time": 0.1333, + "value": 24.92, + "curve": [ 0.158, 24.92, 0.208, -10.62 ] + }, + { + "time": 0.2333, + "value": -10.62, + "curve": [ 0.254, -10.62, 0.312, -9.73 ] + }, + { + "time": 0.3333, + "value": -6.4, + "curve": [ 0.356, -2.95, 0.438, 24.93 ] + }, + { + "time": 0.4667, + "value": 24.93, + "curve": [ 0.492, 24.93, 0.575, -9.78 ] + }, + { + "time": 0.6, + "value": -9.78, + "curve": [ 0.617, -9.78, 0.655, -8.63 ] + }, + { "time": 0.6667, "value": -6.81 } + ] + }, + "torso2": { + "rotate": [ + { + "value": 3.5, + "curve": [ 0.07, 3.51, 0.075, 8.69 ] + }, + { + "time": 0.1, + "value": 8.69, + "curve": [ 0.139, 8.69, 0.214, 6.9 ] + }, + { + "time": 0.2333, + "value": 6.33, + "curve": [ 0.266, 5.34, 0.285, 3.48 ] + }, + { + "time": 0.3333, + "value": 3.48, + "curve": [ 0.398, 3.48, 0.408, 8.68 ] + }, + { + "time": 0.4333, + "value": 8.68, + "curve": [ 0.458, 8.68, 0.551, 6.8 ] + }, + { + "time": 0.5667, + "value": 6.26, + "curve": [ 0.598, 5.17, 0.642, 3.49 ] + }, + { "time": 0.6667, "value": 3.5 } + ] + }, + "torso3": { + "rotate": [ + { + "value": 4.52, + "curve": [ 0.067, 4.54, 0.075, -7.27 ] + }, + { + "time": 0.1, + "value": -7.27, + "curve": [ 0.125, -7.27, 0.227, 0.84 ] + }, + { + "time": 0.2333, + "value": 1.24, + "curve": [ 0.254, 2.5, 0.301, 4.51 ] + }, + { + "time": 0.3333, + "value": 4.52, + "curve": [ 0.386, 4.54, 0.408, -7.35 ] + }, + { + "time": 0.4333, + "value": -7.35, + "curve": [ 0.458, -7.35, 0.549, -0.14 ] + }, + { + "time": 0.5667, + "value": 0.95, + "curve": [ 0.586, 2.18, 0.632, 4.54 ] + }, + { "time": 0.6667, "value": 4.52 } + ] + }, + "aim-constraint-target": { + "rotate": [ + { "value": 30.57 } + ] + }, + "rear-foot": { + "rotate": [ + { "value": -6.5 } + ] + }, + "front-foot": { + "rotate": [ + { "value": 4.5 } + ] + }, + "head-control": { + "translate": [ + { + "y": -9.94, + "curve": [ 0.058, 0, 0.175, -15.32, 0.044, -4.19, 0.175, 5 ] + }, + { + "time": 0.2333, + "x": -15.32, + "y": 5, + "curve": [ 0.317, -15.32, 0.429, -9.74, 0.317, 5, 0.382, -31.71 ] + }, + { + "time": 0.4667, + "x": -7.81, + "y": -31.59, + "curve": [ 0.507, -5.76, 0.617, 0, 0.549, -31.47, 0.628, -13.33 ] + }, + { "time": 0.6667, "y": -9.94 } + ] + }, + "front-shoulder": { + "translate": [ + { + "x": -0.74, + "y": 11.22, + "curve": [ 0.061, -0.74, 0.144, 1.17, 0.061, 11.22, 0.143, -17.93 ] + }, + { + "time": 0.2333, + "x": 1.19, + "y": -17.9, + "curve": [ 0.54, 1.25, 0.558, -0.74, 0.545, -17.8, 0.558, 11.22 ] + }, + { "time": 0.6667, "x": -0.74, "y": 11.22 } + ] + }, + "back-shoulder": { + "translate": [ + { + "curve": [ 0.083, 0, 0.25, 0, 0.083, 0, 0.25, 8.93 ] + }, + { + "time": 0.3333, + "y": 8.93, + "curve": [ 0.417, 0, 0.583, 0, 0.417, 8.93, 0.583, 0 ] + }, + { "time": 0.6667 } + ] + } + }, + "ik": { + "front-leg-ik": [ + { "softness": 10, "bendPositive": false }, + { "time": 0.5667, "softness": 14.8, "bendPositive": false }, + { "time": 0.6, "softness": 48.2, "bendPositive": false }, + { "time": 0.6667, "softness": 10, "bendPositive": false } + ], + "rear-leg-ik": [ + { "bendPositive": false }, + { "time": 0.1667, "softness": 22.5, "bendPositive": false }, + { "time": 0.3, "softness": 61.4, "bendPositive": false }, + { "time": 0.6667, "bendPositive": false } + ] + }, + "events": [ + { "time": 0.2333, "name": "footstep" }, + { "time": 0.5667, "name": "footstep" } + ] + }, + "run-to-idle": { + "slots": { + "front-fist": { + "attachment": [ + { "name": "front-fist-open" } + ] + } + }, + "bones": { + "front-foot-target": { + "translate": [ + { + "x": -16.5, + "y": 3.41, + "curve": [ 0.033, -16.5, 0.1, -69.06, 0.033, 3.41, 0.1, 0 ] + }, + { "time": 0.1333, "x": -69.06 } + ] + }, + "hip": { + "translate": [ + { + "x": -28.78, + "y": -72.96, + "curve": [ 0.036, -28.63, 0.2, -10.85, 0.135, -62.35, 0.2, -23.15 ] + }, + { "time": 0.2667, "x": -11.97, "y": -23.15 } + ] + }, + "rear-foot-target": { + "translate": [ + { + "x": 33.15, + "y": 31.61, + "curve": [ 0.017, 33.15, 0.05, 24.41, 0.017, 31.61, 0.041, 20.73 ] + }, + { + "time": 0.0667, + "x": 24.41, + "y": 0.19, + "curve": [ 0.117, 24.41, 0.217, 48.87, 0.117, 0.19, 0.217, 0 ] + }, + { "time": 0.2667, "x": 48.87 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -80.61, + "curve": [ 0.067, -80.61, 0.2, -60.87 ] + }, + { "time": 0.2667, "value": -60.87 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 8.79, + "curve": [ 0.041, 8.79, 0.115, 6.3 ] + }, + { + "time": 0.1667, + "value": 6.41, + "curve": [ 0.201, 6.48, 0.241, 42.46 ] + }, + { "time": 0.2667, "value": 42.46 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 55.3, + "curve": [ 0.067, 55.3, 0.2, 39.2 ] + }, + { "time": 0.2667, "value": 39.2 } + ] + }, + "head": { + "rotate": [ + { + "curve": [ 0.05, 0, 0.083, 2.67 ] + }, + { + "time": 0.1333, + "value": 2.67, + "curve": [ 0.15, 2.67, 0.25, -6.75 ] + }, + { "time": 0.2667, "value": -6.75 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": 38.26, + "curve": [ 0.041, 38.26, 0.127, -2.19 ] + }, + { + "time": 0.1667, + "value": -3, + "curve": [ 0.209, -3.84, 0.241, 0 ] + }, + { "time": 0.2667 } + ], + "scale": [ + { + "x": 0.844, + "curve": [ 0.067, 0.844, 0.2, 1, 0.067, 1, 0.2, 1 ] + }, + { "time": 0.2667 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 57.24, + "curve": [ 0.067, 57.24, 0.2, 0 ] + }, + { "time": 0.2667 } + ] + }, + "gun": { + "rotate": [ + { + "value": 2.28, + "curve": [ 0.041, 2.28, 0.105, 15.34 ] + }, + { + "time": 0.1667, + "value": 15.32, + "curve": [ 0.205, 15.31, 0.241, 0 ] + }, + { "time": 0.2667 } + ] + }, + "torso": { + "rotate": [ + { + "value": -12.98, + "curve": [ 0.033, -12.98, 0.103, -14.81 ] + }, + { + "time": 0.1333, + "value": -16.63, + "curve": [ 0.168, -18.69, 0.233, -22.88 ] + }, + { "time": 0.2667, "value": -22.88 } + ], + "scale": [ + { + "x": 0.963, + "y": 1.074, + "curve": [ 0.067, 0.963, 0.132, 1, 0.067, 1.074, 0.132, 1 ] + }, + { "time": 0.2667 } + ] + }, + "neck": { + "rotate": [ + {}, + { "time": 0.2667, "value": 3.78 } + ] + }, + "hair3": { + "rotate": [ + { + "curve": [ 0.033, 0, 0.1, 0.88 ] + }, + { + "time": 0.1333, + "value": 0.88, + "curve": [ 0.167, 0.88, 0.233, 0 ] + }, + { "time": 0.2667 } + ] + }, + "hair4": { + "rotate": [ + { + "curve": [ 0.033, 0, 0.1, 15.97 ] + }, + { + "time": 0.1333, + "value": 15.97, + "curve": [ 0.167, 15.97, 0.233, 0 ] + }, + { "time": 0.2667 } + ] + }, + "hair1": { + "rotate": [ + { + "curve": [ 0.033, 0, 0.1, 10.76 ] + }, + { + "time": 0.1333, + "value": 10.76, + "curve": [ 0.167, 10.76, 0.233, 0 ] + }, + { "time": 0.2667 } + ] + }, + "hair2": { + "rotate": [ + { + "curve": [ 0.014, -2.28, 0.042, -7.84 ] + }, + { + "time": 0.0667, + "value": -7.82, + "curve": [ 0.108, -7.79, 0.166, 6.57 ] + }, + { + "time": 0.2, + "value": 6.67, + "curve": [ 0.222, 6.73, 0.255, 1.98 ] + }, + { "time": 0.2667 } + ] + }, + "torso2": { + "rotate": [ + { + "curve": [ 0.041, 0, 0.107, 3.03 ] + }, + { + "time": 0.1667, + "value": 3.03, + "curve": [ 0.205, 3.03, 0.241, 0 ] + }, + { "time": 0.2667 } + ] + }, + "torso3": { + "rotate": [ + { + "curve": [ 0.049, 0, 0.166, 0.66 ] + }, + { + "time": 0.2, + "value": 0.66, + "curve": [ 0.232, 0.65, 0.249, -2.15 ] + }, + { "time": 0.2667, "value": -2.15 } + ] + }, + "head-control": { + "translate": [ + { "x": -10.12, "y": 8.71 }, + { "time": 0.2667 } + ] + }, + "front-shoulder": { + "translate": [ + { "x": 4.91, "y": 11.54 }, + { "time": 0.2667 } + ] + } + } + }, + "shoot": { + "slots": { + "muzzle": { + "rgba": [ + { "time": 0.1333, "color": "ffffffff" }, + { "time": 0.2, "color": "ffffff62" } + ], + "attachment": [ + { "time": 0.0333, "name": "muzzle01" }, + { "time": 0.0667, "name": "muzzle02" }, + { "time": 0.1, "name": "muzzle03" }, + { "time": 0.1333, "name": "muzzle04" }, + { "time": 0.1667, "name": "muzzle05" }, + { "time": 0.2 } + ] + }, + "muzzle-glow": { + "rgba": [ + { "color": "ff0c0c00" }, + { + "time": 0.0333, + "color": "ffc9adff", + "curve": [ 0.255, 1, 0.273, 1, 0.255, 0.76, 0.273, 0.4, 0.255, 0.65, 0.273, 0.22, 0.255, 1, 0.273, 1 ] + }, + { "time": 0.3, "color": "ff400cff" }, + { "time": 0.6333, "color": "ff0c0c00" } + ], + "attachment": [ + { "name": "muzzle-glow" } + ] + }, + "muzzle-ring": { + "rgba": [ + { + "time": 0.0333, + "color": "d8baffff", + "curve": [ 0.202, 0.85, 0.214, 0.84, 0.202, 0.73, 0.214, 0.73, 0.202, 1, 0.214, 1, 0.202, 1, 0.214, 0.21 ] + }, + { "time": 0.2333, "color": "d7baff00" } + ], + "attachment": [ + { "time": 0.0333, "name": "muzzle-ring" }, + { "time": 0.2333 } + ] + }, + "muzzle-ring2": { + "rgba": [ + { + "time": 0.0333, + "color": "d8baffff", + "curve": [ 0.174, 0.85, 0.184, 0.84, 0.174, 0.73, 0.184, 0.73, 0.174, 1, 0.184, 1, 0.174, 1, 0.184, 0.21 ] + }, + { "time": 0.2, "color": "d7baff00" } + ], + "attachment": [ + { "time": 0.0333, "name": "muzzle-ring" }, + { "time": 0.2 } + ] + }, + "muzzle-ring3": { + "rgba": [ + { + "time": 0.0333, + "color": "d8baffff", + "curve": [ 0.174, 0.85, 0.184, 0.84, 0.174, 0.73, 0.184, 0.73, 0.174, 1, 0.184, 1, 0.174, 1, 0.184, 0.21 ] + }, + { "time": 0.2, "color": "d7baff00" } + ], + "attachment": [ + { "time": 0.0333, "name": "muzzle-ring" }, + { "time": 0.2 } + ] + }, + "muzzle-ring4": { + "rgba": [ + { + "time": 0.0333, + "color": "d8baffff", + "curve": [ 0.174, 0.85, 0.184, 0.84, 0.174, 0.73, 0.184, 0.73, 0.174, 1, 0.184, 1, 0.174, 1, 0.184, 0.21 ] + }, + { "time": 0.2, "color": "d7baff00" } + ], + "attachment": [ + { "time": 0.0333, "name": "muzzle-ring" }, + { "time": 0.2 } + ] + } + }, + "bones": { + "gun": { + "rotate": [ + { + "time": 0.0667, + "curve": [ 0.094, 25.89, 0.112, 45.27 ] + }, + { + "time": 0.1333, + "value": 45.35, + "curve": [ 0.192, 45.28, 0.18, -0.09 ] + }, + { "time": 0.6333 } + ] + }, + "muzzle": { + "translate": [ + { "x": -11.02, "y": 25.16 } + ] + }, + "rear-upper-arm": { + "translate": [ + { + "time": 0.0333, + "curve": [ 0.045, 0.91, 0.083, 3.46, 0.044, 0.86, 0.083, 3.32 ] + }, + { + "time": 0.1, + "x": 3.46, + "y": 3.32, + "curve": [ 0.133, 3.46, 0.176, -0.1, 0.133, 3.32, 0.169, 0 ] + }, + { "time": 0.2333 } + ] + }, + "rear-bracer": { + "translate": [ + { + "time": 0.0333, + "curve": [ 0.075, -3.78, 0.083, -4.36, 0.08, -2.7, 0.083, -2.88 ] + }, + { + "time": 0.1, + "x": -4.36, + "y": -2.88, + "curve": [ 0.133, -4.36, 0.168, 0.18, 0.133, -2.88, 0.167, 0 ] + }, + { "time": 0.2333 } + ] + }, + "gun-tip": { + "translate": [ + {}, + { "time": 0.3, "x": 3.15, "y": 0.39 } + ], + "scale": [ + { "x": 0.366, "y": 0.366 }, + { "time": 0.0333, "x": 1.453, "y": 1.453 }, + { "time": 0.3, "x": 0.366, "y": 0.366 } + ] + }, + "muzzle-ring": { + "translate": [ + { "time": 0.0333 }, + { "time": 0.2333, "x": 64.47 } + ], + "scale": [ + { "time": 0.0333 }, + { "time": 0.2333, "x": 5.951, "y": 5.951 } + ] + }, + "muzzle-ring2": { + "translate": [ + { "time": 0.0333 }, + { "time": 0.2, "x": 172.57 } + ], + "scale": [ + { "time": 0.0333 }, + { "time": 0.2, "x": 4, "y": 4 } + ] + }, + "muzzle-ring3": { + "translate": [ + { "time": 0.0333 }, + { "time": 0.2, "x": 277.17 } + ], + "scale": [ + { "time": 0.0333 }, + { "time": 0.2, "x": 2, "y": 2 } + ] + }, + "muzzle-ring4": { + "translate": [ + { "time": 0.0333 }, + { "time": 0.2, "x": 392.06 } + ] + } + } + }, + "walk": { + "bones": { + "rear-foot-target": { + "rotate": [ + { + "value": -32.82, + "curve": [ 0.035, -42.69, 0.057, -70.49 ] + }, + { + "time": 0.1, + "value": -70.59, + "curve": [ 0.236, -70.78, 0.335, -9.87 ] + }, + { + "time": 0.3667, + "value": -1.56, + "curve": [ 0.393, 5.5, 0.477, 13.96 ] + }, + { + "time": 0.5, + "value": 13.96, + "curve": [ 0.519, 13.96, 0.508, 0.13 ] + }, + { "time": 0.5667, "value": -0.28 }, + { + "time": 0.7333, + "value": -0.28, + "curve": [ 0.827, -0.06, 0.958, -21.07 ] + }, + { "time": 1, "value": -32.82 } + ], + "translate": [ + { + "x": -167.32, + "y": 0.58, + "curve": [ 0.022, -180.55, 0.075, -235.51, 0.045, 0.58, 0.075, 30.12 ] + }, + { + "time": 0.1, + "x": -235.51, + "y": 39.92, + "curve": [ 0.142, -235.51, 0.208, -201.73, 0.138, 54.94, 0.18, 60.78 ] + }, + { + "time": 0.2333, + "x": -176.33, + "y": 61.48, + "curve": [ 0.272, -136.61, 0.321, -45.18, 0.275, 62.02, 0.321, 56.6 ] + }, + { + "time": 0.3667, + "x": 8.44, + "y": 49.67, + "curve": [ 0.403, 51.03, 0.486, 66.86, 0.401, 44.37, 0.48, 23.11 ] + }, + { "time": 0.5, "x": 66.57, "y": 14.22 }, + { "time": 0.5333, "x": 52.58, "y": 0.6 }, + { "time": 1, "x": -167.32, "y": 0.58 } + ] + }, + "front-foot-target": { + "rotate": [ + { + "value": 18.19, + "curve": [ 0.01, 11.17, 0.043, 1.37 ] + }, + { "time": 0.1, "value": 0.47 }, + { + "time": 0.2333, + "value": 0.55, + "curve": [ 0.364, 0.3, 0.515, -80.48 ] + }, + { + "time": 0.7333, + "value": -80.78, + "curve": [ 0.788, -80.38, 0.921, 17.42 ] + }, + { "time": 1, "value": 18.19 } + ], + "translate": [ + { + "x": 139.21, + "y": 22.94, + "curve": [ 0.025, 139.21, 0.069, 111.46, 0.031, 3.25, 0.075, 0.06 ] + }, + { "time": 0.1, "x": 96.69, "y": 0.06 }, + { + "time": 0.5, + "x": -94.87, + "y": -0.03, + "curve": [ 0.518, -106.82, 0.575, -152.56, 0.534, 5.42, 0.557, 38.46 ] + }, + { + "time": 0.6, + "x": -152.56, + "y": 57.05, + "curve": [ 0.633, -152.56, 0.688, -128.05, 0.643, 75.61, 0.7, 84.14 ] + }, + { + "time": 0.7333, + "x": -109.42, + "y": 84.14, + "curve": [ 0.771, -93.91, 0.832, -30.64, 0.787, 84.14, 0.799, 89.65 ] + }, + { + "time": 0.8667, + "x": 17, + "y": 75.25, + "curve": [ 0.903, 66.18, 0.967, 139.21, 0.932, 61.53, 0.967, 44.02 ] + }, + { "time": 1, "x": 139.21, "y": 22.94 } + ] + }, + "hip": { + "rotate": [ + { "value": -4.35 } + ], + "translate": [ + { + "x": -2.86, + "y": -13.86, + "curve": [ 0.025, -2.84, 0.067, -2.82, 0.028, -19.14, 0.054, -24.02 ] + }, + { + "time": 0.1, + "x": -2.61, + "y": -24.19, + "curve": [ 0.143, -2.34, 0.202, -1.79, 0.152, -23.98, 0.213, -14.81 ] + }, + { + "time": 0.2667, + "x": -1.21, + "y": -7.12, + "curve": [ 0.308, -0.86, 0.345, -0.51, 0.306, -1.63, 0.341, 3.15 ] + }, + { + "time": 0.3667, + "x": -0.33, + "y": 3.15, + "curve": [ 0.41, 0.02, 0.458, 0.26, 0.427, 3.3, 0.481, -6.75 ] + }, + { + "time": 0.5, + "x": 0.26, + "y": -10.59, + "curve": [ 0.553, 0.26, 0.559, 0.2, 0.519, -14.41, 0.548, -23.88 ] + }, + { + "time": 0.6, + "x": -0.17, + "y": -23.71, + "curve": [ 0.663, -0.72, 0.798, -2.09, 0.702, -23.36, 0.802, 3.53 ] + }, + { + "time": 0.8667, + "x": -2.46, + "y": 3.48, + "curve": [ 0.901, -2.63, 0.967, -2.87, 0.913, 3.45, 0.967, -7.64 ] + }, + { "time": 1, "x": -2.86, "y": -13.86 } + ] + }, + "front-foot-tip": { + "rotate": [ + { + "value": 28.96, + "curve": [ 0.056, 28.74, 0.049, 19.6 ] + }, + { "time": 0.0667, "value": 1.68 }, + { + "time": 0.5, + "value": -10, + "curve": [ 0.525, -10, 0.592, -54.69 ] + }, + { + "time": 0.6, + "value": -59.66, + "curve": [ 0.623, -74.54, 0.674, -101.78 ] + }, + { + "time": 0.7333, + "value": -101.78, + "curve": [ 0.812, -101.78, 0.855, -84.67 ] + }, + { + "time": 0.8667, + "value": -63.53, + "curve": [ 0.869, -58.38, 0.975, 28.96 ] + }, + { "time": 1, "value": 28.96 } + ] + }, + "torso": { + "rotate": [ + { + "value": -20.72, + "curve": [ 0.025, -20.57, 0.071, -20.04 ] + }, + { + "time": 0.1333, + "value": -20.04, + "curve": [ 0.187, -20.04, 0.285, -21.16 ] + }, + { + "time": 0.3667, + "value": -21.16, + "curve": [ 0.405, -21.16, 0.47, -20.9 ] + }, + { + "time": 0.5, + "value": -20.71, + "curve": [ 0.518, -20.6, 0.582, -20.03 ] + }, + { + "time": 0.6333, + "value": -20.04, + "curve": [ 0.709, -20.05, 0.815, -21.18 ] + }, + { + "time": 0.8667, + "value": -21.18, + "curve": [ 0.908, -21.18, 0.971, -20.93 ] + }, + { "time": 1, "value": -20.72 } + ] + }, + "neck": { + "rotate": [ + { + "value": 17.78, + "curve": [ 0.025, 17.93, 0.071, 18.46 ] + }, + { + "time": 0.1333, + "value": 18.46, + "curve": [ 0.187, 18.46, 0.285, 17.34 ] + }, + { + "time": 0.3667, + "value": 17.34, + "curve": [ 0.405, 17.34, 0.47, 17.6 ] + }, + { + "time": 0.5, + "value": 17.79, + "curve": [ 0.518, 17.9, 0.582, 18.47 ] + }, + { + "time": 0.6333, + "value": 18.46, + "curve": [ 0.709, 18.45, 0.815, 17.32 ] + }, + { + "time": 0.8667, + "value": 17.32, + "curve": [ 0.908, 17.32, 0.971, 17.57 ] + }, + { "time": 1, "value": 17.78 } + ] + }, + "head": { + "rotate": [ + { + "value": -12.23, + "curve": [ 0.061, -12.23, 0.191, -7.45 ] + }, + { + "time": 0.2667, + "value": -7.43, + "curve": [ 0.341, -7.42, 0.421, -12.23 ] + }, + { + "time": 0.5, + "value": -12.23, + "curve": [ 0.567, -12.26, 0.694, -7.46 ] + }, + { + "time": 0.7667, + "value": -7.47, + "curve": [ 0.853, -7.49, 0.943, -12.23 ] + }, + { "time": 1, "value": -12.23 } + ], + "scale": [ + { + "curve": [ 0.039, 1, 0.084, 0.991, 0.039, 1, 0.084, 1.019 ] + }, + { + "time": 0.1333, + "x": 0.991, + "y": 1.019, + "curve": [ 0.205, 0.991, 0.318, 1.019, 0.205, 1.019, 0.337, 0.992 ] + }, + { + "time": 0.4, + "x": 1.019, + "y": 0.992, + "curve": [ 0.456, 1.019, 0.494, 1.001, 0.483, 0.991, 0.493, 0.999 ] + }, + { + "time": 0.5, + "curve": [ 0.508, 0.998, 0.584, 0.991, 0.51, 1.002, 0.584, 1.019 ] + }, + { + "time": 0.6333, + "x": 0.991, + "y": 1.019, + "curve": [ 0.705, 0.991, 0.818, 1.019, 0.705, 1.019, 0.837, 0.992 ] + }, + { + "time": 0.9, + "x": 1.019, + "y": 0.992, + "curve": [ 0.956, 1.019, 0.955, 1, 0.983, 0.991, 0.955, 1 ] + }, + { "time": 1 } + ] + }, + "back-foot-tip": { + "rotate": [ + { "value": 4.09 }, + { "time": 0.0333, "value": 3.05 }, + { + "time": 0.1, + "value": -59.01, + "curve": [ 0.124, -72.97, 0.169, -100.05 ] + }, + { + "time": 0.2333, + "value": -99.71, + "curve": [ 0.326, -99.21, 0.349, -37.4 ] + }, + { + "time": 0.3667, + "value": -17.85, + "curve": [ 0.388, 4.74, 0.451, 32.35 ] + }, + { + "time": 0.5, + "value": 32.4, + "curve": [ 0.537, 32.44, 0.566, 6.43 ] + }, + { "time": 0.5667, "value": 2 }, + { "time": 1, "value": 4.09 } + ] + }, + "front-thigh": { + "translate": [ + { + "x": 17.15, + "y": -0.09, + "curve": [ 0.178, 17.14, 0.295, -4.26, 0.009, -0.09, 0.475, 0.02 ] + }, + { + "time": 0.5, + "x": -4.26, + "y": 0.02, + "curve": [ 0.705, -4.27, 0.848, 17.15, 0.525, 0.02, 0.975, -0.09 ] + }, + { "time": 1, "x": 17.15, "y": -0.09 } + ] + }, + "rear-thigh": { + "translate": [ + { + "x": -17.71, + "y": -4.63, + "curve": [ 0.036, -19.81, 0.043, -20.86, 0.036, -4.63, 0.05, -7.03 ] + }, + { + "time": 0.1, + "x": -20.95, + "y": -7.06, + "curve": [ 0.162, -21.05, 0.4, 7.79, 0.2, -7.13, 0.4, -1.9 ] + }, + { + "time": 0.5, + "x": 7.79, + "y": -1.94, + "curve": [ 0.612, 7.69, 0.875, -10.49, 0.592, -1.97, 0.917, -3.25 ] + }, + { "time": 1, "x": -17.71, "y": -4.63 } + ] + }, + "torso2": { + "rotate": [ + { + "value": 1, + "curve": [ 0.006, 1.2, 0.084, 2.88 ] + }, + { + "time": 0.1333, + "value": 2.88, + "curve": [ 0.205, 2.88, 0.284, -1.17 ] + }, + { + "time": 0.3667, + "value": -1.17, + "curve": [ 0.411, -1.17, 0.481, 0.57 ] + }, + { + "time": 0.5, + "value": 1, + "curve": [ 0.515, 1.33, 0.59, 2.83 ] + }, + { + "time": 0.6333, + "value": 2.85, + "curve": [ 0.683, 2.86, 0.796, -1.2 ] + }, + { + "time": 0.8667, + "value": -1.2, + "curve": [ 0.916, -1.2, 0.984, 0.62 ] + }, + { "time": 1, "value": 1 } + ] + }, + "torso3": { + "rotate": [ + { "value": -1.81 } + ] + }, + "front-upper-arm": { + "rotate": [ + { + "value": -9.51, + "curve": [ 0.021, -13.32, 0.058, -19.4 ] + }, + { + "time": 0.1, + "value": -19.4, + "curve": [ 0.238, -19.69, 0.337, 7.78 ] + }, + { + "time": 0.3667, + "value": 16.2, + "curve": [ 0.399, 25.42, 0.497, 60.19 ] + }, + { + "time": 0.6, + "value": 60.26, + "curve": [ 0.719, 60.13, 0.845, 27.61 ] + }, + { + "time": 0.8667, + "value": 22.45, + "curve": [ 0.892, 16.38, 0.979, -3.27 ] + }, + { "time": 1, "value": -9.51 } + ] + }, + "front-bracer": { + "rotate": [ + { + "value": 13.57, + "curve": [ 0.022, 9.71, 0.147, -3.78 ] + }, + { + "time": 0.3667, + "value": -3.69, + "curve": [ 0.457, -3.66, 0.479, 0.83 ] + }, + { + "time": 0.5, + "value": 4.05, + "curve": [ 0.513, 6.08, 0.635, 30.8 ] + }, + { + "time": 0.8, + "value": 30.92, + "curve": [ 0.974, 31, 0.98, 18.35 ] + }, + { "time": 1, "value": 13.57 } + ] + }, + "front-fist": { + "rotate": [ + { + "value": -28.72, + "curve": [ 0.024, -31.74, 0.176, -43.4 ] + }, + { + "time": 0.3667, + "value": -43.6, + "curve": [ 0.403, -43.65, 0.47, -40.15 ] + }, + { + "time": 0.5, + "value": -35.63, + "curve": [ 0.547, -28.59, 0.624, -4.57 ] + }, + { + "time": 0.7333, + "value": -4.59, + "curve": [ 0.891, -4.62, 0.954, -24.28 ] + }, + { "time": 1, "value": -28.48 } + ] + }, + "rear-upper-arm": { + "rotate": [ + { + "value": 28.28, + "curve": [ 0.034, 30.94, 0.068, 32.05 ] + }, + { + "time": 0.1, + "value": 31.88, + "curve": [ 0.194, 31.01, 0.336, -0.11 ] + }, + { + "time": 0.3667, + "value": -7.11, + "curve": [ 0.421, -19.73, 0.53, -46.21 ] + }, + { + "time": 0.6, + "value": -45.75, + "curve": [ 0.708, -45.03, 0.844, -13.56 ] + }, + { + "time": 0.8667, + "value": -6.48, + "curve": [ 0.909, 6.59, 0.958, 24.21 ] + }, + { "time": 1, "value": 28.28 } + ] + }, + "hair2": { + "rotate": [ + { + "value": -2.79, + "curve": [ 0.074, -2.84, 0.121, 25.08 ] + }, + { + "time": 0.2333, + "value": 24.99, + "curve": [ 0.35, 24.89, 0.427, -2.86 ] + }, + { + "time": 0.5, + "value": -2.8, + "curve": [ 0.575, -2.73, 0.652, 24.5 ] + }, + { + "time": 0.7333, + "value": 24.55, + "curve": [ 0.828, 24.6, 0.932, -2.69 ] + }, + { "time": 1, "value": -2.79 } + ] + }, + "hair4": { + "rotate": [ + { + "value": -6.01, + "curve": [ 0.106, -5.97, 0.151, 18.62 ] + }, + { + "time": 0.2333, + "value": 18.72, + "curve": [ 0.336, 18.7, 0.405, -11.37 ] + }, + { + "time": 0.5, + "value": -11.45, + "curve": [ 0.626, -11.46, 0.629, 18.94 ] + }, + { + "time": 0.7333, + "value": 18.92, + "curve": [ 0.833, 18.92, 0.913, -6.06 ] + }, + { "time": 1, "value": -6.01 } + ], + "translate": [ + { "x": 0.03, "y": 1.35 } + ] + }, + "rear-bracer": { + "rotate": [ + { + "value": 10.06, + "curve": [ 0.044, 11.16, 0.063, 11.49 ] + }, + { + "time": 0.1, + "value": 11.49, + "curve": [ 0.215, 11.49, 0.336, 2.92 ] + }, + { + "time": 0.3667, + "value": 0.84, + "curve": [ 0.416, -2.52, 0.498, -10.84 ] + }, + { + "time": 0.6, + "value": -10.83, + "curve": [ 0.762, -10.71, 0.845, -3.05 ] + }, + { + "time": 0.8667, + "value": -1.34, + "curve": [ 0.917, 2.54, 0.977, 8.81 ] + }, + { "time": 1, "value": 10.06 } + ] + }, + "gun": { + "rotate": [ + { + "value": -14.67, + "curve": [ 0.086, -14.67, 0.202, 8.31 ] + }, + { + "time": 0.2333, + "value": 12.14, + "curve": [ 0.279, 17.71, 0.391, 25.79 ] + }, + { + "time": 0.5, + "value": 25.77, + "curve": [ 0.631, 25.74, 0.694, 4.53 ] + }, + { + "time": 0.7333, + "value": -0.65, + "curve": [ 0.768, -5.21, 0.902, -14.4 ] + }, + { "time": 1, "value": -14.67 } + ] + }, + "front-leg-target": { + "translate": [ + { + "x": -2.83, + "y": -8.48, + "curve": [ 0.008, -2.83, 0.058, 0.09, 0.001, 4.97, 0.058, 6.68 ] + }, + { + "time": 0.0667, + "x": 0.09, + "y": 6.68, + "curve": [ 0.3, 0.09, 0.767, -2.83, 0.3, 6.68, 0.767, -8.48 ] + }, + { "time": 1, "x": -2.83, "y": -8.48 } + ] + }, + "hair1": { + "rotate": [ + { + "curve": [ 0.028, 1.24, 0.016, 3.46 ] + }, + { + "time": 0.1, + "value": 3.45, + "curve": [ 0.159, 3.45, 0.189, 0.23 ] + }, + { + "time": 0.2333, + "value": -2.29, + "curve": [ 0.265, -4.32, 0.305, -5.92 ] + }, + { + "time": 0.3667, + "value": -5.94, + "curve": [ 0.446, -5.96, 0.52, 3.41 ] + }, + { + "time": 0.6, + "value": 3.42, + "curve": [ 0.717, 3.42, 0.772, -5.93 ] + }, + { + "time": 0.8667, + "value": -5.97, + "curve": [ 0.933, -5.99, 0.982, -0.94 ] + }, + { "time": 1 } + ] + }, + "hair3": { + "rotate": [ + { + "curve": [ 0.067, 0, 0.159, -10.48 ] + }, + { + "time": 0.2333, + "value": -10.49, + "curve": [ 0.334, -10.5, 0.439, -0.09 ] + }, + { + "time": 0.5, + "value": -0.09, + "curve": [ 0.569, -0.09, 0.658, -10.75 ] + }, + { + "time": 0.7333, + "value": -10.7, + "curve": [ 0.833, -10.63, 0.947, 0 ] + }, + { "time": 1 } + ] + }, + "gun-tip": { + "rotate": [ + { "time": 0.2333, "value": 0.11 } + ] + }, + "muzzle-ring": { + "rotate": [ + { "time": 0.2333, "value": 0.11 } + ] + }, + "muzzle-ring2": { + "rotate": [ + { "time": 0.2667, "value": 0.11 } + ] + }, + "muzzle-ring3": { + "rotate": [ + { "time": 0.2667, "value": 0.11 } + ] + }, + "muzzle-ring4": { + "rotate": [ + { "time": 0.2667, "value": 0.11 } + ] + }, + "back-shoulder": { + "translate": [ + { + "x": -0.18, + "y": -4.49, + "curve": [ 0.133, -0.18, 0.333, 7.69, 0.133, -4.49, 0.333, 2.77 ] + }, + { + "time": 0.4667, + "x": 7.69, + "y": 2.77, + "curve": [ 0.6, 7.69, 0.858, -0.18, 0.6, 2.77, 0.858, -4.49 ] + }, + { "time": 1, "x": -0.18, "y": -4.49 } + ] + }, + "front-shoulder": { + "translate": [ + { + "x": 1.46, + "y": 9.37, + "curve": [ 0.162, 1.41, 0.333, -1.66, 0.162, 9.37, 0.301, -7.23 ] + }, + { + "time": 0.5, + "x": -1.6, + "y": -7.27, + "curve": [ 0.735, -1.5, 0.847, 1.46, 0.723, -7.31, 0.838, 9.32 ] + }, + { "time": 1, "x": 1.46, "y": 9.37 } + ] + }, + "head-control": { + "translate": [ + { + "x": -6.46, + "y": -8.4, + "curve": [ 0.053, -5.31, 0.167, -3.64, 0.093, -8.4, 0.196, -3.81 ] + }, + { + "time": 0.2333, + "x": -3.64, + "y": -1.32, + "curve": [ 0.309, -3.64, 0.436, -5.84, 0.275, 1.43, 0.38, 10.3 ] + }, + { + "time": 0.5, + "x": -7.03, + "y": 10.29, + "curve": [ 0.538, -7.75, 0.66, -10.54, 0.598, 10.27, 0.694, 1.56 ] + }, + { + "time": 0.7333, + "x": -10.54, + "y": -1.26, + "curve": [ 0.797, -10.54, 0.933, -7.91, 0.768, -3.79, 0.875, -8.4 ] + }, + { "time": 1, "x": -6.46, "y": -8.4 } + ] + } + }, + "ik": { + "front-leg-ik": [ + { + "softness": 25.7, + "bendPositive": false, + "curve": [ 0.008, 1, 0.025, 1, 0.008, 25.7, 0.025, 9.9 ] + }, + { + "time": 0.0333, + "softness": 9.9, + "bendPositive": false, + "curve": [ 0.15, 1, 0.383, 1, 0.15, 9.9, 0.383, 43.2 ] + }, + { + "time": 0.5, + "softness": 43.2, + "bendPositive": false, + "curve": [ 0.625, 1, 0.875, 1, 0.625, 43.2, 0.846, 45.57 ] + }, + { "time": 1, "softness": 25.7, "bendPositive": false } + ], + "rear-leg-ik": [ + { "softness": 5, "bendPositive": false }, + { "time": 0.4333, "softness": 4.9, "bendPositive": false }, + { "time": 0.5, "softness": 28.81, "bendPositive": false }, + { "time": 0.6, "softness": 43.8, "bendPositive": false }, + { "time": 1, "softness": 5, "bendPositive": false } + ] + }, + "events": [ + { "name": "footstep" }, + { "time": 0.5, "name": "footstep" } + ] + } +} +} \ No newline at end of file diff --git a/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/spineboy/spineboy-pro.skel b/spine-godot/example/spineboy/spineboy-pro.skel new file mode 100644 index 000000000..199839b49 Binary files /dev/null and b/spine-godot/example/spineboy/spineboy-pro.skel differ diff --git a/spine-godot/example/spineboy/spineboy.atlas b/spine-godot/example/spineboy/spineboy.atlas new file mode 100644 index 000000000..b07ccc3bf --- /dev/null +++ b/spine-godot/example/spineboy/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/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/spineboy.png b/spine-godot/example/spineboy/spineboy.png new file mode 100644 index 000000000..d1c3ac1be Binary files /dev/null and b/spine-godot/example/spineboy/spineboy.png differ diff --git a/spine-godot/example/spineboy/spineboy.png.import b/spine-godot/example/spineboy/spineboy.png.import new file mode 100644 index 000000000..8518e5044 --- /dev/null +++ b/spine-godot/example/spineboy/spineboy.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/spineboy.png-a63588ec3a5ca6e83ef256edf38d798a.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://spineboy/spineboy.png" +dest_files=[ "res://.import/spineboy.png-a63588ec3a5ca6e83ef256edf38d798a.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 +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/spine-godot/godot/custom.py b/spine-godot/godot/custom.py new file mode 100644 index 000000000..946f42cf2 --- /dev/null +++ b/spine-godot/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/godot/modules/spine_godot/GodotSpineExtension.cpp b/spine-godot/godot/modules/spine_godot/GodotSpineExtension.cpp new file mode 100644 index 000000000..cace4e354 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/GodotSpineExtension.h b/spine-godot/godot/modules/spine_godot/GodotSpineExtension.h new file mode 100644 index 000000000..e00726051 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.cpp b/spine-godot/godot/modules/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.cpp new file mode 100644 index 000000000..9c1cc80e5 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.h b/spine-godot/godot/modules/spine_godot/ResourceFormatLoaderSpineSkeletonJsonData.h new file mode 100644 index 000000000..9736655f6 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.cpp b/spine-godot/godot/modules/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.cpp new file mode 100644 index 000000000..5fa669c04 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.h b/spine-godot/godot/modules/spine_godot/ResourceFormatSaverSpineSkeletonJsonData.h new file mode 100644 index 000000000..2c42ee5d0 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SCsub b/spine-godot/godot/modules/spine_godot/SCsub new file mode 100644 index 000000000..f7d88af0b --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineAnimation.cpp b/spine-godot/godot/modules/spine_godot/SpineAnimation.cpp new file mode 100644 index 000000000..7f0772f24 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineAnimation.h b/spine-godot/godot/modules/spine_godot/SpineAnimation.h new file mode 100644 index 000000000..98dbed587 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineAnimationState.cpp b/spine-godot/godot/modules/spine_godot/SpineAnimationState.cpp new file mode 100644 index 000000000..155a1d6d3 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineAnimationState.h b/spine-godot/godot/modules/spine_godot/SpineAnimationState.h new file mode 100644 index 000000000..097be72ac --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineAnimationStateDataResource.cpp b/spine-godot/godot/modules/spine_godot/SpineAnimationStateDataResource.cpp new file mode 100644 index 000000000..de4041ec2 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineAnimationStateDataResource.h b/spine-godot/godot/modules/spine_godot/SpineAnimationStateDataResource.h new file mode 100644 index 000000000..58f0cd536 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineAtlasResource.cpp b/spine-godot/godot/modules/spine_godot/SpineAtlasResource.cpp new file mode 100644 index 000000000..088426621 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineAtlasResource.h b/spine-godot/godot/modules/spine_godot/SpineAtlasResource.h new file mode 100644 index 000000000..84c7cc9ca --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineAttachment.cpp b/spine-godot/godot/modules/spine_godot/SpineAttachment.cpp new file mode 100644 index 000000000..e25f54c5e --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineAttachment.h b/spine-godot/godot/modules/spine_godot/SpineAttachment.h new file mode 100644 index 000000000..81ec52c9d --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineBone.cpp b/spine-godot/godot/modules/spine_godot/SpineBone.cpp new file mode 100644 index 000000000..afde7a781 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineBone.h b/spine-godot/godot/modules/spine_godot/SpineBone.h new file mode 100644 index 000000000..b7efd1381 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineBoneData.cpp b/spine-godot/godot/modules/spine_godot/SpineBoneData.cpp new file mode 100644 index 000000000..b870527dc --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineBoneData.h b/spine-godot/godot/modules/spine_godot/SpineBoneData.h new file mode 100644 index 000000000..dc3e3feb6 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineCollisionShapeProxy.cpp b/spine-godot/godot/modules/spine_godot/SpineCollisionShapeProxy.cpp new file mode 100644 index 000000000..9015db60d --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineCollisionShapeProxy.h b/spine-godot/godot/modules/spine_godot/SpineCollisionShapeProxy.h new file mode 100644 index 000000000..c29eaa591 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineConstant.cpp b/spine-godot/godot/modules/spine_godot/SpineConstant.cpp new file mode 100644 index 000000000..760ff668a --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineConstant.h b/spine-godot/godot/modules/spine_godot/SpineConstant.h new file mode 100644 index 000000000..c7f86d8b9 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineConstraintData.cpp b/spine-godot/godot/modules/spine_godot/SpineConstraintData.cpp new file mode 100644 index 000000000..16bbac435 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineConstraintData.h b/spine-godot/godot/modules/spine_godot/SpineConstraintData.h new file mode 100644 index 000000000..35b9dd52a --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineEvent.cpp b/spine-godot/godot/modules/spine_godot/SpineEvent.cpp new file mode 100644 index 000000000..9d753db33 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineEvent.h b/spine-godot/godot/modules/spine_godot/SpineEvent.h new file mode 100644 index 000000000..bbbf0b986 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineEventData.cpp b/spine-godot/godot/modules/spine_godot/SpineEventData.cpp new file mode 100644 index 000000000..bca195e79 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineEventData.h b/spine-godot/godot/modules/spine_godot/SpineEventData.h new file mode 100644 index 000000000..1cf669f26 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineIkConstraint.cpp b/spine-godot/godot/modules/spine_godot/SpineIkConstraint.cpp new file mode 100644 index 000000000..d88492b48 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineIkConstraint.h b/spine-godot/godot/modules/spine_godot/SpineIkConstraint.h new file mode 100644 index 000000000..c7c4aeefe --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineIkConstraintData.cpp b/spine-godot/godot/modules/spine_godot/SpineIkConstraintData.cpp new file mode 100644 index 000000000..62731aecf --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineIkConstraintData.h b/spine-godot/godot/modules/spine_godot/SpineIkConstraintData.h new file mode 100644 index 000000000..da0434d0b --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpinePathConstraint.cpp b/spine-godot/godot/modules/spine_godot/SpinePathConstraint.cpp new file mode 100644 index 000000000..3df032a22 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpinePathConstraint.h b/spine-godot/godot/modules/spine_godot/SpinePathConstraint.h new file mode 100644 index 000000000..dcd41d09e --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpinePathConstraintData.cpp b/spine-godot/godot/modules/spine_godot/SpinePathConstraintData.cpp new file mode 100644 index 000000000..5d0f34b64 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpinePathConstraintData.h b/spine-godot/godot/modules/spine_godot/SpinePathConstraintData.h new file mode 100644 index 000000000..068a68ec0 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineRendererObject.h b/spine-godot/godot/modules/spine_godot/SpineRendererObject.h new file mode 100644 index 000000000..11b9370a9 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineRuntimeEditorPlugin.cpp b/spine-godot/godot/modules/spine_godot/SpineRuntimeEditorPlugin.cpp new file mode 100644 index 000000000..80de73af7 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineRuntimeEditorPlugin.h b/spine-godot/godot/modules/spine_godot/SpineRuntimeEditorPlugin.h new file mode 100644 index 000000000..cf95ec696 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineSkeleton.cpp b/spine-godot/godot/modules/spine_godot/SpineSkeleton.cpp new file mode 100644 index 000000000..2f3d1fd2b --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineSkeleton.h b/spine-godot/godot/modules/spine_godot/SpineSkeleton.h new file mode 100644 index 000000000..942665c6a --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineSkeletonDataResource.cpp b/spine-godot/godot/modules/spine_godot/SpineSkeletonDataResource.cpp new file mode 100644 index 000000000..977913c61 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineSkeletonDataResource.h b/spine-godot/godot/modules/spine_godot/SpineSkeletonDataResource.h new file mode 100644 index 000000000..eaabaa11c --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineSkeletonJsonDataResource.cpp b/spine-godot/godot/modules/spine_godot/SpineSkeletonJsonDataResource.cpp new file mode 100644 index 000000000..d332a791a --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineSkeletonJsonDataResource.h b/spine-godot/godot/modules/spine_godot/SpineSkeletonJsonDataResource.h new file mode 100644 index 000000000..8b6045bf6 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineSkin.cpp b/spine-godot/godot/modules/spine_godot/SpineSkin.cpp new file mode 100644 index 000000000..b30f01ae5 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineSkin.h b/spine-godot/godot/modules/spine_godot/SpineSkin.h new file mode 100644 index 000000000..3e1780f2a --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineSkinAttachmentMapEntries.cpp b/spine-godot/godot/modules/spine_godot/SpineSkinAttachmentMapEntries.cpp new file mode 100644 index 000000000..67089b011 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineSkinAttachmentMapEntries.h b/spine-godot/godot/modules/spine_godot/SpineSkinAttachmentMapEntries.h new file mode 100644 index 000000000..b0f3922ef --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineSlot.cpp b/spine-godot/godot/modules/spine_godot/SpineSlot.cpp new file mode 100644 index 000000000..14149b9e1 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineSlot.h b/spine-godot/godot/modules/spine_godot/SpineSlot.h new file mode 100644 index 000000000..afca412af --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineSlotData.cpp b/spine-godot/godot/modules/spine_godot/SpineSlotData.cpp new file mode 100644 index 000000000..bf3c48f20 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineSlotData.h b/spine-godot/godot/modules/spine_godot/SpineSlotData.h new file mode 100644 index 000000000..1778bba55 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineSprite.cpp b/spine-godot/godot/modules/spine_godot/SpineSprite.cpp new file mode 100644 index 000000000..29f163c42 --- /dev/null +++ b/spine-godot/godot/modules/spine_godot/SpineSprite.cpp @@ -0,0 +1,959 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE 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 + for (size_t i = 0, n = get_child_count(); i < n; ++i) { + auto node = get_child(i); + if (node && node->is_class("SpineSpriteMeshInstance2D")) { + if (mesh_instances.find((SpineSpriteMeshInstance2D *) node) == -1) { + ms.push_back(node); + } + } + } + for (size_t i = 0, n = ms.size(); i < n; ++i) { + remove_child(ms[i]); + memdelete(ms[i]); + } + ms.clear(); +} + +#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) { + 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, vertices); + 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/godot/modules/spine_godot/SpineSprite.h b/spine-godot/godot/modules/spine_godot/SpineSprite.h new file mode 100644 index 000000000..fc7276091 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineSpriteAnimateDialog.cpp b/spine-godot/godot/modules/spine_godot/SpineSpriteAnimateDialog.cpp new file mode 100644 index 000000000..33bebdd66 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineSpriteAnimateDialog.h b/spine-godot/godot/modules/spine_godot/SpineSpriteAnimateDialog.h new file mode 100644 index 000000000..04f26d619 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineSpriteMeshInstance2D.cpp b/spine-godot/godot/modules/spine_godot/SpineSpriteMeshInstance2D.cpp new file mode 100644 index 000000000..aba2064f0 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineSpriteMeshInstance2D.h b/spine-godot/godot/modules/spine_godot/SpineSpriteMeshInstance2D.h new file mode 100644 index 000000000..c748b21cb --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineTimeline.cpp b/spine-godot/godot/modules/spine_godot/SpineTimeline.cpp new file mode 100644 index 000000000..29561c595 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineTimeline.h b/spine-godot/godot/modules/spine_godot/SpineTimeline.h new file mode 100644 index 000000000..404d7dd26 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineTrackEntry.cpp b/spine-godot/godot/modules/spine_godot/SpineTrackEntry.cpp new file mode 100644 index 000000000..fe6979af9 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineTrackEntry.h b/spine-godot/godot/modules/spine_godot/SpineTrackEntry.h new file mode 100644 index 000000000..25c4b785f --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineTransformConstraint.cpp b/spine-godot/godot/modules/spine_godot/SpineTransformConstraint.cpp new file mode 100644 index 000000000..2166a5917 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineTransformConstraint.h b/spine-godot/godot/modules/spine_godot/SpineTransformConstraint.h new file mode 100644 index 000000000..6430f05fb --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineTransformConstraintData.cpp b/spine-godot/godot/modules/spine_godot/SpineTransformConstraintData.cpp new file mode 100644 index 000000000..c7534cafb --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/SpineTransformConstraintData.h b/spine-godot/godot/modules/spine_godot/SpineTransformConstraintData.h new file mode 100644 index 000000000..6c1b21569 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/config.py b/spine-godot/godot/modules/spine_godot/config.py new file mode 100644 index 000000000..827e2c435 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/register_types.cpp b/spine-godot/godot/modules/spine_godot/register_types.cpp new file mode 100644 index 000000000..1fd9ad626 --- /dev/null +++ b/spine-godot/godot/modules/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/godot/modules/spine_godot/register_types.h b/spine-godot/godot/modules/spine_godot/register_types.h new file mode 100644 index 000000000..59ef9515f --- /dev/null +++ b/spine-godot/godot/modules/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(); diff --git a/spine-godot/setup.sh b/spine-godot/setup.sh new file mode 100755 index 000000000..9f0bc593c --- /dev/null +++ b/spine-godot/setup.sh @@ -0,0 +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