Added clip.
435
spine-ts/spine-webgl/example/assets/chibi-stickers-pma.atlas
Normal file
@ -0,0 +1,435 @@
|
||||
chibi-stickers-pma.png
|
||||
size: 512, 128
|
||||
filter: Linear, Linear
|
||||
pma: true
|
||||
scale: 0.5
|
||||
common/angry-mark
|
||||
bounds: 278, 85, 42, 41
|
||||
common/big-purple-fear
|
||||
bounds: 2, 54, 134, 72
|
||||
common/big-tear
|
||||
bounds: 138, 93, 33, 82
|
||||
rotate: 90
|
||||
common/eye-3
|
||||
bounds: 226, 25, 15, 26
|
||||
common/eye-closed-happy
|
||||
bounds: 267, 7, 25, 9
|
||||
rotate: 90
|
||||
common/eye-dafault
|
||||
bounds: 203, 20, 22, 21
|
||||
rotate: 90
|
||||
common/eye-equal
|
||||
bounds: 308, 43, 25, 15
|
||||
common/eye-fire
|
||||
bounds: 278, 57, 26, 28
|
||||
rotate: 90
|
||||
common/eye-half-open
|
||||
bounds: 138, 2, 26, 16
|
||||
common/eye-heart
|
||||
bounds: 308, 60, 26, 23
|
||||
common/eye-reverse-v
|
||||
bounds: 166, 2, 26, 16
|
||||
common/eye-sideway-v
|
||||
bounds: 336, 60, 21, 23
|
||||
common/eye-slant-close
|
||||
bounds: 194, 2, 23, 16
|
||||
common/eye-small-dot
|
||||
bounds: 119, 2, 15, 15
|
||||
common/eye-sparkle
|
||||
bounds: 372, 97, 30, 29
|
||||
common/eye-star
|
||||
bounds: 404, 99, 29, 27
|
||||
common/eye-twirl
|
||||
bounds: 226, 2, 21, 23
|
||||
rotate: 90
|
||||
common/eye-u
|
||||
bounds: 2, 2, 24, 17
|
||||
common/eye-x
|
||||
bounds: 176, 20, 25, 22
|
||||
common/lamp
|
||||
bounds: 138, 44, 47, 65
|
||||
rotate: 90
|
||||
common/mouth-3
|
||||
bounds: 89, 2, 15, 28
|
||||
rotate: 90
|
||||
common/mouth-bracket
|
||||
bounds: 322, 85, 34, 11
|
||||
common/mouth-doubt
|
||||
bounds: 243, 34, 26, 15
|
||||
common/mouth-fangs
|
||||
bounds: 205, 52, 39, 14
|
||||
rotate: 90
|
||||
common/mouth-line
|
||||
bounds: 435, 96, 36, 7
|
||||
common/mouth-neutral
|
||||
bounds: 245, 51, 27, 12
|
||||
common/mouth-o-tall
|
||||
bounds: 221, 53, 22, 33
|
||||
common/mouth-open-smile
|
||||
bounds: 138, 20, 36, 22
|
||||
common/mouth-rectangle
|
||||
bounds: 435, 105, 35, 21
|
||||
common/mouth-reverse-v
|
||||
bounds: 473, 95, 27, 10
|
||||
common/mouth-s
|
||||
bounds: 28, 8, 41, 11
|
||||
common/mouth-smile-little
|
||||
bounds: 117, 19, 33, 19
|
||||
rotate: 90
|
||||
common/mouth-toungue-sticking-out
|
||||
bounds: 245, 65, 31, 21
|
||||
common/mouth-u
|
||||
bounds: 472, 107, 36, 19
|
||||
common/mouth-v
|
||||
bounds: 251, 5, 27, 14
|
||||
rotate: 90
|
||||
common/mouth-x
|
||||
bounds: 335, 38, 21, 20
|
||||
common/purple-fear-lines
|
||||
bounds: 322, 98, 48, 28
|
||||
common/shadow
|
||||
bounds: 2, 21, 113, 31
|
||||
common/small-dash
|
||||
bounds: 404, 88, 9, 20
|
||||
rotate: 90
|
||||
common/small-drop-line
|
||||
bounds: 71, 2, 16, 17
|
||||
common/small-purple-fear
|
||||
bounds: 222, 88, 54, 38
|
||||
common/tear
|
||||
bounds: 274, 36, 20, 19
|
||||
|
||||
chibi-stickers-pma_2.png
|
||||
size: 1024, 256
|
||||
filter: Linear, Linear
|
||||
pma: true
|
||||
scale: 0.5
|
||||
erikari/arm
|
||||
bounds: 981, 164, 28, 90
|
||||
erikari/arm-shoulder-decoration
|
||||
bounds: 790, 149, 32, 43
|
||||
erikari/back-hair
|
||||
bounds: 258, 113, 158, 141
|
||||
erikari/back-hair-long
|
||||
bounds: 2, 34, 220, 254
|
||||
rotate: 90
|
||||
erikari/blush
|
||||
bounds: 981, 133, 29, 18
|
||||
rotate: 90
|
||||
erikari/body
|
||||
bounds: 584, 115, 70, 98
|
||||
erikari/bracelet
|
||||
bounds: 1011, 221, 33, 11
|
||||
rotate: 90
|
||||
erikari/collar
|
||||
bounds: 390, 48, 61, 62
|
||||
erikari/ear
|
||||
bounds: 258, 2, 34, 42
|
||||
erikari/eyebrow
|
||||
bounds: 453, 98, 20, 12
|
||||
erikari/hair-front
|
||||
bounds: 258, 46, 130, 65
|
||||
erikari/hair-side
|
||||
bounds: 656, 149, 43, 132
|
||||
rotate: 90
|
||||
erikari/hat-border
|
||||
bounds: 418, 215, 254, 39
|
||||
erikari/hat-top
|
||||
bounds: 674, 194, 160, 60
|
||||
erikari/head-base
|
||||
bounds: 836, 129, 143, 125
|
||||
erikari/leg
|
||||
bounds: 2, 4, 28, 101
|
||||
rotate: 90
|
||||
erikari/leg-decoration
|
||||
bounds: 770, 134, 36, 13
|
||||
erikari/skirt
|
||||
bounds: 418, 112, 164, 101
|
||||
erikari/strawberries-decoration
|
||||
bounds: 656, 91, 112, 56
|
||||
|
||||
chibi-stickers-pma_3.png
|
||||
size: 512, 256
|
||||
filter: Linear, Linear
|
||||
pma: true
|
||||
scale: 0.5
|
||||
harri/arm
|
||||
bounds: 147, 21, 28, 90
|
||||
rotate: 90
|
||||
harri/back-hair
|
||||
bounds: 2, 107, 158, 141
|
||||
harri/back-hair-long
|
||||
bounds: 147, 51, 40, 80
|
||||
rotate: 90
|
||||
harri/beard
|
||||
bounds: 2, 2, 10, 11
|
||||
harri/blush
|
||||
bounds: 265, 103, 29, 18
|
||||
harri/body
|
||||
bounds: 307, 94, 70, 98
|
||||
rotate: 90
|
||||
harri/body-decoration
|
||||
bounds: 407, 97, 70, 67
|
||||
harri/ear
|
||||
bounds: 229, 57, 34, 42
|
||||
rotate: 90
|
||||
harri/eyebrow
|
||||
bounds: 494, 226, 22, 12
|
||||
rotate: 90
|
||||
harri/hair-front
|
||||
bounds: 2, 15, 143, 90
|
||||
harri/head-base
|
||||
bounds: 162, 123, 143, 125
|
||||
harri/leg
|
||||
bounds: 162, 93, 28, 101
|
||||
rotate: 90
|
||||
harri/sword
|
||||
bounds: 307, 166, 185, 82
|
||||
|
||||
chibi-stickers-pma_4.png
|
||||
size: 1024, 256
|
||||
filter: Linear, Linear
|
||||
pma: true
|
||||
scale: 0.5
|
||||
luke/arm
|
||||
bounds: 930, 224, 28, 90
|
||||
rotate: 90
|
||||
luke/arm-shoulder-decoration
|
||||
bounds: 581, 112, 31, 27
|
||||
rotate: 90
|
||||
luke/back-hair
|
||||
bounds: 173, 111, 158, 141
|
||||
luke/blush
|
||||
bounds: 151, 68, 29, 18
|
||||
rotate: 90
|
||||
luke/body
|
||||
bounds: 700, 123, 70, 98
|
||||
rotate: 90
|
||||
luke/eyebrow
|
||||
bounds: 2, 2, 27, 12
|
||||
luke/face-cover
|
||||
bounds: 2, 99, 169, 153
|
||||
luke/glasses-shadow
|
||||
bounds: 2, 16, 147, 81
|
||||
luke/hair-decoration
|
||||
bounds: 478, 145, 130, 107
|
||||
luke/hair-front
|
||||
bounds: 700, 195, 122, 57
|
||||
luke/head-base
|
||||
bounds: 333, 127, 143, 125
|
||||
luke/leg
|
||||
bounds: 478, 115, 28, 101
|
||||
rotate: 90
|
||||
luke/shield
|
||||
bounds: 610, 148, 88, 104
|
||||
luke/skirt
|
||||
bounds: 930, 191, 81, 31
|
||||
luke/sword
|
||||
bounds: 824, 181, 104, 71
|
||||
|
||||
chibi-stickers-pma_5.png
|
||||
size: 512, 256
|
||||
filter: Linear, Linear
|
||||
pma: true
|
||||
scale: 0.5
|
||||
mario/arm
|
||||
bounds: 244, 2, 28, 90
|
||||
mario/back-hair
|
||||
bounds: 2, 101, 168, 148
|
||||
mario/back-hair-long
|
||||
bounds: 151, 6, 86, 91
|
||||
rotate: 90
|
||||
mario/beard
|
||||
bounds: 2, 6, 147, 93
|
||||
mario/blush
|
||||
bounds: 492, 220, 29, 18
|
||||
rotate: 90
|
||||
mario/body
|
||||
bounds: 317, 111, 70, 98
|
||||
rotate: 90
|
||||
mario/ear
|
||||
bounds: 456, 207, 34, 42
|
||||
mario/eyebrow
|
||||
bounds: 417, 164, 32, 17
|
||||
mario/hair-front
|
||||
bounds: 317, 183, 137, 66
|
||||
mario/head-base
|
||||
bounds: 172, 124, 143, 125
|
||||
mario/leg
|
||||
bounds: 172, 94, 28, 101
|
||||
rotate: 90
|
||||
|
||||
chibi-stickers-pma_6.png
|
||||
size: 1024, 256
|
||||
filter: Linear, Linear
|
||||
pma: true
|
||||
scale: 0.5
|
||||
misaki/arm
|
||||
bounds: 609, 95, 28, 90
|
||||
misaki/back-hair
|
||||
bounds: 194, 105, 158, 141
|
||||
misaki/back-hair-long
|
||||
bounds: 2, 51, 190, 195
|
||||
misaki/belt
|
||||
bounds: 741, 190, 76, 26
|
||||
misaki/blush
|
||||
bounds: 844, 228, 29, 18
|
||||
misaki/body
|
||||
bounds: 641, 176, 70, 98
|
||||
rotate: 90
|
||||
misaki/ear
|
||||
bounds: 144, 7, 34, 42
|
||||
misaki/eyebrow
|
||||
bounds: 194, 54, 30, 12
|
||||
misaki/glasses
|
||||
bounds: 194, 68, 141, 35
|
||||
misaki/glasses-side
|
||||
bounds: 354, 111, 8, 23
|
||||
rotate: 90
|
||||
misaki/hair-front
|
||||
bounds: 499, 187, 140, 59
|
||||
misaki/hair-side
|
||||
bounds: 2, 2, 47, 140
|
||||
rotate: 90
|
||||
misaki/head-base
|
||||
bounds: 354, 121, 143, 125
|
||||
misaki/leg
|
||||
bounds: 741, 218, 28, 101
|
||||
rotate: 90
|
||||
misaki/skirt
|
||||
bounds: 499, 95, 108, 90
|
||||
|
||||
chibi-stickers-pma_7.png
|
||||
size: 512, 256
|
||||
filter: Linear, Linear
|
||||
pma: true
|
||||
scale: 0.5
|
||||
nate/arm
|
||||
bounds: 151, 65, 28, 90
|
||||
rotate: 90
|
||||
nate/back-hair
|
||||
bounds: 2, 109, 158, 141
|
||||
nate/beard
|
||||
bounds: 2, 39, 147, 68
|
||||
nate/blush
|
||||
bounds: 407, 165, 29, 18
|
||||
nate/body
|
||||
bounds: 307, 113, 70, 98
|
||||
rotate: 90
|
||||
nate/ear
|
||||
bounds: 451, 208, 34, 42
|
||||
nate/eyebrow
|
||||
bounds: 265, 111, 27, 12
|
||||
nate/glasses
|
||||
bounds: 2, 2, 141, 35
|
||||
nate/glasses-side
|
||||
bounds: 151, 47, 8, 16
|
||||
nate/hair-front
|
||||
bounds: 307, 185, 142, 65
|
||||
nate/head-base
|
||||
bounds: 162, 125, 143, 125
|
||||
nate/leg
|
||||
bounds: 162, 95, 28, 101
|
||||
rotate: 90
|
||||
|
||||
chibi-stickers-pma_8.png
|
||||
size: 512, 256
|
||||
filter: Linear, Linear
|
||||
pma: true
|
||||
scale: 0.5
|
||||
sinisa/arm
|
||||
bounds: 147, 52, 28, 90
|
||||
rotate: 90
|
||||
sinisa/back-hair
|
||||
bounds: 2, 96, 158, 141
|
||||
sinisa/beard
|
||||
bounds: 307, 192, 139, 45
|
||||
sinisa/blush
|
||||
bounds: 147, 32, 29, 18
|
||||
sinisa/body
|
||||
bounds: 307, 120, 70, 98
|
||||
rotate: 90
|
||||
sinisa/body-decoration
|
||||
bounds: 265, 83, 27, 27
|
||||
sinisa/ear
|
||||
bounds: 448, 195, 34, 42
|
||||
sinisa/eyebrow
|
||||
bounds: 407, 171, 38, 19
|
||||
sinisa/hair-front
|
||||
bounds: 2, 2, 143, 92
|
||||
sinisa/head-base
|
||||
bounds: 162, 112, 143, 125
|
||||
sinisa/leg
|
||||
bounds: 162, 82, 28, 101
|
||||
rotate: 90
|
||||
|
||||
chibi-stickers-pma_9.png
|
||||
size: 512, 256
|
||||
filter: Linear, Linear
|
||||
pma: true
|
||||
scale: 0.5
|
||||
soeren/arm
|
||||
bounds: 254, 47, 28, 90
|
||||
soeren/back-hair
|
||||
bounds: 2, 111, 150, 141
|
||||
soeren/beard
|
||||
bounds: 2, 41, 145, 68
|
||||
soeren/blush
|
||||
bounds: 284, 119, 29, 18
|
||||
soeren/body
|
||||
bounds: 154, 67, 70, 98
|
||||
rotate: 90
|
||||
soeren/ear
|
||||
bounds: 200, 23, 34, 42
|
||||
soeren/eyebrow
|
||||
bounds: 460, 137, 27, 12
|
||||
soeren/glasses
|
||||
bounds: 2, 2, 152, 37
|
||||
soeren/glasses-side
|
||||
bounds: 490, 245, 7, 20
|
||||
rotate: 90
|
||||
soeren/glove
|
||||
bounds: 156, 12, 42, 53
|
||||
soeren/hair-front
|
||||
bounds: 154, 139, 159, 113
|
||||
soeren/head-base
|
||||
bounds: 315, 127, 143, 125
|
||||
soeren/leg
|
||||
bounds: 460, 151, 28, 101
|
||||
|
||||
chibi-stickers-pma_10.png
|
||||
size: 512, 256
|
||||
filter: Linear, Linear
|
||||
pma: true
|
||||
scale: 0.5
|
||||
spineboy/arm
|
||||
bounds: 407, 97, 28, 90
|
||||
rotate: 90
|
||||
spineboy/arm-decoration
|
||||
bounds: 307, 127, 32, 29
|
||||
spineboy/arm-shoulder-decoration
|
||||
bounds: 451, 72, 23, 23
|
||||
spineboy/back-hair
|
||||
bounds: 2, 106, 158, 141
|
||||
spineboy/blush
|
||||
bounds: 2, 2, 29, 18
|
||||
spineboy/body
|
||||
bounds: 307, 55, 70, 98
|
||||
rotate: 90
|
||||
spineboy/ear
|
||||
bounds: 407, 61, 34, 42
|
||||
rotate: 90
|
||||
spineboy/eyebrow
|
||||
bounds: 143, 77, 27, 12
|
||||
rotate: 90
|
||||
spineboy/glasses
|
||||
bounds: 162, 158, 179, 89
|
||||
spineboy/glasses-shadow
|
||||
bounds: 2, 22, 139, 82
|
||||
spineboy/hair-front
|
||||
bounds: 343, 127, 145, 120
|
||||
spineboy/head-base
|
||||
bounds: 162, 31, 143, 125
|
||||
spineboy/leg
|
||||
bounds: 307, 24, 29, 101
|
||||
rotate: 90
|
||||
BIN
spine-ts/spine-webgl/example/assets/chibi-stickers-pma.png
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
spine-ts/spine-webgl/example/assets/chibi-stickers-pma_10.png
Normal file
|
After Width: | Height: | Size: 72 KiB |
BIN
spine-ts/spine-webgl/example/assets/chibi-stickers-pma_2.png
Normal file
|
After Width: | Height: | Size: 137 KiB |
BIN
spine-ts/spine-webgl/example/assets/chibi-stickers-pma_3.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
spine-ts/spine-webgl/example/assets/chibi-stickers-pma_4.png
Normal file
|
After Width: | Height: | Size: 100 KiB |
BIN
spine-ts/spine-webgl/example/assets/chibi-stickers-pma_5.png
Normal file
|
After Width: | Height: | Size: 57 KiB |
BIN
spine-ts/spine-webgl/example/assets/chibi-stickers-pma_6.png
Normal file
|
After Width: | Height: | Size: 87 KiB |
BIN
spine-ts/spine-webgl/example/assets/chibi-stickers-pma_7.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
spine-ts/spine-webgl/example/assets/chibi-stickers-pma_8.png
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
spine-ts/spine-webgl/example/assets/chibi-stickers-pma_9.png
Normal file
|
After Width: | Height: | Size: 67 KiB |
425
spine-ts/spine-webgl/example/assets/chibi-stickers.atlas
Normal file
@ -0,0 +1,425 @@
|
||||
chibi-stickers.png
|
||||
size: 512, 128
|
||||
filter: Linear, Linear
|
||||
scale: 0.5
|
||||
common/angry-mark
|
||||
bounds: 278, 85, 42, 41
|
||||
common/big-purple-fear
|
||||
bounds: 2, 54, 134, 72
|
||||
common/big-tear
|
||||
bounds: 138, 93, 33, 82
|
||||
rotate: 90
|
||||
common/eye-3
|
||||
bounds: 226, 25, 15, 26
|
||||
common/eye-closed-happy
|
||||
bounds: 267, 7, 25, 9
|
||||
rotate: 90
|
||||
common/eye-dafault
|
||||
bounds: 203, 20, 22, 21
|
||||
rotate: 90
|
||||
common/eye-equal
|
||||
bounds: 308, 43, 25, 15
|
||||
common/eye-fire
|
||||
bounds: 278, 57, 26, 28
|
||||
rotate: 90
|
||||
common/eye-half-open
|
||||
bounds: 138, 2, 26, 16
|
||||
common/eye-heart
|
||||
bounds: 308, 60, 26, 23
|
||||
common/eye-reverse-v
|
||||
bounds: 166, 2, 26, 16
|
||||
common/eye-sideway-v
|
||||
bounds: 336, 60, 21, 23
|
||||
common/eye-slant-close
|
||||
bounds: 194, 2, 23, 16
|
||||
common/eye-small-dot
|
||||
bounds: 119, 2, 15, 15
|
||||
common/eye-sparkle
|
||||
bounds: 372, 97, 30, 29
|
||||
common/eye-star
|
||||
bounds: 404, 99, 29, 27
|
||||
common/eye-twirl
|
||||
bounds: 226, 2, 21, 23
|
||||
rotate: 90
|
||||
common/eye-u
|
||||
bounds: 2, 2, 24, 17
|
||||
common/eye-x
|
||||
bounds: 176, 20, 25, 22
|
||||
common/lamp
|
||||
bounds: 138, 44, 47, 65
|
||||
rotate: 90
|
||||
common/mouth-3
|
||||
bounds: 89, 2, 15, 28
|
||||
rotate: 90
|
||||
common/mouth-bracket
|
||||
bounds: 322, 85, 34, 11
|
||||
common/mouth-doubt
|
||||
bounds: 243, 34, 26, 15
|
||||
common/mouth-fangs
|
||||
bounds: 205, 52, 39, 14
|
||||
rotate: 90
|
||||
common/mouth-line
|
||||
bounds: 435, 96, 36, 7
|
||||
common/mouth-neutral
|
||||
bounds: 245, 51, 27, 12
|
||||
common/mouth-o-tall
|
||||
bounds: 221, 53, 22, 33
|
||||
common/mouth-open-smile
|
||||
bounds: 138, 20, 36, 22
|
||||
common/mouth-rectangle
|
||||
bounds: 435, 105, 35, 21
|
||||
common/mouth-reverse-v
|
||||
bounds: 473, 95, 27, 10
|
||||
common/mouth-s
|
||||
bounds: 28, 8, 41, 11
|
||||
common/mouth-smile-little
|
||||
bounds: 117, 19, 33, 19
|
||||
rotate: 90
|
||||
common/mouth-toungue-sticking-out
|
||||
bounds: 245, 65, 31, 21
|
||||
common/mouth-u
|
||||
bounds: 472, 107, 36, 19
|
||||
common/mouth-v
|
||||
bounds: 251, 5, 27, 14
|
||||
rotate: 90
|
||||
common/mouth-x
|
||||
bounds: 335, 38, 21, 20
|
||||
common/purple-fear-lines
|
||||
bounds: 322, 98, 48, 28
|
||||
common/shadow
|
||||
bounds: 2, 21, 113, 31
|
||||
common/small-dash
|
||||
bounds: 404, 88, 9, 20
|
||||
rotate: 90
|
||||
common/small-drop-line
|
||||
bounds: 71, 2, 16, 17
|
||||
common/small-purple-fear
|
||||
bounds: 222, 88, 54, 38
|
||||
common/tear
|
||||
bounds: 274, 36, 20, 19
|
||||
|
||||
chibi-stickers_2.png
|
||||
size: 1024, 256
|
||||
filter: Linear, Linear
|
||||
scale: 0.5
|
||||
erikari/arm
|
||||
bounds: 981, 164, 28, 90
|
||||
erikari/arm-shoulder-decoration
|
||||
bounds: 790, 149, 32, 43
|
||||
erikari/back-hair
|
||||
bounds: 258, 113, 158, 141
|
||||
erikari/back-hair-long
|
||||
bounds: 2, 34, 220, 254
|
||||
rotate: 90
|
||||
erikari/blush
|
||||
bounds: 981, 133, 29, 18
|
||||
rotate: 90
|
||||
erikari/body
|
||||
bounds: 584, 115, 70, 98
|
||||
erikari/bracelet
|
||||
bounds: 1011, 221, 33, 11
|
||||
rotate: 90
|
||||
erikari/collar
|
||||
bounds: 390, 48, 61, 62
|
||||
erikari/ear
|
||||
bounds: 258, 2, 34, 42
|
||||
erikari/eyebrow
|
||||
bounds: 453, 98, 20, 12
|
||||
erikari/hair-front
|
||||
bounds: 258, 46, 130, 65
|
||||
erikari/hair-side
|
||||
bounds: 656, 149, 43, 132
|
||||
rotate: 90
|
||||
erikari/hat-border
|
||||
bounds: 418, 215, 254, 39
|
||||
erikari/hat-top
|
||||
bounds: 674, 194, 160, 60
|
||||
erikari/head-base
|
||||
bounds: 836, 129, 143, 125
|
||||
erikari/leg
|
||||
bounds: 2, 4, 28, 101
|
||||
rotate: 90
|
||||
erikari/leg-decoration
|
||||
bounds: 770, 134, 36, 13
|
||||
erikari/skirt
|
||||
bounds: 418, 112, 164, 101
|
||||
erikari/strawberries-decoration
|
||||
bounds: 656, 91, 112, 56
|
||||
|
||||
chibi-stickers_3.png
|
||||
size: 512, 256
|
||||
filter: Linear, Linear
|
||||
scale: 0.5
|
||||
harri/arm
|
||||
bounds: 147, 21, 28, 90
|
||||
rotate: 90
|
||||
harri/back-hair
|
||||
bounds: 2, 107, 158, 141
|
||||
harri/back-hair-long
|
||||
bounds: 147, 51, 40, 80
|
||||
rotate: 90
|
||||
harri/beard
|
||||
bounds: 2, 2, 10, 11
|
||||
harri/blush
|
||||
bounds: 265, 103, 29, 18
|
||||
harri/body
|
||||
bounds: 307, 94, 70, 98
|
||||
rotate: 90
|
||||
harri/body-decoration
|
||||
bounds: 407, 97, 70, 67
|
||||
harri/ear
|
||||
bounds: 229, 57, 34, 42
|
||||
rotate: 90
|
||||
harri/eyebrow
|
||||
bounds: 494, 226, 22, 12
|
||||
rotate: 90
|
||||
harri/hair-front
|
||||
bounds: 2, 15, 143, 90
|
||||
harri/head-base
|
||||
bounds: 162, 123, 143, 125
|
||||
harri/leg
|
||||
bounds: 162, 93, 28, 101
|
||||
rotate: 90
|
||||
harri/sword
|
||||
bounds: 307, 166, 185, 82
|
||||
|
||||
chibi-stickers_4.png
|
||||
size: 1024, 256
|
||||
filter: Linear, Linear
|
||||
scale: 0.5
|
||||
luke/arm
|
||||
bounds: 930, 224, 28, 90
|
||||
rotate: 90
|
||||
luke/arm-shoulder-decoration
|
||||
bounds: 581, 112, 31, 27
|
||||
rotate: 90
|
||||
luke/back-hair
|
||||
bounds: 173, 111, 158, 141
|
||||
luke/blush
|
||||
bounds: 151, 68, 29, 18
|
||||
rotate: 90
|
||||
luke/body
|
||||
bounds: 700, 123, 70, 98
|
||||
rotate: 90
|
||||
luke/eyebrow
|
||||
bounds: 2, 2, 27, 12
|
||||
luke/face-cover
|
||||
bounds: 2, 99, 169, 153
|
||||
luke/glasses-shadow
|
||||
bounds: 2, 16, 147, 81
|
||||
luke/hair-decoration
|
||||
bounds: 478, 145, 130, 107
|
||||
luke/hair-front
|
||||
bounds: 700, 195, 122, 57
|
||||
luke/head-base
|
||||
bounds: 333, 127, 143, 125
|
||||
luke/leg
|
||||
bounds: 478, 115, 28, 101
|
||||
rotate: 90
|
||||
luke/shield
|
||||
bounds: 610, 148, 88, 104
|
||||
luke/skirt
|
||||
bounds: 930, 191, 81, 31
|
||||
luke/sword
|
||||
bounds: 824, 181, 104, 71
|
||||
|
||||
chibi-stickers_5.png
|
||||
size: 512, 256
|
||||
filter: Linear, Linear
|
||||
scale: 0.5
|
||||
mario/arm
|
||||
bounds: 244, 2, 28, 90
|
||||
mario/back-hair
|
||||
bounds: 2, 101, 168, 148
|
||||
mario/back-hair-long
|
||||
bounds: 151, 6, 86, 91
|
||||
rotate: 90
|
||||
mario/beard
|
||||
bounds: 2, 6, 147, 93
|
||||
mario/blush
|
||||
bounds: 492, 220, 29, 18
|
||||
rotate: 90
|
||||
mario/body
|
||||
bounds: 317, 111, 70, 98
|
||||
rotate: 90
|
||||
mario/ear
|
||||
bounds: 456, 207, 34, 42
|
||||
mario/eyebrow
|
||||
bounds: 417, 164, 32, 17
|
||||
mario/hair-front
|
||||
bounds: 317, 183, 137, 66
|
||||
mario/head-base
|
||||
bounds: 172, 124, 143, 125
|
||||
mario/leg
|
||||
bounds: 172, 94, 28, 101
|
||||
rotate: 90
|
||||
|
||||
chibi-stickers_6.png
|
||||
size: 1024, 256
|
||||
filter: Linear, Linear
|
||||
scale: 0.5
|
||||
misaki/arm
|
||||
bounds: 609, 95, 28, 90
|
||||
misaki/back-hair
|
||||
bounds: 194, 105, 158, 141
|
||||
misaki/back-hair-long
|
||||
bounds: 2, 51, 190, 195
|
||||
misaki/belt
|
||||
bounds: 741, 190, 76, 26
|
||||
misaki/blush
|
||||
bounds: 844, 228, 29, 18
|
||||
misaki/body
|
||||
bounds: 641, 176, 70, 98
|
||||
rotate: 90
|
||||
misaki/ear
|
||||
bounds: 144, 7, 34, 42
|
||||
misaki/eyebrow
|
||||
bounds: 194, 54, 30, 12
|
||||
misaki/glasses
|
||||
bounds: 194, 68, 141, 35
|
||||
misaki/glasses-side
|
||||
bounds: 354, 111, 8, 23
|
||||
rotate: 90
|
||||
misaki/hair-front
|
||||
bounds: 499, 187, 140, 59
|
||||
misaki/hair-side
|
||||
bounds: 2, 2, 47, 140
|
||||
rotate: 90
|
||||
misaki/head-base
|
||||
bounds: 354, 121, 143, 125
|
||||
misaki/leg
|
||||
bounds: 741, 218, 28, 101
|
||||
rotate: 90
|
||||
misaki/skirt
|
||||
bounds: 499, 95, 108, 90
|
||||
|
||||
chibi-stickers_7.png
|
||||
size: 512, 256
|
||||
filter: Linear, Linear
|
||||
scale: 0.5
|
||||
nate/arm
|
||||
bounds: 151, 65, 28, 90
|
||||
rotate: 90
|
||||
nate/back-hair
|
||||
bounds: 2, 109, 158, 141
|
||||
nate/beard
|
||||
bounds: 2, 39, 147, 68
|
||||
nate/blush
|
||||
bounds: 407, 165, 29, 18
|
||||
nate/body
|
||||
bounds: 307, 113, 70, 98
|
||||
rotate: 90
|
||||
nate/ear
|
||||
bounds: 451, 208, 34, 42
|
||||
nate/eyebrow
|
||||
bounds: 265, 111, 27, 12
|
||||
nate/glasses
|
||||
bounds: 2, 2, 141, 35
|
||||
nate/glasses-side
|
||||
bounds: 151, 47, 8, 16
|
||||
nate/hair-front
|
||||
bounds: 307, 185, 142, 65
|
||||
nate/head-base
|
||||
bounds: 162, 125, 143, 125
|
||||
nate/leg
|
||||
bounds: 162, 95, 28, 101
|
||||
rotate: 90
|
||||
|
||||
chibi-stickers_8.png
|
||||
size: 512, 256
|
||||
filter: Linear, Linear
|
||||
scale: 0.5
|
||||
sinisa/arm
|
||||
bounds: 147, 52, 28, 90
|
||||
rotate: 90
|
||||
sinisa/back-hair
|
||||
bounds: 2, 96, 158, 141
|
||||
sinisa/beard
|
||||
bounds: 307, 192, 139, 45
|
||||
sinisa/blush
|
||||
bounds: 147, 32, 29, 18
|
||||
sinisa/body
|
||||
bounds: 307, 120, 70, 98
|
||||
rotate: 90
|
||||
sinisa/body-decoration
|
||||
bounds: 265, 83, 27, 27
|
||||
sinisa/ear
|
||||
bounds: 448, 195, 34, 42
|
||||
sinisa/eyebrow
|
||||
bounds: 407, 171, 38, 19
|
||||
sinisa/hair-front
|
||||
bounds: 2, 2, 143, 92
|
||||
sinisa/head-base
|
||||
bounds: 162, 112, 143, 125
|
||||
sinisa/leg
|
||||
bounds: 162, 82, 28, 101
|
||||
rotate: 90
|
||||
|
||||
chibi-stickers_9.png
|
||||
size: 512, 256
|
||||
filter: Linear, Linear
|
||||
scale: 0.5
|
||||
soeren/arm
|
||||
bounds: 254, 47, 28, 90
|
||||
soeren/back-hair
|
||||
bounds: 2, 111, 150, 141
|
||||
soeren/beard
|
||||
bounds: 2, 41, 145, 68
|
||||
soeren/blush
|
||||
bounds: 284, 119, 29, 18
|
||||
soeren/body
|
||||
bounds: 154, 67, 70, 98
|
||||
rotate: 90
|
||||
soeren/ear
|
||||
bounds: 200, 23, 34, 42
|
||||
soeren/eyebrow
|
||||
bounds: 460, 137, 27, 12
|
||||
soeren/glasses
|
||||
bounds: 2, 2, 152, 37
|
||||
soeren/glasses-side
|
||||
bounds: 490, 245, 7, 20
|
||||
rotate: 90
|
||||
soeren/glove
|
||||
bounds: 156, 12, 42, 53
|
||||
soeren/hair-front
|
||||
bounds: 154, 139, 159, 113
|
||||
soeren/head-base
|
||||
bounds: 315, 127, 143, 125
|
||||
soeren/leg
|
||||
bounds: 460, 151, 28, 101
|
||||
|
||||
chibi-stickers_10.png
|
||||
size: 512, 256
|
||||
filter: Linear, Linear
|
||||
scale: 0.5
|
||||
spineboy/arm
|
||||
bounds: 407, 97, 28, 90
|
||||
rotate: 90
|
||||
spineboy/arm-decoration
|
||||
bounds: 307, 127, 32, 29
|
||||
spineboy/arm-shoulder-decoration
|
||||
bounds: 451, 72, 23, 23
|
||||
spineboy/back-hair
|
||||
bounds: 2, 106, 158, 141
|
||||
spineboy/blush
|
||||
bounds: 2, 2, 29, 18
|
||||
spineboy/body
|
||||
bounds: 307, 55, 70, 98
|
||||
rotate: 90
|
||||
spineboy/ear
|
||||
bounds: 407, 61, 34, 42
|
||||
rotate: 90
|
||||
spineboy/eyebrow
|
||||
bounds: 143, 77, 27, 12
|
||||
rotate: 90
|
||||
spineboy/glasses
|
||||
bounds: 162, 158, 179, 89
|
||||
spineboy/glasses-shadow
|
||||
bounds: 2, 22, 139, 82
|
||||
spineboy/hair-front
|
||||
bounds: 343, 127, 145, 120
|
||||
spineboy/head-base
|
||||
bounds: 162, 31, 143, 125
|
||||
spineboy/leg
|
||||
bounds: 307, 24, 29, 101
|
||||
rotate: 90
|
||||
7597
spine-ts/spine-webgl/example/assets/chibi-stickers.json
Normal file
BIN
spine-ts/spine-webgl/example/assets/chibi-stickers.skel
Normal file
@ -132,196 +132,78 @@
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- <div style="height: 1200px; flex-direction: column;">
|
||||
</div> -->
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// start section 1 //
|
||||
/////////////////////
|
||||
-->
|
||||
|
||||
<div id="section1" class="section vertical-split">
|
||||
|
||||
<div class="split-top split">
|
||||
<div class="split-left">
|
||||
<spine-widget
|
||||
atlas="assets/raptor-pma.atlas"
|
||||
skeleton="assets/raptor-pro.skel"
|
||||
animation="walk"
|
||||
scale="3"
|
||||
clip="true"
|
||||
fit="fitHeight"
|
||||
></spine-widget>
|
||||
</div>
|
||||
<div class="split-right">
|
||||
<spine-widget
|
||||
atlas="assets/spineboy-pma.atlas"
|
||||
skeleton="assets/spineboy-pro.skel"
|
||||
animation="walk"
|
||||
scale="1.5"
|
||||
fit="none"
|
||||
clip="true"
|
||||
></spine-widget>
|
||||
</div>
|
||||
<div class="split-right">
|
||||
<spine-widget
|
||||
atlas="assets/spineboy-pma.atlas"
|
||||
skeleton="assets/spineboy-pro.skel"
|
||||
animation="walk"
|
||||
scale="1"
|
||||
fit="none"
|
||||
clip="true"
|
||||
></spine-widget>
|
||||
</div>
|
||||
<!-- <div class="split-right">
|
||||
<spine-widget
|
||||
atlas="assets/cloud-pot-pma.atlas"
|
||||
skeleton="assets/cloud-pot.skel"
|
||||
animation="playing-in-the-rain"
|
||||
draggable="true"
|
||||
></spine-widget>
|
||||
</div>
|
||||
<div class="split-right">
|
||||
<spine-widget
|
||||
atlas="assets/celestial-circus-pma.atlas"
|
||||
skeleton="assets/celestial-circus-pro.skel"
|
||||
animation="wings-and-feet"
|
||||
draggable="true"
|
||||
></spine-widget>
|
||||
</div> -->
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div style="height: 1200px; flex-direction: column;">
|
||||
</div>
|
||||
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// start section 7 //
|
||||
// end section 1 //
|
||||
/////////////////////
|
||||
-->
|
||||
<div id="section1" class="section vertical-split">
|
||||
|
||||
<div class="split" style="width: 100%; flex-direction: column;">
|
||||
|
||||
<div class="split-left" style="width: 80%; box-sizing: border-box;">
|
||||
If you have many atlas pages, for example one for each skin, and you want to show only some of the skins,
|
||||
pass to the <code>pages</code> the atlas pages you want to load as a comma concatenated list of indices.
|
||||
</div>
|
||||
|
||||
<div class="skin-grid">
|
||||
<div class="skin-grid-element">
|
||||
<spine-widget
|
||||
atlas="assets/chibi-stickers-pma.atlas"
|
||||
skeleton="assets/chibi-stickers.skel"
|
||||
animation="emotes/wave"
|
||||
skin="nate"
|
||||
pages="0,1,4,6"
|
||||
></spine-widget>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="skin-grid">
|
||||
<div class="skin-grid-element">
|
||||
<spine-widget
|
||||
atlas="assets/chibi-stickers-pma.atlas"
|
||||
skeleton="assets/chibi-stickers.skel"
|
||||
animation="emotes/wave"
|
||||
skin="erikari"
|
||||
pages="0,1,4,6"
|
||||
offscreen="update"
|
||||
></spine-widget>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="skin-grid">
|
||||
<div class="skin-grid-element">
|
||||
<spine-widget
|
||||
atlas="assets/chibi-stickers-pma.atlas"
|
||||
skeleton="assets/chibi-stickers.skel"
|
||||
animation="emotes/wave"
|
||||
skin="mario"
|
||||
pages="0,1,4,6"
|
||||
offscreen="pose"
|
||||
></spine-widget>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="split-bottom">
|
||||
<pre><code id="code-display">
|
||||
<script>
|
||||
escapeHTMLandInject(`
|
||||
<div class="skin-grid">
|
||||
<div class="skin-grid-element">
|
||||
<spine-widget
|
||||
atlas="assets/chibi-stickers-pma.atlas"
|
||||
skeleton="assets/chibi-stickers.skel"
|
||||
animation="emotes/wave"
|
||||
skin="nate"
|
||||
pages="0,1,4,6"
|
||||
></spine-widget>
|
||||
</div>
|
||||
<div class="skin-grid-element">
|
||||
<spine-widget
|
||||
atlas="assets/chibi-stickers-pma.atlas"
|
||||
skeleton="assets/chibi-stickers.skel"
|
||||
animation="movement/trot-left"
|
||||
skin="nate"
|
||||
pages="0,1,4,6"
|
||||
></spine-widget>
|
||||
</div>
|
||||
<div class="skin-grid-element">
|
||||
<spine-widget
|
||||
atlas="assets/chibi-stickers-pma.atlas"
|
||||
skeleton="assets/chibi-stickers.skel"
|
||||
animation="emotes/idea"
|
||||
skin="nate"
|
||||
pages="0,1,4,6"
|
||||
></spine-widget>
|
||||
</div>
|
||||
<div class="skin-grid-element">
|
||||
<spine-widget
|
||||
atlas="assets/chibi-stickers-pma.atlas"
|
||||
skeleton="assets/chibi-stickers.skel"
|
||||
animation="emotes/hooray"
|
||||
skin="nate"
|
||||
pages="0,1,4,6"
|
||||
></spine-widget>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="skin-grid">
|
||||
<div class="skin-grid-element">
|
||||
<spine-widget
|
||||
atlas="assets/chibi-stickers-pma.atlas"
|
||||
skeleton="assets/chibi-stickers.skel"
|
||||
animation="emotes/wave"
|
||||
skin="erikari"
|
||||
pages="0,1,4,6"
|
||||
></spine-widget>
|
||||
</div>
|
||||
<div class="skin-grid-element">
|
||||
<spine-widget
|
||||
atlas="assets/chibi-stickers-pma.atlas"
|
||||
skeleton="assets/chibi-stickers.skel"
|
||||
animation="movement/trot-left"
|
||||
skin="erikari"
|
||||
pages="0,1,4,6"
|
||||
></spine-widget>
|
||||
</div>
|
||||
<div class="skin-grid-element">
|
||||
<spine-widget
|
||||
atlas="assets/chibi-stickers-pma.atlas"
|
||||
skeleton="assets/chibi-stickers.skel"
|
||||
animation="emotes/idea"
|
||||
skin="erikari"
|
||||
pages="0,1,4,6"
|
||||
></spine-widget>
|
||||
</div>
|
||||
<div class="skin-grid-element">
|
||||
<spine-widget
|
||||
atlas="assets/chibi-stickers-pma.atlas"
|
||||
skeleton="assets/chibi-stickers.skel"
|
||||
animation="emotes/hooray"
|
||||
skin="erikari"
|
||||
pages="0,1,4,6"
|
||||
></spine-widget>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="skin-grid">
|
||||
<div class="skin-grid-element">
|
||||
<spine-widget
|
||||
atlas="assets/chibi-stickers-pma.atlas"
|
||||
skeleton="assets/chibi-stickers.skel"
|
||||
animation="emotes/wave"
|
||||
skin="mario"
|
||||
pages="0,1,4,6"
|
||||
></spine-widget>
|
||||
</div>
|
||||
<div class="skin-grid-element">
|
||||
<spine-widget
|
||||
atlas="assets/chibi-stickers-pma.atlas"
|
||||
skeleton="assets/chibi-stickers.skel"
|
||||
animation="movement/trot-left"
|
||||
skin="mario"
|
||||
pages="0,1,4,6"
|
||||
></spine-widget>
|
||||
</div>
|
||||
<div class="skin-grid-element">
|
||||
<spine-widget
|
||||
atlas="assets/chibi-stickers-pma.atlas"
|
||||
skeleton="assets/chibi-stickers.skel"
|
||||
animation="emotes/idea"
|
||||
skin="mario"
|
||||
pages="0,1,4,6"
|
||||
></spine-widget>
|
||||
</div>
|
||||
<div class="skin-grid-element">
|
||||
<spine-widget
|
||||
atlas="assets/chibi-stickers-pma.atlas"
|
||||
skeleton="assets/chibi-stickers.skel"
|
||||
animation="emotes/hooray"
|
||||
skin="mario"
|
||||
pages="0,1,4,6"
|
||||
></spine-widget>
|
||||
</div>
|
||||
</div>`)
|
||||
</script>
|
||||
</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<!--
|
||||
/////////////////////
|
||||
// end section 7 //
|
||||
/////////////////////
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
|
||||
@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<script src="../dist/iife/spine-webgl.js"></script>
|
||||
<!-- <script src="./spine-webgl.min.js"></script> -->
|
||||
<!-- <script src="../dist/iife/spine-webgl.js"></script> -->
|
||||
<script src="./spine-webgl.min.js"></script>
|
||||
<title>JS Library Showcase</title>
|
||||
<style>
|
||||
body {
|
||||
@ -1558,6 +1558,200 @@ stretchyman.update = (canvas, delta, skeleton, state) => {
|
||||
/////////////////////
|
||||
-->
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// start section 8 //
|
||||
/////////////////////
|
||||
-->
|
||||
<div id="section1" class="section vertical-split">
|
||||
|
||||
<div class="split" style="width: 100%; flex-direction: column;">
|
||||
|
||||
<div class="split-left" style="width: 80%; box-sizing: border-box;">
|
||||
If for some reason your skeleton bounds go outside the div,
|
||||
you can use the <code>clip</code> property to clip everything is outside the html container.
|
||||
<br>
|
||||
<br>
|
||||
Be aware that this will break batching!
|
||||
</div>
|
||||
|
||||
<div class="split-left" style="width: 80%; box-sizing: border-box; height: 150px;">
|
||||
<spine-widget
|
||||
identifier="tank2"
|
||||
atlas="assets/tank-pma.atlas"
|
||||
skeleton="assets/tank-pro.skel"
|
||||
animation="drive"
|
||||
></spine-widget>
|
||||
</div>
|
||||
|
||||
<div class="split-left" style="width: 30%; box-sizing: border-box; height: 150px;">
|
||||
<spine-widget
|
||||
identifier="tank"
|
||||
atlas="assets/tank-pma.atlas"
|
||||
skeleton="assets/tank-pro.skel"
|
||||
animation="drive"
|
||||
fit="none"
|
||||
clip="true"
|
||||
></spine-widget>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(async () => {
|
||||
const tank = spine.getSpineWidget("tank");
|
||||
const tank2 = spine.getSpineWidget("tank2");
|
||||
await tank.loadingPromise;
|
||||
await tank2.loadingPromise;
|
||||
|
||||
tank.beforeUpdateWorldTransforms = (canvas, delta, skeleton, state) => {
|
||||
if (!tank.onScreen) return;
|
||||
tank.skeleton.scaleX = tank2.skeleton.scaleX;
|
||||
tank.skeleton.scaleY = tank2.skeleton.scaleY;
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="split-bottom">
|
||||
<pre><code id="code-display">
|
||||
<script>
|
||||
escapeHTMLandInject(`
|
||||
<div class="split-left" style="width: 80%; box-sizing: border-box; height: 150px;">
|
||||
<spine-widget
|
||||
identifier="tank2"
|
||||
atlas="assets/tank-pma.atlas"
|
||||
skeleton="assets/tank-pro.skel"
|
||||
animation="drive"
|
||||
></spine-widget>
|
||||
</div>
|
||||
|
||||
<div class="split-left" style="width: 30%; box-sizing: border-box; height: 150px;">
|
||||
<spine-widget
|
||||
identifier="tank"
|
||||
atlas="assets/tank-pma.atlas"
|
||||
skeleton="assets/tank-pro.skel"
|
||||
animation="drive"
|
||||
fit="none"
|
||||
clip="true"
|
||||
></spine-widget>
|
||||
</div>
|
||||
|
||||
...
|
||||
|
||||
(async () => {
|
||||
const tank = spine.getSpineWidget("tank");
|
||||
const tank2 = spine.getSpineWidget("tank2");
|
||||
await tank.loadingPromise;
|
||||
await tank2.loadingPromise;
|
||||
|
||||
// since we want the tank to overflow the div, we set fit to none
|
||||
// then we "sync" the tank scale to the one of the tank above
|
||||
tank.beforeUpdateWorldTransforms = (canvas, delta, skeleton, state) => {
|
||||
if (!tank.onScreen) return;
|
||||
tank.skeleton.scaleX = tank2.skeleton.scaleX;
|
||||
tank.skeleton.scaleY = tank2.skeleton.scaleY;
|
||||
}
|
||||
})();`);
|
||||
</script>
|
||||
</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// end section 8 //
|
||||
/////////////////////
|
||||
-->
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// start section 8 //
|
||||
/////////////////////
|
||||
-->
|
||||
<div id="section1" class="section vertical-split">
|
||||
|
||||
<div class="split" style="width: 100%; flex-direction: column;">
|
||||
|
||||
<div class="split-top split">
|
||||
<div class="split-left">
|
||||
<spine-widget
|
||||
atlas="assets/spineboy-pma.atlas"
|
||||
skeleton="assets/spineboy-pro.skel"
|
||||
animation="walk"
|
||||
scale="3"
|
||||
fit="none"
|
||||
clip="true"
|
||||
></spine-widget>
|
||||
</div>
|
||||
<div class="split-right">
|
||||
<spine-widget
|
||||
atlas="assets/spineboy-pma.atlas"
|
||||
skeleton="assets/spineboy-pro.skel"
|
||||
animation="walk"
|
||||
scale="1.5"
|
||||
fit="none"
|
||||
clip="true"
|
||||
></spine-widget>
|
||||
</div>
|
||||
<div class="split-right">
|
||||
<spine-widget
|
||||
atlas="assets/spineboy-pma.atlas"
|
||||
skeleton="assets/spineboy-pro.skel"
|
||||
animation="walk"
|
||||
scale="1"
|
||||
fit="none"
|
||||
clip="true"
|
||||
></spine-widget>
|
||||
</div>
|
||||
<div class="split-right">
|
||||
<spine-widget
|
||||
atlas="assets/cloud-pot-pma.atlas"
|
||||
skeleton="assets/cloud-pot.skel"
|
||||
animation="playing-in-the-rain"
|
||||
scale="0.5"
|
||||
fit="none"
|
||||
clip="true"
|
||||
></spine-widget>
|
||||
</div>
|
||||
<div class="split-right">
|
||||
<spine-widget
|
||||
identifier="celeste"
|
||||
atlas="assets/celestial-circus-pma.atlas"
|
||||
skeleton="assets/celestial-circus-pro.skel"
|
||||
animation="wings-and-feet"
|
||||
clip="true"
|
||||
></spine-widget>
|
||||
|
||||
<script>
|
||||
(async () => {
|
||||
const celeste = spine.getSpineWidget("celeste");
|
||||
await celeste.loadingPromise;
|
||||
celeste.state.setAnimation(0, "swing", true);
|
||||
})();
|
||||
</script>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="split-bottom">
|
||||
<pre><code id="code-display">
|
||||
<script>
|
||||
escapeHTMLandInject(`
|
||||
...`);
|
||||
</script>
|
||||
</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// end section 8 //
|
||||
/////////////////////
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
|
||||
1941
spine-ts/spine-webgl/example/canvas9.html
Normal file
@ -470,6 +470,17 @@ export class SceneRenderer implements Disposable {
|
||||
this.camera.update();
|
||||
}
|
||||
|
||||
resize3 (width: number, height: number) {
|
||||
console.log("resize gl")
|
||||
let canvas = this.canvas;
|
||||
const dpr = window.devicePixelRatio;
|
||||
this.canvas.width = Math.round(width * dpr);
|
||||
this.canvas.height = Math.round(height * dpr);
|
||||
this.context.gl.viewport(0, 0, canvas.width, canvas.height);
|
||||
this.camera.setViewport(canvas.width, canvas.height);
|
||||
this.camera.update();
|
||||
}
|
||||
|
||||
resize (resizeMode: ResizeMode) {
|
||||
let canvas = this.canvas;
|
||||
var dpr = window.devicePixelRatio || 1;
|
||||
|
||||
@ -36,7 +36,7 @@ interface Rectangle {
|
||||
height: number,
|
||||
}
|
||||
|
||||
type UpdateSpineFunction = (canvas: SpineCanvas, delta: number, skeleton: Skeleton, state: AnimationState) => void;
|
||||
type UpdateSpineWidgetFunction = (canvas: SpineCanvas, delta: number, skeleton: Skeleton, state: AnimationState) => void;
|
||||
|
||||
type OffScreenUpdateBehaviourType = "pause" | "update" | "pose";
|
||||
function isOffScreenUpdateBehaviourType(value: string): value is OffScreenUpdateBehaviourType {
|
||||
@ -97,6 +97,7 @@ interface WidgetInternalState {
|
||||
dragY: number
|
||||
}
|
||||
|
||||
// TODO: add missing assets to main assets folder (chibi)
|
||||
|
||||
class SpineWebComponentWidget extends HTMLElement implements WidgetLayoutOptions, WidgetInternalState, Partial<WidgetPublicState> {
|
||||
|
||||
@ -107,7 +108,9 @@ class SpineWebComponentWidget extends HTMLElement implements WidgetLayoutOptions
|
||||
public animation?: string;
|
||||
public skin?: string;
|
||||
skeletonData?: SkeletonData; // TODO
|
||||
update?: UpdateSpineFunction; // TODO
|
||||
update?: UpdateSpineWidgetFunction;
|
||||
beforeUpdateWorldTransforms: UpdateSpineWidgetFunction = () => {};
|
||||
afterUpdateWorldTransforms: UpdateSpineWidgetFunction= () => {};
|
||||
|
||||
// layout options
|
||||
public fit: FitType = "contain";
|
||||
@ -125,6 +128,7 @@ class SpineWebComponentWidget extends HTMLElement implements WidgetLayoutOptions
|
||||
public manualStart = false;
|
||||
public pages?: Array<number>;
|
||||
public offScreenUpdateBehaviour: OffScreenUpdateBehaviourType = "pause";
|
||||
public clip = false;
|
||||
|
||||
// state
|
||||
public skeleton?: Skeleton;
|
||||
@ -135,14 +139,6 @@ class SpineWebComponentWidget extends HTMLElement implements WidgetLayoutOptions
|
||||
public started = false;
|
||||
public onScreenAtLeastOnce = false;
|
||||
|
||||
// TODO tomorrow: la onScreenFunction di default carica le textures quando il widget viene rivelato sullo schermo.
|
||||
// capire se va bene come comportamento di default
|
||||
// poi spiegare i tre case
|
||||
// no manual loading, no pages: tutte le pagine vengono caricate subito
|
||||
// no manual loading, si pages: solo le pagine specificate vengono caricate subito (le altre se ne deve occupare manualmente il tizio)
|
||||
// manual loading, no pages: tutte le pagine vengono caricate solo quando il widget è nella viewport
|
||||
// manual loading, si pages: le pagine specificate vengono caricate solo quando il widget è nella viewport
|
||||
// magari capire se mettere un altro parametro, tipo: loadsOnViewport
|
||||
public onScreenFunction: (widget: SpineWebComponentWidget) => void = async (widget) => {
|
||||
if (widget.loading && !widget.onScreenAtLeastOnce) {
|
||||
widget.onScreenAtLeastOnce = true;
|
||||
@ -193,7 +189,8 @@ class SpineWebComponentWidget extends HTMLElement implements WidgetLayoutOptions
|
||||
"manual-start",
|
||||
"spinner",
|
||||
"pages",
|
||||
"offscreen"
|
||||
"offscreen",
|
||||
"clip",
|
||||
];
|
||||
}
|
||||
|
||||
@ -327,6 +324,10 @@ class SpineWebComponentWidget extends HTMLElement implements WidgetLayoutOptions
|
||||
this.manualStart = Boolean(newValue);
|
||||
}
|
||||
|
||||
if (name === "clip") {
|
||||
this.clip = Boolean(newValue);
|
||||
}
|
||||
|
||||
if (name === "pages") {
|
||||
this.pages = newValue.split(",").reduce((acc, pageIndex) => {
|
||||
const index = parseInt(pageIndex);
|
||||
@ -591,6 +592,7 @@ class SpineWebComponentOverlay extends HTMLElement {
|
||||
private resizeObserver:ResizeObserver;
|
||||
private input: Input;
|
||||
|
||||
// TODO: the canvas is now beg as the screen - maybe we can reduce the enhancement of the canvas and just translate
|
||||
// how many pixels to add to the edges to prevent "edge cuttin" on fast scrolling
|
||||
// be aware that the canvas is already big as the display size
|
||||
// making it bigger might reduce performance significantly
|
||||
@ -623,6 +625,17 @@ class SpineWebComponentOverlay extends HTMLElement {
|
||||
this.canvas.style.position = "absolute";
|
||||
this.canvas.style.top = "0";
|
||||
this.canvas.style.left = "0";
|
||||
|
||||
// sono per l'ennesima volta fermo alla dimensione del canvas.
|
||||
// purtroppo la dimensione dello schermo non permette di determinare la posizione dei div container relativamente allo schermo
|
||||
// se trovassimo un modo per farlo, sarebbe fatta. provare prima a investigare un pochino lì.
|
||||
//
|
||||
// alternativamente giocare ancora con i lvh o qualcosa del genere
|
||||
// purtroppo ho già provato un po' e si hanno oggettivamente dei brevi flash allo scroll quando la dimensione del canvas
|
||||
// ovvero quando compare o scompare la barra durante lo scroll da mobile
|
||||
|
||||
// this.canvas.style.width = "100lvw";
|
||||
// this.canvas.style.height = "120lvh";
|
||||
this.canvas.style.setProperty("pointer-events", "none");
|
||||
this.canvas.style.transform =`translate(0px,0px)`;
|
||||
// this.canvas.style.setProperty("will-change", "transform"); // performance seems to be even worse with this uncommented
|
||||
@ -675,9 +688,10 @@ class SpineWebComponentOverlay extends HTMLElement {
|
||||
const red = new Color(1, 0, 0, 1);
|
||||
const green = new Color(0, 1, 0, 1);
|
||||
const blue = new Color(0, 0, 1, 1);
|
||||
const transparentWhite = new Color(1, 1, 1, .3);
|
||||
return {
|
||||
update: (canvas: SpineCanvas, delta: number) => {
|
||||
this.skeletonList.forEach(({ skeleton, state, update, onScreen, offScreenUpdateBehaviour, skeletonPath }) => {
|
||||
this.skeletonList.forEach(({ skeleton, state, update, onScreen, offScreenUpdateBehaviour, skeletonPath, beforeUpdateWorldTransforms, afterUpdateWorldTransforms }) => {
|
||||
if (!skeleton || !state) return;
|
||||
if (!onScreen && offScreenUpdateBehaviour === "pause") return;
|
||||
if (update) update(canvas, delta, skeleton, state)
|
||||
@ -688,7 +702,9 @@ class SpineWebComponentOverlay extends HTMLElement {
|
||||
|
||||
if (onScreen || (!onScreen && offScreenUpdateBehaviour === "pose") ) {
|
||||
state.apply(skeleton);
|
||||
beforeUpdateWorldTransforms(canvas, delta, skeleton, state);
|
||||
skeleton.updateWorldTransform(Physics.update);
|
||||
afterUpdateWorldTransforms(canvas, delta, skeleton, state);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -703,67 +719,106 @@ class SpineWebComponentOverlay extends HTMLElement {
|
||||
const devicePixelRatio = window.devicePixelRatio;
|
||||
const tempVector = new Vector3();
|
||||
this.skeletonList.forEach((widget) => {
|
||||
const { skeleton, bounds, mode, debug, offsetX, offsetY, xAxis, yAxis, dragX, dragY, fit, loadingSpinner, onScreen, loading } = widget;
|
||||
const { skeleton, bounds, mode, debug, offsetX, offsetY, xAxis, yAxis, dragX, dragY, fit, loadingSpinner, onScreen, loading, clip } = widget;
|
||||
|
||||
if ((!onScreen && dragX === 0 && dragY === 0)) return;
|
||||
|
||||
const divBounds = widget.getHTMLElementReference().getBoundingClientRect();
|
||||
divBounds.x += this.overflowLeftSize;
|
||||
divBounds.y += this.overflowTopSize;
|
||||
// get the desired point into the the div (center by default) in world coordinate
|
||||
const divX = divBounds.x + divBounds.width * (xAxis + .5);
|
||||
const divY = divBounds.y + divBounds.height * (-yAxis + .5);
|
||||
this.screenToWorld(tempVector, divX, divY);
|
||||
|
||||
if (loading) {
|
||||
if (loadingSpinner) {
|
||||
if (!widget.loadingScreen) widget.loadingScreen = new LoadingScreenWidget(renderer);
|
||||
widget.loadingScreen!.draw(true, tempVector.x, tempVector.y, divBounds.width * devicePixelRatio, divBounds.height * devicePixelRatio);
|
||||
// TODO: drag does not work while clip is on
|
||||
|
||||
// TODO: now that the clip logic works, remove the code duplication
|
||||
if (clip) {
|
||||
const clipToBoundStart = (canvas: SpineCanvas, divBounds: Rectangle) => {
|
||||
const renderer = canvas.renderer;
|
||||
|
||||
// break current batch and start a new one
|
||||
renderer.end();
|
||||
|
||||
// set the new viewport to the div bound
|
||||
const viewportWidth = divBounds.width * window.devicePixelRatio;
|
||||
const viewporthHeight = divBounds.height * window.devicePixelRatio;
|
||||
canvas.gl.viewport(
|
||||
divBounds.x * window.devicePixelRatio,
|
||||
this.canvas.height - (divBounds.y + divBounds.height) * window.devicePixelRatio,
|
||||
viewportWidth,
|
||||
viewporthHeight
|
||||
);
|
||||
renderer.camera.setViewport(viewportWidth, viewporthHeight);
|
||||
renderer.camera.update();
|
||||
|
||||
// start the new batch that will be filled with only this skeleton
|
||||
renderer.begin();
|
||||
|
||||
// TODO: debug - to remove
|
||||
if (false) {
|
||||
renderer.circle(true, -viewportWidth / 2, -viewporthHeight / 2, 20, red);
|
||||
renderer.circle(true, viewportWidth / 2, -viewporthHeight / 2, 20, red);
|
||||
renderer.circle(true, -viewportWidth / 2, viewporthHeight / 2, 20, red);
|
||||
renderer.circle(true, viewportWidth / 2, viewporthHeight / 2, 20, red);
|
||||
renderer.circle(true, 0, 0, 10, red);
|
||||
|
||||
renderer.rect(true, 0, 0, -viewportWidth, -viewporthHeight, transparentWhite);
|
||||
renderer.rect(true, 0, 0, viewportWidth, viewporthHeight, transparentWhite);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (skeleton) {
|
||||
let x = tempVector.x;
|
||||
let y = tempVector.y;
|
||||
if (mode === 'inside') {
|
||||
let { x: ax, y: ay, width: aw, height: ah } = bounds!;
|
||||
const clipToBoundEnd = () => {
|
||||
// end clip batch
|
||||
renderer.end();
|
||||
|
||||
// scale ratio
|
||||
const scaleWidth = divBounds.width * devicePixelRatio / aw;
|
||||
const scaleHeight = divBounds.height * devicePixelRatio / ah;
|
||||
canvas.gl.viewport(0, 0, this.canvas.width, this.canvas.height);
|
||||
canvas.renderer.camera.setViewport(this.canvas.width, this.canvas.height);
|
||||
canvas.renderer.camera.update();
|
||||
|
||||
let ratioW = skeleton.scaleX;
|
||||
let ratioH = skeleton.scaleY;
|
||||
// start new normal batch
|
||||
renderer.begin();
|
||||
}
|
||||
|
||||
if (fit === "fill") { // Fill the target box by distorting the source's aspect ratio.
|
||||
ratioW = scaleWidth;
|
||||
ratioH = scaleHeight;
|
||||
} else if (fit === "fitWidth") {
|
||||
ratioW = scaleWidth;
|
||||
ratioH = scaleWidth;
|
||||
} else if (fit === "fitHeight") {
|
||||
ratioW = scaleHeight;
|
||||
ratioH = scaleHeight;
|
||||
} else if (fit === "contain") {
|
||||
// if scaled height is bigger than div height, use height ratio instead
|
||||
if (ah * scaleWidth > divBounds.height * devicePixelRatio){
|
||||
ratioW = scaleHeight;
|
||||
|
||||
|
||||
clipToBoundStart(canvas, divBounds)
|
||||
|
||||
|
||||
|
||||
// get the desired point into the the div (center by default) in world coordinate
|
||||
const divX = divBounds.x + divBounds.width * (xAxis + .5);
|
||||
const divY = divBounds.y + divBounds.height * (-yAxis + .5);
|
||||
this.screenToWorld(tempVector, divX, divY);
|
||||
|
||||
if (loading) {
|
||||
if (loadingSpinner) {
|
||||
if (!widget.loadingScreen) widget.loadingScreen = new LoadingScreenWidget(renderer);
|
||||
widget.loadingScreen!.draw(true, tempVector.x, tempVector.y, divBounds.width * devicePixelRatio, divBounds.height * devicePixelRatio);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (skeleton) {
|
||||
let x = tempVector.x;
|
||||
let y = tempVector.y;
|
||||
if (mode === 'inside') {
|
||||
let { x: ax, y: ay, width: aw, height: ah } = bounds!;
|
||||
|
||||
// scale ratio
|
||||
const scaleWidth = divBounds.width * devicePixelRatio / aw;
|
||||
const scaleHeight = divBounds.height * devicePixelRatio / ah;
|
||||
|
||||
let ratioW = skeleton.scaleX;
|
||||
let ratioH = skeleton.scaleY;
|
||||
|
||||
if (fit === "fill") { // Fill the target box by distorting the source's aspect ratio.
|
||||
ratioW = scaleWidth;
|
||||
ratioH = scaleHeight;
|
||||
} else {
|
||||
} else if (fit === "fitWidth") {
|
||||
ratioW = scaleWidth;
|
||||
ratioH = scaleWidth;
|
||||
}
|
||||
} else if (fit === "cover") {
|
||||
if (ah * scaleWidth < divBounds.height * devicePixelRatio){
|
||||
} else if (fit === "fitHeight") {
|
||||
ratioW = scaleHeight;
|
||||
ratioH = scaleHeight;
|
||||
} else {
|
||||
ratioW = scaleWidth;
|
||||
ratioH = scaleWidth;
|
||||
}
|
||||
} else if (fit === "scaleDown") {
|
||||
if (aw > divBounds.width * devicePixelRatio || ah > divBounds.height * devicePixelRatio) {
|
||||
} else if (fit === "contain") {
|
||||
// if scaled height is bigger than div height, use height ratio instead
|
||||
if (ah * scaleWidth > divBounds.height * devicePixelRatio){
|
||||
ratioW = scaleHeight;
|
||||
ratioH = scaleHeight;
|
||||
@ -771,66 +826,225 @@ class SpineWebComponentOverlay extends HTMLElement {
|
||||
ratioW = scaleWidth;
|
||||
ratioH = scaleWidth;
|
||||
}
|
||||
} else if (fit === "cover") {
|
||||
if (ah * scaleWidth < divBounds.height * devicePixelRatio){
|
||||
ratioW = scaleHeight;
|
||||
ratioH = scaleHeight;
|
||||
} else {
|
||||
ratioW = scaleWidth;
|
||||
ratioH = scaleWidth;
|
||||
}
|
||||
} else if (fit === "scaleDown") {
|
||||
if (aw > divBounds.width * devicePixelRatio || ah > divBounds.height * devicePixelRatio) {
|
||||
if (ah * scaleWidth > divBounds.height * devicePixelRatio){
|
||||
ratioW = scaleHeight;
|
||||
ratioH = scaleHeight;
|
||||
} else {
|
||||
ratioW = scaleWidth;
|
||||
ratioH = scaleWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get the center of the bounds
|
||||
const boundsX = (ax + aw / 2) * ratioW;
|
||||
const boundsY = (ay + ah / 2) * ratioH;
|
||||
|
||||
// get vertices offset: calculate the distance between div center and bounds center
|
||||
x = - boundsX;
|
||||
y = - boundsY;
|
||||
|
||||
if (fit !== "none") {
|
||||
// scale the skeleton
|
||||
skeleton.scaleX = ratioW;
|
||||
skeleton.scaleY = ratioH;
|
||||
skeleton.updateWorldTransform(Physics.update);
|
||||
}
|
||||
}
|
||||
|
||||
// get the center of the bounds
|
||||
const boundsX = (ax + aw / 2) * ratioW;
|
||||
const boundsY = (ay + ah / 2) * ratioH;
|
||||
widget.worldOffsetX = x + offsetX + dragX;
|
||||
widget.worldOffsetY = y + offsetY + dragY;
|
||||
|
||||
// get vertices offset: calculate the distance between div center and bounds center
|
||||
x = tempVector.x - boundsX;
|
||||
y = tempVector.y - boundsY;
|
||||
renderer.drawSkeleton(skeleton, true, -1, -1, (vertices, size, vertexSize) => {
|
||||
for (let i = 0; i < size; i+=vertexSize) {
|
||||
vertices[i] = vertices[i] + widget.worldOffsetX;
|
||||
vertices[i+1] = vertices[i+1] + widget.worldOffsetY;
|
||||
}
|
||||
});
|
||||
|
||||
if (fit !== "none") {
|
||||
// scale the skeleton
|
||||
skeleton.scaleX = ratioW;
|
||||
skeleton.scaleY = ratioH;
|
||||
skeleton.updateWorldTransform(Physics.update);
|
||||
// drawing debug stuff
|
||||
if (debug) {
|
||||
// if (true) {
|
||||
let { x: ax, y: ay, width: aw, height: ah } = bounds!;
|
||||
|
||||
// show bounds and its center
|
||||
renderer.rect(false,
|
||||
ax * skeleton.scaleX + widget.worldOffsetX,
|
||||
ay * skeleton.scaleY + widget.worldOffsetY,
|
||||
aw * skeleton.scaleX,
|
||||
ah * skeleton.scaleY,
|
||||
blue);
|
||||
const bbCenterX = (ax + aw / 2) * skeleton.scaleX + widget.worldOffsetX;
|
||||
const bbCenterY = (ay + ah / 2) * skeleton.scaleY + widget.worldOffsetY;
|
||||
renderer.circle(true, bbCenterX, bbCenterY, 10, blue);
|
||||
|
||||
// show skeleton root
|
||||
const root = skeleton.getRootBone()!;
|
||||
renderer.circle(true, root.x + widget.worldOffsetX, root.y + widget.worldOffsetY, 10, red);
|
||||
|
||||
// show shifted origin
|
||||
const originX = widget.worldOffsetX - dragX - offsetX;
|
||||
const originY = widget.worldOffsetY - dragY - offsetY;
|
||||
renderer.circle(true, originX, originY, 10, green);
|
||||
|
||||
// show line from origin to bounds center
|
||||
renderer.line(originX, originY, bbCenterX, bbCenterY, green);
|
||||
}
|
||||
}
|
||||
|
||||
widget.worldOffsetX = x + offsetX + dragX;
|
||||
widget.worldOffsetY = y + offsetY + dragY;
|
||||
|
||||
renderer.drawSkeleton(skeleton, true, -1, -1, (vertices, size, vertexSize) => {
|
||||
// console.log(vertices[0])
|
||||
for (let i = 0; i < size; i+=vertexSize) {
|
||||
vertices[i] = vertices[i] + widget.worldOffsetX;
|
||||
vertices[i+1] = vertices[i+1] + widget.worldOffsetY;
|
||||
}
|
||||
});
|
||||
|
||||
// drawing debug stuff
|
||||
if (debug) {
|
||||
// if (true) {
|
||||
let { x: ax, y: ay, width: aw, height: ah } = bounds!;
|
||||
clipToBoundEnd();
|
||||
|
||||
// show bounds and its center
|
||||
renderer.rect(false,
|
||||
ax * skeleton.scaleX + widget.worldOffsetX,
|
||||
ay * skeleton.scaleY + widget.worldOffsetY,
|
||||
aw * skeleton.scaleX,
|
||||
ah * skeleton.scaleY,
|
||||
blue);
|
||||
const bbCenterX = (ax + aw / 2) * skeleton.scaleX + widget.worldOffsetX;
|
||||
const bbCenterY = (ay + ah / 2) * skeleton.scaleY + widget.worldOffsetY;
|
||||
renderer.circle(true, bbCenterX, bbCenterY, 10, blue);
|
||||
|
||||
// show skeleton root
|
||||
const root = skeleton.getRootBone()!;
|
||||
renderer.circle(true, root.x + widget.worldOffsetX, root.y + widget.worldOffsetY, 10, red);
|
||||
|
||||
// show shifted origin
|
||||
const originX = widget.worldOffsetX - dragX - offsetX;
|
||||
const originY = widget.worldOffsetY - dragY - offsetY;
|
||||
renderer.circle(true, originX, originY, 10, green);
|
||||
|
||||
// show line from origin to bounds center
|
||||
renderer.line(originX, originY, bbCenterX, bbCenterY, green);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
else {
|
||||
|
||||
|
||||
// get the desired point into the the div (center by default) in world coordinate
|
||||
const divX = divBounds.x + divBounds.width * (xAxis + .5);
|
||||
const divY = divBounds.y + divBounds.height * (-yAxis + .5);
|
||||
this.screenToWorld(tempVector, divX, divY);
|
||||
|
||||
if (loading) {
|
||||
if (loadingSpinner) {
|
||||
if (!widget.loadingScreen) widget.loadingScreen = new LoadingScreenWidget(renderer);
|
||||
widget.loadingScreen!.draw(true, tempVector.x, tempVector.y, divBounds.width * devicePixelRatio, divBounds.height * devicePixelRatio);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (skeleton) {
|
||||
let x = tempVector.x;
|
||||
let y = tempVector.y;
|
||||
if (mode === 'inside') {
|
||||
let { x: ax, y: ay, width: aw, height: ah } = bounds!;
|
||||
|
||||
// scale ratio
|
||||
const scaleWidth = divBounds.width * devicePixelRatio / aw;
|
||||
const scaleHeight = divBounds.height * devicePixelRatio / ah;
|
||||
|
||||
let ratioW = skeleton.scaleX;
|
||||
let ratioH = skeleton.scaleY;
|
||||
|
||||
if (fit === "fill") { // Fill the target box by distorting the source's aspect ratio.
|
||||
ratioW = scaleWidth;
|
||||
ratioH = scaleHeight;
|
||||
} else if (fit === "fitWidth") {
|
||||
ratioW = scaleWidth;
|
||||
ratioH = scaleWidth;
|
||||
} else if (fit === "fitHeight") {
|
||||
ratioW = scaleHeight;
|
||||
ratioH = scaleHeight;
|
||||
} else if (fit === "contain") {
|
||||
// if scaled height is bigger than div height, use height ratio instead
|
||||
if (ah * scaleWidth > divBounds.height * devicePixelRatio){
|
||||
ratioW = scaleHeight;
|
||||
ratioH = scaleHeight;
|
||||
} else {
|
||||
ratioW = scaleWidth;
|
||||
ratioH = scaleWidth;
|
||||
}
|
||||
} else if (fit === "cover") {
|
||||
if (ah * scaleWidth < divBounds.height * devicePixelRatio){
|
||||
ratioW = scaleHeight;
|
||||
ratioH = scaleHeight;
|
||||
} else {
|
||||
ratioW = scaleWidth;
|
||||
ratioH = scaleWidth;
|
||||
}
|
||||
} else if (fit === "scaleDown") {
|
||||
if (aw > divBounds.width * devicePixelRatio || ah > divBounds.height * devicePixelRatio) {
|
||||
if (ah * scaleWidth > divBounds.height * devicePixelRatio){
|
||||
ratioW = scaleHeight;
|
||||
ratioH = scaleHeight;
|
||||
} else {
|
||||
ratioW = scaleWidth;
|
||||
ratioH = scaleWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get the center of the bounds
|
||||
const boundsX = (ax + aw / 2) * ratioW;
|
||||
const boundsY = (ay + ah / 2) * ratioH;
|
||||
|
||||
// get vertices offset: calculate the distance between div center and bounds center
|
||||
x = tempVector.x - boundsX;
|
||||
y = tempVector.y - boundsY;
|
||||
|
||||
if (fit !== "none") {
|
||||
// scale the skeleton
|
||||
skeleton.scaleX = ratioW;
|
||||
skeleton.scaleY = ratioH;
|
||||
skeleton.updateWorldTransform(Physics.update);
|
||||
}
|
||||
}
|
||||
|
||||
widget.worldOffsetX = x + offsetX + dragX;
|
||||
widget.worldOffsetY = y + offsetY + dragY;
|
||||
|
||||
renderer.drawSkeleton(skeleton, true, -1, -1, (vertices, size, vertexSize) => {
|
||||
for (let i = 0; i < size; i+=vertexSize) {
|
||||
vertices[i] = vertices[i] + widget.worldOffsetX;
|
||||
vertices[i+1] = vertices[i+1] + widget.worldOffsetY;
|
||||
}
|
||||
});
|
||||
|
||||
// drawing debug stuff
|
||||
if (debug) {
|
||||
// if (true) {
|
||||
let { x: ax, y: ay, width: aw, height: ah } = bounds!;
|
||||
|
||||
// show bounds and its center
|
||||
renderer.rect(false,
|
||||
ax * skeleton.scaleX + widget.worldOffsetX,
|
||||
ay * skeleton.scaleY + widget.worldOffsetY,
|
||||
aw * skeleton.scaleX,
|
||||
ah * skeleton.scaleY,
|
||||
blue);
|
||||
const bbCenterX = (ax + aw / 2) * skeleton.scaleX + widget.worldOffsetX;
|
||||
const bbCenterY = (ay + ah / 2) * skeleton.scaleY + widget.worldOffsetY;
|
||||
renderer.circle(true, bbCenterX, bbCenterY, 10, blue);
|
||||
|
||||
// show skeleton root
|
||||
const root = skeleton.getRootBone()!;
|
||||
renderer.circle(true, root.x + widget.worldOffsetX, root.y + widget.worldOffsetY, 10, red);
|
||||
|
||||
// show shifted origin
|
||||
const originX = widget.worldOffsetX - dragX - offsetX;
|
||||
const originY = widget.worldOffsetY - dragY - offsetY;
|
||||
renderer.circle(true, originX, originY, 10, green);
|
||||
|
||||
// show line from origin to bounds center
|
||||
renderer.line(originX, originY, bbCenterX, bbCenterY, green);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
renderer.end();
|
||||
@ -946,14 +1160,10 @@ class SpineWebComponentOverlay extends HTMLElement {
|
||||
|
||||
const totalWidth = width * (1 + (this.overflowLeft + this.overflowRight));
|
||||
const totalHeight = height * (1 + (this.overflowTop + this.overflowBottom));
|
||||
|
||||
this.canvas.style.width = totalWidth + "px";
|
||||
this.canvas.style.height = totalHeight + "px";
|
||||
|
||||
const dpr = window.devicePixelRatio;
|
||||
this.canvas.width = Math.round(totalWidth * dpr);
|
||||
this.canvas.height = Math.round(totalHeight * dpr);
|
||||
|
||||
this.spineCanvas.renderer.resize2();
|
||||
this.spineCanvas.renderer.resize3(totalWidth, totalHeight);
|
||||
}
|
||||
}
|
||||
|
||||
@ -981,6 +1191,12 @@ class SpineWebComponentOverlay extends HTMLElement {
|
||||
skeleton.scaleX = skeleton.scaleX / widget.currentScaleDpi * scale;
|
||||
skeleton.scaleY = skeleton.scaleY / widget.currentScaleDpi * scale;
|
||||
widget.currentScaleDpi = scale;
|
||||
|
||||
// TODO: improve this horrible thing
|
||||
this.spineCanvas.renderer.resize3(
|
||||
+this.canvas.style.width.substring(0, this.canvas.style.width.length - 2),
|
||||
+this.canvas.style.height.substring(0, this.canvas.style.height.length - 2),
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
|
||||