[haxe] Physics porting - Missing Skeleton loaders, examples and TODO

This commit is contained in:
Davide Tantillo 2024-04-12 17:25:09 +02:00
parent 49350d1174
commit bb9d23c4d0
62 changed files with 7703 additions and 627 deletions

3
spine-haxe/.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"cmake.configureOnOpen": false
}

View 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

View 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": [
{}
]
}
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -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());
}
}

View File

@ -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());
}
}
}

View File

@ -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 {

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View 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;
}
}

View File

@ -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;

View File

@ -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) {

View File

@ -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;

View 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;
}
}

View 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);
}
}

View File

@ -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);
}
}

View File

@ -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());

View File

@ -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;
}

View File

@ -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)) {

View File

@ -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
{

View File

@ -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)

View File

@ -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);
}

View File

@ -30,7 +30,7 @@
package spine;
interface Updatable {
function update():Void;
function update(physics:Physics):Void;
function isActive():Bool;
}

View File

@ -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:

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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) {

View File

@ -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;

View File

@ -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;

View 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])];
}
}

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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() {}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}
}
}

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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 {

View File

@ -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;

View File

@ -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();
}
}