mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-04 14:24:53 +08:00
[haxe] Physics porting - Missing Skeleton loaders, examples and TODO
This commit is contained in:
parent
49350d1174
commit
bb9d23c4d0
3
spine-haxe/.vscode/settings.json
vendored
Normal file
3
spine-haxe/.vscode/settings.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"cmake.configureOnOpen": false
|
||||
}
|
||||
116
spine-haxe/example/assets/cloud-pot.atlas
Normal file
116
spine-haxe/example/assets/cloud-pot.atlas
Normal file
@ -0,0 +1,116 @@
|
||||
cloud-pot.png
|
||||
size:4096,512
|
||||
filter:MipMapLinearLinear,MipMapLinearLinear
|
||||
cloud-base-1
|
||||
bounds:1109,8,458,415
|
||||
offsets:5,1,465,420
|
||||
cloud-base-10
|
||||
bounds:279,175,190,199
|
||||
offsets:2,1,193,201
|
||||
cloud-base-2
|
||||
bounds:1575,10,416,413
|
||||
offsets:3,1,420,415
|
||||
cloud-base-3
|
||||
bounds:2331,91,332,324
|
||||
offsets:16,1,349,327
|
||||
rotate:90
|
||||
cloud-base-4
|
||||
bounds:1999,78,345,324
|
||||
offsets:6,1,352,326
|
||||
rotate:90
|
||||
cloud-base-5
|
||||
bounds:3496,137,286,248
|
||||
offsets:2,1,289,250
|
||||
rotate:90
|
||||
cloud-base-6
|
||||
bounds:2663,104,319,269
|
||||
offsets:2,1,322,272
|
||||
rotate:90
|
||||
cloud-base-7
|
||||
bounds:2940,128,287,295
|
||||
offsets:12,1,300,297
|
||||
cloud-base-8
|
||||
bounds:3235,123,300,253
|
||||
offsets:6,1,307,256
|
||||
rotate:90
|
||||
cloud-base-9
|
||||
bounds:3752,209,211,214
|
||||
offsets:2,1,214,216
|
||||
cloud-cheeks
|
||||
bounds:548,227,433,156
|
||||
offsets:1,1,435,158
|
||||
cloud-eyes-closed
|
||||
bounds:279,382,261,41
|
||||
offsets:1,1,263,43
|
||||
cloud-eyes-open
|
||||
bounds:8,374,263,49
|
||||
offsets:1,1,265,51
|
||||
cloud-eyes-reflex
|
||||
bounds:548,391,237,32
|
||||
offsets:1,1,239,34
|
||||
cloud-mouth-closed
|
||||
bounds:166,336,95,30
|
||||
offsets:1,1,97,32
|
||||
cloud-mouth-open
|
||||
bounds:3971,307,116,68
|
||||
offsets:1,1,118,70
|
||||
rotate:90
|
||||
leaf-big
|
||||
bounds:989,359,40,98
|
||||
rotate:90
|
||||
leaf-small
|
||||
bounds:989,319,32,57
|
||||
offsets:1,1,34,59
|
||||
rotate:90
|
||||
petal-1
|
||||
bounds:477,292,50,34
|
||||
offsets:1,1,52,36
|
||||
petal-2
|
||||
bounds:166,296,54,32
|
||||
offsets:1,1,56,34
|
||||
petal-3
|
||||
bounds:477,334,56,40
|
||||
offsets:1,1,58,42
|
||||
pot-base
|
||||
bounds:8,250,150,116
|
||||
offsets:1,1,152,118
|
||||
pot-eyes-closed
|
||||
bounds:1011,408,90,15
|
||||
offsets:1,1,92,17
|
||||
pot-eyes-open
|
||||
bounds:989,291,78,20
|
||||
offsets:1,1,80,22
|
||||
pot-mouth-open
|
||||
bounds:4047,394,25,29
|
||||
offsets:1,1,27,31
|
||||
pot-mouth-pouty
|
||||
bounds:228,287,33,17
|
||||
offsets:1,1,35,19
|
||||
pot-mouth-smile
|
||||
bounds:3971,281,25,18
|
||||
offsets:1,1,27,20
|
||||
pot-mouth-smile-big
|
||||
bounds:228,312,37,16
|
||||
offsets:1,1,39,18
|
||||
rain-blue
|
||||
bounds:4047,310,21,34
|
||||
offsets:1,1,23,36
|
||||
rain-color
|
||||
bounds:4047,270,16,32
|
||||
offsets:1,1,18,34
|
||||
rain-green
|
||||
bounds:4047,352,21,34
|
||||
offsets:1,1,23,36
|
||||
rain-white
|
||||
bounds:1054,330,21,42
|
||||
offsets:1,1,23,44
|
||||
rotate:90
|
||||
rain-white-reflex
|
||||
bounds:4080,406,8,17
|
||||
offsets:1,1,10,19
|
||||
stem
|
||||
bounds:793,407,16,210
|
||||
rotate:90
|
||||
stem-end
|
||||
bounds:1075,298,23,24
|
||||
offsets:1,1,25,26
|
||||
779
spine-haxe/example/assets/cloud-pot.json
Normal file
779
spine-haxe/example/assets/cloud-pot.json
Normal file
@ -0,0 +1,779 @@
|
||||
{
|
||||
"skeleton": { "hash": "WlXIcG5lrwQ", "spine": "4.2.67-beta", "x": -345, "y": -17, "width": 756, "height": 1098 },
|
||||
"bones": [
|
||||
{ "name": "root" },
|
||||
{ "name": "pot-control", "parent": "root", "x": 5, "y": 42 },
|
||||
{ "name": "cloud", "parent": "pot-control", "x": 26.5, "y": 772 },
|
||||
{ "name": "cloud-base-1", "parent": "cloud", "x": -4, "y": 57 },
|
||||
{ "name": "cloud-base-2", "parent": "cloud-base-1", "x": 148.5, "y": -18.5 },
|
||||
{ "name": "cloud-base-3", "parent": "cloud-base-1", "x": -182, "y": -87.5 },
|
||||
{ "name": "cloud-base-4", "parent": "cloud", "x": -31.5, "y": -77 },
|
||||
{ "name": "cloud-base-5", "parent": "cloud-base-4", "x": 177.5, "y": 8 },
|
||||
{ "name": "cloud-base-6", "parent": "cloud-base-1", "x": -150.5, "y": 40 },
|
||||
{ "name": "cloud-base-7", "parent": "cloud-base-1", "x": 8.5, "y": 36.5 },
|
||||
{ "name": "cloud-base-8", "parent": "cloud-base-2", "x": 3.5, "y": 68.5 },
|
||||
{ "name": "cloud-base-9", "parent": "cloud-base-3", "x": -83.5, "y": 30.5 },
|
||||
{ "name": "cloud-base-10", "parent": "cloud-base-5", "x": 137, "y": 54.5 },
|
||||
{ "name": "rain-blue", "parent": "cloud", "x": 102.49, "y": -26 },
|
||||
{ "name": "rain-color", "parent": "cloud", "x": -39.42, "y": -26 },
|
||||
{ "name": "rain-green", "parent": "cloud", "x": 35.08, "y": -26 },
|
||||
{ "name": "rain-white", "parent": "cloud", "x": -103.92, "y": -26 },
|
||||
{ "name": "pot", "parent": "pot-control", "x": -5, "y": -42 },
|
||||
{ "name": "pot-face", "parent": "pot", "x": -1.06, "y": 28.16 },
|
||||
{ "name": "leaf-big", "parent": "pot", "length": 46.73, "rotation": 119.24, "x": 4.04, "y": 95.05 },
|
||||
{ "name": "leaf-big-tip", "parent": "leaf-big", "length": 46.73, "x": 46.73 },
|
||||
{ "name": "leaf-small", "parent": "pot", "length": 51.32, "rotation": 50.93, "x": 10.16, "y": 96.81 },
|
||||
{ "name": "stem", "parent": "pot", "length": 104.76, "rotation": 90, "x": 7.24, "y": 92.61 },
|
||||
{ "name": "stem2", "parent": "stem", "length": 69.84, "x": 104.76 },
|
||||
{ "name": "stem3", "parent": "stem2", "length": 34.92, "x": 69.84 },
|
||||
{ "name": "petal-3", "parent": "stem3", "length": 37.74, "rotation": 1.03, "x": 30.73, "y": 0.64 },
|
||||
{ "name": "petal-1", "parent": "stem3", "length": 40.11, "rotation": 70.18, "x": 34.13, "y": 3.02 },
|
||||
{ "name": "petal-2", "parent": "stem3", "length": 48.62, "rotation": -80.34, "x": 32.09, "y": -4.46 },
|
||||
{ "name": "cloud-face", "parent": "cloud", "y": 14.93 }
|
||||
],
|
||||
"slots": [
|
||||
{ "name": "rain-green", "bone": "rain-green", "attachment": "rain-green" },
|
||||
{ "name": "rain-blue", "bone": "rain-blue", "attachment": "rain-blue" },
|
||||
{ "name": "rain-color", "bone": "rain-color", "attachment": "rain-color" },
|
||||
{ "name": "rain-white", "bone": "rain-white", "attachment": "rain-white" },
|
||||
{ "name": "rain-white-reflex", "bone": "rain-white", "attachment": "rain-white-reflex" },
|
||||
{ "name": "petal-1", "bone": "petal-1", "attachment": "petal-1" },
|
||||
{ "name": "petal-2", "bone": "petal-2", "attachment": "petal-2" },
|
||||
{ "name": "petal-3", "bone": "petal-3", "attachment": "petal-3" },
|
||||
{ "name": "stem", "bone": "stem", "attachment": "stem" },
|
||||
{ "name": "leaf-big", "bone": "leaf-big", "attachment": "leaf-big" },
|
||||
{ "name": "leaf-small", "bone": "leaf-small", "attachment": "leaf-small" },
|
||||
{ "name": "stem-end", "bone": "stem3", "attachment": "stem-end" },
|
||||
{ "name": "pot-base", "bone": "pot", "attachment": "pot-base" },
|
||||
{ "name": "pot-mouth", "bone": "pot-face", "attachment": "pot-mouth-smile-big" },
|
||||
{ "name": "pot-eyes", "bone": "pot-face", "attachment": "pot-eyes-open" },
|
||||
{ "name": "cloud-base-1", "bone": "cloud-base-1", "attachment": "cloud-base-1" },
|
||||
{ "name": "cloud-base-2", "bone": "cloud-base-2", "attachment": "cloud-base-2" },
|
||||
{ "name": "cloud-base-3", "bone": "cloud-base-3", "attachment": "cloud-base-3" },
|
||||
{ "name": "cloud-base-4", "bone": "cloud-base-4", "attachment": "cloud-base-4" },
|
||||
{ "name": "cloud-base-5", "bone": "cloud-base-5", "attachment": "cloud-base-5" },
|
||||
{ "name": "cloud-base-6", "bone": "cloud-base-6", "attachment": "cloud-base-6" },
|
||||
{ "name": "cloud-base-7", "bone": "cloud-base-7", "attachment": "cloud-base-7" },
|
||||
{ "name": "cloud-base-8", "bone": "cloud-base-8", "attachment": "cloud-base-8" },
|
||||
{ "name": "cloud-base-9", "bone": "cloud-base-9", "attachment": "cloud-base-9" },
|
||||
{ "name": "cloud-base-10", "bone": "cloud-base-10", "attachment": "cloud-base-10" },
|
||||
{ "name": "cloud-cheeks", "bone": "cloud-face", "attachment": "cloud-cheeks" },
|
||||
{ "name": "cloud-eyes", "bone": "cloud-face", "attachment": "cloud-eyes-open" },
|
||||
{ "name": "cloud-eyes-reflex", "bone": "cloud-face", "attachment": "cloud-eyes-reflex" },
|
||||
{ "name": "cloud-mouth", "bone": "cloud-face", "attachment": "cloud-mouth-closed" }
|
||||
],
|
||||
"physics": [
|
||||
{
|
||||
"name": "cloud",
|
||||
"order": 25,
|
||||
"bone": "cloud",
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"inertia": 0.5,
|
||||
"strength": 172.8,
|
||||
"damping": 0.8571,
|
||||
"mass": 3
|
||||
},
|
||||
{
|
||||
"name": "cloud-face",
|
||||
"order": 24,
|
||||
"bone": "cloud-face",
|
||||
"x": 0.1923,
|
||||
"y": 0.141,
|
||||
"limit": 500,
|
||||
"inertia": 0.5,
|
||||
"damping": 0.15
|
||||
},
|
||||
{
|
||||
"name": "pot-face",
|
||||
"order": 23,
|
||||
"bone": "pot-face",
|
||||
"x": 0.1667,
|
||||
"y": 0.1026,
|
||||
"limit": 500,
|
||||
"inertia": 0.5,
|
||||
"strength": 137.3,
|
||||
"damping": 0.6078
|
||||
},
|
||||
{
|
||||
"name": "cloud-base/cloud-base-1",
|
||||
"order": 4,
|
||||
"bone": "cloud-base-1",
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"limit": 500,
|
||||
"inertia": 0.3741,
|
||||
"strength": 134.7,
|
||||
"damping": 0.8163,
|
||||
"mass": 2.8
|
||||
},
|
||||
{
|
||||
"name": "cloud-base/cloud-base-2",
|
||||
"order": 5,
|
||||
"bone": "cloud-base-2",
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"limit": 300,
|
||||
"inertia": 0.3741,
|
||||
"strength": 134.7,
|
||||
"damping": 0.8163,
|
||||
"mass": 2.8
|
||||
},
|
||||
{
|
||||
"name": "cloud-base/cloud-base-3",
|
||||
"order": 6,
|
||||
"bone": "cloud-base-3",
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"limit": 300,
|
||||
"inertia": 0.3741,
|
||||
"strength": 134.7,
|
||||
"damping": 0.8163,
|
||||
"mass": 2.8
|
||||
},
|
||||
{
|
||||
"name": "cloud-base/cloud-base-4",
|
||||
"order": 7,
|
||||
"bone": "cloud-base-4",
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"limit": 500,
|
||||
"inertia": 0.3741,
|
||||
"strength": 134.7,
|
||||
"damping": 0.8163,
|
||||
"mass": 2.8
|
||||
},
|
||||
{
|
||||
"name": "cloud-base/cloud-base-5",
|
||||
"order": 8,
|
||||
"bone": "cloud-base-5",
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"limit": 300,
|
||||
"inertia": 0.3741,
|
||||
"strength": 134.7,
|
||||
"damping": 0.8163,
|
||||
"mass": 2.8
|
||||
},
|
||||
{
|
||||
"name": "cloud-base/cloud-base-6",
|
||||
"order": 9,
|
||||
"bone": "cloud-base-6",
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"limit": 300,
|
||||
"inertia": 0.3741,
|
||||
"strength": 134.7,
|
||||
"damping": 0.8163,
|
||||
"mass": 2.8
|
||||
},
|
||||
{
|
||||
"name": "cloud-base/cloud-base-7",
|
||||
"order": 10,
|
||||
"bone": "cloud-base-7",
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"limit": 300,
|
||||
"inertia": 0.3741,
|
||||
"strength": 134.7,
|
||||
"damping": 0.8163,
|
||||
"mass": 2.8
|
||||
},
|
||||
{
|
||||
"name": "cloud-base/cloud-base-8",
|
||||
"order": 11,
|
||||
"bone": "cloud-base-8",
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"limit": 300,
|
||||
"inertia": 0.3741,
|
||||
"strength": 134.7,
|
||||
"damping": 0.8163,
|
||||
"mass": 2.8
|
||||
},
|
||||
{
|
||||
"name": "cloud-base/cloud-base-9",
|
||||
"order": 12,
|
||||
"bone": "cloud-base-9",
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"limit": 300,
|
||||
"inertia": 0.3741,
|
||||
"strength": 134.7,
|
||||
"damping": 0.8163,
|
||||
"mass": 2.8
|
||||
},
|
||||
{
|
||||
"name": "cloud-base/cloud-base-10",
|
||||
"order": 13,
|
||||
"bone": "cloud-base-10",
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"limit": 300,
|
||||
"inertia": 0.3741,
|
||||
"strength": 134.7,
|
||||
"damping": 0.8163,
|
||||
"mass": 2.8
|
||||
},
|
||||
{
|
||||
"name": "plant/leaf-big",
|
||||
"order": 14,
|
||||
"bone": "leaf-big",
|
||||
"rotate": 0.7532,
|
||||
"shearX": 0.2468,
|
||||
"limit": 500,
|
||||
"inertia": 0.5,
|
||||
"strength": 160.5,
|
||||
"damping": 0.8367,
|
||||
"mass": 4
|
||||
},
|
||||
{
|
||||
"name": "plant/leaf-big-tip",
|
||||
"order": 22,
|
||||
"bone": "leaf-big-tip",
|
||||
"rotate": 1,
|
||||
"limit": 500,
|
||||
"inertia": 0.5,
|
||||
"strength": 160.5,
|
||||
"damping": 0.8367,
|
||||
"mass": 4
|
||||
},
|
||||
{
|
||||
"name": "plant/leaf-small",
|
||||
"order": 15,
|
||||
"bone": "leaf-small",
|
||||
"rotate": 0.6026,
|
||||
"limit": 500,
|
||||
"inertia": 0.5,
|
||||
"strength": 160.5,
|
||||
"damping": 0.8367,
|
||||
"mass": 4
|
||||
},
|
||||
{
|
||||
"name": "plant/petal-1",
|
||||
"order": 19,
|
||||
"bone": "petal-1",
|
||||
"rotate": 1,
|
||||
"limit": 500,
|
||||
"inertia": 0.5,
|
||||
"strength": 164.6,
|
||||
"damping": 0.6531,
|
||||
"mass": 2.6
|
||||
},
|
||||
{
|
||||
"name": "plant/petal-2",
|
||||
"order": 21,
|
||||
"bone": "petal-2",
|
||||
"rotate": 1,
|
||||
"limit": 500,
|
||||
"inertia": 0.5,
|
||||
"strength": 164.6,
|
||||
"damping": 0.6531,
|
||||
"mass": 2.6
|
||||
},
|
||||
{
|
||||
"name": "plant/petal-3",
|
||||
"order": 20,
|
||||
"bone": "petal-3",
|
||||
"rotate": 1,
|
||||
"limit": 500,
|
||||
"inertia": 0.5,
|
||||
"strength": 164.6,
|
||||
"damping": 0.7823,
|
||||
"mass": 3.83
|
||||
},
|
||||
{
|
||||
"name": "plant/stem",
|
||||
"order": 16,
|
||||
"bone": "stem",
|
||||
"rotate": 0.8205,
|
||||
"limit": 700,
|
||||
"inertia": 0.5,
|
||||
"strength": 152.4,
|
||||
"damping": 0.9388,
|
||||
"mass": 2.6
|
||||
},
|
||||
{
|
||||
"name": "plant/stem2",
|
||||
"order": 17,
|
||||
"bone": "stem2",
|
||||
"rotate": 0.8205,
|
||||
"limit": 700,
|
||||
"inertia": 0.5,
|
||||
"strength": 152.4,
|
||||
"damping": 0.9388,
|
||||
"mass": 2.6
|
||||
},
|
||||
{
|
||||
"name": "plant/stem3",
|
||||
"order": 18,
|
||||
"bone": "stem3",
|
||||
"rotate": 0.8205,
|
||||
"limit": 700,
|
||||
"inertia": 0.5,
|
||||
"strength": 152.4,
|
||||
"damping": 0.9388,
|
||||
"mass": 2.6
|
||||
},
|
||||
{
|
||||
"name": "rain/rain-blue",
|
||||
"order": 3,
|
||||
"bone": "rain-blue",
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"strength": 0,
|
||||
"gravity": 70
|
||||
},
|
||||
{
|
||||
"name": "rain/rain-color",
|
||||
"order": 2,
|
||||
"bone": "rain-color",
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"strength": 0,
|
||||
"gravity": 70
|
||||
},
|
||||
{
|
||||
"name": "rain/rain-green",
|
||||
"order": 1,
|
||||
"bone": "rain-green",
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"strength": 0,
|
||||
"gravity": 70
|
||||
},
|
||||
{ "name": "rain/rain-white", "bone": "rain-white", "x": 1, "y": 1, "strength": 0, "gravity": 70 }
|
||||
],
|
||||
"skins": [
|
||||
{
|
||||
"name": "default",
|
||||
"attachments": {
|
||||
"cloud-base-1": {
|
||||
"cloud-base-1": { "width": 465, "height": 420 }
|
||||
},
|
||||
"cloud-base-2": {
|
||||
"cloud-base-2": { "width": 420, "height": 415 }
|
||||
},
|
||||
"cloud-base-3": {
|
||||
"cloud-base-3": { "width": 349, "height": 327 }
|
||||
},
|
||||
"cloud-base-4": {
|
||||
"cloud-base-4": { "width": 352, "height": 326 }
|
||||
},
|
||||
"cloud-base-5": {
|
||||
"cloud-base-5": { "width": 289, "height": 250 }
|
||||
},
|
||||
"cloud-base-6": {
|
||||
"cloud-base-6": { "width": 322, "height": 272 }
|
||||
},
|
||||
"cloud-base-7": {
|
||||
"cloud-base-7": { "width": 300, "height": 297 }
|
||||
},
|
||||
"cloud-base-8": {
|
||||
"cloud-base-8": { "width": 307, "height": 256 }
|
||||
},
|
||||
"cloud-base-9": {
|
||||
"cloud-base-9": { "width": 214, "height": 216 }
|
||||
},
|
||||
"cloud-base-10": {
|
||||
"cloud-base-10": { "width": 193, "height": 201 }
|
||||
},
|
||||
"cloud-cheeks": {
|
||||
"cloud-cheeks": { "x": -19, "y": -53.93, "width": 435, "height": 158 }
|
||||
},
|
||||
"cloud-eyes": {
|
||||
"cloud-eyes-closed": { "x": -10, "y": -5.43, "width": 263, "height": 43 },
|
||||
"cloud-eyes-open": { "x": -8, "y": -4.43, "width": 265, "height": 51 }
|
||||
},
|
||||
"cloud-eyes-reflex": {
|
||||
"cloud-eyes-reflex": { "x": -10, "y": 2.07, "width": 239, "height": 34 }
|
||||
},
|
||||
"cloud-mouth": {
|
||||
"cloud-mouth-closed": { "y": -14.93, "width": 97, "height": 32 },
|
||||
"cloud-mouth-open": { "x": -0.5, "y": -27.93, "width": 118, "height": 70 }
|
||||
},
|
||||
"leaf-big": {
|
||||
"leaf-big": {
|
||||
"type": "mesh",
|
||||
"uvs": [ 1, 1, 0, 1, 0, 0.75, 0, 0.5, 0, 0.25, 0, 0, 1, 0, 1, 0.25, 1, 0.5, 1, 0.75 ],
|
||||
"triangles": [ 8, 3, 7, 3, 4, 7, 7, 4, 6, 4, 5, 6, 0, 1, 9, 1, 2, 9, 9, 2, 8, 2, 3, 8 ],
|
||||
"vertices": [ 1, 19, -5.05, -21.72, 1, 1, 19, -5.05, 18.28, 1, 2, 19, 19.45, 18.28, 0.75483, 20, -27.28, 18.28, 0.24517, 2, 19, 43.95, 18.28, 0.50538, 20, -2.78, 18.28, 0.49462, 2, 19, 68.45, 18.28, 0.25278, 20, 21.72, 18.28, 0.74722, 1, 20, 46.22, 18.28, 1, 1, 20, 46.22, -21.72, 1, 2, 19, 68.45, -21.72, 0.24458, 20, 21.72, -21.72, 0.75542, 2, 19, 43.95, -21.72, 0.4937, 20, -2.78, -21.72, 0.5063, 2, 19, 19.45, -21.72, 0.74651, 20, -27.28, -21.72, 0.25349 ],
|
||||
"hull": 10
|
||||
}
|
||||
},
|
||||
"leaf-small": {
|
||||
"leaf-small": { "x": 25.02, "y": 0.4, "rotation": -91.36, "width": 34, "height": 59 }
|
||||
},
|
||||
"petal-1": {
|
||||
"petal-1": { "x": 18.88, "y": -4.54, "rotation": -160.18, "width": 52, "height": 36 }
|
||||
},
|
||||
"petal-2": {
|
||||
"petal-2": { "x": 21.96, "y": 2.06, "rotation": -9.66, "width": 56, "height": 34 }
|
||||
},
|
||||
"petal-3": {
|
||||
"petal-3": { "x": 16.97, "y": -5.71, "rotation": -91.03, "width": 58, "height": 42 }
|
||||
},
|
||||
"stem": {
|
||||
"stem": {
|
||||
"type": "mesh",
|
||||
"uvs": [ 1, 1, 0, 1, 0, 0.90909, 0, 0.81818, 0, 0.72727, 0, 0.63636, 0, 0.54545, 0, 0.45455, 0, 0.36364, 0, 0.27273, 0, 0.18182, 0, 0.09091, 0, 0, 1, 0, 1, 0.09091, 1, 0.18182, 1, 0.27273, 1, 0.36364, 1, 0.45455, 1, 0.54545, 1, 0.63636, 1, 0.72727, 1, 0.81818, 1, 0.90909 ],
|
||||
"triangles": [ 15, 10, 14, 10, 11, 14, 14, 11, 13, 11, 12, 13, 18, 7, 17, 7, 8, 17, 17, 8, 16, 8, 9, 16, 16, 9, 15, 9, 10, 15, 0, 1, 23, 1, 2, 23, 23, 2, 22, 2, 3, 22, 22, 3, 21, 3, 4, 21, 21, 4, 20, 4, 5, 20, 20, 5, 19, 5, 6, 19, 19, 6, 18, 6, 7, 18 ],
|
||||
"vertices": [ 1, 22, -3.61, -6.76, 1, 1, 22, -3.61, 9.24, 1, 3, 22, 15.49, 9.24, 0.97258, 23, -89.27, 9.24, 0.02734, 24, -159.11, 9.24, 8.0E-5, 3, 22, 34.58, 9.24, 0.92758, 23, -70.18, 9.24, 0.07175, 24, -140.02, 9.24, 6.7E-4, 3, 22, 53.67, 9.24, 0.851, 23, -51.09, 9.24, 0.14565, 24, -120.93, 9.24, 0.00335, 3, 22, 72.76, 9.24, 0.73702, 23, -32, 9.24, 0.25075, 24, -101.84, 9.24, 0.01223, 3, 22, 91.85, 9.24, 0.59184, 23, -12.91, 9.24, 0.37282, 24, -82.74, 9.24, 0.03534, 3, 22, 110.94, 9.24, 0.43333, 23, 6.18, 9.24, 0.482, 24, -63.65, 9.24, 0.08467, 3, 22, 130.03, 9.24, 0.28467, 23, 25.27, 9.24, 0.54153, 24, -44.56, 9.24, 0.1738, 3, 22, 149.12, 9.24, 0.16502, 23, 44.37, 9.24, 0.52188, 24, -25.47, 9.24, 0.3131, 3, 22, 168.21, 9.24, 0.08234, 23, 63.46, 9.24, 0.4129, 24, -6.38, 9.24, 0.50477, 3, 22, 187.3, 9.24, 0.03198, 23, 82.55, 9.24, 0.228, 24, 12.71, 9.24, 0.74001, 1, 24, 31.8, 9.24, 1, 1, 24, 31.8, -6.76, 1, 3, 22, 187.3, -6.76, 0.02989, 23, 82.55, -6.76, 0.23389, 24, 12.71, -6.76, 0.73622, 3, 22, 168.21, -6.76, 0.07799, 23, 63.46, -6.76, 0.42357, 24, -6.38, -6.76, 0.49844, 3, 22, 149.12, -6.76, 0.1584, 23, 44.37, -6.76, 0.53549, 24, -25.47, -6.76, 0.30611, 3, 22, 130.03, -6.76, 0.27629, 23, 25.27, -6.76, 0.55594, 24, -44.56, -6.76, 0.16777, 3, 22, 110.94, -6.76, 0.42428, 23, 6.18, -6.76, 0.49529, 24, -63.65, -6.76, 0.08044, 3, 22, 91.85, -6.76, 0.58346, 23, -12.91, -6.76, 0.38366, 24, -82.74, -6.76, 0.03289, 3, 22, 72.76, -6.76, 0.73038, 23, -32, -6.76, 0.25856, 24, -101.84, -6.76, 0.01107, 3, 22, 53.67, -6.76, 0.84652, 23, -51.09, -6.76, 0.15057, 24, -120.93, -6.76, 0.00291, 3, 22, 34.58, -6.76, 0.92506, 23, -70.18, -6.76, 0.0744, 24, -140.02, -6.76, 5.4E-4, 3, 22, 15.49, -6.76, 0.97151, 23, -89.27, -6.76, 0.02843, 24, -159.11, -6.76, 6.0E-5 ],
|
||||
"hull": 24
|
||||
}
|
||||
},
|
||||
"stem-end": {
|
||||
"stem-end": { "x": 25.8, "y": -0.26, "rotation": -90, "width": 25, "height": 26 }
|
||||
},
|
||||
"pot-base": {
|
||||
"pot-base": { "x": 5, "y": 42, "width": 152, "height": 118 }
|
||||
},
|
||||
"pot-eyes": {
|
||||
"pot-eyes-closed": { "x": -0.94, "y": 2.34, "width": 92, "height": 17 },
|
||||
"pot-eyes-open": { "x": 0.06, "y": 3.84, "width": 80, "height": 22 }
|
||||
},
|
||||
"pot-mouth": {
|
||||
"pot-mouth-open": { "x": -1.44, "y": -13.66, "width": 27, "height": 31 },
|
||||
"pot-mouth-pouty": { "x": 0.56, "y": -12.66, "width": 35, "height": 19 },
|
||||
"pot-mouth-smile": { "x": 0.56, "y": -12.16, "width": 27, "height": 20 },
|
||||
"pot-mouth-smile-big": { "x": 1.56, "y": -9.16, "width": 39, "height": 18 }
|
||||
},
|
||||
"rain-blue": {
|
||||
"rain-blue": { "width": 23, "height": 36 }
|
||||
},
|
||||
"rain-color": {
|
||||
"rain-color": { "width": 18, "height": 34 }
|
||||
},
|
||||
"rain-green": {
|
||||
"rain-green": { "width": 23, "height": 36 }
|
||||
},
|
||||
"rain-white": {
|
||||
"rain-white": { "width": 23, "height": 44 }
|
||||
},
|
||||
"rain-white-reflex": {
|
||||
"rain-white-reflex": { "x": -0.5, "y": 3.5, "width": 10, "height": 19 }
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"animations": {
|
||||
"playing-in-the-rain": {
|
||||
"slots": {
|
||||
"cloud-eyes": {
|
||||
"attachment": [
|
||||
{ "time": 0.2, "name": "cloud-eyes-closed" },
|
||||
{ "time": 0.9, "name": "cloud-eyes-open" },
|
||||
{ "time": 1.7667, "name": "cloud-eyes-closed" },
|
||||
{ "time": 1.9333, "name": "cloud-eyes-open" },
|
||||
{ "time": 2.4333, "name": "cloud-eyes-closed" },
|
||||
{ "time": 2.6, "name": "cloud-eyes-open" },
|
||||
{ "time": 3.9333, "name": "cloud-eyes-closed" },
|
||||
{ "time": 4.1, "name": "cloud-eyes-open" }
|
||||
]
|
||||
},
|
||||
"cloud-mouth": {
|
||||
"attachment": [
|
||||
{ "time": 0.2, "name": "cloud-mouth-open" },
|
||||
{ "time": 0.9, "name": "cloud-mouth-closed" }
|
||||
]
|
||||
},
|
||||
"pot-eyes": {
|
||||
"attachment": [
|
||||
{ "time": 0.1333, "name": "pot-eyes-closed" },
|
||||
{ "time": 0.3, "name": "pot-eyes-open" },
|
||||
{ "time": 1.0667, "name": "pot-eyes-closed" },
|
||||
{ "time": 1.5, "name": "pot-eyes-open" },
|
||||
{ "time": 3.0333, "name": "pot-eyes-closed" },
|
||||
{ "time": 3.2333, "name": "pot-eyes-open" },
|
||||
{ "time": 3.4667, "name": "pot-eyes-closed" },
|
||||
{ "time": 3.6667, "name": "pot-eyes-open" }
|
||||
]
|
||||
},
|
||||
"pot-mouth": {
|
||||
"attachment": [
|
||||
{ "time": 0.1333, "name": "pot-mouth-open" },
|
||||
{ "time": 0.3, "name": "pot-mouth-smile-big" },
|
||||
{ "time": 1.0667, "name": "pot-mouth-pouty" },
|
||||
{ "time": 2.4, "name": "pot-mouth-smile" },
|
||||
{ "time": 3.0333, "name": "pot-mouth-smile-big" }
|
||||
]
|
||||
}
|
||||
},
|
||||
"bones": {
|
||||
"pot": {
|
||||
"rotate": [
|
||||
{ "time": 1.1 },
|
||||
{ "time": 1.2, "value": -12.76 },
|
||||
{ "time": 1.5333, "curve": "stepped" },
|
||||
{ "time": 3.7667 },
|
||||
{ "time": 3.9, "value": 8.28 },
|
||||
{ "time": 4.2333, "value": -4.34 },
|
||||
{ "time": 4.4333 }
|
||||
],
|
||||
"scale": [
|
||||
{},
|
||||
{ "time": 0.2, "y": 0.752 },
|
||||
{ "time": 0.4, "x": 0.845, "y": 1.068 },
|
||||
{ "time": 0.6333 }
|
||||
]
|
||||
},
|
||||
"pot-control": {
|
||||
"translatex": [
|
||||
{
|
||||
"time": 1.0667,
|
||||
"curve": [ 1.222, -203.48, 1.378, -610.44 ]
|
||||
},
|
||||
{ "time": 1.5333, "value": -610.44, "curve": "stepped" },
|
||||
{
|
||||
"time": 2.2333,
|
||||
"value": -610.44,
|
||||
"curve": [ 2.389, -610.44, 2.544, -478.45 ]
|
||||
},
|
||||
{ "time": 2.7, "value": -478.45, "curve": "stepped" },
|
||||
{
|
||||
"time": 3.8333,
|
||||
"value": -478.45,
|
||||
"curve": [ 3.971, -478.45, 4.095, -135.56 ]
|
||||
},
|
||||
{ "time": 4.2333 }
|
||||
],
|
||||
"translatey": [
|
||||
{
|
||||
"time": 1.0333,
|
||||
"curve": [ 1.089, 10.56, 1.144, 44.34 ]
|
||||
},
|
||||
{
|
||||
"time": 1.2,
|
||||
"value": 44.34,
|
||||
"curve": [ 1.256, 44.34, 1.311, 0 ]
|
||||
},
|
||||
{ "time": 1.3667, "curve": "stepped" },
|
||||
{
|
||||
"time": 2.2333,
|
||||
"curve": [ 2.408, 0, 2.392, 44.34 ]
|
||||
},
|
||||
{
|
||||
"time": 2.4333,
|
||||
"value": 44.34,
|
||||
"curve": [ 2.455, 44.34, 2.51, 0 ]
|
||||
},
|
||||
{ "time": 2.6, "curve": "stepped" },
|
||||
{
|
||||
"time": 3.8,
|
||||
"curve": [ 3.841, 14.78, 3.893, 44.34 ]
|
||||
},
|
||||
{
|
||||
"time": 3.9333,
|
||||
"value": 44.34,
|
||||
"curve": [ 4.023, 44.34, 4.111, 14.78 ]
|
||||
},
|
||||
{ "time": 4.2 }
|
||||
]
|
||||
},
|
||||
"cloud-base-1": {
|
||||
"rotate": [
|
||||
{
|
||||
"curve": [ 0.144, -9.36, 0.289, -17.29 ]
|
||||
},
|
||||
{
|
||||
"time": 0.4333,
|
||||
"value": -17.29,
|
||||
"curve": [ 0.5, -17.29, 0.567, -4.32 ]
|
||||
},
|
||||
{ "time": 0.6333 }
|
||||
],
|
||||
"scale": [
|
||||
{
|
||||
"curve": [ 0.089, 1, 0.178, 1.064, 0.089, 1, 0.178, 1.064 ]
|
||||
},
|
||||
{
|
||||
"time": 0.2667,
|
||||
"x": 1.064,
|
||||
"y": 1.064,
|
||||
"curve": [ 0.411, 1.064, 0.556, 1.021, 0.411, 1.064, 0.556, 1.021 ]
|
||||
},
|
||||
{ "time": 0.7 }
|
||||
]
|
||||
},
|
||||
"cloud-base-4": {
|
||||
"rotate": [
|
||||
{
|
||||
"curve": [ 0.1, 5.55, 0.2, 14.81 ]
|
||||
},
|
||||
{
|
||||
"time": 0.3,
|
||||
"value": 14.81,
|
||||
"curve": [ 0.467, 14.81, 0.633, 9.25 ]
|
||||
},
|
||||
{ "time": 0.8 }
|
||||
],
|
||||
"scale": [
|
||||
{
|
||||
"curve": [ 0.089, 1, 0.178, 1.064, 0.089, 1, 0.178, 1.064 ]
|
||||
},
|
||||
{
|
||||
"time": 0.2667,
|
||||
"x": 1.064,
|
||||
"y": 1.064,
|
||||
"curve": [ 0.411, 1.064, 0.556, 1.021, 0.411, 1.064, 0.556, 1.021 ]
|
||||
},
|
||||
{ "time": 0.7 }
|
||||
]
|
||||
},
|
||||
"cloud": {
|
||||
"translate": [
|
||||
{ "time": 0.2333 },
|
||||
{ "time": 0.3333, "y": 30.43 },
|
||||
{ "time": 0.4667 },
|
||||
{ "time": 0.5667, "y": 30.43 },
|
||||
{ "time": 0.6667 },
|
||||
{ "time": 0.7667, "y": 30.43 },
|
||||
{ "time": 0.9333 }
|
||||
]
|
||||
}
|
||||
},
|
||||
"physics": {
|
||||
"rain/rain-blue": {
|
||||
"reset": [
|
||||
{ "time": 0.4667 },
|
||||
{ "time": 0.9333 },
|
||||
{ "time": 1.4 },
|
||||
{ "time": 1.8667 },
|
||||
{ "time": 2.3333 },
|
||||
{ "time": 2.8 },
|
||||
{ "time": 3.2667 },
|
||||
{ "time": 3.7333 },
|
||||
{ "time": 4.2 },
|
||||
{ "time": 4.6667 }
|
||||
]
|
||||
},
|
||||
"rain/rain-color": {
|
||||
"reset": [
|
||||
{ "time": 0.3 },
|
||||
{ "time": 0.7667 },
|
||||
{ "time": 1.2333 },
|
||||
{ "time": 1.7 },
|
||||
{ "time": 2.1667 },
|
||||
{ "time": 2.6333 },
|
||||
{ "time": 3.1 },
|
||||
{ "time": 3.5667 },
|
||||
{ "time": 4.0333 },
|
||||
{ "time": 4.5 }
|
||||
]
|
||||
},
|
||||
"rain/rain-green": {
|
||||
"reset": [
|
||||
{ "time": 0.1333 },
|
||||
{ "time": 0.6 },
|
||||
{ "time": 1.0667 },
|
||||
{ "time": 1.5333 },
|
||||
{ "time": 2 },
|
||||
{ "time": 2.4667 },
|
||||
{ "time": 2.9333 },
|
||||
{ "time": 3.4 },
|
||||
{ "time": 3.8667 },
|
||||
{ "time": 4.3333 }
|
||||
]
|
||||
},
|
||||
"rain/rain-white": {
|
||||
"reset": [
|
||||
{},
|
||||
{ "time": 0.4667 },
|
||||
{ "time": 0.9333 },
|
||||
{ "time": 1.4 },
|
||||
{ "time": 1.8667 },
|
||||
{ "time": 2.3333 },
|
||||
{ "time": 2.8 },
|
||||
{ "time": 3.2667 },
|
||||
{ "time": 3.7333 },
|
||||
{ "time": 4.2 }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"pot-moving-followed-by-rain": {
|
||||
"bones": {
|
||||
"pot-control": {
|
||||
"translate": [
|
||||
{},
|
||||
{ "time": 0.5667, "x": -389.34, "curve": "stepped" },
|
||||
{ "time": 1.1667, "x": -389.34 },
|
||||
{ "time": 2.2, "x": 463.88, "curve": "stepped" },
|
||||
{ "time": 2.4667, "x": 463.88 },
|
||||
{ "time": 3 }
|
||||
]
|
||||
}
|
||||
},
|
||||
"physics": {
|
||||
"rain/rain-blue": {
|
||||
"reset": [
|
||||
{ "time": 0.4667 },
|
||||
{ "time": 0.9333 },
|
||||
{ "time": 1.4 },
|
||||
{ "time": 1.8667 },
|
||||
{ "time": 2.3333 },
|
||||
{ "time": 2.8 },
|
||||
{ "time": 3.2667 }
|
||||
]
|
||||
},
|
||||
"rain/rain-color": {
|
||||
"reset": [
|
||||
{ "time": 0.3 },
|
||||
{ "time": 0.7667 },
|
||||
{ "time": 1.2333 },
|
||||
{ "time": 1.7 },
|
||||
{ "time": 2.1667 },
|
||||
{ "time": 2.6333 },
|
||||
{ "time": 3.1 }
|
||||
]
|
||||
},
|
||||
"rain/rain-green": {
|
||||
"reset": [
|
||||
{ "time": 0.1333 },
|
||||
{ "time": 0.6 },
|
||||
{ "time": 1.0667 },
|
||||
{ "time": 1.5333 },
|
||||
{ "time": 2 },
|
||||
{ "time": 2.4667 },
|
||||
{ "time": 2.9333 }
|
||||
]
|
||||
},
|
||||
"rain/rain-white": {
|
||||
"reset": [
|
||||
{},
|
||||
{ "time": 0.4667 },
|
||||
{ "time": 0.9333 },
|
||||
{ "time": 1.4 },
|
||||
{ "time": 1.8667 },
|
||||
{ "time": 2.3333 },
|
||||
{ "time": 2.8 }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"rain": {
|
||||
"physics": {
|
||||
"rain/rain-blue": {
|
||||
"reset": [
|
||||
{ "time": 0.4667 }
|
||||
]
|
||||
},
|
||||
"rain/rain-color": {
|
||||
"reset": [
|
||||
{ "time": 0.3 }
|
||||
]
|
||||
},
|
||||
"rain/rain-green": {
|
||||
"reset": [
|
||||
{ "time": 0.1333 }
|
||||
]
|
||||
},
|
||||
"rain/rain-white": {
|
||||
"reset": [
|
||||
{}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
spine-haxe/example/assets/cloud-pot.png
Normal file
BIN
spine-haxe/example/assets/cloud-pot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 MiB |
11
spine-haxe/example/assets/sack-pma.atlas
Normal file
11
spine-haxe/example/assets/sack-pma.atlas
Normal file
@ -0,0 +1,11 @@
|
||||
sack-pma.png
|
||||
size: 512, 512
|
||||
filter: Linear, Linear
|
||||
pma: true
|
||||
scale: 0.5
|
||||
cape-back
|
||||
bounds: 237, 149, 260, 260
|
||||
cape-front
|
||||
bounds: 237, 43, 200, 104
|
||||
sack
|
||||
bounds: 2, 2, 233, 407
|
||||
BIN
spine-haxe/example/assets/sack-pma.png
Normal file
BIN
spine-haxe/example/assets/sack-pma.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 163 KiB |
4940
spine-haxe/example/assets/sack-pro.json
Normal file
4940
spine-haxe/example/assets/sack-pro.json
Normal file
File diff suppressed because one or more lines are too long
BIN
spine-haxe/example/assets/sack-pro.skel
Normal file
BIN
spine-haxe/example/assets/sack-pro.skel
Normal file
Binary file not shown.
@ -49,6 +49,7 @@ class Main extends Sprite {
|
||||
starlingSingleton.start();
|
||||
Starling.current.stage.color = 0x000000;
|
||||
|
||||
// SceneManager.getInstance().switchScene(new TankExample());
|
||||
SceneManager.getInstance().switchScene(new VineExample());
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,9 +27,11 @@
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
import spine.BlendMode;
|
||||
import Scene.SceneManager;
|
||||
import openfl.utils.Assets;
|
||||
import spine.SkeletonData;
|
||||
import spine.Physics;
|
||||
import spine.animation.AnimationStateData;
|
||||
import spine.atlas.TextureAtlas;
|
||||
import spine.starling.SkeletonSprite;
|
||||
@ -43,17 +45,31 @@ class VineExample extends Scene {
|
||||
|
||||
public function load():Void {
|
||||
background.color = 0xffffffff;
|
||||
var atlas = new TextureAtlas(Assets.getText("assets/vine.atlas"), new StarlingTextureLoader("assets/vine.atlas"));
|
||||
var skeletondata = SkeletonData.from(loadBinary ? Assets.getBytes("assets/vine-pro.skel") : Assets.getText("assets/vine-pro.json"), atlas);
|
||||
|
||||
// var atlas = new TextureAtlas(Assets.getText("assets/cloud-pot.atlas"), new StarlingTextureLoader("assets/cloud-pot.atlas"));
|
||||
// var skeletondata = SkeletonData.from(Assets.getText("assets/cloud-pot.json"), atlas);
|
||||
|
||||
var atlas = new TextureAtlas(Assets.getText("assets/sack-pma.atlas"), new StarlingTextureLoader("assets/sack-pma.atlas"));
|
||||
var skeletondata = SkeletonData.from(Assets.getText("assets/sack-pro.json"), atlas);
|
||||
|
||||
var animationStateData = new AnimationStateData(skeletondata);
|
||||
animationStateData.defaultMix = 0.25;
|
||||
|
||||
var skeletonSprite = new SkeletonSprite(skeletondata, animationStateData);
|
||||
skeletonSprite.skeleton.updateWorldTransform();
|
||||
skeletonSprite.skeleton.updateWorldTransform(Physics.update);
|
||||
var bounds = skeletonSprite.skeleton.getBounds();
|
||||
skeletonSprite.scale = Starling.current.stage.stageWidth / bounds.width;
|
||||
|
||||
|
||||
skeletonSprite.scale = 0.2;
|
||||
skeletonSprite.x = Starling.current.stage.stageWidth / 2;
|
||||
skeletonSprite.y = Starling.current.stage.stageHeight * 0.5;
|
||||
skeletonSprite.y = Starling.current.stage.stageHeight/ 2;
|
||||
|
||||
trace(skeletonSprite);
|
||||
|
||||
// skeletonSprite.state.setAnimationByName(0, "playing-in-the-rain", true);
|
||||
|
||||
|
||||
skeletonSprite.state.setAnimationByName(0, "cape-follow-example", true);
|
||||
|
||||
addChild(skeletonSprite);
|
||||
juggler.add(skeletonSprite);
|
||||
@ -64,7 +80,7 @@ class VineExample extends Scene {
|
||||
public function onTouch(e:TouchEvent) {
|
||||
var touch = e.getTouch(this);
|
||||
if (touch != null && touch.phase == TouchPhase.ENDED) {
|
||||
SceneManager.getInstance().switchScene(new BasicExample());
|
||||
// SceneManager.getInstance().switchScene(new BasicExample());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,159 +57,10 @@ class Bone implements Updatable {
|
||||
public var d:Float = 0;
|
||||
public var worldX:Float = 0;
|
||||
public var worldY:Float = 0;
|
||||
public var inherit:Inherit = Inherit.normal;
|
||||
public var sorted:Bool = false;
|
||||
public var active:Bool = false;
|
||||
|
||||
/** @param parent May be null. */
|
||||
public function new(data:BoneData, skeleton:Skeleton, parent:Bone) {
|
||||
if (data == null)
|
||||
throw new SpineException("data cannot be null.");
|
||||
if (skeleton == null)
|
||||
throw new SpineException("skeleton cannot be null.");
|
||||
_data = data;
|
||||
_skeleton = skeleton;
|
||||
_parent = parent;
|
||||
setToSetupPose();
|
||||
}
|
||||
|
||||
public function isActive():Bool {
|
||||
return active;
|
||||
}
|
||||
|
||||
/** Same as updateWorldTransform(). This method exists for Bone to implement Updatable. */
|
||||
public function update():Void {
|
||||
updateWorldTransformWith(ax, ay, arotation, ascaleX, ascaleY, ashearX, ashearY);
|
||||
}
|
||||
|
||||
/** Computes the world SRT using the parent bone and this bone's local SRT. */
|
||||
public function updateWorldTransform():Void {
|
||||
updateWorldTransformWith(x, y, rotation, scaleX, scaleY, shearX, shearY);
|
||||
}
|
||||
|
||||
/** Computes the world SRT using the parent bone and the specified local SRT. */
|
||||
public function updateWorldTransformWith(x:Float, y:Float, rotation:Float, scaleX:Float, scaleY:Float, shearX:Float, shearY:Float):Void {
|
||||
ax = x;
|
||||
ay = y;
|
||||
arotation = rotation;
|
||||
ascaleX = scaleX;
|
||||
ascaleY = scaleY;
|
||||
ashearX = shearX;
|
||||
ashearY = shearY;
|
||||
|
||||
var rotationY:Float = 0;
|
||||
var la:Float = 0;
|
||||
var lb:Float = 0;
|
||||
var lc:Float = 0;
|
||||
var ld:Float = 0;
|
||||
var sin:Float = 0;
|
||||
var cos:Float = 0;
|
||||
var s:Float = 0;
|
||||
var sx:Float = skeleton.scaleX;
|
||||
var sy:Float = skeleton.scaleY * (yDown ? -1 : 1);
|
||||
|
||||
var parent:Bone = _parent;
|
||||
if (parent == null) {
|
||||
// Root bone.
|
||||
rotationY = rotation + 90 + shearY;
|
||||
a = MathUtils.cosDeg(rotation + shearX) * scaleX * sx;
|
||||
b = MathUtils.cosDeg(rotationY) * scaleY * sx;
|
||||
c = MathUtils.sinDeg(rotation + shearX) * scaleX * sy;
|
||||
d = MathUtils.sinDeg(rotationY) * scaleY * sy;
|
||||
worldX = x * sx + skeleton.x;
|
||||
worldY = y * sy + skeleton.y;
|
||||
return;
|
||||
}
|
||||
|
||||
var pa:Float = parent.a,
|
||||
pb:Float = parent.b,
|
||||
pc:Float = parent.c,
|
||||
pd:Float = parent.d;
|
||||
worldX = pa * x + pb * y + parent.worldX;
|
||||
worldY = pc * x + pd * y + parent.worldY;
|
||||
|
||||
switch (data.transformMode) {
|
||||
case TransformMode.normal:
|
||||
rotationY = rotation + 90 + shearY;
|
||||
la = MathUtils.cosDeg(rotation + shearX) * scaleX;
|
||||
lb = MathUtils.cosDeg(rotationY) * scaleY;
|
||||
lc = MathUtils.sinDeg(rotation + shearX) * scaleX;
|
||||
ld = MathUtils.sinDeg(rotationY) * scaleY;
|
||||
a = pa * la + pb * lc;
|
||||
b = pa * lb + pb * ld;
|
||||
c = pc * la + pd * lc;
|
||||
d = pc * lb + pd * ld;
|
||||
return;
|
||||
case TransformMode.onlyTranslation:
|
||||
rotationY = rotation + 90 + shearY;
|
||||
a = MathUtils.cosDeg(rotation + shearX) * scaleX;
|
||||
b = MathUtils.cosDeg(rotationY) * scaleY;
|
||||
c = MathUtils.sinDeg(rotation + shearX) * scaleX;
|
||||
d = MathUtils.sinDeg(rotationY) * scaleY;
|
||||
case TransformMode.noRotationOrReflection:
|
||||
s = pa * pa + pc * pc;
|
||||
var prx:Float = 0;
|
||||
if (s > 0.0001) {
|
||||
s = Math.abs(pa * pd - pb * pc) / s;
|
||||
pb = pc * s;
|
||||
pd = pa * s;
|
||||
prx = Math.atan2(pc, pa) * MathUtils.radDeg;
|
||||
} else {
|
||||
pa = 0;
|
||||
pc = 0;
|
||||
prx = 90 - Math.atan2(pd, pb) * MathUtils.radDeg;
|
||||
}
|
||||
var rx:Float = rotation + shearX - prx;
|
||||
var ry:Float = rotation + shearY - prx + 90;
|
||||
la = MathUtils.cosDeg(rx) * scaleX;
|
||||
lb = MathUtils.cosDeg(ry) * scaleY;
|
||||
lc = MathUtils.sinDeg(rx) * scaleX;
|
||||
ld = MathUtils.sinDeg(ry) * scaleY;
|
||||
a = pa * la - pb * lc;
|
||||
b = pa * lb - pb * ld;
|
||||
c = pc * la + pd * lc;
|
||||
d = pc * lb + pd * ld;
|
||||
case TransformMode.noScale, TransformMode.noScaleOrReflection:
|
||||
cos = MathUtils.cosDeg(rotation);
|
||||
sin = MathUtils.sinDeg(rotation);
|
||||
var za:Float = (pa * cos + pb * sin) / sx;
|
||||
var zc:Float = (pc * cos + pd * sin) / sy;
|
||||
s = Math.sqrt(za * za + zc * zc);
|
||||
if (s > 0.00001)
|
||||
s = 1 / s;
|
||||
za *= s;
|
||||
zc *= s;
|
||||
s = Math.sqrt(za * za + zc * zc);
|
||||
if (data.transformMode == TransformMode.noScale && ((pa * pd - pb * pc < 0) != ((sx < 0) != (sy < 0)))) {
|
||||
s = -s;
|
||||
}
|
||||
var r:Float = Math.PI / 2 + Math.atan2(zc, za);
|
||||
var zb:Float = Math.cos(r) * s;
|
||||
var zd:Float = Math.sin(r) * s;
|
||||
la = MathUtils.cosDeg(shearX) * scaleX;
|
||||
lb = MathUtils.cosDeg(90 + shearY) * scaleY;
|
||||
lc = MathUtils.sinDeg(shearX) * scaleX;
|
||||
ld = MathUtils.sinDeg(90 + shearY) * scaleY;
|
||||
a = za * la + zb * lc;
|
||||
b = za * lb + zb * ld;
|
||||
c = zc * la + zd * lc;
|
||||
d = zc * lb + zd * ld;
|
||||
}
|
||||
a *= sx;
|
||||
b *= sx;
|
||||
c *= sy;
|
||||
d *= sy;
|
||||
}
|
||||
|
||||
public function setToSetupPose():Void {
|
||||
x = data.x;
|
||||
y = data.y;
|
||||
rotation = data.rotation;
|
||||
scaleX = data.scaleX;
|
||||
scaleY = data.scaleY;
|
||||
shearX = data.shearX;
|
||||
shearY = data.shearY;
|
||||
}
|
||||
|
||||
public var data(get, never):BoneData;
|
||||
|
||||
private function get_data():BoneData {
|
||||
@ -234,6 +85,248 @@ class Bone implements Updatable {
|
||||
return _children;
|
||||
}
|
||||
|
||||
/** @param parent May be null. */
|
||||
public function new(data:BoneData, skeleton:Skeleton, parent:Bone) {
|
||||
if (data == null)
|
||||
throw new SpineException("data cannot be null.");
|
||||
if (skeleton == null)
|
||||
throw new SpineException("skeleton cannot be null.");
|
||||
_data = data;
|
||||
_skeleton = skeleton;
|
||||
_parent = parent;
|
||||
setToSetupPose();
|
||||
}
|
||||
|
||||
public function isActive():Bool {
|
||||
return active;
|
||||
}
|
||||
|
||||
/** Same as updateWorldTransform(). This method exists for Bone to implement Updatable. */
|
||||
public function update(physics:Physics):Void {
|
||||
updateWorldTransformWith(ax, ay, arotation, ascaleX, ascaleY, ashearX, ashearY);
|
||||
}
|
||||
|
||||
/** Computes the world SRT using the parent bone and this bone's local SRT. */
|
||||
public function updateWorldTransform():Void {
|
||||
updateWorldTransformWith(x, y, rotation, scaleX, scaleY, shearX, shearY);
|
||||
}
|
||||
|
||||
/** Computes the world SRT using the parent bone and the specified local SRT. */
|
||||
public function updateWorldTransformWith(x:Float, y:Float, rotation:Float, scaleX:Float, scaleY:Float, shearX:Float, shearY:Float):Void {
|
||||
ax = x;
|
||||
ay = y;
|
||||
arotation = rotation;
|
||||
ascaleX = scaleX;
|
||||
ascaleY = scaleY;
|
||||
ashearX = shearX;
|
||||
ashearY = shearY;
|
||||
|
||||
var la:Float = 0;
|
||||
var lb:Float = 0;
|
||||
var lc:Float = 0;
|
||||
var ld:Float = 0;
|
||||
var sin:Float = 0;
|
||||
var cos:Float = 0;
|
||||
var s:Float = 0;
|
||||
var sx:Float = skeleton.scaleX;
|
||||
var sy:Float = skeleton.scaleY * (yDown ? -1 : 1);
|
||||
|
||||
var parent:Bone = _parent;
|
||||
if (parent == null) {
|
||||
// Root bone.
|
||||
var rx:Float = (rotation + shearX) * MathUtils.degRad;
|
||||
var ry:Float = (rotation + 90 + shearY) * MathUtils.degRad;
|
||||
a = Math.cos(rx) * scaleX * sx;
|
||||
b = Math.cos(ry) * scaleY * sx;
|
||||
c = Math.sin(rx) * scaleX * sy;
|
||||
d = Math.sin(ry) * scaleY * sy;
|
||||
worldX = x * sx + skeleton.x;
|
||||
worldY = y * sy + skeleton.y;
|
||||
return;
|
||||
}
|
||||
|
||||
var pa:Float = parent.a,
|
||||
pb:Float = parent.b,
|
||||
pc:Float = parent.c,
|
||||
pd:Float = parent.d;
|
||||
worldX = pa * x + pb * y + parent.worldX;
|
||||
worldY = pc * x + pd * y + parent.worldY;
|
||||
|
||||
switch (data.inherit) {
|
||||
case Inherit.normal:
|
||||
var rx:Float = (rotation + shearX) * MathUtils.degRad;
|
||||
var ry:Float = (rotation + 90 + shearY) * MathUtils.degRad;
|
||||
la = Math.cos(rx) * scaleX;
|
||||
lb = Math.cos(ry) * scaleY;
|
||||
lc = Math.sin(rx) * scaleX;
|
||||
ld = Math.sin(ry) * scaleY;
|
||||
a = pa * la + pb * lc;
|
||||
b = pa * lb + pb * ld;
|
||||
c = pc * la + pd * lc;
|
||||
d = pc * lb + pd * ld;
|
||||
return;
|
||||
case Inherit.onlyTranslation:
|
||||
var rx:Float = (rotation + shearX) * MathUtils.degRad;
|
||||
var ry:Float = (rotation + 90 + shearY) * MathUtils.degRad;
|
||||
a = Math.cos(rx) * scaleX;
|
||||
b = Math.cos(ry) * scaleY;
|
||||
c = Math.sin(rx) * scaleX;
|
||||
d = Math.sin(ry) * scaleY;
|
||||
case Inherit.noRotationOrReflection:
|
||||
s = pa * pa + pc * pc;
|
||||
var prx:Float = 0;
|
||||
if (s > 0.0001) {
|
||||
s = Math.abs(pa * pd - pb * pc) / s;
|
||||
pb = pc * s;
|
||||
pd = pa * s;
|
||||
prx = Math.atan2(pc, pa) * MathUtils.radDeg;
|
||||
} else {
|
||||
pa = 0;
|
||||
pc = 0;
|
||||
prx = 90 - Math.atan2(pd, pb) * MathUtils.radDeg;
|
||||
}
|
||||
var rx:Float = (rotation + shearX - prx) * MathUtils.degRad;
|
||||
var ry:Float = (rotation + shearY - prx + 90) * MathUtils.degRad;
|
||||
la = Math.cos(rx) * scaleX;
|
||||
lb = Math.cos(ry) * scaleY;
|
||||
lc = Math.sin(rx) * scaleX;
|
||||
ld = Math.sin(ry) * scaleY;
|
||||
a = pa * la - pb * lc;
|
||||
b = pa * lb - pb * ld;
|
||||
c = pc * la + pd * lc;
|
||||
d = pc * lb + pd * ld;
|
||||
case Inherit.noScale, Inherit.noScaleOrReflection:
|
||||
rotation *= MathUtils.degRad;
|
||||
cos = Math.cos(rotation);
|
||||
sin = Math.sin(rotation);
|
||||
var za:Float = (pa * cos + pb * sin) / sx;
|
||||
var zc:Float = (pc * cos + pd * sin) / sy;
|
||||
s = Math.sqrt(za * za + zc * zc);
|
||||
if (s > 0.00001)
|
||||
s = 1 / s;
|
||||
za *= s;
|
||||
zc *= s;
|
||||
s = Math.sqrt(za * za + zc * zc);
|
||||
if (data.inherit == Inherit.noScale && ((pa * pd - pb * pc < 0) != ((sx < 0) != (sy < 0)))) {
|
||||
s = -s;
|
||||
}
|
||||
rotation = Math.PI / 2 + Math.atan2(zc, za);
|
||||
var zb:Float = Math.cos(rotation) * s;
|
||||
var zd:Float = Math.sin(rotation) * s;
|
||||
shearX *= MathUtils.degRad;
|
||||
shearY = (90 + shearY) * MathUtils.degRad;
|
||||
la = Math.cos(shearX) * scaleX;
|
||||
lb = Math.cos(shearY) * scaleY;
|
||||
lc = Math.sin(shearX) * scaleX;
|
||||
ld = Math.sin(shearY) * scaleY;
|
||||
a = za * la + zb * lc;
|
||||
b = za * lb + zb * ld;
|
||||
c = zc * la + zd * lc;
|
||||
d = zc * lb + zd * ld;
|
||||
}
|
||||
a *= sx;
|
||||
b *= sx;
|
||||
c *= sy;
|
||||
d *= sy;
|
||||
}
|
||||
|
||||
public function setToSetupPose():Void {
|
||||
x = data.x;
|
||||
y = data.y;
|
||||
rotation = data.rotation;
|
||||
scaleX = data.scaleX;
|
||||
scaleY = data.scaleY;
|
||||
shearX = data.shearX;
|
||||
shearY = data.shearY;
|
||||
inherit = data.inherit;
|
||||
}
|
||||
|
||||
/** Computes the individual applied transform values from the world transform. This can be useful to perform processing using
|
||||
* the applied transform after the world transform has been modified directly (eg, by a constraint).
|
||||
* <p>
|
||||
* Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. */
|
||||
public function updateAppliedTransform():Void {
|
||||
var parent:Bone = parent;
|
||||
if (parent == null) {
|
||||
ax = worldX - skeleton.x;
|
||||
ay = worldY - skeleton.y;
|
||||
arotation = Math.atan2(c, a) * MathUtils.radDeg;
|
||||
ascaleX = Math.sqrt(a * a + c * c);
|
||||
ascaleY = Math.sqrt(b * b + d * d);
|
||||
ashearX = 0;
|
||||
ashearY = Math.atan2(a * b + c * d, a * d - b * c) * MathUtils.radDeg;
|
||||
return;
|
||||
}
|
||||
var pa:Float = parent.a,
|
||||
pb:Float = parent.b,
|
||||
pc:Float = parent.c,
|
||||
pd:Float = parent.d;
|
||||
var pid:Float = 1 / (pa * pd - pb * pc);
|
||||
var ia:Float = pd * pid,
|
||||
ib:Float = pb * pid,
|
||||
ic:Float = pc * pid,
|
||||
id:Float = pa * pid;
|
||||
var dx:Float = worldX - parent.worldX,
|
||||
dy:Float = worldY - parent.worldY;
|
||||
ax = (dx * ia - dy * ib);
|
||||
ay = (dy * id - dx * ic);
|
||||
var ra:Float, rb:Float, rc:Float, rd:Float;
|
||||
if (inherit == Inherit.onlyTranslation) {
|
||||
ra = a;
|
||||
rb = b;
|
||||
rc = c;
|
||||
rd = d;
|
||||
} else {
|
||||
switch (inherit) {
|
||||
case Inherit.noRotationOrReflection:
|
||||
var s:Float = Math.abs(pa * pd - pb * pc) / (pa * pa + pc * pc);
|
||||
var sa:Float = pa / skeleton.scaleX;
|
||||
var sc:Float = pc / skeleton.scaleY;
|
||||
pb = -sc * s * skeleton.scaleX;
|
||||
pd = sa * s * skeleton.scaleY;
|
||||
pid = 1 / (pa * pd - pb * pc);
|
||||
ia = pd * pid;
|
||||
ib = pb * pid;
|
||||
case Inherit.noScale | Inherit.noScaleOrReflection:
|
||||
var cos:Float = MathUtils.cosDeg(rotation), sin:Float = MathUtils.sinDeg(rotation);
|
||||
pa = (pa * cos + pb * sin) / skeleton.scaleX;
|
||||
pc = (pc * cos + pd * sin) / skeleton.scaleY;
|
||||
var s:Float = Math.sqrt(pa * pa + pc * pc);
|
||||
if (s > 0.00001) s = 1 / s;
|
||||
pa *= s;
|
||||
pc *= s;
|
||||
s = Math.sqrt(pa * pa + pc * pc);
|
||||
if (inherit == Inherit.noScale && pid < 0 != ((skeleton.scaleX < 0) != (skeleton.scaleY < 0))) s = -s;
|
||||
var r:Float = MathUtils.PI / 2 + Math.atan2(pc, pa);
|
||||
pb = Math.cos(r) * s;
|
||||
pd = Math.sin(r) * s;
|
||||
pid = 1 / (pa * pd - pb * pc);
|
||||
ia = pd * pid;
|
||||
ib = pb * pid;
|
||||
ic = pc * pid;
|
||||
id = pa * pid;
|
||||
}
|
||||
ra = ia * a - ib * c;
|
||||
rb = ia * b - ib * d;
|
||||
rc = id * c - ic * a;
|
||||
rd = id * d - ic * b;
|
||||
}
|
||||
|
||||
ashearX = 0;
|
||||
ascaleX = Math.sqrt(ra * ra + rc * rc);
|
||||
if (scaleX > 0.0001) {
|
||||
var det:Float = ra * rd - rb * rc;
|
||||
ascaleY = det / ascaleX;
|
||||
ashearY = -Math.atan2(ra * rb + rc * rd, det) * MathUtils.radDeg;
|
||||
arotation = Math.atan2(rc, ra) * MathUtils.radDeg;
|
||||
} else {
|
||||
ascaleX = 0;
|
||||
ascaleY = Math.sqrt(rb * rb + rd * rd);
|
||||
ashearY = 0;
|
||||
arotation = 90 - Math.atan2(rd, rb) * MathUtils.radDeg;
|
||||
}
|
||||
}
|
||||
|
||||
public var worldRotationX(get, never):Float;
|
||||
|
||||
private function get_worldRotationX():Float {
|
||||
@ -258,66 +351,32 @@ class Bone implements Updatable {
|
||||
return Math.sqrt(b * b + d * d);
|
||||
}
|
||||
|
||||
/** Computes the individual applied transform values from the world transform. This can be useful to perform processing using
|
||||
* the applied transform after the world transform has been modified directly (eg, by a constraint).
|
||||
* <p>
|
||||
* Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. */
|
||||
public function updateAppliedTransform():Void {
|
||||
var parent:Bone = parent;
|
||||
if (parent == null) {
|
||||
ax = worldX - skeleton.x;
|
||||
ay = worldY - skeleton.y;
|
||||
arotation = Math.atan2(c, a) * MathUtils.radDeg;
|
||||
ascaleX = Math.sqrt(a * a + c * c);
|
||||
ascaleY = Math.sqrt(b * b + d * d);
|
||||
ashearX = 0;
|
||||
ashearY = Math.atan2(a * b + c * d, a * d - b * c) * MathUtils.radDeg;
|
||||
return;
|
||||
}
|
||||
var pa:Float = parent.a,
|
||||
pb:Float = parent.b,
|
||||
pc:Float = parent.c,
|
||||
pd:Float = parent.d;
|
||||
var pid:Float = 1 / (pa * pd - pb * pc);
|
||||
var dx:Float = worldX - parent.worldX,
|
||||
dy:Float = worldY - parent.worldY;
|
||||
ax = (dx * pd * pid - dy * pb * pid);
|
||||
ay = (dy * pa * pid - dx * pc * pid);
|
||||
var ia:Float = pid * pd;
|
||||
var id:Float = pid * pa;
|
||||
var ib:Float = pid * pb;
|
||||
var ic:Float = pid * pc;
|
||||
var ra:Float = ia * a - ib * c;
|
||||
var rb:Float = ia * b - ib * d;
|
||||
var rc:Float = id * c - ic * a;
|
||||
var rd:Float = id * d - ic * b;
|
||||
ashearX = 0;
|
||||
ascaleX = Math.sqrt(ra * ra + rc * rc);
|
||||
if (scaleX > 0.0001) {
|
||||
var det:Float = ra * rd - rb * rc;
|
||||
ascaleY = det / ascaleX;
|
||||
ashearY = Math.atan2(ra * rb + rc * rd, det) * MathUtils.radDeg;
|
||||
arotation = Math.atan2(rc, ra) * MathUtils.radDeg;
|
||||
} else {
|
||||
ascaleX = 0;
|
||||
ascaleY = Math.sqrt(rb * rb + rd * rd);
|
||||
ashearY = 0;
|
||||
arotation = 90 - Math.atan2(rd, rb) * MathUtils.radDeg;
|
||||
}
|
||||
private function worldToParent(world: Array<Float>):Array<Float> {
|
||||
if (world == null)
|
||||
throw new SpineException("world cannot be null.");
|
||||
return parent == null ? world : parent.worldToLocal(world);
|
||||
}
|
||||
|
||||
public function worldToLocal(world:Array<Float>):Void {
|
||||
private function parentToWorld(world: Array<Float>):Array<Float> {
|
||||
if (world == null)
|
||||
throw new SpineException("world cannot be null.");
|
||||
return parent == null ? world : parent.localToWorld(world);
|
||||
}
|
||||
|
||||
public function worldToLocal(world:Array<Float>):Array<Float> {
|
||||
var a:Float = a, b:Float = b, c:Float = c, d:Float = d;
|
||||
var invDet:Float = 1 / (a * d - b * c);
|
||||
var x:Float = world[0] - worldX, y:Float = world[1] - worldY;
|
||||
world[0] = (x * d * invDet - y * b * invDet);
|
||||
world[1] = (y * a * invDet - x * c * invDet);
|
||||
return world;
|
||||
}
|
||||
|
||||
public function localToWorld(local:Array<Float>):Void {
|
||||
public function localToWorld(local:Array<Float>):Array<Float> {
|
||||
var localX:Float = local[0], localY:Float = local[1];
|
||||
local[0] = localX * a + localY * b + worldX;
|
||||
local[1] = localX * c + localY * d + worldY;
|
||||
return local;
|
||||
}
|
||||
|
||||
public function worldToLocalRotation(worldRotation:Float):Float {
|
||||
@ -334,16 +393,13 @@ class Bone implements Updatable {
|
||||
}
|
||||
|
||||
public function rotateWorld(degrees:Float):Void {
|
||||
var a:Float = this.a,
|
||||
b:Float = this.b,
|
||||
c:Float = this.c,
|
||||
d:Float = this.d;
|
||||
var cos:Float = MathUtils.cosDeg(degrees),
|
||||
sin:Float = MathUtils.sinDeg(degrees);
|
||||
this.a = cos * a - sin * c;
|
||||
this.b = cos * b - sin * d;
|
||||
this.c = sin * a + cos * c;
|
||||
this.d = sin * b + cos * d;
|
||||
degrees *= MathUtils.degRad;
|
||||
var sin:Float = Math.sin(degrees), cos:Float = Math.cos(degrees);
|
||||
var ra:Float = a, rb:Float = b;
|
||||
a = cos * ra - sin * c;
|
||||
b = cos * rb - sin * d;
|
||||
c = sin * ra + cos * c;
|
||||
d = sin * rb + cos * d;
|
||||
}
|
||||
|
||||
public function toString():String {
|
||||
|
||||
@ -42,9 +42,11 @@ class BoneData {
|
||||
public var scaleY:Float = 1;
|
||||
public var shearX:Float = 0;
|
||||
public var shearY:Float = 0;
|
||||
public var transformMode:TransformMode = TransformMode.normal;
|
||||
public var inherit:Inherit = Inherit.normal;
|
||||
public var skinRequired:Bool = false;
|
||||
public var color:Color = new Color(0, 0, 0, 0);
|
||||
public var icon:String;
|
||||
public var visible:Bool = false;
|
||||
|
||||
/** @param parent May be null. */
|
||||
public function new(index:Int, name:String, parent:BoneData) {
|
||||
@ -65,7 +67,7 @@ class BoneData {
|
||||
|
||||
public var name(get, never):String;
|
||||
|
||||
private function get_name():String {
|
||||
function get_name():String {
|
||||
return _name;
|
||||
}
|
||||
|
||||
|
||||
@ -64,7 +64,16 @@ class IkConstraint implements Updatable {
|
||||
return active;
|
||||
}
|
||||
|
||||
public function update():Void {
|
||||
public function setToSetupPose () {
|
||||
var data:IkConstraintData = _data;
|
||||
mix = data.mix;
|
||||
softness = data.softness;
|
||||
bendDirection = data.bendDirection;
|
||||
compress = data.compress;
|
||||
stretch = data.stretch;
|
||||
}
|
||||
|
||||
public function update(physics:Physics):Void {
|
||||
if (mix == 0)
|
||||
return;
|
||||
switch (bones.length) {
|
||||
@ -93,11 +102,11 @@ class IkConstraint implements Updatable {
|
||||
var rotationIK:Float = -bone.ashearX - bone.arotation,
|
||||
tx:Float = 0,
|
||||
ty:Float = 0;
|
||||
switch (bone.data.transformMode) {
|
||||
case TransformMode.onlyTranslation:
|
||||
switch (bone.inherit) {
|
||||
case Inherit.onlyTranslation:
|
||||
tx = (targetX - bone.worldX) * MathUtils.signum(bone.skeleton.scaleX);
|
||||
ty = (targetY - bone.worldY) * MathUtils.signum(bone.skeleton.scaleY);
|
||||
case TransformMode.noRotationOrReflection:
|
||||
case Inherit.noRotationOrReflection:
|
||||
var s = Math.abs(pa * pd - pb * pc) / Math.max(0.0001, pa * pa + pc * pc);
|
||||
var sa:Float = pa / bone.skeleton.scaleX;
|
||||
var sc:Float = pc / bone.skeleton.scaleY;
|
||||
@ -108,6 +117,7 @@ class IkConstraint implements Updatable {
|
||||
var d:Float = pa * pd - pb * pc;
|
||||
tx = (x * pd - y * pb) / d - bone.ax;
|
||||
ty = (y * pa - x * pc) / d - bone.ay;
|
||||
// TODO: this should fall-through!
|
||||
default:
|
||||
var x:Float = targetX - p.worldX, y:Float = targetY - p.worldY;
|
||||
var d:Float = pa * pd - pb * pc;
|
||||
@ -130,18 +140,19 @@ class IkConstraint implements Updatable {
|
||||
var sx:Float = bone.ascaleX;
|
||||
var sy:Float = bone.ascaleY;
|
||||
if (compress || stretch) {
|
||||
switch (bone.data.transformMode) {
|
||||
case TransformMode.noScale, TransformMode.noScaleOrReflection:
|
||||
switch (bone.inherit) {
|
||||
case Inherit.noScale, Inherit.noScaleOrReflection:
|
||||
tx = targetX - bone.worldX;
|
||||
ty = targetY - bone.worldY;
|
||||
}
|
||||
var b:Float = bone.data.length * sx,
|
||||
dd:Float = Math.sqrt(tx * tx + ty * ty);
|
||||
if ((compress && dd < b) || (stretch && dd > b) && b > 0.0001) {
|
||||
var ss:Float = (dd / b - 1) * alpha + 1;
|
||||
sx *= ss;
|
||||
if (uniform)
|
||||
sy *= ss;
|
||||
var b:Float = bone.data.length * sx;
|
||||
if (b > 0.0001) {
|
||||
var dd:Float = tx * tx + ty * ty;
|
||||
if ((compress && dd < b * b) || (stretch && dd > b * b)) {
|
||||
var s:Float = (Math.sqrt(dd) / b - 1) * alpha + 1;
|
||||
sx *= s;
|
||||
if (uniform) sy *= s;
|
||||
}
|
||||
}
|
||||
}
|
||||
bone.updateWorldTransformWith(bone.ax, bone.ay, bone.arotation + rotationIK * alpha, sx, sy, bone.ashearX, bone.ashearY);
|
||||
@ -152,6 +163,7 @@ class IkConstraint implements Updatable {
|
||||
* @param child Any descendant bone of the parent. */
|
||||
static public function apply2(parent:Bone, child:Bone, targetX:Float, targetY:Float, bendDir:Int, stretch:Bool, uniform:Bool, softness:Float,
|
||||
alpha:Float):Void {
|
||||
if (parent.inherit != Inherit.normal || child.inherit != Inherit.normal) return;
|
||||
var px:Float = parent.ax;
|
||||
var py:Float = parent.ay;
|
||||
var psx:Float = parent.ascaleX;
|
||||
|
||||
@ -32,8 +32,8 @@ package spine;
|
||||
class IkConstraintData extends ConstraintData {
|
||||
public var bones:Array<BoneData> = new Array<BoneData>();
|
||||
public var target:BoneData;
|
||||
public var mix:Float = 1;
|
||||
public var bendDirection:Int = 1;
|
||||
public var mix:Float = 0;
|
||||
public var bendDirection:Int = 0;
|
||||
public var compress:Bool = false;
|
||||
public var stretch:Bool = false;
|
||||
public var uniform:Bool = false;
|
||||
|
||||
56
spine-haxe/spine-haxe/spine/Inherit.hx
Normal file
56
spine-haxe/spine-haxe/spine/Inherit.hx
Normal file
@ -0,0 +1,56 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package spine;
|
||||
|
||||
class Inherit {
|
||||
public static var normal(default, never):Inherit = new Inherit(0, "normal");
|
||||
public static var onlyTranslation(default, never):Inherit = new Inherit(1, "onlyTranslation");
|
||||
public static var noRotationOrReflection(default, never):Inherit = new Inherit(2, "noRotationOrReflection");
|
||||
public static var noScale(default, never):Inherit = new Inherit(3, "noScale");
|
||||
public static var noScaleOrReflection(default, never):Inherit = new Inherit(4, "noScaleOrReflection");
|
||||
|
||||
public static var values:Array<Inherit> = [normal, onlyTranslation, noRotationOrReflection, noScale, noScaleOrReflection];
|
||||
|
||||
public var ordinal(default, null):Int;
|
||||
public var name(default, null):String;
|
||||
|
||||
public function new(ordinal:Int, name:String) {
|
||||
this.ordinal = ordinal;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public static function fromName(name:String):Inherit {
|
||||
for (value in values) {
|
||||
if (value.name == name)
|
||||
return value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -32,6 +32,7 @@ package spine;
|
||||
class MathUtils {
|
||||
static public var PI:Float = Math.PI;
|
||||
static public var PI2:Float = Math.PI * 2;
|
||||
static public var invPI2 = 1 / MathUtils.PI2;
|
||||
static public var radDeg:Float = 180 / Math.PI;
|
||||
static public var degRad:Float = Math.PI / 180;
|
||||
|
||||
@ -43,6 +44,10 @@ class MathUtils {
|
||||
return Math.sin(degrees * degRad);
|
||||
}
|
||||
|
||||
static public function atan2Deg (y:Float, x:Float):Float {
|
||||
return Math.atan2(y, x) * MathUtils.degRad;
|
||||
}
|
||||
|
||||
static public function clamp(value:Float, min:Float, max:Float):Float {
|
||||
if (value < min)
|
||||
return min;
|
||||
|
||||
@ -78,7 +78,16 @@ class PathConstraint implements Updatable {
|
||||
return active;
|
||||
}
|
||||
|
||||
public function update():Void {
|
||||
public function setToSetupPose () {
|
||||
var data:PathConstraintData = _data;
|
||||
position = data.position;
|
||||
spacing = data.spacing;
|
||||
mixRotate = data.mixRotate;
|
||||
mixX = data.mixX;
|
||||
mixY = data.mixY;
|
||||
}
|
||||
|
||||
public function update(physics:Physics):Void {
|
||||
var attachment:PathAttachment = cast(target.attachment, PathAttachment);
|
||||
if (attachment == null)
|
||||
return;
|
||||
@ -111,13 +120,9 @@ class PathConstraint implements Updatable {
|
||||
for (i in 0...n) {
|
||||
bone = bones[i];
|
||||
setupLength = bone.data.length;
|
||||
if (setupLength < PathConstraint.epsilon) {
|
||||
_lengths[i] = 0;
|
||||
} else {
|
||||
x = setupLength * bone.a;
|
||||
y = setupLength * bone.c;
|
||||
_lengths[i] = Math.sqrt(x * x + y * y);
|
||||
}
|
||||
x = setupLength * bone.a;
|
||||
y = setupLength * bone.c;
|
||||
_lengths[i] = Math.sqrt(x * x + y * y);
|
||||
}
|
||||
}
|
||||
for (i in 1...spacesCount) {
|
||||
|
||||
@ -29,14 +29,13 @@
|
||||
|
||||
package spine;
|
||||
|
||||
class TransformMode {
|
||||
public static var normal(default, never):TransformMode = new TransformMode("normal");
|
||||
public static var onlyTranslation(default, never):TransformMode = new TransformMode("onlyTranslation");
|
||||
public static var noRotationOrReflection(default, never):TransformMode = new TransformMode("noRotationOrReflection");
|
||||
public static var noScale(default, never):TransformMode = new TransformMode("noScale");
|
||||
public static var noScaleOrReflection(default, never):TransformMode = new TransformMode("noScaleOrReflection");
|
||||
class Physics {
|
||||
public static var none(default, never):Physics = new Physics("none");
|
||||
public static var reset(default, never):Physics = new Physics("reset");
|
||||
public static var update(default, never):Physics = new Physics("update");
|
||||
public static var pose(default, never):Physics = new Physics("pose");
|
||||
|
||||
public static var values:Array<TransformMode> = [normal, onlyTranslation, noRotationOrReflection, noScale, noScaleOrReflection];
|
||||
public static var values:Array<Physics> = [none, reset, update, pose];
|
||||
|
||||
public var name(default, null):String;
|
||||
|
||||
@ -44,7 +43,7 @@ class TransformMode {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public static function fromName(name:String):TransformMode {
|
||||
public static function fromName(name:String):Physics {
|
||||
for (value in values) {
|
||||
if (value.name == name)
|
||||
return value;
|
||||
322
spine-haxe/spine-haxe/spine/PhysicsConstraint.hx
Normal file
322
spine-haxe/spine-haxe/spine/PhysicsConstraint.hx
Normal file
@ -0,0 +1,322 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package spine;
|
||||
|
||||
class PhysicsConstraint implements Updatable {
|
||||
private var _data:PhysicsConstraintData;
|
||||
private var _bone:Bone = null;
|
||||
|
||||
public var inertia:Float = 0;
|
||||
public var strength:Float = 0;
|
||||
public var damping:Float = 0;
|
||||
public var massInverse:Float = 0;
|
||||
public var wind:Float = 0;
|
||||
public var gravity:Float = 0;
|
||||
public var mix:Float = 0;
|
||||
|
||||
private var _reset:Bool = true;
|
||||
|
||||
public var ux:Float = 0;
|
||||
public var uy:Float = 0;
|
||||
public var cx:Float = 0;
|
||||
public var cy:Float = 0;
|
||||
public var tx:Float = 0;
|
||||
public var ty:Float = 0;
|
||||
public var xOffset:Float = 0;
|
||||
public var xVelocity:Float = 0;
|
||||
public var yOffset:Float = 0;
|
||||
public var yVelocity:Float = 0;
|
||||
public var rotateOffset:Float = 0;
|
||||
public var rotateVelocity:Float = 0;
|
||||
public var scaleOffset:Float = 0;
|
||||
public var scaleVelocity:Float = 0;
|
||||
|
||||
public var active:Bool = false;
|
||||
|
||||
private var _skeleton:Skeleton;
|
||||
public var remaining:Float = 0;
|
||||
public var lastTime:Float = 0;
|
||||
|
||||
public function new(data: PhysicsConstraintData, skeleton: Skeleton) {
|
||||
_data = data;
|
||||
_skeleton = skeleton;
|
||||
_bone = skeleton.bones[data.bone.index];
|
||||
inertia = data.inertia;
|
||||
strength = data.strength;
|
||||
damping = data.damping;
|
||||
massInverse = data.massInverse;
|
||||
wind = data.wind;
|
||||
gravity = data.gravity;
|
||||
mix = data.mix;
|
||||
}
|
||||
|
||||
public function reset () {
|
||||
remaining = 0;
|
||||
lastTime = skeleton.time;
|
||||
_reset = true;
|
||||
xOffset = 0;
|
||||
xVelocity = 0;
|
||||
yOffset = 0;
|
||||
yVelocity = 0;
|
||||
rotateOffset = 0;
|
||||
rotateVelocity = 0;
|
||||
scaleOffset = 0;
|
||||
scaleVelocity = 0;
|
||||
}
|
||||
|
||||
public function setToSetupPose () {
|
||||
var data:PhysicsConstraintData = _data;
|
||||
inertia = data.inertia;
|
||||
strength = data.strength;
|
||||
damping = data.damping;
|
||||
massInverse = data.massInverse;
|
||||
wind = data.wind;
|
||||
gravity = data.gravity;
|
||||
mix = data.mix;
|
||||
}
|
||||
|
||||
public function isActive():Bool {
|
||||
return active;
|
||||
}
|
||||
|
||||
public function update(physics:Physics):Void {
|
||||
var mix:Float = this.mix;
|
||||
if (mix == 0) return;
|
||||
|
||||
var x:Bool = _data.x > 0, y:Bool = _data.y > 0,
|
||||
rotateOrShearX:Bool = _data.rotate > 0 || _data.shearX > 0,
|
||||
scaleX:Bool = _data.scaleX > 0;
|
||||
var bone:Bone = _bone;
|
||||
var l:Float = bone.data.length;
|
||||
|
||||
switch (physics) {
|
||||
case Physics.none:
|
||||
return;
|
||||
case Physics.reset, Physics.update:
|
||||
if (physics == Physics.reset) reset();
|
||||
|
||||
var delta:Float = Math.max(skeleton.time - lastTime, 0);
|
||||
remaining += delta;
|
||||
lastTime = _skeleton.time;
|
||||
|
||||
var bx:Float = bone.worldX, by:Float = bone.worldY;
|
||||
if (_reset) {
|
||||
_reset = false;
|
||||
ux = bx;
|
||||
uy = by;
|
||||
} else {
|
||||
var a:Float = remaining,
|
||||
i:Float = inertia,
|
||||
q:Float = _data.limit * delta,
|
||||
t:Float = _data.step,
|
||||
f:Float = skeleton.data.referenceScale,
|
||||
d:Float = -1;
|
||||
if (x || y) {
|
||||
if (x) {
|
||||
var u:Float = (ux - bx) * i;
|
||||
xOffset += u > q ? q : u < -q ? -q : u;
|
||||
ux = bx;
|
||||
}
|
||||
if (y) {
|
||||
var u:Float = (uy - by) * i;
|
||||
yOffset += u > q ? q : u < -q ? -q : u;
|
||||
uy = by;
|
||||
}
|
||||
if (a >= t) {
|
||||
d = Math.pow(damping, 60 * t);
|
||||
var m:Float = massInverse * t,
|
||||
e:Float = strength,
|
||||
w:Float = wind * f,
|
||||
g:Float = (Bone.yDown ? -gravity : gravity) * f;
|
||||
do {
|
||||
if (x) {
|
||||
xVelocity += (w - xOffset * e) * m;
|
||||
xOffset += xVelocity * t;
|
||||
xVelocity *= d;
|
||||
}
|
||||
if (y) {
|
||||
yVelocity -= (g + yOffset * e) * m;
|
||||
yOffset += yVelocity * t;
|
||||
yVelocity *= d;
|
||||
}
|
||||
a -= t;
|
||||
} while (a >= t);
|
||||
}
|
||||
if (x) bone.worldX += xOffset * mix * data.x;
|
||||
if (y) bone.worldY += yOffset * mix * data.y;
|
||||
}
|
||||
if (rotateOrShearX || scaleX) {
|
||||
var ca:Float = Math.atan2(bone.c, bone.a),
|
||||
c:Float = 0,
|
||||
s:Float = 0,
|
||||
mr:Float = 0;
|
||||
var dx:Float = cx - bone.worldX,
|
||||
dy:Float = cy - bone.worldY;
|
||||
if (dx > q)
|
||||
dx = q;
|
||||
else if (dx < -q) //
|
||||
dx = -q;
|
||||
if (dy > q)
|
||||
dy = q;
|
||||
else if (dy < -q) //
|
||||
dy = -q;
|
||||
if (rotateOrShearX) {
|
||||
mr = (_data.rotate + _data.shearX) * mix;
|
||||
var r:Float = Math.atan2(dy + ty, dx + tx) - ca - rotateOffset * mr;
|
||||
rotateOffset += (r - Math.ceil(r * MathUtils.invPI2 - 0.5) * MathUtils.PI2) * i;
|
||||
r = rotateOffset * mr + ca;
|
||||
c = Math.cos(r);
|
||||
s = Math.sin(r);
|
||||
if (scaleX) {
|
||||
r = l * bone.worldScaleX;
|
||||
if (r > 0) scaleOffset += (dx * c + dy * s) * i / r;
|
||||
}
|
||||
} else {
|
||||
c = Math.cos(ca);
|
||||
s = Math.sin(ca);
|
||||
var r:Float = l * bone.worldScaleX;
|
||||
if (r > 0) scaleOffset += (dx * c + dy * s) * i / r;
|
||||
}
|
||||
a = remaining;
|
||||
if (a >= t) {
|
||||
if (d == -1) d = Math.pow(damping, 60 * t);
|
||||
var m:Float = massInverse * t,
|
||||
e:Float = strength,
|
||||
w:Float = wind,
|
||||
g:Float = (Bone.yDown ? -gravity : gravity),
|
||||
h:Float = l / f;
|
||||
while (true) {
|
||||
a -= t;
|
||||
if (scaleX) {
|
||||
scaleVelocity += (w * c - g * s - scaleOffset * e) * m;
|
||||
scaleOffset += scaleVelocity * t;
|
||||
scaleVelocity *= d;
|
||||
}
|
||||
if (rotateOrShearX) {
|
||||
rotateVelocity -= ((w * s + g * c) * h + rotateOffset * e) * m;
|
||||
rotateOffset += rotateVelocity * t;
|
||||
rotateVelocity *= d;
|
||||
if (a < t) break;
|
||||
var r:Float = rotateOffset * mr + ca;
|
||||
c = Math.cos(r);
|
||||
s = Math.sin(r);
|
||||
} else if (a < t) //
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
remaining = a;
|
||||
}
|
||||
cx = bone.worldX;
|
||||
cy = bone.worldY;
|
||||
case Physics.pose:
|
||||
if (x) bone.worldX += xOffset * mix * data.x;
|
||||
if (y) bone.worldY += yOffset * mix * data.y;
|
||||
}
|
||||
|
||||
if (rotateOrShearX) {
|
||||
var o:Float = rotateOffset * mix,
|
||||
s:Float = 0,
|
||||
c:Float = 0,
|
||||
a:Float = 0;
|
||||
if (_data.shearX > 0) {
|
||||
var r:Float = 0;
|
||||
if (_data.rotate > 0) {
|
||||
r = o * _data.rotate;
|
||||
s = Math.sin(r);
|
||||
c = Math.cos(r);
|
||||
a = bone.b;
|
||||
bone.b = c * a - s * bone.d;
|
||||
bone.d = s * a + c * bone.d;
|
||||
}
|
||||
r += o * _data.shearX;
|
||||
s = Math.sin(r);
|
||||
c = Math.cos(r);
|
||||
a = bone.a;
|
||||
bone.a = c * a - s * bone.c;
|
||||
bone.c = s * a + c * bone.c;
|
||||
} else {
|
||||
o *= _data.rotate;
|
||||
s = Math.sin(o);
|
||||
c = Math.cos(o);
|
||||
a = bone.a;
|
||||
bone.a = c * a - s * bone.c;
|
||||
bone.c = s * a + c * bone.c;
|
||||
a = bone.b;
|
||||
bone.b = c * a - s * bone.d;
|
||||
bone.d = s * a + c * bone.d;
|
||||
}
|
||||
}
|
||||
if (scaleX) {
|
||||
var s:Float = 1 + scaleOffset * mix * data.scaleX;
|
||||
bone.a *= s;
|
||||
bone.c *= s;
|
||||
}
|
||||
if (physics != Physics.pose) {
|
||||
tx = l * bone.a;
|
||||
ty = l * bone.c;
|
||||
}
|
||||
bone.updateAppliedTransform();
|
||||
}
|
||||
|
||||
public function translate (x:Float, y:Float):Void {
|
||||
ux -= x;
|
||||
uy -= y;
|
||||
cx -= x;
|
||||
cy -= y;
|
||||
}
|
||||
|
||||
public function rotate (x:Float, y:Float, degrees:Float):Void {
|
||||
var r:Float = degrees * MathUtils.degRad, cos:Float = Math.cos(r), sin:Float = Math.sin(r);
|
||||
var dx:Float = cx - x, dy:Float = cy - y;
|
||||
translate(dx * cos - dy * sin - dx, dx * sin + dy * cos - dy);
|
||||
}
|
||||
|
||||
public var bone(get, never):Bone;
|
||||
|
||||
private function get_bone():Bone {
|
||||
if (_bone == null)
|
||||
throw new SpineException("Bone not set.")
|
||||
else return _bone;
|
||||
}
|
||||
|
||||
public var data(get, never):PhysicsConstraintData;
|
||||
|
||||
private function get_data():PhysicsConstraintData {
|
||||
return _data;
|
||||
}
|
||||
|
||||
public var skeleton(get, never):Skeleton;
|
||||
|
||||
private function get_skeleton():Skeleton {
|
||||
return _skeleton;
|
||||
}
|
||||
|
||||
}
|
||||
60
spine-haxe/spine-haxe/spine/PhysicsConstraintData.hx
Normal file
60
spine-haxe/spine-haxe/spine/PhysicsConstraintData.hx
Normal file
@ -0,0 +1,60 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package spine;
|
||||
|
||||
class PhysicsConstraintData extends ConstraintData {
|
||||
public var bone:BoneData;
|
||||
public var x:Float = 0;
|
||||
public var y:Float = 0;
|
||||
public var rotate:Float = 0;
|
||||
public var scaleX:Float = 0;
|
||||
public var shearX:Float = 0;
|
||||
public var limit:Float = 0;
|
||||
public var step:Float = 0;
|
||||
public var inertia:Float = 0;
|
||||
public var strength:Float = 0;
|
||||
public var damping:Float = 0;
|
||||
public var massInverse:Float = 0;
|
||||
public var wind:Float = 0;
|
||||
public var gravity:Float = 0;
|
||||
public var mix:Float = 0;
|
||||
public var inertiaGlobal:Bool = false;
|
||||
public var strengthGlobal:Bool = false;
|
||||
public var dampingGlobal:Bool = false;
|
||||
public var massGlobal:Bool = false;
|
||||
public var windGlobal:Bool = false;
|
||||
public var gravityGlobal:Bool = false;
|
||||
public var mixGlobal:Bool = false;
|
||||
|
||||
public function new(name:String) {
|
||||
super(name, 0, false);
|
||||
}
|
||||
|
||||
}
|
||||
@ -40,11 +40,12 @@ class Skeleton {
|
||||
private var _data:SkeletonData;
|
||||
|
||||
public var bones:Array<Bone>;
|
||||
public var slots:Array<Slot>;
|
||||
public var slots:Array<Slot>; // Setup pose draw order.
|
||||
public var drawOrder:Array<Slot>;
|
||||
public var ikConstraints:Array<IkConstraint>;
|
||||
public var transformConstraints:Array<TransformConstraint>;
|
||||
public var pathConstraints:Array<PathConstraint>;
|
||||
public var physicsConstraints:Array<PhysicsConstraint>;
|
||||
|
||||
private var _updateCache:Array<Updatable> = new Array<Updatable>();
|
||||
private var _skin:Skin;
|
||||
@ -54,6 +55,7 @@ class Skeleton {
|
||||
public var scaleY:Float = 1;
|
||||
public var x:Float = 0;
|
||||
public var y:Float = 0;
|
||||
public var time:Float = 0;
|
||||
|
||||
public function new(data:SkeletonData) {
|
||||
if (data == null) {
|
||||
@ -98,6 +100,11 @@ class Skeleton {
|
||||
pathConstraints.push(new PathConstraint(pathConstraintData, this));
|
||||
}
|
||||
|
||||
physicsConstraints = new Array<PhysicsConstraint>();
|
||||
for (physicConstraintData in data.physicsConstraints) {
|
||||
physicsConstraints.push(new PhysicsConstraint(physicConstraintData, this));
|
||||
}
|
||||
|
||||
updateCache();
|
||||
}
|
||||
|
||||
@ -127,7 +134,8 @@ class Skeleton {
|
||||
var ikCount:Int = ikConstraints.length;
|
||||
var transformCount:Int = transformConstraints.length;
|
||||
var pathCount:Int = pathConstraints.length;
|
||||
var constraintCount:Int = ikCount + transformCount + pathCount;
|
||||
var physicCount:Int = physicsConstraints.length;
|
||||
var constraintCount:Int = ikCount + transformCount + pathCount + physicCount;
|
||||
|
||||
var continueOuter:Bool;
|
||||
for (i in 0...constraintCount) {
|
||||
@ -156,6 +164,14 @@ class Skeleton {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (continueOuter)
|
||||
continue;
|
||||
for (physicConstraint in physicsConstraints) {
|
||||
if (physicConstraint.data.order == i) {
|
||||
sortPhysicsConstraint(physicConstraint);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (bone in bones) {
|
||||
@ -294,6 +310,19 @@ class Skeleton {
|
||||
}
|
||||
}
|
||||
|
||||
private function sortPhysicsConstraint (constraint: PhysicsConstraint) {
|
||||
var bone:Bone = constraint.bone;
|
||||
constraint.active = bone.active && (!constraint.data.skinRequired || (skin != null && contains(skin.constraints, constraint.data)));
|
||||
if (!constraint.active) return;
|
||||
|
||||
sortBone(bone);
|
||||
|
||||
_updateCache.push(constraint);
|
||||
|
||||
sortReset(bone.children);
|
||||
bone.sorted = true;
|
||||
}
|
||||
|
||||
private function sortBone(bone:Bone):Void {
|
||||
if (bone.sorted)
|
||||
return;
|
||||
@ -315,7 +344,8 @@ class Skeleton {
|
||||
}
|
||||
|
||||
/** Updates the world transform for each bone and applies constraints. */
|
||||
public function updateWorldTransform():Void {
|
||||
public function updateWorldTransform(physics:Physics):Void {
|
||||
if (physics == null) throw new SpineException("physics is undefined");
|
||||
for (bone in bones) {
|
||||
bone.ax = bone.x;
|
||||
bone.ay = bone.y;
|
||||
@ -327,11 +357,11 @@ class Skeleton {
|
||||
}
|
||||
|
||||
for (updatable in _updateCache) {
|
||||
updatable.update();
|
||||
updatable.update(physics);
|
||||
}
|
||||
}
|
||||
|
||||
public function updateWorldTransformWith(parent:Bone):Void {
|
||||
public function updateWorldTransformWith(physics:Physics, parent:Bone):Void {
|
||||
// Apply the parent bone transform to the root bone. The root bone always inherits scale, rotation and reflection.
|
||||
var rootBone:Bone = rootBone;
|
||||
var pa:Float = parent.a,
|
||||
@ -341,11 +371,12 @@ class Skeleton {
|
||||
rootBone.worldX = pa * x + pb * y + parent.worldX;
|
||||
rootBone.worldY = pc * x + pd * y + parent.worldY;
|
||||
|
||||
var rotationY:Float = rootBone.rotation + 90 + rootBone.shearY;
|
||||
var la:Float = MathUtils.cosDeg(rootBone.rotation + rootBone.shearX) * rootBone.scaleX;
|
||||
var lb:Float = MathUtils.cosDeg(rotationY) * rootBone.scaleY;
|
||||
var lc:Float = MathUtils.sinDeg(rootBone.rotation + rootBone.shearX) * rootBone.scaleX;
|
||||
var ld:Float = MathUtils.sinDeg(rotationY) * rootBone.scaleY;
|
||||
var rx:Float = (rootBone.rotation + rootBone.shearX) * MathUtils.degRad;
|
||||
var ry:Float = (rootBone.rotation + 90 + rootBone.shearY) * MathUtils.degRad;
|
||||
var la:Float = Math.cos(rx) * rootBone.scaleX;
|
||||
var lb:Float = Math.cos(ry) * rootBone.scaleY;
|
||||
var lc:Float = Math.sin(rx) * rootBone.scaleX;
|
||||
var ld:Float = Math.sin(ry) * rootBone.scaleY;
|
||||
rootBone.a = (pa * la + pb * lc) * scaleX;
|
||||
rootBone.b = (pa * lb + pb * ld) * scaleX;
|
||||
rootBone.c = (pc * la + pd * lc) * scaleY;
|
||||
@ -354,7 +385,7 @@ class Skeleton {
|
||||
// Update everything except root bone.
|
||||
for (updatable in _updateCache) {
|
||||
if (updatable != rootBone)
|
||||
updatable.update();
|
||||
updatable.update(physics);
|
||||
}
|
||||
}
|
||||
|
||||
@ -366,34 +397,11 @@ class Skeleton {
|
||||
|
||||
/** Sets the bones and constraints to their setup pose values. */
|
||||
public function setBonesToSetupPose():Void {
|
||||
for (bone in bones) {
|
||||
bone.setToSetupPose();
|
||||
}
|
||||
|
||||
for (ikConstraint in ikConstraints) {
|
||||
ikConstraint.mix = ikConstraint.data.mix;
|
||||
ikConstraint.softness = ikConstraint.data.softness;
|
||||
ikConstraint.bendDirection = ikConstraint.data.bendDirection;
|
||||
ikConstraint.compress = ikConstraint.data.compress;
|
||||
ikConstraint.stretch = ikConstraint.data.stretch;
|
||||
}
|
||||
|
||||
for (transformConstraint in transformConstraints) {
|
||||
transformConstraint.mixRotate = transformConstraint.data.mixRotate;
|
||||
transformConstraint.mixX = transformConstraint.data.mixX;
|
||||
transformConstraint.mixY = transformConstraint.data.mixY;
|
||||
transformConstraint.mixScaleX = transformConstraint.data.mixScaleX;
|
||||
transformConstraint.mixScaleY = transformConstraint.data.mixScaleY;
|
||||
transformConstraint.mixShearY = transformConstraint.data.mixShearY;
|
||||
}
|
||||
|
||||
for (pathConstraint in pathConstraints) {
|
||||
pathConstraint.position = pathConstraint.data.position;
|
||||
pathConstraint.spacing = pathConstraint.data.spacing;
|
||||
pathConstraint.mixRotate = pathConstraint.data.mixRotate;
|
||||
pathConstraint.mixX = pathConstraint.data.mixX;
|
||||
pathConstraint.mixY = pathConstraint.data.mixY;
|
||||
}
|
||||
for (bone in this.bones) bone.setToSetupPose();
|
||||
for (constraint in this.ikConstraints) constraint.setToSetupPose();
|
||||
for (constraint in this.transformConstraints) constraint.setToSetupPose();
|
||||
for (constraint in this.pathConstraints) constraint.setToSetupPose();
|
||||
for (constraint in this.physicsConstraints) constraint.setToSetupPose();
|
||||
}
|
||||
|
||||
public function setSlotsToSetupPose():Void {
|
||||
@ -585,6 +593,17 @@ class Skeleton {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @return May be null. */
|
||||
public function findPhysicsConstraint(constraintName:String):PhysicsConstraint {
|
||||
if (constraintName == null)
|
||||
throw new SpineException("constraintName cannot be null.");
|
||||
for (physicsConstraint in physicsConstraints) {
|
||||
if (physicsConstraint.data.name == constraintName)
|
||||
return physicsConstraint;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function toString():String {
|
||||
return _data.name != null ? _data.name : "Skeleton?";
|
||||
}
|
||||
@ -632,4 +651,18 @@ class Skeleton {
|
||||
_bounds.height = maxY - minY;
|
||||
return _bounds;
|
||||
}
|
||||
|
||||
public function update (delta:Float):Void {
|
||||
time += delta;
|
||||
}
|
||||
|
||||
public function physicsTranslate (x:Float, y:Float):Void {
|
||||
for (physicsConstraint in physicsConstraints)
|
||||
physicsConstraint.translate(x, y);
|
||||
}
|
||||
|
||||
public function physicsRotate (x:Float, y:Float, degrees:Float):Void {
|
||||
for (physicsConstraint in physicsConstraints)
|
||||
physicsConstraint.rotate(x, y, degrees);
|
||||
}
|
||||
}
|
||||
|
||||
@ -127,6 +127,7 @@ class SkeletonBinary {
|
||||
skeletonData.y = input.readFloat();
|
||||
skeletonData.width = input.readFloat();
|
||||
skeletonData.height = input.readFloat();
|
||||
skeletonData.referenceScale = input.readFloat() * scale;
|
||||
|
||||
var nonessential:Bool = input.readBoolean();
|
||||
if (nonessential) {
|
||||
@ -158,7 +159,7 @@ class SkeletonBinary {
|
||||
boneData.shearX = input.readFloat();
|
||||
boneData.shearY = input.readFloat();
|
||||
boneData.length = input.readFloat() * scale;
|
||||
boneData.transformMode = TransformMode.values[input.readInt(true)];
|
||||
boneData.inherit = Inherit.values[input.readInt(true)];
|
||||
boneData.skinRequired = input.readBoolean();
|
||||
if (nonessential)
|
||||
boneData.color.setFromRgba8888(input.readInt32());
|
||||
|
||||
@ -48,10 +48,12 @@ class SkeletonData {
|
||||
public var ikConstraints:Array<IkConstraintData> = new Array<IkConstraintData>();
|
||||
public var transformConstraints:Array<TransformConstraintData> = new Array<TransformConstraintData>();
|
||||
public var pathConstraints:Array<PathConstraintData> = new Array<PathConstraintData>();
|
||||
public var physicsConstraints:Array<PhysicsConstraintData> = new Array<PhysicsConstraintData>();
|
||||
public var x:Float = 0;
|
||||
public var y:Float = 0;
|
||||
public var width:Float = 0;
|
||||
public var height:Float = 0;
|
||||
public var referenceScale:Float = 100;
|
||||
public var version:String;
|
||||
public var hash:String;
|
||||
public var fps:Float = 0;
|
||||
@ -214,6 +216,31 @@ class SkeletonData {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// --- Physics constraints.
|
||||
|
||||
/** @return May be null. */
|
||||
public function findPhysicsConstraint(constraintName:String):PhysicsConstraintData {
|
||||
if (constraintName == null)
|
||||
throw new SpineException("physicsConstraintName cannot be null.");
|
||||
for (i in 0...physicsConstraints.length) {
|
||||
var constraint:PhysicsConstraintData = physicsConstraints[i];
|
||||
if (constraint.name == constraintName)
|
||||
return constraint;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @return -1 if the path constraint was not found. */
|
||||
public function findPhysicsConstraintIndex(constraintName:String):Int {
|
||||
if (constraintName == null)
|
||||
throw new SpineException("constraintName cannot be null.");
|
||||
for (i in 0...physicsConstraints.length) {
|
||||
if (physicsConstraints[i].name == constraintName)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public function toString():String {
|
||||
return name;
|
||||
}
|
||||
|
||||
@ -41,9 +41,19 @@ import spine.animation.DeformTimeline;
|
||||
import spine.animation.DrawOrderTimeline;
|
||||
import spine.animation.EventTimeline;
|
||||
import spine.animation.IkConstraintTimeline;
|
||||
import spine.animation.InheritTimeline;
|
||||
import spine.animation.PathConstraintMixTimeline;
|
||||
import spine.animation.PathConstraintPositionTimeline;
|
||||
import spine.animation.PathConstraintSpacingTimeline;
|
||||
import spine.animation.PhysicsConstraintResetTimeline;
|
||||
import spine.animation.PhysicsConstraintInertiaTimeline;
|
||||
import spine.animation.PhysicsConstraintStrengthTimeline;
|
||||
import spine.animation.PhysicsConstraintDampingTimeline;
|
||||
import spine.animation.PhysicsConstraintMassTimeline;
|
||||
import spine.animation.PhysicsConstraintWindTimeline;
|
||||
import spine.animation.PhysicsConstraintGravityTimeline;
|
||||
import spine.animation.PhysicsConstraintMixTimeline;
|
||||
import spine.animation.PhysicsConstraintTimeline;
|
||||
import spine.animation.RGB2Timeline;
|
||||
import spine.animation.RGBA2Timeline;
|
||||
import spine.animation.RGBATimeline;
|
||||
@ -99,8 +109,10 @@ class SkeletonJson {
|
||||
skeletonData.y = getFloat(skeletonMap, "y");
|
||||
skeletonData.width = getFloat(skeletonMap, "width");
|
||||
skeletonData.height = getFloat(skeletonMap, "height");
|
||||
skeletonData.referenceScale = getFloat(skeletonMap, "referenceScale", 100);
|
||||
skeletonData.fps = getFloat(skeletonMap, "fps");
|
||||
skeletonData.imagesPath = getString(skeletonMap, "images", "");
|
||||
skeletonData.audioPath = getString(skeletonMap, "audio", "");
|
||||
}
|
||||
|
||||
// Bones.
|
||||
@ -122,8 +134,8 @@ class SkeletonJson {
|
||||
boneData.scaleY = getFloat(boneMap, "scaleY", 1);
|
||||
boneData.shearX = getFloat(boneMap, "shearX");
|
||||
boneData.shearY = getFloat(boneMap, "shearY");
|
||||
boneData.transformMode = Reflect.hasField(boneMap,
|
||||
"transform") ? TransformMode.fromName(Reflect.getProperty(boneMap, "transform")) : TransformMode.normal;
|
||||
boneData.inherit = Reflect.hasField(boneMap,
|
||||
"inherit") ? Inherit.fromName(Reflect.getProperty(boneMap, "inherit")) : Inherit.normal;
|
||||
boneData.skinRequired = Reflect.hasField(boneMap, "skin") ? cast(Reflect.getProperty(boneMap, "skin"), Bool) : false;
|
||||
|
||||
var color:String = Reflect.getProperty(boneMap, "color");
|
||||
@ -136,7 +148,14 @@ class SkeletonJson {
|
||||
|
||||
// Slots.
|
||||
for (slotMap in cast(Reflect.getProperty(root, "slots"), Array<Dynamic>)) {
|
||||
var path:String = null;
|
||||
var slotName:String = Reflect.getProperty(slotMap, "name");
|
||||
var slash:Int = slotName.lastIndexOf('/');
|
||||
if (slash != -1) {
|
||||
path = slotName.substring(0, slash);
|
||||
slotName = slotName.substring(slash + 1);
|
||||
}
|
||||
|
||||
var boneName:String = Reflect.getProperty(slotMap, "bone");
|
||||
boneData = skeletonData.findBone(boneName);
|
||||
if (boneData == null)
|
||||
@ -156,6 +175,8 @@ class SkeletonJson {
|
||||
|
||||
slotData.attachmentName = Reflect.getProperty(slotMap, "attachment");
|
||||
slotData.blendMode = Reflect.hasField(slotMap, "blend") ? BlendMode.fromName(Reflect.getProperty(slotMap, "blend")) : BlendMode.normal;
|
||||
slotData.visible = getValue(slotMap, "visible", true);
|
||||
slotData.path = path;
|
||||
skeletonData.slots.push(slotData);
|
||||
}
|
||||
|
||||
@ -270,6 +291,45 @@ class SkeletonJson {
|
||||
}
|
||||
}
|
||||
|
||||
// Physics constraints.
|
||||
if (Reflect.hasField(root, "physics")) {
|
||||
for (constraintMap in cast(Reflect.getProperty(root, "physics"), Array<Dynamic>)) {
|
||||
var physicsData:PhysicsConstraintData = new PhysicsConstraintData(Reflect.getProperty(constraintMap, "name"));
|
||||
physicsData.order = getInt(constraintMap, "order");
|
||||
physicsData.skinRequired = Reflect.hasField(constraintMap, "skin") ? cast(Reflect.getProperty(constraintMap, "skin"), Bool) : false;
|
||||
|
||||
var boneName:String = Reflect.getProperty(constraintMap, "bone");
|
||||
var bone = skeletonData.findBone(boneName);
|
||||
if (bone == null)
|
||||
throw new SpineException("Physics constraint bone not found: " + boneName);
|
||||
physicsData.bone = bone;
|
||||
|
||||
physicsData.x = getFloat(constraintMap, "x");
|
||||
physicsData.y = getFloat(constraintMap, "y");
|
||||
physicsData.rotate = getFloat(constraintMap, "rotate");
|
||||
physicsData.scaleX = getFloat(constraintMap, "scaleX");
|
||||
physicsData.shearX = getFloat(constraintMap, "shearX");
|
||||
physicsData.limit = getFloat(constraintMap, "limit", 5000) * scale;
|
||||
physicsData.step = 1 / getFloat(constraintMap, "fps", 60);
|
||||
physicsData.inertia = getFloat(constraintMap, "inertia", 1);
|
||||
physicsData.strength = getFloat(constraintMap, "strength", 100);
|
||||
physicsData.damping = getFloat(constraintMap, "damping", 1);
|
||||
physicsData.massInverse = 1 / getFloat(constraintMap, "mass", 1);
|
||||
physicsData.wind = getFloat(constraintMap, "wind");
|
||||
physicsData.gravity = getFloat(constraintMap, "gravity");
|
||||
physicsData.mix = getValue(constraintMap, "mix", 1);
|
||||
physicsData.inertiaGlobal = Reflect.hasField(constraintMap, "inertiaGlobal") ? cast(Reflect.getProperty(constraintMap, "inertiaGlobal"), Bool) : false;
|
||||
physicsData.strengthGlobal = Reflect.hasField(constraintMap, "strengthGlobal") ? cast(Reflect.getProperty(constraintMap, "strengthGlobal"), Bool) : false;
|
||||
physicsData.dampingGlobal = Reflect.hasField(constraintMap, "dampingGlobal") ? cast(Reflect.getProperty(constraintMap, "dampingGlobal"), Bool) : false;
|
||||
physicsData.dampingGlobal = Reflect.hasField(constraintMap, "dampingGlobal") ? cast(Reflect.getProperty(constraintMap, "dampingGlobal"), Bool) : false;
|
||||
physicsData.windGlobal = Reflect.hasField(constraintMap, "windGlobal") ? cast(Reflect.getProperty(constraintMap, "windGlobal"), Bool) : false;
|
||||
physicsData.gravityGlobal = Reflect.hasField(constraintMap, "gravityGlobal") ? cast(Reflect.getProperty(constraintMap, "gravityGlobal"), Bool) : false;
|
||||
physicsData.mixGlobal = Reflect.hasField(constraintMap, "mixGlobal") ? cast(Reflect.getProperty(constraintMap, "mixGlobal"), Bool) : false;
|
||||
|
||||
skeletonData.physicsConstraints.push(physicsData);
|
||||
}
|
||||
}
|
||||
|
||||
// Skins.
|
||||
if (Reflect.hasField(root, "skins")) {
|
||||
for (skinMap in cast(Reflect.getProperty(root, "skins"), Array<Dynamic>)) {
|
||||
@ -315,6 +375,16 @@ class SkeletonJson {
|
||||
}
|
||||
}
|
||||
|
||||
if (Reflect.hasField(skinMap, "physics")) {
|
||||
var physics:Array<Dynamic> = cast(Reflect.getProperty(skinMap, "physics"), Array<Dynamic>);
|
||||
for (ii in 0...physics.length) {
|
||||
var constraint:ConstraintData = skeletonData.findPhysicsConstraint(physics[ii]);
|
||||
if (constraint == null)
|
||||
throw new SpineException("Skin physics constraint not found: " + physics[ii]);
|
||||
skin.constraints.push(constraint);
|
||||
}
|
||||
}
|
||||
|
||||
if (Reflect.hasField(skinMap, "attachments")) {
|
||||
var attachments:Dynamic = Reflect.getProperty(skinMap, "attachments");
|
||||
for (slotName in Reflect.fields(attachments)) {
|
||||
@ -759,6 +829,13 @@ class SkeletonJson {
|
||||
} else if (timelineName == "sheary") {
|
||||
var shearYTimeline:ShearYTimeline = new ShearYTimeline(timelineMap.length, timelineMap.length, boneIndex);
|
||||
timelines.push(readTimeline(timelineMap, shearYTimeline, 0, 1));
|
||||
} else if (timelineName == "inherit") {
|
||||
var inheritTimeline:InheritTimeline = new InheritTimeline(timelineMap.length, boneIndex);
|
||||
for (frame in 0...timelineMap.length) {
|
||||
var aFrame:Dynamic = timelineMap[frame];
|
||||
inheritTimeline.setFrame(frame, getFloat(aFrame, "time"), Inherit.fromName(getValue(aFrame, "inherit", "Normal")));
|
||||
}
|
||||
timelines.push(inheritTimeline);
|
||||
} else {
|
||||
throw new SpineException("Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")");
|
||||
}
|
||||
@ -938,6 +1015,50 @@ class SkeletonJson {
|
||||
}
|
||||
}
|
||||
|
||||
// Physics constraint timelines.
|
||||
var physics:Dynamic = Reflect.getProperty(map, "physics");
|
||||
for (physicsName in Reflect.fields(physics)) {
|
||||
var constraintIndex:Int = skeletonData.findPhysicsConstraintIndex(physicsName);
|
||||
if (constraintIndex == -1)
|
||||
throw new SpineException("Physics constraint not found: " + physicsName);
|
||||
|
||||
var physicsMap:Dynamic = Reflect.field(physics, physicsName);
|
||||
for (timelineName in Reflect.fields(physicsMap)) {
|
||||
timelineMap = Reflect.field(physicsMap, timelineName);
|
||||
keyMap = timelineMap[0];
|
||||
if (keyMap == null)
|
||||
continue;
|
||||
|
||||
var frames:Int = timelineMap.length;
|
||||
if (timelineName == "reset") {
|
||||
var timeline:PhysicsConstraintResetTimeline = new PhysicsConstraintResetTimeline(frames, constraintIndex);
|
||||
for (frame => keyMap in timelineMap)
|
||||
timeline.setFrame(frame, getFloat(keyMap, "time"));
|
||||
timelines.push(timeline);
|
||||
continue;
|
||||
}
|
||||
|
||||
var timeline:PhysicsConstraintTimeline;
|
||||
if (timelineName == "inertia")
|
||||
timeline = new PhysicsConstraintInertiaTimeline(frames, frames, constraintIndex);
|
||||
else if (timelineName == "strength")
|
||||
timeline = new PhysicsConstraintStrengthTimeline(frames, frames, constraintIndex);
|
||||
else if (timelineName == "damping")
|
||||
timeline = new PhysicsConstraintDampingTimeline(frames, frames, constraintIndex);
|
||||
else if (timelineName == "mass")
|
||||
timeline = new PhysicsConstraintMassTimeline(frames, frames, constraintIndex);
|
||||
else if (timelineName == "wind")
|
||||
timeline = new PhysicsConstraintWindTimeline(frames, frames, constraintIndex);
|
||||
else if (timelineName == "gravity")
|
||||
timeline = new PhysicsConstraintGravityTimeline(frames, frames, constraintIndex);
|
||||
else if (timelineName == "mix") //
|
||||
timeline = new PhysicsConstraintMixTimeline(frames, frames, constraintIndex);
|
||||
else
|
||||
continue;
|
||||
timelines.push(readTimeline(timelineMap, timeline, 0, 1));
|
||||
}
|
||||
}
|
||||
|
||||
// Attachment timelines.
|
||||
var attachments:Dynamic = Reflect.getProperty(map, "attachments");
|
||||
for (attachmentsName in Reflect.fields(attachments)) {
|
||||
|
||||
@ -39,6 +39,7 @@ class Skin {
|
||||
private var _attachments:Array<StringMap<Attachment>> = new Array<StringMap<Attachment>>();
|
||||
private var _bones:Array<BoneData> = new Array<BoneData>();
|
||||
private var _constraints:Array<ConstraintData> = new Array<ConstraintData>();
|
||||
private var _color:Color = new Color(0.99607843, 0.61960787, 0.30980393, 1); // fe9e4fff
|
||||
|
||||
public function new(name:String) {
|
||||
if (name == null)
|
||||
@ -208,6 +209,12 @@ class Skin {
|
||||
return _name;
|
||||
}
|
||||
|
||||
public var color(get, never):Color;
|
||||
|
||||
private function get_color():Color {
|
||||
return _color;
|
||||
}
|
||||
|
||||
/*
|
||||
public function toString():String
|
||||
{
|
||||
|
||||
@ -38,6 +38,8 @@ class SlotData {
|
||||
public var darkColor:Color = null;
|
||||
public var attachmentName:String;
|
||||
public var blendMode:BlendMode = BlendMode.normal;
|
||||
public var visible:Bool = true;
|
||||
public var path:String = null;
|
||||
|
||||
public function new(index:Int, name:String, boneData:BoneData) {
|
||||
if (index < 0)
|
||||
|
||||
@ -68,7 +68,17 @@ class TransformConstraint implements Updatable {
|
||||
return active;
|
||||
}
|
||||
|
||||
public function update():Void {
|
||||
public function setToSetupPose () {
|
||||
var data:TransformConstraintData = _data;
|
||||
mixRotate = data.mixRotate;
|
||||
mixX = data.mixX;
|
||||
mixY = data.mixY;
|
||||
mixScaleX = data.mixScaleX;
|
||||
mixScaleY = data.mixScaleY;
|
||||
mixShearY = data.mixShearY;
|
||||
}
|
||||
|
||||
public function update(physics:Physics):Void {
|
||||
if (mixRotate == 0 && mixX == 0 && mixY == 0 && mixScaleX == 0 && mixScaleY == 0 && mixShearY == 0)
|
||||
return;
|
||||
|
||||
@ -226,11 +236,7 @@ class TransformConstraint implements Updatable {
|
||||
public function applyAbsoluteLocal():Void {
|
||||
for (bone in bones) {
|
||||
var rotation:Float = bone.arotation;
|
||||
if (mixRotate != 0) {
|
||||
var r:Float = target.arotation - rotation + _data.offsetRotation;
|
||||
r -= (16384 - (Std.int(16384.499999999996 - r / 360) | 0)) * 360;
|
||||
rotation += r * mixRotate;
|
||||
}
|
||||
if (mixRotate != 0) rotation += (target.arotation - rotation + _data.offsetRotation) * mixRotate;
|
||||
|
||||
var x:Float = bone.ax, y:Float = bone.ay;
|
||||
x += (target.ax - x + _data.offsetX) * mixX;
|
||||
@ -245,11 +251,7 @@ class TransformConstraint implements Updatable {
|
||||
}
|
||||
|
||||
var shearY:Float = bone.ashearY;
|
||||
if (mixShearY != 0) {
|
||||
var r:Float = target.ashearY - shearY + _data.offsetShearY;
|
||||
r -= (16384 - (Std.int(16384.499999999996 - r / 360) | 0)) * 360;
|
||||
bone.shearY += r * mixShearY;
|
||||
}
|
||||
if (mixShearY != 0) shearY += (target.ashearY - shearY + _data.offsetShearY) * mixShearY;
|
||||
|
||||
bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY);
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
package spine;
|
||||
|
||||
interface Updatable {
|
||||
function update():Void;
|
||||
function update(physics:Physics):Void;
|
||||
|
||||
function isActive():Bool;
|
||||
}
|
||||
|
||||
@ -61,8 +61,7 @@ class AlphaTimeline extends CurveTimeline1 implements SlotTimeline {
|
||||
return;
|
||||
|
||||
var color:Color = slot.color;
|
||||
if (time < frames[0]) // Time is before first frame.
|
||||
{
|
||||
if (time < frames[0]) {
|
||||
var setup:Color = slot.data.color;
|
||||
switch (blend) {
|
||||
case MixBlend.setup:
|
||||
|
||||
@ -181,12 +181,13 @@ class AnimationState {
|
||||
var blend:MixBlend = i == 0 ? MixBlend.first : current.mixBlend;
|
||||
|
||||
// Apply mixing from entries first.
|
||||
var mix:Float = current.alpha;
|
||||
var alpha:Float = current.alpha;
|
||||
if (current.mixingFrom != null) {
|
||||
mix *= applyMixingFrom(current, skeleton, blend);
|
||||
alpha *= applyMixingFrom(current, skeleton, blend);
|
||||
} else if (current.trackTime >= current.trackEnd && current.next == null) {
|
||||
mix = 0;
|
||||
alpha = 0;
|
||||
}
|
||||
var attachments:Bool = alpha >= current.alphaAttachmentThreshold;
|
||||
|
||||
// Apply current entry.
|
||||
var animationLast:Float = current.animationLast,
|
||||
@ -200,9 +201,14 @@ class AnimationState {
|
||||
var timelines:Array<Timeline> = current.animation.timelines;
|
||||
var timelineCount:Int = timelines.length;
|
||||
var timeline:Timeline;
|
||||
if ((i == 0 && mix == 1) || blend == MixBlend.add) {
|
||||
if ((i == 0 && alpha == 1) || blend == MixBlend.add) {
|
||||
if (i == 0) attachments = true;
|
||||
for (timeline in timelines) {
|
||||
timeline.apply(skeleton, animationLast, applyTime, applyEvents, mix, blend, MixDirection.mixIn);
|
||||
if (Std.isOfType(timeline, AttachmentTimeline)) {
|
||||
applyAttachmentTimeline(cast(timeline, AttachmentTimeline), skeleton, applyTime, blend, attachments);
|
||||
} else {
|
||||
timeline.apply(skeleton, animationLast, applyTime, applyEvents, alpha, blend, MixDirection.mixIn);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var timelineMode:Array<Int> = current.timelineMode;
|
||||
@ -216,12 +222,12 @@ class AnimationState {
|
||||
var timeline:Timeline = timelines[ii];
|
||||
var timelineBlend:MixBlend = timelineMode[ii] == SUBSEQUENT ? blend : MixBlend.setup;
|
||||
if (!shortestRotation && Std.isOfType(timeline, RotateTimeline)) {
|
||||
this.applyRotateTimeline(cast(timeline, RotateTimeline), skeleton, applyTime, mix, timelineBlend, current.timelinesRotation, ii << 1,
|
||||
this.applyRotateTimeline(cast(timeline, RotateTimeline), skeleton, applyTime, alpha, timelineBlend, current.timelinesRotation, ii << 1,
|
||||
firstFrame);
|
||||
} else if (Std.isOfType(timeline, AttachmentTimeline)) {
|
||||
this.applyAttachmentTimeline(cast(timeline, AttachmentTimeline), skeleton, applyTime, blend, true);
|
||||
this.applyAttachmentTimeline(cast(timeline, AttachmentTimeline), skeleton, applyTime, blend, attachments);
|
||||
} else {
|
||||
timeline.apply(skeleton, animationLast, applyTime, applyEvents, mix, timelineBlend, MixDirection.mixIn);
|
||||
timeline.apply(skeleton, animationLast, applyTime, applyEvents, alpha, timelineBlend, MixDirection.mixIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -266,8 +272,8 @@ class AnimationState {
|
||||
blend = from.mixBlend;
|
||||
}
|
||||
|
||||
var attachments:Bool = mix < from.attachmentThreshold,
|
||||
drawOrder:Bool = mix < from.drawOrderThreshold;
|
||||
var attachments:Bool = mix < from.mixAttachmentThreshold,
|
||||
drawOrder:Bool = mix < from.mixDrawOrderThreshold;
|
||||
var timelineCount:Int = from.animation.timelines.length;
|
||||
var timelines:Array<Timeline> = from.animation.timelines;
|
||||
var alphaHold:Float = from.alpha * to.interruptAlpha,
|
||||
@ -322,13 +328,12 @@ class AnimationState {
|
||||
var holdMix:TrackEntry = timelineHoldMix[i];
|
||||
alpha = alphaHold * Math.max(0, 1 - holdMix.mixTime / holdMix.mixDuration);
|
||||
}
|
||||
|
||||
from.totalAlpha += alpha;
|
||||
|
||||
if (!shortestRotation && Std.isOfType(timeline, RotateTimeline)) {
|
||||
applyRotateTimeline(cast(timeline, RotateTimeline), skeleton, applyTime, alpha, timelineBlend, from.timelinesRotation, i << 1, firstFrame);
|
||||
} else if (Std.isOfType(timeline, AttachmentTimeline)) {
|
||||
applyAttachmentTimeline(cast(timeline, AttachmentTimeline), skeleton, applyTime, timelineBlend, attachments);
|
||||
applyAttachmentTimeline(cast(timeline, AttachmentTimeline), skeleton, applyTime, timelineBlend, attachments && alpha >= from.alphaAttachmentThreshold);
|
||||
} else {
|
||||
if (drawOrder && Std.isOfType(timeline, DrawOrderTimeline) && timelineBlend == MixBlend.setup)
|
||||
direction = MixDirection.mixIn;
|
||||
@ -394,7 +399,7 @@ class AnimationState {
|
||||
|
||||
// Mix between rotations using the direction of the shortest route on the first frame while detecting crosses.
|
||||
var total:Float = 0, diff:Float = r2 - r1;
|
||||
diff -= (16384.0 - Std.int((16384.499999999996 - diff / 360.0))) * 360.0;
|
||||
diff -= Math.ceil(diff / 360 - 0.5) * 360;
|
||||
if (diff == 0) {
|
||||
total = timelinesRotation[i];
|
||||
} else {
|
||||
@ -403,18 +408,21 @@ class AnimationState {
|
||||
lastTotal = 0;
|
||||
lastDiff = diff;
|
||||
} else {
|
||||
lastTotal = timelinesRotation[i]; // Angle and direction of mix, including loops.
|
||||
lastDiff = timelinesRotation[i + 1]; // Difference between bones.
|
||||
lastTotal = timelinesRotation[i];
|
||||
lastDiff = timelinesRotation[i + 1];
|
||||
}
|
||||
var current = diff > 0, dir = lastTotal >= 0;
|
||||
// Detect cross at 0 (not 180).
|
||||
if (MathUtils.signum(lastDiff) != MathUtils.signum(diff) && Math.abs(lastDiff) <= 90) {
|
||||
// A cross after a 360 rotation is a loop.
|
||||
if (Math.abs(lastTotal) > 180)
|
||||
lastTotal += 360 * MathUtils.signum(lastTotal);
|
||||
dir = current;
|
||||
var loops:Float = lastTotal - lastTotal % 360;
|
||||
total = diff + loops;
|
||||
var current = diff >= 0, dir = lastTotal >= 0;
|
||||
if (Math.abs(lastDiff) <= 90 && MathUtils.signum(lastDiff) != MathUtils.signum(diff)) {
|
||||
if (Math.abs(lastTotal - loops) > 180) {
|
||||
total += 360 * MathUtils.signum(lastTotal);
|
||||
dir = current;
|
||||
} else if (loops != 0)
|
||||
total -= 360 * MathUtils.signum(lastTotal);
|
||||
else
|
||||
dir = current;
|
||||
}
|
||||
total = diff + lastTotal - lastTotal % 360; // Store loops as part of lastTotal.
|
||||
if (dir != current)
|
||||
total += 360 * MathUtils.signum(lastTotal);
|
||||
timelinesRotation[i] = total;
|
||||
@ -451,14 +459,17 @@ class AnimationState {
|
||||
}
|
||||
|
||||
// Queue complete if completed a loop iteration or the animation.
|
||||
var complete:Bool;
|
||||
var complete = false;
|
||||
if (entry.loop) {
|
||||
complete = duration == 0 || trackLastWrapped > entry.trackTime % duration;
|
||||
} else {
|
||||
if (duration == 0)
|
||||
complete = true;
|
||||
else {
|
||||
var cycles:Float = Math.floor(entry.trackTime / duration);
|
||||
complete = cycles > 0 && cycles > Math.floor(entry.trackTime / duration);
|
||||
}
|
||||
} else
|
||||
complete = animationTime >= animationEnd && entry.animationLast < animationEnd;
|
||||
}
|
||||
if (complete)
|
||||
queue.complete(entry);
|
||||
if (complete) queue.complete(entry);
|
||||
|
||||
// Queue events after complete.
|
||||
while (i < n) {
|
||||
@ -641,8 +652,9 @@ class AnimationState {
|
||||
entry.shortestRotation = false;
|
||||
|
||||
entry.eventThreshold = 0;
|
||||
entry.attachmentThreshold = 0;
|
||||
entry.drawOrderThreshold = 0;
|
||||
entry.alphaAttachmentThreshold = 0;
|
||||
entry.mixAttachmentThreshold = 0;
|
||||
entry.mixDrawOrderThreshold = 0;
|
||||
|
||||
entry.animationStart = 0;
|
||||
entry.animationEnd = animation.duration;
|
||||
|
||||
@ -75,4 +75,91 @@ class CurveTimeline1 extends CurveTimeline {
|
||||
}
|
||||
return getBezierValue(time, i, VALUE, curveType - CurveTimeline.BEZIER);
|
||||
}
|
||||
|
||||
public function getRelativeValue (time:Float, alpha:Float, blend: MixBlend, current:Float, setup:Float):Float {
|
||||
if (time < frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend.setup:
|
||||
return setup;
|
||||
case MixBlend.first:
|
||||
return current + (setup - current) * alpha;
|
||||
}
|
||||
return current;
|
||||
}
|
||||
var value:Float = getCurveValue(time);
|
||||
switch (blend) {
|
||||
case MixBlend.setup:
|
||||
return setup + value * alpha;
|
||||
case MixBlend.first, MixBlend.replace:
|
||||
value += setup - current;
|
||||
}
|
||||
return current + value * alpha;
|
||||
}
|
||||
|
||||
public function getAbsoluteValue (time:Float, alpha:Float, blend: MixBlend, current:Float, setup:Float):Float {
|
||||
if (time < frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend.setup:
|
||||
return setup;
|
||||
case MixBlend.first:
|
||||
return current + (setup - current) * alpha;
|
||||
}
|
||||
return current;
|
||||
}
|
||||
var value:Float = getCurveValue(time);
|
||||
if (blend == MixBlend.setup) return setup + (value - setup) * alpha;
|
||||
return current + (value - current) * alpha;
|
||||
}
|
||||
|
||||
public function getAbsoluteValue2 (time:Float, alpha:Float, blend: MixBlend, current:Float, setup:Float, value:Float):Float {
|
||||
if (time < frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend.setup:
|
||||
return setup;
|
||||
case MixBlend.first:
|
||||
return current + (setup - current) * alpha;
|
||||
}
|
||||
return current;
|
||||
}
|
||||
if (blend == MixBlend.setup) return setup + (value - setup) * alpha;
|
||||
return current + (value - current) * alpha;
|
||||
}
|
||||
|
||||
public function getScaleValue (time:Float, alpha:Float, blend: MixBlend, direction: MixDirection, current:Float, setup:Float):Float {
|
||||
var frames:Array<Float> = frames;
|
||||
if (time < frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend.setup:
|
||||
return setup;
|
||||
case MixBlend.first:
|
||||
return current + (setup - current) * alpha;
|
||||
}
|
||||
return current;
|
||||
}
|
||||
var value:Float = getCurveValue(time) * setup;
|
||||
if (alpha == 1) {
|
||||
if (blend == MixBlend.add) return current + value - setup;
|
||||
return value;
|
||||
}
|
||||
// Mixing out uses sign of setup or current pose, else use sign of key.
|
||||
if (direction == MixDirection.mixOut) {
|
||||
switch (blend) {
|
||||
case MixBlend.setup:
|
||||
return setup + (Math.abs(value) * MathUtils.signum(setup) - setup) * alpha;
|
||||
case MixBlend.first, MixBlend.replace:
|
||||
return current + (Math.abs(value) * MathUtils.signum(current) - current) * alpha;
|
||||
}
|
||||
} else {
|
||||
var s:Float = 0;
|
||||
switch (blend) {
|
||||
case MixBlend.setup:
|
||||
s = Math.abs(setup) * MathUtils.signum(value);
|
||||
return s + (value - s) * alpha;
|
||||
case MixBlend.first, MixBlend.replace:
|
||||
s = Math.abs(current) * MathUtils.signum(value);
|
||||
return s + (value - s) * alpha;
|
||||
}
|
||||
}
|
||||
return current + (value - setup) * alpha;
|
||||
}
|
||||
}
|
||||
|
||||
@ -177,8 +177,7 @@ class DeformTimeline extends CurveTimeline implements SlotTimeline {
|
||||
|
||||
ArrayUtils.resize(deform, vertexCount, 0);
|
||||
var setup:Float;
|
||||
if (time >= frames[frames.length - 1]) // Time is after last frame.
|
||||
{
|
||||
if (time >= frames[frames.length - 1]) {
|
||||
var lastVertices:Array<Float> = vertices[frames.length - 1];
|
||||
if (alpha == 1) {
|
||||
if (blend == MixBlend.add) {
|
||||
|
||||
@ -60,7 +60,7 @@ class EventTimeline extends Timeline {
|
||||
|
||||
var frameCount:Int = frames.length;
|
||||
|
||||
if (lastTime > time) // Fire events after last time for looped animations.
|
||||
if (lastTime > time) // Apply events after lastTime for looped animations.
|
||||
{
|
||||
apply(skeleton, lastTime, 2147483647, events, alpha, blend, direction);
|
||||
lastTime = -1;
|
||||
@ -69,10 +69,7 @@ class EventTimeline extends Timeline {
|
||||
return;
|
||||
}
|
||||
|
||||
if (time < frames[0]) // Time is before first frame.
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (time < frames[0]) return;
|
||||
|
||||
var frame:Int;
|
||||
var i:Int = 0;
|
||||
|
||||
@ -41,12 +41,12 @@ class IkConstraintTimeline extends CurveTimeline {
|
||||
private static inline var COMPRESS:Int = 4;
|
||||
private static inline var STRETCH:Int = 5;
|
||||
|
||||
/** The index of the IK constraint slot in {@link Skeleton#ikConstraints} that will be changed. */
|
||||
public var ikConstraintIndex:Int = 0;
|
||||
/** The index of the IK constraint in {@link Skeleton#ikConstraints} when this timeline is applied. */
|
||||
public var constraintIndex:Int = 0;
|
||||
|
||||
public function new(frameCount:Int, bezierCount:Int, ikConstraintIndex:Int) {
|
||||
super(frameCount, bezierCount, [Property.ikConstraint + "|" + ikConstraintIndex]);
|
||||
this.ikConstraintIndex = ikConstraintIndex;
|
||||
this.constraintIndex = ikConstraintIndex;
|
||||
}
|
||||
|
||||
public override function getFrameEntries():Int {
|
||||
@ -66,7 +66,7 @@ class IkConstraintTimeline extends CurveTimeline {
|
||||
|
||||
public override function apply(skeleton:Skeleton, lastTime:Float, time:Float, events:Array<Event>, alpha:Float, blend:MixBlend,
|
||||
direction:MixDirection):Void {
|
||||
var constraint:IkConstraint = skeleton.ikConstraints[ikConstraintIndex];
|
||||
var constraint:IkConstraint = skeleton.ikConstraints[constraintIndex];
|
||||
if (!constraint.active)
|
||||
return;
|
||||
|
||||
|
||||
73
spine-haxe/spine-haxe/spine/animation/InheritTimeline.hx
Normal file
73
spine-haxe/spine-haxe/spine/animation/InheritTimeline.hx
Normal file
@ -0,0 +1,73 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package spine.animation;
|
||||
|
||||
import spine.Bone;
|
||||
import spine.Event;
|
||||
import spine.Skeleton;
|
||||
|
||||
class InheritTimeline extends Timeline implements BoneTimeline {
|
||||
public static inline var ENTRIES:Int = 2;
|
||||
private static inline var INHERIT:Int = 1;
|
||||
|
||||
private var boneIndex:Int = 0;
|
||||
|
||||
public function new(frameCount:Int, boneIndex:Int) {
|
||||
super(frameCount, [Property.inherit + "|" + boneIndex]);
|
||||
this.boneIndex = boneIndex;
|
||||
}
|
||||
|
||||
public override function getFrameEntries():Int {
|
||||
return ENTRIES;
|
||||
}
|
||||
|
||||
public function getBoneIndex():Int {
|
||||
return boneIndex;
|
||||
}
|
||||
|
||||
public function setFrame(frame:Int, time:Float, inherit: Inherit):Void {
|
||||
frame *= ENTRIES;
|
||||
frames[frame] = time;
|
||||
frames[frame + INHERIT] = inherit.ordinal;
|
||||
}
|
||||
|
||||
override public function apply(skeleton:Skeleton, lastTime:Float, time:Float, events:Array<Event>, alpha:Float, blend:MixBlend,
|
||||
direction:MixDirection):Void {
|
||||
var bone:Bone = skeleton.bones[boneIndex];
|
||||
if (!bone.active) return;
|
||||
|
||||
var frames:Array<Float> = frames;
|
||||
if (time < frames[0]) {
|
||||
if (blend == MixBlend.setup || blend == MixBlend.first) bone.inherit = bone.data.inherit;
|
||||
return;
|
||||
}
|
||||
bone.inherit = Inherit.values[Std.int(frames[Timeline.search(frames, time, ENTRIES) + INHERIT])];
|
||||
}
|
||||
}
|
||||
@ -39,12 +39,12 @@ class PathConstraintMixTimeline extends CurveTimeline {
|
||||
private static inline var X:Int = 2;
|
||||
private static inline var Y:Int = 3;
|
||||
|
||||
/** The index of the path constraint slot in {@link Skeleton#getPathConstraints()} that will be changed. */
|
||||
public var pathConstraintIndex:Int = 0;
|
||||
/** The index of the path constraint in {@link Skeleton#getPathConstraints()} when this timeline is applied. */
|
||||
public var constraintIndex:Int = 0;
|
||||
|
||||
public function new(frameCount:Int, bezierCount:Int, pathConstraintIndex:Int) {
|
||||
super(frameCount, bezierCount, [Property.pathConstraintMix + "|" + pathConstraintIndex]);
|
||||
this.pathConstraintIndex = pathConstraintIndex;
|
||||
this.constraintIndex = pathConstraintIndex;
|
||||
}
|
||||
|
||||
public override function getFrameEntries():Int {
|
||||
@ -61,7 +61,7 @@ class PathConstraintMixTimeline extends CurveTimeline {
|
||||
|
||||
public override function apply(skeleton:Skeleton, lastTime:Float, time:Float, events:Array<Event>, alpha:Float, blend:MixBlend,
|
||||
direction:MixDirection):Void {
|
||||
var constraint:PathConstraint = skeleton.pathConstraints[pathConstraintIndex];
|
||||
var constraint:PathConstraint = skeleton.pathConstraints[constraintIndex];
|
||||
if (!constraint.active)
|
||||
return;
|
||||
|
||||
|
||||
@ -34,35 +34,18 @@ import spine.PathConstraint;
|
||||
import spine.Skeleton;
|
||||
|
||||
class PathConstraintPositionTimeline extends CurveTimeline1 {
|
||||
/** The index of the path constraint slot in {@link Skeleton#pathConstraints} that will be changed. */
|
||||
public var pathConstraintIndex:Int = 0;
|
||||
/** The index of the path constraint in {@link Skeleton#pathConstraints} when this timeline is applied. */
|
||||
public var constraintIndex:Int = 0;
|
||||
|
||||
public function new(frameCount:Int, bezierCount:Int, pathConstraintIndex:Int) {
|
||||
super(frameCount, bezierCount, [Property.pathConstraintPosition + "|" + pathConstraintIndex]);
|
||||
this.pathConstraintIndex = pathConstraintIndex;
|
||||
this.constraintIndex = pathConstraintIndex;
|
||||
}
|
||||
|
||||
public override function apply(skeleton:Skeleton, lastTime:Float, time:Float, events:Array<Event>, alpha:Float, blend:MixBlend,
|
||||
direction:MixDirection):Void {
|
||||
var constraint:PathConstraint = skeleton.pathConstraints[pathConstraintIndex];
|
||||
if (!constraint.active)
|
||||
return;
|
||||
|
||||
if (time < frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend.setup:
|
||||
constraint.position = constraint.data.position;
|
||||
case MixBlend.first:
|
||||
constraint.position += (constraint.data.position - constraint.position) * alpha;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var position:Float = getCurveValue(time);
|
||||
if (blend == MixBlend.setup) {
|
||||
constraint.position = constraint.data.position + (position - constraint.data.position) * alpha;
|
||||
} else {
|
||||
constraint.position += (position - constraint.position) * alpha;
|
||||
}
|
||||
var constraint:PathConstraint = skeleton.pathConstraints[constraintIndex];
|
||||
if (constraint.active)
|
||||
constraint.position = getAbsoluteValue(time, alpha, blend, constraint.position, constraint.data.position);
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,35 +34,17 @@ import spine.PathConstraint;
|
||||
import spine.Skeleton;
|
||||
|
||||
class PathConstraintSpacingTimeline extends CurveTimeline1 {
|
||||
/** The index of the path constraint slot in {@link Skeleton#pathConstraints} that will be changed. */
|
||||
public var pathConstraintIndex:Int = 0;
|
||||
/** The index of the path constraint in {@link Skeleton#pathConstraints} when this timeline is applied. */
|
||||
public var constraintIndex:Int = 0;
|
||||
|
||||
public function new(frameCount:Int, bezierCount:Int, pathConstraintIndex:Int) {
|
||||
super(frameCount, bezierCount, [Property.pathConstraintSpacing + "|" + pathConstraintIndex]);
|
||||
this.pathConstraintIndex = pathConstraintIndex;
|
||||
this.constraintIndex = pathConstraintIndex;
|
||||
}
|
||||
|
||||
public override function apply(skeleton:Skeleton, lastTime:Float, time:Float, events:Array<Event>, alpha:Float, blend:MixBlend,
|
||||
direction:MixDirection):Void {
|
||||
var constraint:PathConstraint = skeleton.pathConstraints[pathConstraintIndex];
|
||||
if (!constraint.active)
|
||||
return;
|
||||
|
||||
if (time < frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend.setup:
|
||||
constraint.spacing = constraint.data.spacing;
|
||||
case MixBlend.first:
|
||||
constraint.spacing += (constraint.data.spacing - constraint.spacing) * alpha;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var spacing:Float = getCurveValue(time);
|
||||
if (blend == MixBlend.setup) {
|
||||
constraint.spacing = constraint.data.spacing + (spacing - constraint.data.spacing) * alpha;
|
||||
} else {
|
||||
constraint.spacing += (spacing - constraint.spacing) * alpha;
|
||||
}
|
||||
var constraint:PathConstraint = skeleton.pathConstraints[constraintIndex];
|
||||
if (constraint.active) constraint.spacing = getAbsoluteValue(time, alpha, blend, constraint.spacing, constraint.data.spacing);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,54 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package spine.animation;
|
||||
|
||||
/** Changes a physics constraint's {@link PhysicsConstraint#getDamping()}. */
|
||||
class PhysicsConstraintDampingTimeline extends PhysicsConstraintTimeline {
|
||||
public function new(frameCount:Int, bezierCount:Int, physicsConstraintIndex:Int) {
|
||||
super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintDamping);
|
||||
}
|
||||
|
||||
public function setup (constraint: PhysicsConstraint):Float {
|
||||
return constraint.data.damping;
|
||||
}
|
||||
|
||||
public function get (constraint: PhysicsConstraint):Float {
|
||||
return constraint.damping;
|
||||
}
|
||||
|
||||
public function set (constraint: PhysicsConstraint, value:Float):Void {
|
||||
constraint.damping = value;
|
||||
}
|
||||
|
||||
public function global (constraint: PhysicsConstraintData):Bool {
|
||||
return constraint.dampingGlobal;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package spine.animation;
|
||||
|
||||
/** Changes a physics constraint's {@link PhysicsConstraint#getWind()}. */
|
||||
class PhysicsConstraintGravityTimeline extends PhysicsConstraintTimeline {
|
||||
public function new(frameCount:Int, bezierCount:Int, physicsConstraintIndex:Int) {
|
||||
super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintGravity);
|
||||
}
|
||||
|
||||
public function setup (constraint: PhysicsConstraint):Float {
|
||||
return constraint.data.gravity;
|
||||
}
|
||||
|
||||
public function get (constraint: PhysicsConstraint):Float {
|
||||
return constraint.gravity;
|
||||
}
|
||||
|
||||
public function set (constraint: PhysicsConstraint, value:Float):Void {
|
||||
constraint.gravity = value;
|
||||
}
|
||||
|
||||
public function global (constraint: PhysicsConstraintData):Bool {
|
||||
return constraint.gravityGlobal;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package spine.animation;
|
||||
|
||||
/** Changes a physics constraint's {@link PhysicsConstraint#getInertia()}. */
|
||||
class PhysicsConstraintInertiaTimeline extends PhysicsConstraintTimeline {
|
||||
public function new(frameCount:Int, bezierCount:Int, physicsConstraintIndex:Int) {
|
||||
super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintInertia);
|
||||
}
|
||||
|
||||
public function setup (constraint: PhysicsConstraint):Float {
|
||||
return constraint.data.inertia;
|
||||
}
|
||||
|
||||
public function get (constraint: PhysicsConstraint):Float {
|
||||
return constraint.inertia;
|
||||
}
|
||||
|
||||
public function set (constraint: PhysicsConstraint, value:Float):Void {
|
||||
constraint.inertia = value;
|
||||
}
|
||||
|
||||
public function global (constraint: PhysicsConstraintData):Bool {
|
||||
return constraint.inertiaGlobal;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package spine.animation;
|
||||
|
||||
/** Changes a physics constraint's {@link PhysicsConstraint#getMassInverse()}. The timeline values are not inverted. */
|
||||
class PhysicsConstraintMassTimeline extends PhysicsConstraintTimeline {
|
||||
public function new(frameCount:Int, bezierCount:Int, physicsConstraintIndex:Int) {
|
||||
super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintMass);
|
||||
}
|
||||
|
||||
public function setup (constraint: PhysicsConstraint):Float {
|
||||
return constraint.data.massInverse;
|
||||
}
|
||||
|
||||
public function get (constraint: PhysicsConstraint):Float {
|
||||
return constraint.massInverse;
|
||||
}
|
||||
|
||||
public function set (constraint: PhysicsConstraint, value:Float):Void {
|
||||
constraint.massInverse = value;
|
||||
}
|
||||
|
||||
public function global (constraint: PhysicsConstraintData):Bool {
|
||||
return constraint.massGlobal;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package spine.animation;
|
||||
|
||||
/** Changes a physics constraint's {@link PhysicsConstraint#getWind()}. */
|
||||
class PhysicsConstraintMixTimeline extends PhysicsConstraintTimeline {
|
||||
public function new(frameCount:Int, bezierCount:Int, physicsConstraintIndex:Int) {
|
||||
super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintMix);
|
||||
}
|
||||
|
||||
public function setup (constraint: PhysicsConstraint):Float {
|
||||
return constraint.data.mix;
|
||||
}
|
||||
|
||||
public function get (constraint: PhysicsConstraint):Float {
|
||||
return constraint.mix;
|
||||
}
|
||||
|
||||
public function set (constraint: PhysicsConstraint, value:Float):Void {
|
||||
constraint.mix = value;
|
||||
}
|
||||
|
||||
public function global (constraint: PhysicsConstraintData):Bool {
|
||||
return constraint.mixGlobal;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,86 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package spine.animation;
|
||||
|
||||
import spine.animation.Timeline;
|
||||
import spine.Event;
|
||||
import spine.Skeleton;
|
||||
|
||||
class PhysicsConstraintResetTimeline extends Timeline {
|
||||
/** The index of the physics constraint in {@link Skeleton#physicsConstraints} that will be reset when this timeline is
|
||||
* applied, or -1 if all physics constraints in the skeleton will be reset. */
|
||||
public var constraintIndex:Int = 0;
|
||||
|
||||
public function new(frameCount:Int, physicsConstraintIndex:Int) {
|
||||
propertyIds = [Std.string(Property.physicsConstraintReset)];
|
||||
super(frameCount, propertyIds);
|
||||
constraintIndex = physicsConstraintIndex;
|
||||
}
|
||||
|
||||
public override function getFrameCount():Int {
|
||||
return frames.length;
|
||||
}
|
||||
|
||||
/** Sets the time in seconds and the event for the specified key frame. */
|
||||
public function setFrame(frame:Int, time:Float):Void {
|
||||
frames[frame] = time;
|
||||
}
|
||||
|
||||
/** Resets the physics constraint when frames > lastTime and <= time. */
|
||||
public override function apply(skeleton:Skeleton, lastTime:Float, time:Float, firedEvents:Array<Event>, alpha:Float, blend:MixBlend,
|
||||
direction:MixDirection):Void {
|
||||
var constraint:PhysicsConstraint = null;
|
||||
if (this.constraintIndex != -1) {
|
||||
constraint = skeleton.physicsConstraints[constraintIndex];
|
||||
if (!constraint.active) return;
|
||||
}
|
||||
|
||||
var frames:Array<Float> = this.frames;
|
||||
if (lastTime > time) // Apply events after lastTime for looped animations.
|
||||
{
|
||||
apply(skeleton, lastTime, 2147483647, [], alpha, blend, direction);
|
||||
lastTime = -1;
|
||||
} else if (lastTime >= frames[frames.length - 1]) // Last time is after last frame.
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (time < frames[0]) return;
|
||||
|
||||
if (lastTime < frames[0] || time >= frames[Timeline.search1(frames, lastTime) + 1]) {
|
||||
if (constraint != null)
|
||||
constraint.reset();
|
||||
else {
|
||||
for (constraint in skeleton.physicsConstraints) {
|
||||
if (constraint.active) constraint.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package spine.animation;
|
||||
|
||||
/** Changes a physics constraint's {@link PhysicsConstraint#getStrength()}. */
|
||||
class PhysicsConstraintStrengthTimeline extends PhysicsConstraintTimeline {
|
||||
public function new(frameCount:Int, bezierCount:Int, physicsConstraintIndex:Int) {
|
||||
super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintStrength);
|
||||
}
|
||||
|
||||
public function setup (constraint: PhysicsConstraint):Float {
|
||||
return constraint.data.strength;
|
||||
}
|
||||
|
||||
public function get (constraint: PhysicsConstraint):Float {
|
||||
return constraint.strength;
|
||||
}
|
||||
|
||||
public function set (constraint: PhysicsConstraint, value:Float):Void {
|
||||
constraint.strength = value;
|
||||
}
|
||||
|
||||
public function global (constraint: PhysicsConstraintData):Bool {
|
||||
return constraint.strengthGlobal;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,70 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package spine.animation;
|
||||
|
||||
import spine.Event;
|
||||
import spine.PathConstraint;
|
||||
import spine.Skeleton;
|
||||
|
||||
/** The base class for most {@link PhysicsConstraint} timelines. */
|
||||
abstract class PhysicsConstraintTimeline extends CurveTimeline1 {
|
||||
/** The index of the physics constraint in {@link Skeleton#getPhysicsConstraints()} that will be changed when this timeline
|
||||
* is applied, or -1 if all physics constraints in the skeleton will be changed. */
|
||||
public var constraintIndex:Int = 0;
|
||||
|
||||
/** @param physicsConstraintIndex -1 for all physics constraints in the skeleton. */
|
||||
public function new(frameCount:Int, bezierCount:Int, physicsConstraintIndex:Int, property:Int) {
|
||||
super(frameCount, bezierCount, [property + "|" + physicsConstraintIndex]);
|
||||
constraintIndex = physicsConstraintIndex;
|
||||
}
|
||||
|
||||
public override function apply (skeleton:Skeleton, lastTime:Float, time:Float, firedEvents:Array<Event>, alpha:Float, blend:MixBlend, direction:MixDirection):Void {
|
||||
var constraint:PhysicsConstraint;
|
||||
if (constraintIndex == -1) {
|
||||
var value:Float = time >= frames[0] ? getCurveValue(time) : 0;
|
||||
|
||||
for (constraint in skeleton.physicsConstraints) {
|
||||
if (constraint.active && global(constraint.data))
|
||||
set(constraint, getAbsoluteValue2(time, alpha, blend, get(constraint), setup(constraint), value));
|
||||
}
|
||||
} else {
|
||||
constraint = skeleton.physicsConstraints[constraintIndex];
|
||||
if (constraint.active) set(constraint, getAbsoluteValue(time, alpha, blend, get(constraint), setup(constraint)));
|
||||
}
|
||||
}
|
||||
|
||||
abstract public function setup (constraint: PhysicsConstraint):Float;
|
||||
|
||||
abstract public function get (constraint: PhysicsConstraint):Float;
|
||||
|
||||
abstract public function set (constraint: PhysicsConstraint, value:Float):Void;
|
||||
|
||||
abstract public function global (constraint: PhysicsConstraintData):Bool;
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package spine.animation;
|
||||
|
||||
/** Changes a physics constraint's {@link PhysicsConstraint#getWind()}. */
|
||||
class PhysicsConstraintWindTimeline extends PhysicsConstraintTimeline {
|
||||
public function new(frameCount:Int, bezierCount:Int, physicsConstraintIndex:Int) {
|
||||
super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintWind);
|
||||
}
|
||||
|
||||
public function setup (constraint: PhysicsConstraint):Float {
|
||||
return constraint.data.wind;
|
||||
}
|
||||
|
||||
public function get (constraint: PhysicsConstraint):Float {
|
||||
return constraint.wind;
|
||||
}
|
||||
|
||||
public function set (constraint: PhysicsConstraint, value:Float):Void {
|
||||
constraint.wind = value;
|
||||
}
|
||||
|
||||
public function global (constraint: PhysicsConstraintData):Bool {
|
||||
return constraint.windGlobal;
|
||||
}
|
||||
|
||||
}
|
||||
@ -37,25 +37,35 @@ class Property {
|
||||
public static inline var scaleY:Int = 4;
|
||||
public static inline var shearX:Int = 5;
|
||||
public static inline var shearY:Int = 6;
|
||||
public static inline var inherit:Int = 7;
|
||||
|
||||
public static inline var rgb:Int = 7;
|
||||
public static inline var alpha:Int = 8;
|
||||
public static inline var rgb2:Int = 9;
|
||||
public static inline var rgb:Int = 8;
|
||||
public static inline var alpha:Int = 9;
|
||||
public static inline var rgb2:Int = 10;
|
||||
|
||||
public static inline var attachment:Int = 10;
|
||||
public static inline var deform:Int = 11;
|
||||
public static inline var attachment:Int = 11;
|
||||
public static inline var deform:Int = 12;
|
||||
|
||||
public static inline var event:Int = 12;
|
||||
public static inline var drawOrder:Int = 13;
|
||||
public static inline var event:Int = 13;
|
||||
public static inline var drawOrder:Int = 14;
|
||||
|
||||
public static inline var ikConstraint:Int = 14;
|
||||
public static inline var transformConstraint:Int = 15;
|
||||
public static inline var ikConstraint:Int = 15;
|
||||
public static inline var transformConstraint:Int = 16;
|
||||
|
||||
public static inline var pathConstraintPosition:Int = 16;
|
||||
public static inline var pathConstraintSpacing:Int = 17;
|
||||
public static inline var pathConstraintMix:Int = 18;
|
||||
public static inline var pathConstraintPosition:Int = 17;
|
||||
public static inline var pathConstraintSpacing:Int = 18;
|
||||
public static inline var pathConstraintMix:Int = 19;
|
||||
|
||||
public static inline var sequence:Int = 19;
|
||||
public static inline var physicsConstraintInertia:Int = 20;
|
||||
public static inline var physicsConstraintStrength:Int = 21;
|
||||
public static inline var physicsConstraintDamping:Int = 22;
|
||||
public static inline var physicsConstraintMass:Int = 23;
|
||||
public static inline var physicsConstraintWind:Int = 24;
|
||||
public static inline var physicsConstraintGravity:Int = 25;
|
||||
public static inline var physicsConstraintMix:Int = 26;
|
||||
public static inline var physicsConstraintReset:Int = 27;
|
||||
|
||||
public static inline var sequence:Int = 28;
|
||||
|
||||
public function new() {}
|
||||
}
|
||||
|
||||
@ -48,29 +48,7 @@ class RotateTimeline extends CurveTimeline1 implements BoneTimeline {
|
||||
override public function apply(skeleton:Skeleton, lastTime:Float, time:Float, events:Array<Event>, alpha:Float, blend:MixBlend,
|
||||
direction:MixDirection):Void {
|
||||
var bone:Bone = skeleton.bones[boneIndex];
|
||||
if (!bone.active)
|
||||
return;
|
||||
if (time < frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend.setup:
|
||||
bone.rotation = bone.data.rotation;
|
||||
case MixBlend.first:
|
||||
bone.rotation += (bone.data.rotation - bone.rotation) * alpha;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var r:Float = getCurveValue(time);
|
||||
if (Math.abs(r) == 360)
|
||||
r = 0;
|
||||
switch (blend) {
|
||||
case MixBlend.setup:
|
||||
bone.rotation = bone.data.rotation + r * alpha;
|
||||
case MixBlend.first, MixBlend.replace:
|
||||
r += bone.data.rotation - bone.rotation;
|
||||
bone.rotation += r * alpha;
|
||||
case MixBlend.add:
|
||||
bone.rotation += r * alpha;
|
||||
}
|
||||
if (bone.active)
|
||||
bone.rotation = getRelativeValue(time, alpha, blend, bone.rotation, bone.data.rotation);
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,51 +49,6 @@ class ScaleXTimeline extends CurveTimeline1 implements BoneTimeline {
|
||||
override public function apply(skeleton:Skeleton, lastTime:Float, time:Float, events:Array<Event>, alpha:Float, blend:MixBlend,
|
||||
direction:MixDirection):Void {
|
||||
var bone:Bone = skeleton.bones[boneIndex];
|
||||
if (!bone.active)
|
||||
return;
|
||||
|
||||
if (time < frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend.setup:
|
||||
bone.scaleX = bone.data.scaleX;
|
||||
case MixBlend.first:
|
||||
bone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var x:Float = getCurveValue(time) * bone.data.scaleX;
|
||||
if (alpha == 1) {
|
||||
if (blend == MixBlend.add)
|
||||
bone.scaleX += x - bone.data.scaleX;
|
||||
else
|
||||
bone.scaleX = x;
|
||||
} else {
|
||||
// Mixing out uses sign of setup or current pose, else use sign of key.
|
||||
var bx:Float = 0;
|
||||
if (direction == MixDirection.mixOut) {
|
||||
switch (blend) {
|
||||
case MixBlend.setup:
|
||||
bx = bone.data.scaleX;
|
||||
bone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha;
|
||||
case MixBlend.first, MixBlend.replace:
|
||||
bx = bone.scaleX;
|
||||
bone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha;
|
||||
case MixBlend.add:
|
||||
bone.scaleX = (x - bone.data.scaleX) * alpha;
|
||||
}
|
||||
} else {
|
||||
switch (blend) {
|
||||
case MixBlend.setup:
|
||||
bx = Math.abs(bone.data.scaleX) * MathUtils.signum(x);
|
||||
bone.scaleX = bx + (x - bx) * alpha;
|
||||
case MixBlend.first, MixBlend.replace:
|
||||
bx = Math.abs(bone.scaleX) * MathUtils.signum(x);
|
||||
bone.scaleX = bx + (x - bx) * alpha;
|
||||
case MixBlend.add:
|
||||
bone.scaleX += (x - bone.data.scaleX) * alpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bone.active) bone.scaleX = getScaleValue(time, alpha, blend, direction, bone.scaleX, bone.data.scaleX);
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,51 +49,7 @@ class ScaleYTimeline extends CurveTimeline1 implements BoneTimeline {
|
||||
override public function apply(skeleton:Skeleton, lastTime:Float, time:Float, events:Array<Event>, alpha:Float, blend:MixBlend,
|
||||
direction:MixDirection):Void {
|
||||
var bone:Bone = skeleton.bones[boneIndex];
|
||||
if (!bone.active)
|
||||
return;
|
||||
if (bone.active) bone.scaleY = getScaleValue(time, alpha, blend, direction, bone.scaleY, bone.data.scaleY);
|
||||
|
||||
if (time < frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend.setup:
|
||||
bone.scaleY = bone.data.scaleY;
|
||||
case MixBlend.first:
|
||||
bone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var y:Float = getCurveValue(time) * bone.data.scaleY;
|
||||
if (alpha == 1) {
|
||||
if (blend == MixBlend.add)
|
||||
bone.scaleY += y - bone.data.scaleY;
|
||||
else
|
||||
bone.scaleY = y;
|
||||
} else {
|
||||
// Mixing out uses sign of setup or current pose, else use sign of key.
|
||||
var by:Float = 0;
|
||||
if (direction == MixDirection.mixOut) {
|
||||
switch (blend) {
|
||||
case MixBlend.setup:
|
||||
by = bone.data.scaleY;
|
||||
bone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha;
|
||||
case MixBlend.first, MixBlend.replace:
|
||||
by = bone.scaleY;
|
||||
bone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha;
|
||||
case MixBlend.add:
|
||||
bone.scaleY = (y - bone.data.scaleY) * alpha;
|
||||
}
|
||||
} else {
|
||||
switch (blend) {
|
||||
case MixBlend.setup:
|
||||
by = Math.abs(bone.data.scaleY) * MathUtils.signum(y);
|
||||
bone.scaleY = by + (y - by) * alpha;
|
||||
case MixBlend.first, MixBlend.replace:
|
||||
by = Math.abs(bone.scaleY) * MathUtils.signum(y);
|
||||
bone.scaleY = by + (y - by) * alpha;
|
||||
case MixBlend.add:
|
||||
bone.scaleY += (y - bone.data.scaleY) * alpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,7 +82,7 @@ class SequenceTimeline extends Timeline implements SlotTimeline {
|
||||
return;
|
||||
}
|
||||
|
||||
if (time < frames[0]) { // Time is before first frame.
|
||||
if (time < frames[0]) {
|
||||
if (blend == MixBlend.setup || blend == MixBlend.first)
|
||||
slot.sequenceIndex = -1;
|
||||
return;
|
||||
|
||||
@ -48,27 +48,6 @@ class ShearXTimeline extends CurveTimeline1 implements BoneTimeline {
|
||||
override public function apply(skeleton:Skeleton, lastTime:Float, time:Float, events:Array<Event>, alpha:Float, blend:MixBlend,
|
||||
direction:MixDirection):Void {
|
||||
var bone:Bone = skeleton.bones[boneIndex];
|
||||
if (!bone.active)
|
||||
return;
|
||||
|
||||
if (time < frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend.setup:
|
||||
bone.shearX = bone.data.shearX;
|
||||
case MixBlend.first:
|
||||
bone.shearX += (bone.data.shearX - bone.shearX) * alpha;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var x:Float = getCurveValue(time);
|
||||
switch (blend) {
|
||||
case MixBlend.setup:
|
||||
bone.shearX = bone.data.shearX + x * alpha;
|
||||
case MixBlend.first, MixBlend.replace:
|
||||
bone.shearX += (bone.data.shearX + x - bone.shearX) * alpha;
|
||||
case MixBlend.add:
|
||||
bone.shearX += x * alpha;
|
||||
}
|
||||
if (bone.active) bone.shearX = getRelativeValue(time, alpha, blend, bone.shearX, bone.data.shearX);
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,27 +48,6 @@ class ShearYTimeline extends CurveTimeline1 implements BoneTimeline {
|
||||
override public function apply(skeleton:Skeleton, lastTime:Float, time:Float, events:Array<Event>, alpha:Float, blend:MixBlend,
|
||||
direction:MixDirection):Void {
|
||||
var bone:Bone = skeleton.bones[boneIndex];
|
||||
if (!bone.active)
|
||||
return;
|
||||
|
||||
if (time < frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend.setup:
|
||||
bone.shearY = bone.data.shearY;
|
||||
case MixBlend.first:
|
||||
bone.shearY += (bone.data.shearY - bone.shearY) * alpha;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var y:Float = getCurveValue(time);
|
||||
switch (blend) {
|
||||
case MixBlend.setup:
|
||||
bone.shearY = bone.data.shearY + y * alpha;
|
||||
case MixBlend.first, MixBlend.replace:
|
||||
bone.shearY += (bone.data.shearY + y - bone.shearY) * alpha;
|
||||
case MixBlend.add:
|
||||
bone.shearY += y * alpha;
|
||||
}
|
||||
if (bone.active) bone.shearY = getRelativeValue(time, alpha, blend, bone.shearY, bone.data.shearY);
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,8 +49,9 @@ class TrackEntry implements Poolable {
|
||||
public var reverse:Bool = false;
|
||||
public var holdPrevious:Bool = false;
|
||||
public var eventThreshold:Float = 0;
|
||||
public var attachmentThreshold:Float = 0;
|
||||
public var drawOrderThreshold:Float = 0;
|
||||
public var mixAttachmentThreshold:Float = 0;
|
||||
public var alphaAttachmentThreshold:Float = 0;
|
||||
public var mixDrawOrderThreshold:Float = 0;
|
||||
public var animationStart:Float = 0;
|
||||
public var animationEnd:Float = 0;
|
||||
public var animationLast:Float = 0;
|
||||
@ -63,7 +64,7 @@ class TrackEntry implements Poolable {
|
||||
public var timeScale:Float = 0;
|
||||
public var alpha:Float = 0;
|
||||
public var mixTime:Float = 0;
|
||||
public var mixDuration:Float = 0;
|
||||
@:isVar public var mixDuration(get, set):Float = 0;
|
||||
public var interruptAlpha:Float = 0;
|
||||
public var totalAlpha:Float = 0;
|
||||
public var mixBlend:MixBlend = MixBlend.replace;
|
||||
@ -72,6 +73,16 @@ class TrackEntry implements Poolable {
|
||||
public var timelinesRotation:Array<Float> = new Array<Float>();
|
||||
public var shortestRotation = false;
|
||||
|
||||
function get_mixDuration():Float {
|
||||
return mixDuration;
|
||||
}
|
||||
|
||||
function set_mixDuration(mixDuration:Float):Float {
|
||||
this.mixDuration = mixDuration;
|
||||
if (previous != null && delay <= 0) delay += previous.getTrackComplete() - mixDuration;
|
||||
return mixDuration;
|
||||
}
|
||||
|
||||
public function new() {}
|
||||
|
||||
public function getAnimationTime():Float {
|
||||
@ -98,6 +109,13 @@ class TrackEntry implements Poolable {
|
||||
return trackTime; // Next update.
|
||||
}
|
||||
|
||||
/** Returns true if this track entry has been applied at least once.
|
||||
* <p>
|
||||
* See {@link AnimationState#apply(Skeleton)}. */
|
||||
public function wasApplied () {
|
||||
return nextTrackLast != -1;
|
||||
}
|
||||
|
||||
public function reset():Void {
|
||||
next = null;
|
||||
previous = null;
|
||||
|
||||
@ -44,11 +44,11 @@ class TransformConstraintTimeline extends CurveTimeline {
|
||||
private static inline var SHEARY:Int = 6;
|
||||
|
||||
/** The index of the transform constraint slot in {@link Skeleton#transformConstraints} that will be changed. */
|
||||
public var transformConstraintIndex:Int = 0;
|
||||
public var constraintIndex:Int = 0;
|
||||
|
||||
public function new(frameCount:Int, bezierCount:Int, transformConstraintIndex:Int) {
|
||||
super(frameCount, bezierCount, [Property.transformConstraint + "|" + transformConstraintIndex]);
|
||||
this.transformConstraintIndex = transformConstraintIndex;
|
||||
this.constraintIndex = transformConstraintIndex;
|
||||
}
|
||||
|
||||
public override function getFrameEntries():Int {
|
||||
@ -69,7 +69,7 @@ class TransformConstraintTimeline extends CurveTimeline {
|
||||
|
||||
override public function apply(skeleton:Skeleton, lastTime:Float, time:Float, events:Array<Event>, alpha:Float, blend:MixBlend,
|
||||
direction:MixDirection):Void {
|
||||
var constraint:TransformConstraint = skeleton.transformConstraints[transformConstraintIndex];
|
||||
var constraint:TransformConstraint = skeleton.transformConstraints[constraintIndex];
|
||||
if (!constraint.active)
|
||||
return;
|
||||
|
||||
|
||||
@ -48,27 +48,6 @@ class TranslateXTimeline extends CurveTimeline1 implements BoneTimeline {
|
||||
public override function apply(skeleton:Skeleton, lastTime:Float, time:Float, events:Array<Event>, alpha:Float, blend:MixBlend,
|
||||
direction:MixDirection):Void {
|
||||
var bone:Bone = skeleton.bones[boneIndex];
|
||||
if (!bone.active)
|
||||
return;
|
||||
|
||||
if (time < frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend.setup:
|
||||
bone.x = bone.data.x;
|
||||
case MixBlend.first:
|
||||
bone.x += (bone.data.x - bone.x) * alpha;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var x:Float = getCurveValue(time);
|
||||
switch (blend) {
|
||||
case MixBlend.setup:
|
||||
bone.x = bone.data.x + x * alpha;
|
||||
case MixBlend.first, MixBlend.replace:
|
||||
bone.x += (bone.data.x + x - bone.x) * alpha;
|
||||
case MixBlend.add:
|
||||
bone.x += x * alpha;
|
||||
}
|
||||
if (bone.active) bone.x = getRelativeValue(time, alpha, blend, bone.x, bone.data.x);
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,27 +48,6 @@ class TranslateYTimeline extends CurveTimeline1 implements BoneTimeline {
|
||||
public override function apply(skeleton:Skeleton, lastTime:Float, time:Float, events:Array<Event>, alpha:Float, blend:MixBlend,
|
||||
direction:MixDirection):Void {
|
||||
var bone:Bone = skeleton.bones[boneIndex];
|
||||
if (!bone.active)
|
||||
return;
|
||||
|
||||
if (time < frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend.setup:
|
||||
bone.y = bone.data.y;
|
||||
case MixBlend.first:
|
||||
bone.y += (bone.data.y - bone.y) * alpha;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var y:Float = getCurveValue(time);
|
||||
switch (blend) {
|
||||
case MixBlend.setup:
|
||||
bone.y = bone.data.y + y * alpha;
|
||||
case MixBlend.first, MixBlend.replace:
|
||||
bone.y += (bone.data.y + y - bone.y) * alpha;
|
||||
case MixBlend.add:
|
||||
bone.y += y * alpha;
|
||||
}
|
||||
if (bone.active) bone.y = getRelativeValue(time, alpha, blend, bone.y, bone.data.y);
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,6 +31,7 @@ package spine.attachments;
|
||||
|
||||
import spine.Color;
|
||||
import spine.atlas.TextureAtlasRegion;
|
||||
import spine.atlas.TextureAtlasPage;
|
||||
|
||||
class MeshAttachment extends VertexAttachment implements HasTextureRegion {
|
||||
public var region:TextureRegion;
|
||||
@ -66,9 +67,8 @@ class MeshAttachment extends VertexAttachment implements HasTextureRegion {
|
||||
var n = uvs.length;
|
||||
var u = region.u, v = region.v, width:Float = 0, height:Float = 0;
|
||||
if (Std.isOfType(region, TextureAtlasRegion)) {
|
||||
var atlasRegion:TextureAtlasRegion = cast(region, TextureAtlasRegion);
|
||||
var textureWidth = atlasRegion.page.width,
|
||||
textureHeight = atlasRegion.page.height;
|
||||
var atlasRegion:TextureAtlasRegion = cast(region, TextureAtlasRegion), page:TextureAtlasPage = atlasRegion.page;
|
||||
var textureWidth = page.width, textureHeight = page.height;
|
||||
switch (atlasRegion.degrees) {
|
||||
case 90:
|
||||
u -= (region.originalHeight - region.offsetY - region.height) / textureWidth;
|
||||
|
||||
@ -50,11 +50,10 @@ class PointAttachment extends VertexAttachment {
|
||||
}
|
||||
|
||||
public function computeWorldRotation(bone:Bone):Float {
|
||||
var cos:Float = MathUtils.cosDeg(this.rotation),
|
||||
sin:Float = MathUtils.sinDeg(this.rotation);
|
||||
var r:Float = this.rotation * MathUtils.degRad, cos:Float = Math.cos(r), sin:Float = Math.sin(r);
|
||||
var x:Float = cos * bone.a + sin * bone.b;
|
||||
var y:Float = cos * bone.c + sin * bone.d;
|
||||
return Math.atan2(y, x) * MathUtils.radDeg;
|
||||
return MathUtils.atan2Deg(y, x);
|
||||
}
|
||||
|
||||
override public function copy():Attachment {
|
||||
|
||||
@ -83,7 +83,7 @@ class RegionAttachment extends Attachment implements HasTextureRegion {
|
||||
var localY = -height / 2 * scaleY + region.offsetY * regionScaleY;
|
||||
var localX2 = localX + region.width * regionScaleX;
|
||||
var localY2 = localY + region.height * regionScaleY;
|
||||
var radians = rotation * Math.PI / 180;
|
||||
var radians = rotation * MathUtils.degRad;
|
||||
var cos = Math.cos(radians);
|
||||
var sin = Math.sin(radians);
|
||||
var x = this.x, y = this.y;
|
||||
|
||||
@ -76,7 +76,7 @@ class SkeletonSprite extends DisplayObject implements IAnimatable {
|
||||
super();
|
||||
Bone.yDown = true;
|
||||
_skeleton = new Skeleton(skeletonData);
|
||||
_skeleton.updateWorldTransform();
|
||||
_skeleton.updateWorldTransform(Physics.update);
|
||||
_state = new AnimationState(animationStateData != null ? animationStateData : new AnimationStateData(skeletonData));
|
||||
}
|
||||
|
||||
@ -340,7 +340,9 @@ class SkeletonSprite extends DisplayObject implements IAnimatable {
|
||||
public function advanceTime(time:Float):Void {
|
||||
_state.update(time);
|
||||
_state.apply(skeleton);
|
||||
skeleton.updateWorldTransform();
|
||||
skeleton.update(time);
|
||||
skeleton.updateWorldTransform(Physics.update);
|
||||
|
||||
this.setRequiresRedraw();
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user