Compare commits
1022 Commits
master
...
dev_hero_2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
14ef8d0dc1 | ||
| 6ccc61ca53 | |||
|
|
cc1aa512cd | ||
|
|
7da8cfde40 | ||
|
|
9f9f934b37 | ||
|
|
34e776341c | ||
|
|
96e2f12c19 | ||
|
|
d3eb50711e | ||
|
|
4d0109e170 | ||
|
|
a95682f7ef | ||
|
|
f5e11bdc96 | ||
|
|
34706e809c | ||
|
|
395ef6b9d1 | ||
|
|
6308e200ae | ||
|
|
40d8fbf1e4 | ||
|
|
760af76761 | ||
|
|
35804958f2 | ||
|
|
d3a42f2d27 | ||
|
|
fa1731af65 | ||
|
|
9a17b669ac | ||
|
|
4d33e204f1 | ||
|
|
0e2ce1cace | ||
|
|
511e5078f4 | ||
|
|
b260addf3c | ||
|
|
359ec4a3cc | ||
|
|
77f9bf34c4 | ||
|
|
0beba55d2f | ||
|
|
fc2b3e00b5 | ||
|
|
5c9d1ed228 | ||
|
|
10dfc3149f | ||
|
|
260cde4715 | ||
|
|
dab89f6728 | ||
|
|
932eaf1f96 | ||
|
|
6589e8ed71 | ||
|
|
44d542d44a | ||
|
|
90e38566e9 | ||
|
|
d1c638462f | ||
|
|
1fda830542 | ||
|
|
5653c7e918 | ||
|
|
5663c1ac38 | ||
|
|
cbc90b9df1 | ||
|
|
cc441308b4 | ||
|
|
d015c8ff14 | ||
|
|
e4837e3f73 | ||
|
|
db84769efd | ||
|
|
8d32bd3c9b | ||
|
|
ac79c3a521 | ||
|
|
e89fe8bcf8 | ||
|
|
51e8b73f51 | ||
|
|
96dbef0a3a | ||
|
|
a2ea591c82 | ||
|
|
071af307ab | ||
|
|
dca1c42a33 | ||
|
|
e435ddc3b4 | ||
|
|
4efa87d9a9 | ||
|
|
6790fc508a | ||
|
|
cb6589ece4 | ||
|
|
0c52d1da0c | ||
|
|
20fa27ac2f | ||
|
|
ce1b168e09 | ||
|
|
15cc99eb34 | ||
|
|
74cad70154 | ||
|
|
73bbe304cc | ||
|
|
0ae3b73863 | ||
|
|
3109e57735 | ||
|
|
54a49eb0ab | ||
|
|
835e70e16d | ||
|
|
047c1a34f3 | ||
|
|
1a9a8f0632 | ||
|
|
22ea8bbea0 | ||
|
|
31a67ecc20 | ||
|
|
64bc1ddc83 | ||
|
|
78b3e35b8f | ||
|
|
c0fac6edf2 | ||
|
|
a4befbd41f | ||
|
|
6565e05d5a | ||
|
|
b9a52ed973 | ||
|
|
76b17ad3e6 | ||
|
|
edcfc2edde | ||
|
|
fde6c87a2b | ||
|
|
71dbedf9da | ||
|
|
31f4399df1 | ||
|
|
af0f7be205 | ||
|
|
bca7dfb3a1 | ||
|
|
7f5194d192 | ||
|
|
068f382c47 | ||
|
|
0b5888e268 | ||
|
|
e84346116b | ||
|
|
9e6146fce1 | ||
|
|
3c445a7572 | ||
|
|
cc6f58cc39 | ||
|
|
2e79493e48 | ||
|
|
82c88440fa | ||
|
|
65a1f43e6b | ||
|
|
99698904cb | ||
|
|
407df4f874 | ||
|
|
21dc13c024 | ||
|
|
43565d918e | ||
|
|
8ce6e84459 | ||
|
|
ac0c17307d | ||
|
|
405b5e5a2d | ||
|
|
02588a83fb | ||
|
|
40045cc7e6 | ||
|
|
0b0efd278c | ||
|
|
19533189dd | ||
|
|
d4839a56d7 | ||
|
|
282b5a9eea | ||
|
|
b913aa2870 | ||
|
|
0d0f55d9e4 | ||
|
|
478db2f30d | ||
|
|
d9d75cca2b | ||
|
|
fac7fa6812 | ||
|
|
0641a93040 | ||
|
|
6a04896a5f | ||
|
|
1841186071 | ||
|
|
9f3cffab69 | ||
|
|
834a29e5e7 | ||
|
|
d7964113c3 | ||
|
|
887eb5a9c0 | ||
|
|
3448608f15 | ||
|
|
bbd66e3e00 | ||
|
|
befedf64ec | ||
|
|
5386c24504 | ||
|
|
d686512f63 | ||
|
|
8adf53316b | ||
|
|
b92e5b89ec | ||
|
|
3ced501994 | ||
|
|
3093ef4090 | ||
|
|
df95c52b96 | ||
|
|
6d73ccff00 | ||
|
|
66232f5e98 | ||
|
|
950316ee4b | ||
|
|
39388fd074 | ||
|
|
51b6713b1e | ||
|
|
47fdba73ae | ||
|
|
03cb55a053 | ||
|
|
9b92dfe59c | ||
|
|
6824f0a4ad | ||
|
|
1de3560cbe | ||
|
|
b30f3c7f8e | ||
|
|
0e69e79e7c | ||
|
|
fbb3b526ba | ||
|
|
28dc4d0547 | ||
|
|
f8cd5af72d | ||
|
|
c0d9bde0e3 | ||
|
|
cbce1e763f | ||
|
|
989528fb19 | ||
|
|
bfb73d847f | ||
|
|
9d793b77d8 | ||
|
|
e16ec04399 | ||
|
|
e47b25c768 | ||
|
|
ed24e15ec9 | ||
|
|
451fd0ce81 | ||
|
|
ed413b1ec4 | ||
|
|
8d091709e0 | ||
|
|
71f7222f0a | ||
|
|
dee9d7cc12 | ||
|
|
cfbf191f67 | ||
|
|
590c1e7488 | ||
|
|
f07dc748bc | ||
|
|
ba50a1f1e0 | ||
|
|
0a117db90e | ||
|
|
735742b767 | ||
|
|
5123b7984e | ||
|
|
f235f33dea | ||
|
|
c6877c6828 | ||
|
|
70c510cbbf | ||
|
|
2c04d8d58f | ||
|
|
54d434e7f5 | ||
|
|
4718cc678c | ||
|
|
90cfba07ec | ||
|
|
ea9e7bed20 | ||
|
|
8e10a42a76 | ||
|
|
89759c494f | ||
|
|
76f1bc51ad | ||
|
|
7346cfbd67 | ||
|
|
5cfff8f347 | ||
|
|
6761b1ba0a | ||
|
|
aef5a9a65e | ||
|
|
4be4b62167 | ||
|
|
4394a1e3e2 | ||
|
|
fe53bb012b | ||
|
|
9686b4b97d | ||
|
|
486b5100ac | ||
|
|
208febb5b3 | ||
|
|
651c281c2f | ||
|
|
940340cef8 | ||
|
|
b74e4e435b | ||
|
|
eb4b1152a0 | ||
|
|
3fb0e3c90a | ||
|
|
4cebc4b154 | ||
|
|
ac12bc45c4 | ||
|
|
7150d872cf | ||
|
|
49cf038bdb | ||
|
|
c1ca37bda5 | ||
|
|
4944275cff | ||
|
|
8511e51c00 | ||
|
|
0d26fd250e | ||
|
|
fa630edd73 | ||
|
|
602c93913c | ||
|
|
bad9f48449 | ||
|
|
35dc7f578d | ||
|
|
14d5d42d08 | ||
|
|
7179ed8418 | ||
|
|
cce578bee9 | ||
|
|
67efcf901b | ||
|
|
48d81e5ba5 | ||
|
|
7787a00ee1 | ||
|
|
699e392036 | ||
|
|
c932ccaba6 | ||
|
|
8109001683 | ||
|
|
5d44b88212 | ||
|
|
993d54f500 | ||
|
|
6493b5c699 | ||
|
|
3dc8c37011 | ||
|
|
db8e86b49d | ||
|
|
d8fb97368a | ||
|
|
2ef607f0ab | ||
|
|
ce6f7a090b | ||
|
|
a2d36fb396 | ||
|
|
aa4f2bba5f | ||
|
|
1e8e9cc8f0 | ||
|
|
f2a2650f38 | ||
|
|
f0d7cabc29 | ||
|
|
cdae7019c7 | ||
|
|
e685c77351 | ||
|
|
95851df2af | ||
|
|
639ceeb387 | ||
|
|
275bca1375 | ||
|
|
9886fc088c | ||
|
|
f1410a4f58 | ||
|
|
7d62cb408e | ||
|
|
97b91ec0d9 | ||
|
|
513ee323df | ||
|
|
6f3d42635e | ||
|
|
265b5474e1 | ||
|
|
b727316a77 | ||
|
|
598f288902 | ||
|
|
31be75d787 | ||
|
|
a6d99ba19b | ||
|
|
5f867a9a84 | ||
|
|
a572fe571d | ||
|
|
d51954e25f | ||
|
|
1e99c284b0 | ||
|
|
46b11ccf9e | ||
|
|
c40bb80cca | ||
|
|
2dc4bdae98 | ||
|
|
418dd48412 | ||
|
|
0e44ceaff7 | ||
|
|
f27864d87e | ||
|
|
7dfed34849 | ||
|
|
5d5fd03238 | ||
|
|
9d1e561916 | ||
|
|
c26a8289be | ||
|
|
fc2bc97405 | ||
|
|
ab66a2dd52 | ||
|
|
6448443c0f | ||
|
|
049a754327 | ||
|
|
5d8bf297e8 | ||
|
|
6b062362f2 | ||
|
|
965b98f0a8 | ||
|
|
2ed2daabf2 | ||
|
|
79d68e8caf | ||
|
|
7ecf780dab | ||
|
|
7116c6a74a | ||
|
|
79c7a15552 | ||
|
|
a91941b139 | ||
|
|
11a4631d28 | ||
|
|
7d761de229 | ||
|
|
c9f22e7671 | ||
|
|
8570d9dd2d | ||
|
|
b53e9b037e | ||
|
|
53bd3da968 | ||
|
|
8f20ac7cb0 | ||
|
|
7a4e927513 | ||
|
|
24901b3966 | ||
|
|
3943be89c5 | ||
|
|
ccd96db341 | ||
|
|
9b7fe04959 | ||
|
|
add4dcaa57 | ||
|
|
17510ca30c | ||
|
|
284aed53e3 | ||
|
|
b18bb603cc | ||
|
|
44531ae9f9 | ||
|
|
66157b5c7d | ||
|
|
c09deb3f35 | ||
|
|
9dae3eb965 | ||
|
|
55449888a4 | ||
|
|
3d534e7523 | ||
|
|
56bbcacc2b | ||
|
|
f4387fca51 | ||
|
|
fe31d8da1b | ||
|
|
4142eabe88 | ||
|
|
bc524cbb10 | ||
|
|
7eb00e61fa | ||
|
|
1aa646ca37 | ||
|
|
6100bcc988 | ||
|
|
d5c3de2bcb | ||
|
|
a3a918ec95 | ||
|
|
8803fe5ee4 | ||
|
|
fc43266090 | ||
|
|
caf7e428b7 | ||
|
|
230d4e21a6 | ||
|
|
bc16ece6d7 | ||
|
|
974db01487 | ||
|
|
6c75f30ffe | ||
|
|
29ded94b59 | ||
|
|
b8b1b86fbb | ||
|
|
455e71bf7a | ||
|
|
ac16f8d0d2 | ||
|
|
120d0079ec | ||
|
|
e5f914814d | ||
|
|
2065c73a5c | ||
|
|
c450235ffd | ||
|
|
a500c79107 | ||
|
|
41af84e469 | ||
|
|
7710ffac6b | ||
|
|
70083216c3 | ||
|
|
fb15192cb0 | ||
|
|
b845ca91b3 | ||
|
|
3427faf4bb | ||
|
|
3ea8d17837 | ||
|
|
0e41adbf6d | ||
|
|
b4d109fbc7 | ||
|
|
bc9bfbac0c | ||
|
|
440c601b7b | ||
|
|
1cda0abb3f | ||
|
|
2c4fe56d6c | ||
|
|
e630c77bb0 | ||
|
|
9f533f4da1 | ||
|
|
328dd55733 | ||
|
|
401b940473 | ||
|
|
2c9685502c | ||
|
|
194e1cb608 | ||
|
|
55296e95da | ||
|
|
1c96c3a82f | ||
|
|
6f4a85dd25 | ||
|
|
2ee6438cfc | ||
|
|
6da425e8c2 | ||
|
|
21b74b519c | ||
|
|
b01520ead7 | ||
|
|
9202d9c83b | ||
|
|
9a25a6dd90 | ||
|
|
10b5e282f7 | ||
|
|
24c73e4b5f | ||
|
|
ec76fd9ad9 | ||
|
|
f841ca153f | ||
|
|
dacb122526 | ||
|
|
454bdf3755 | ||
|
|
85fa456381 | ||
|
|
53d965aebc | ||
|
|
29eddc6688 | ||
|
|
7817465e42 | ||
|
|
a6a7f6b75a | ||
|
|
1387150aa7 | ||
|
|
bce3ff4452 | ||
|
|
ab5b4ce521 | ||
|
|
802e756db3 | ||
|
|
6d5a74b44c | ||
|
|
1f90462c46 | ||
|
|
f75e0fccf6 | ||
|
|
21b55ec9b6 | ||
|
|
e7a00cd1e4 | ||
|
|
1b10f1854f | ||
|
|
3a0e919426 | ||
|
|
c623b9f038 | ||
|
|
d527822974 | ||
|
|
3a3ab128ab | ||
|
|
dfd5a42748 | ||
|
|
077a4d0f14 | ||
|
|
e32c238a90 | ||
|
|
40bb3b0c0f | ||
|
|
5935f650b8 | ||
|
|
80db106cd1 | ||
|
|
c1e793fbe3 | ||
|
|
39878f292c | ||
|
|
7b5d3c5836 | ||
|
|
f8e5991c68 | ||
|
|
190d53f430 | ||
|
|
9708208fd5 | ||
|
|
58bc0cc529 | ||
|
|
961fbf6146 | ||
|
|
2659d9950c | ||
|
|
5bd296efe4 | ||
|
|
35e2a37420 | ||
|
|
f78071e910 | ||
|
|
a3771c610b | ||
|
|
ddb9b12654 | ||
|
|
49e7708675 | ||
|
|
2ac928f6a2 | ||
|
|
8dfc52ced1 | ||
|
|
93065c8a00 | ||
|
|
d9cbbb3337 | ||
|
|
271308d569 | ||
|
|
572ea3e46e | ||
|
|
c01bb6dd49 | ||
|
|
46b4b73cda | ||
|
|
92ff9e6393 | ||
|
|
1a89a7e49a | ||
|
|
743d0f097b | ||
|
|
033bdbf11f | ||
|
|
e0d20294fe | ||
|
|
d6ea584023 | ||
|
|
d161fac759 | ||
|
|
b95a8b1378 | ||
|
|
f04c3f44e9 | ||
|
|
007dbf7d4f | ||
|
|
ddcb2c72f0 | ||
|
|
4fc4b6b23e | ||
|
|
4aa2e6f2a7 | ||
|
|
7b6ede56cc | ||
|
|
614909a19f | ||
|
|
8060568ced | ||
|
|
cd4622580a | ||
|
|
9c290fa178 | ||
|
|
5f4f6087d2 | ||
|
|
9858563402 | ||
|
|
479c5976ec | ||
|
|
603a25ed57 | ||
|
|
6fc419c7ce | ||
|
|
c819d7ce8a | ||
|
|
7b4916851e | ||
|
|
2a6bdfd66e | ||
|
|
23ac799d02 | ||
|
|
e911269404 | ||
|
|
e57618f534 | ||
|
|
d8249cc3ac | ||
|
|
bb804e059a | ||
|
|
778505742a | ||
|
|
c3ce4f0615 | ||
|
|
c1e72278f0 | ||
|
|
a1b4dbb1b4 | ||
|
|
b5981bae15 | ||
|
|
f93e31fb95 | ||
|
|
20d555500d | ||
|
|
58b59379d9 | ||
|
|
dc4c1fc49e | ||
|
|
e10aa91ae9 | ||
|
|
6a5c903e48 | ||
|
|
4369ed4075 | ||
|
|
d906155c9c | ||
|
|
0ac2b10096 | ||
|
|
d2005a212d | ||
|
|
e91c3d797d | ||
|
|
eddc613d25 | ||
|
|
fd05b716a9 | ||
|
|
cdce72b7a2 | ||
|
|
9e5acb67ed | ||
|
|
425ea3ec56 | ||
|
|
e3fc446960 | ||
|
|
38345d5909 | ||
|
|
776b6ae29f | ||
|
|
1c5b577038 | ||
|
|
18296991a2 | ||
|
|
955d7cca3f | ||
|
|
4c7e7aaf78 | ||
|
|
d3e870351b | ||
|
|
cfed0a625f | ||
|
|
6f7a26f595 | ||
|
|
365ae2a618 | ||
|
|
d2ac016e74 | ||
|
|
08d3ed2d7e | ||
|
|
8ae9b1c288 | ||
|
|
87b4c11a9c | ||
|
|
aa3cd49667 | ||
|
|
060dcda776 | ||
|
|
72123ff72e | ||
|
|
ad6cc54cfa | ||
|
|
a7d661556a | ||
|
|
6423f40b58 | ||
|
|
6d5086d5e6 | ||
|
|
be9a8be241 | ||
|
|
aa2648ce08 | ||
|
|
dee92b0594 | ||
|
|
65574eecaa | ||
|
|
db1f0229db | ||
|
|
b527d23e44 | ||
|
|
25d14cf9c2 | ||
|
|
689e1a7ef3 | ||
|
|
7edaf6ccc0 | ||
|
|
9cef0fd55f | ||
|
|
fb6c741cc1 | ||
|
|
a831629459 | ||
|
|
5200466331 | ||
|
|
34518800c4 | ||
|
|
c4b592025d | ||
|
|
2278d90172 | ||
|
|
5ef5298243 | ||
|
|
989d1601eb | ||
|
|
0c1b99ad82 | ||
|
|
026fbcc5c4 | ||
|
|
ac5b0c44fa | ||
|
|
545a879fa3 | ||
|
|
5f1b5b34bd | ||
|
|
e7e0bde881 | ||
|
|
e36dd5e583 | ||
|
|
21b5b2b20a | ||
|
|
2647f6925d | ||
|
|
aa340aae4f | ||
|
|
83f941496d | ||
|
|
3598a27b56 | ||
|
|
691bd7cccb | ||
|
|
e0e35ed993 | ||
|
|
0301b00a7d | ||
|
|
a8fc5ea363 | ||
|
|
08cc62b173 | ||
|
|
1c080a08b2 | ||
|
|
73230eef02 | ||
|
|
00845e9738 | ||
|
|
c06f88f8dc | ||
|
|
fb20918bc6 | ||
|
|
50a42a6219 | ||
|
|
4af4b48bca | ||
|
|
603f289cb9 | ||
|
|
85906420c5 | ||
|
|
447a5364dc | ||
|
|
b65a6adc2d | ||
|
|
5f9e2bf603 | ||
|
|
4a8cd3fb1c | ||
|
|
35e73dfc1a | ||
|
|
3d26181207 | ||
|
|
c8d0e2b3c5 | ||
|
|
5873842dae | ||
|
|
7a4cbe79d8 | ||
|
|
31ae34260e | ||
|
|
63ad8832a9 | ||
|
|
2751a48575 | ||
|
|
f03d3de706 | ||
|
|
18096ad14d | ||
|
|
88cee05344 | ||
|
|
6d52fa22c1 | ||
|
|
6f0d6c4eba | ||
|
|
4de0784535 | ||
|
|
f981f0b664 | ||
|
|
44326ddfa0 | ||
|
|
8d621fabe4 | ||
|
|
ec09ae2a0f | ||
|
|
5f766555a7 | ||
|
|
303fb3fef2 | ||
|
|
f250b2c03f | ||
|
|
ab71cd250c | ||
|
|
06261d6465 | ||
|
|
b492e287e4 | ||
|
|
b1b42d5258 | ||
|
|
dbd220fcfc | ||
|
|
04ecb7b08c | ||
|
|
1fc0cbe7b1 | ||
|
|
974e8d2337 | ||
|
|
03cf4e1843 | ||
|
|
d65af7f268 | ||
|
|
dbdaff5f3c | ||
|
|
2483e8bdd4 | ||
|
|
049d79f8dc | ||
|
|
dcc9d416c5 | ||
|
|
b9b7cc1c74 | ||
|
|
ceb9317d64 | ||
|
|
2089171f80 | ||
|
|
7adbf9e3c4 | ||
|
|
f4f0111fa9 | ||
|
|
72ba48e7d1 | ||
|
|
562be8071c | ||
|
|
15f7e7eaf0 | ||
|
|
f11022dc96 | ||
|
|
9627e10463 | ||
|
|
13e846a688 | ||
|
|
af88eb3db9 | ||
|
|
8fb94acaa6 | ||
|
|
797d32155c | ||
|
|
51a75c0906 | ||
|
|
eaee735bff | ||
|
|
5ab0b5f1ab | ||
|
|
991d7f52bb | ||
|
|
defa53883f | ||
|
|
ee14aded6a | ||
|
|
558cfdf2d8 | ||
|
|
9ae7ab2790 | ||
|
|
78af86e37e | ||
|
|
986d295fbe | ||
|
|
bb92d5a24e | ||
|
|
42a58102c4 | ||
|
|
7bec44980b | ||
|
|
64351e1f6b | ||
|
|
9ebcf06b5a | ||
|
|
6262219db6 | ||
|
|
40a48df785 | ||
|
|
c10d5817a0 | ||
|
|
a6dbfc3fa9 | ||
|
|
9ddc8a6c1b | ||
|
|
646cb07192 | ||
|
|
beb9547565 | ||
|
|
f2717b72e9 | ||
|
|
e8842259b6 | ||
|
|
311c587ddd | ||
|
|
6b828c55c0 | ||
|
|
ca872ddab7 | ||
|
|
80edb5a22f | ||
|
|
8f06da008b | ||
|
|
b146f13e91 | ||
|
|
7db1817bf3 | ||
|
|
6bf327ccb7 | ||
|
|
71f4564255 | ||
|
|
3a6e7f9a7c | ||
|
|
fcb5091001 | ||
|
|
aac1a5d5ad | ||
|
|
d3c630ec8e | ||
|
|
fb70f96ed3 | ||
|
|
7a4a8b8f8c | ||
|
|
be828e96cf | ||
|
|
77fc58e672 | ||
|
|
104a6d1bf5 | ||
|
|
748d55bab5 | ||
|
|
dd09e4228b | ||
|
|
8515c13f92 | ||
|
|
efc5900332 | ||
|
|
9a880a3cce | ||
|
|
22d3603f19 | ||
|
|
448becfe4b | ||
|
|
c01ed07ef7 | ||
|
|
3d3d774273 | ||
|
|
5c7be3141e | ||
|
|
8a50d3a5a1 | ||
|
|
a525866905 | ||
|
|
b2a21397d8 | ||
|
|
d05efd7327 | ||
|
|
45835b8706 | ||
|
|
2ccda92192 | ||
|
|
110bc8ba88 | ||
|
|
e9244a90d1 | ||
|
|
a25afdb9dd | ||
|
|
4bfc954ae4 | ||
|
|
953112ed88 | ||
|
|
43a4a54ea6 | ||
|
|
4fd0f4a6d0 | ||
|
|
418d5780bf | ||
|
|
2df5ba26fd | ||
|
|
98cc05b3cc | ||
|
|
65e9cee902 | ||
|
|
008fc9eddf | ||
|
|
49f697de6e | ||
|
|
ef470b60db | ||
|
|
079c1b21f6 | ||
|
|
6488cf581a | ||
|
|
10e8dbb255 | ||
|
|
cd70a96e95 | ||
|
|
7a4275a1c9 | ||
|
|
f154548f34 | ||
|
|
4cf4604a70 | ||
|
|
fc9122f77f | ||
|
|
d193c93fd0 | ||
|
|
0e339930f0 | ||
|
|
4fbafb72c8 | ||
|
|
8cb98ac1c9 | ||
|
|
07e5f3b31f | ||
|
|
d46cea8ec3 | ||
|
|
287f858230 | ||
|
|
fa1198dd00 | ||
|
|
e9244b18c4 | ||
|
|
bbcb866671 | ||
|
|
7998dee76a | ||
|
|
028fc1d88a | ||
|
|
2301851088 | ||
|
|
513dd9b5fc | ||
|
|
db721dbb53 | ||
|
|
d99175f807 | ||
|
|
ab5df0906d | ||
|
|
dbe73675a8 | ||
|
|
4b6d350215 | ||
|
|
67ffcb9c1b | ||
|
|
3fb8fa1c0e | ||
|
|
458e466262 | ||
|
|
3522b65858 | ||
|
|
5ed50c0ede | ||
|
|
1f1356d913 | ||
|
|
5087a05afa | ||
|
|
a01bf53f0a | ||
|
|
c36dec1a7b | ||
|
|
84dca0cd71 | ||
|
|
12211838ce | ||
|
|
eadaf188dd | ||
|
|
7989086ebe | ||
|
|
515bd7e066 | ||
|
|
862a3f0177 | ||
|
|
db6852ca01 | ||
|
|
a0dfd94a24 | ||
|
|
65ae28e715 | ||
|
|
e64cabe516 | ||
|
|
caee46ed04 | ||
|
|
c367168605 | ||
|
|
d76f57d2ec | ||
|
|
0edf4d4b74 | ||
|
|
be2057beb3 | ||
|
|
dca5ec2391 | ||
|
|
8abaf2d846 | ||
|
|
74caaa5a88 | ||
|
|
f9d0b87676 | ||
|
|
12c52903aa | ||
|
|
8fdadba962 | ||
|
|
d392473c6e | ||
|
|
c9bb11ed29 | ||
|
|
b70249c249 | ||
|
|
504e40eb38 | ||
|
|
945a1ce922 | ||
|
|
e4fe7b0726 | ||
|
|
a9c7c04316 | ||
|
|
29317b4ea4 | ||
|
|
e07da910b5 | ||
|
|
06addac953 | ||
|
|
d70dec2f19 | ||
|
|
310e5f4c79 | ||
|
|
9185bd21ce | ||
|
|
adaca35ac5 | ||
|
|
fe9c082c38 | ||
|
|
4477a52fab | ||
|
|
403001b3ab | ||
|
|
41be97bb08 | ||
|
|
1de8644056 | ||
|
|
5d9f65f6d0 | ||
|
|
1a31862d94 | ||
|
|
a4fdfb1dde | ||
|
|
3c915c8d73 | ||
|
|
e041781019 | ||
|
|
6c1aa4263b | ||
|
|
d9e7c928f6 | ||
|
|
b59fd66886 | ||
|
|
6ad37f7cc0 | ||
|
|
1dfc90943f | ||
|
|
d30e9e502f | ||
|
|
1b06feed2c | ||
|
|
d57ef8ace6 | ||
|
|
c737e2cd89 | ||
|
|
a5d135a78a | ||
|
|
f764b389d5 | ||
|
|
e360bb7662 | ||
|
|
2daa1d6006 | ||
|
|
6f86255585 | ||
|
|
3d7c916058 | ||
|
|
f5a3400308 | ||
|
|
2242ca17dd | ||
|
|
df8aef2f45 | ||
|
|
5684447b6a | ||
|
|
aba89f58fc | ||
|
|
fabe2a6b3d | ||
|
|
b7e9c5c3d7 | ||
|
|
584489c613 | ||
|
|
b506620e47 | ||
|
|
b9bd81f802 | ||
|
|
ecd5958b55 | ||
|
|
5fbf156762 | ||
|
|
07adc9afd3 | ||
|
|
52e9a63ab3 | ||
|
|
8c228bfc90 | ||
|
|
d8386149e7 | ||
|
|
925a6cb8eb | ||
|
|
9bfbada234 | ||
|
|
457b3b23a8 | ||
|
|
c301840cb2 | ||
|
|
edfbd9ec35 | ||
|
|
679ae0de42 | ||
|
|
1f414ccc84 | ||
|
|
9dd813c593 | ||
|
|
c79625c019 | ||
|
|
25ca47f63b | ||
|
|
14c28c83bf | ||
|
|
9a4dd35b5b | ||
|
|
6794741f34 | ||
|
|
67d82fdb65 | ||
|
|
ac6a61b6af | ||
|
|
4a7df9f57f | ||
|
|
42d074f1cb | ||
|
|
c74953aabc | ||
|
|
5654eb7445 | ||
|
|
f1f3c2ba6b | ||
|
|
d601930533 | ||
|
|
673739b538 | ||
|
|
f3708369a7 | ||
|
|
40ae361190 | ||
|
|
b2a31dc888 | ||
|
|
e2df1b56e0 | ||
|
|
be813055c8 | ||
|
|
cf8b1aa7a8 | ||
|
|
cb9acdb86b | ||
|
|
46044a175b | ||
|
|
7d0ea33c71 | ||
|
|
8d852e11c3 | ||
|
|
6194090eb3 | ||
|
|
c838e603e6 | ||
|
|
03e7a5368e | ||
|
|
a666ac3417 | ||
|
|
3a26dc2dd2 | ||
|
|
294bf0121b | ||
|
|
ce94619813 | ||
|
|
e61171acc8 | ||
|
|
698cf0922f | ||
|
|
840672e242 | ||
|
|
8f629e1ac0 | ||
|
|
f1cc76dc42 | ||
|
|
d63306b9a4 | ||
|
|
83de30c45e | ||
|
|
f0019edefb | ||
|
|
f0a3b22724 | ||
|
|
b863a8e3f4 | ||
|
|
f57f7e5225 | ||
|
|
3ed6ac716d | ||
|
|
0d574dfec7 | ||
|
|
a83f98212b | ||
|
|
f910e5898d | ||
|
|
19fdca577f | ||
|
|
fe750e0645 | ||
|
|
30e75cf876 | ||
|
|
a234e231e7 | ||
|
|
e88575790b | ||
|
|
4a945ae37d | ||
|
|
01a7063020 | ||
|
|
1468aebe4d | ||
|
|
22a6577076 | ||
|
|
9621200f95 | ||
|
|
1aff7876ec | ||
|
|
a4ea1fabaa | ||
|
|
27b796556c | ||
|
|
05efb66d3b | ||
|
|
881c683953 | ||
|
|
54cdfc3e47 | ||
|
|
1b23618a5d | ||
|
|
48b6c358ef | ||
|
|
d9ddc699c9 | ||
|
|
a0cf7ed49d | ||
|
|
8913c7fc88 | ||
|
|
13126cb4b2 | ||
|
|
2c8a5f70e5 | ||
|
|
d385b8c795 | ||
|
|
7cd4088ecd | ||
|
|
313e3f6bdf | ||
|
|
4acd0f9bcb | ||
|
|
6fa1b63954 | ||
|
|
5b3a108204 | ||
|
|
56a472e971 | ||
|
|
7080ca79f7 | ||
|
|
dd1063d61e | ||
|
|
d8ca62d0c8 | ||
|
|
46488baee7 | ||
|
|
f011b093d6 | ||
|
|
eb10c29940 | ||
|
|
6ef7de12af | ||
|
|
67da3359ac | ||
|
|
c79e3498bc | ||
|
|
b507498f30 | ||
|
|
e763a97390 | ||
|
|
5682c2aace | ||
|
|
26b7f4d109 | ||
|
|
d351d4549f | ||
|
|
4ce72abeb5 | ||
|
|
a351869a40 | ||
|
|
568915467c | ||
|
|
c2d8f2f894 | ||
|
|
e1593159f8 | ||
|
|
fcfcbfd9ae | ||
|
|
d398da007f | ||
|
|
284cdfbe53 | ||
|
|
a509b5b119 | ||
|
|
7456741201 | ||
|
|
62e22bc2e8 | ||
|
|
cdc40c57ad | ||
|
|
f8a2738052 | ||
|
|
79e55d3646 | ||
|
|
e1b1bafd78 | ||
|
|
5810bba3d8 | ||
|
|
7bb1df9f35 | ||
|
|
f0bb21c710 | ||
|
|
f7b00effe8 | ||
|
|
a0c49f6a6e | ||
|
|
e4aadf984d | ||
|
|
a335e07912 | ||
|
|
2080d5d643 | ||
|
|
b50725a99c | ||
|
|
6d7ddf4a25 | ||
|
|
f12dad8c7f | ||
|
|
3c60d66567 | ||
|
|
2b95659045 | ||
|
|
2018520302 | ||
|
|
d0fa3731bb | ||
|
|
7db28b8e49 | ||
|
|
bec8324c7b | ||
|
|
cdb2e850fb | ||
|
|
3f12d50201 | ||
|
|
4fb30c128d | ||
|
|
b2cd80a254 | ||
|
|
f3b8eec0cd | ||
|
|
3510a6bef5 | ||
|
|
94227802b4 | ||
|
|
c17c28f4fe | ||
|
|
97ba55700d | ||
|
|
080cb76743 | ||
|
|
b921faab86 | ||
|
|
7515a0ef1b | ||
|
|
61e7e50afd | ||
|
|
86f8891173 | ||
|
|
4429fb0e24 | ||
|
|
776d33f119 | ||
|
|
a8e400309d | ||
|
|
6cfa99a2fd | ||
|
|
ff7526810b | ||
|
|
bff03d9595 | ||
|
|
e1abcbf979 | ||
|
|
d7db1af006 | ||
|
|
ccf4d4cf3e | ||
|
|
ac48012ed0 | ||
|
|
c47f373913 | ||
|
|
6fbcf645cb | ||
|
|
b4c27e47f0 | ||
|
|
a4c4632f98 | ||
|
|
fd3cac4e2e | ||
|
|
424c407aba | ||
|
|
604b634b80 | ||
|
|
c7b30dcf87 | ||
|
|
0845703721 | ||
|
|
10693e85b3 | ||
|
|
d06e38ae36 | ||
|
|
bbcbdabe27 | ||
|
|
194eef9612 | ||
|
|
d92df2510a | ||
|
|
d66db62d4b | ||
|
|
d128fb5203 | ||
|
|
d5bdd59e65 | ||
|
|
3a47091fa5 | ||
|
|
d988308e79 | ||
|
|
4bd8a963ce | ||
|
|
d8fe750a63 | ||
|
|
8611677a5d | ||
|
|
f199aa4642 | ||
|
|
bab3c5b294 | ||
|
|
1d826dca2d | ||
|
|
5d042832ad | ||
|
|
c8ef9aa7e7 | ||
|
|
3e707f40a6 | ||
|
|
d1c1de9e75 | ||
|
|
f526f0fcfb | ||
|
|
e6eca956a3 | ||
|
|
0970248aaa | ||
|
|
5291201c37 | ||
|
|
27296bd4ed | ||
|
|
75da39d626 | ||
|
|
7106d1b991 | ||
|
|
69701634df | ||
|
|
b457d91a2d | ||
|
|
0223007bc4 | ||
|
|
4bf6afa963 | ||
|
|
01569a9965 | ||
|
|
5ee0c9c5f1 | ||
|
|
9cedb170d6 | ||
|
|
08434ef5b5 | ||
|
|
513acf7dc9 | ||
|
|
9034e6a452 | ||
|
|
5b143a061f | ||
|
|
dd355826d3 | ||
|
|
c530cf25b9 | ||
|
|
99cccbbb75 | ||
|
|
0510e5c71b | ||
|
|
71edfe09ca | ||
|
|
35e3a95e79 | ||
| 1dde46fb3a | |||
| 47d3a203d8 | |||
|
|
7f796f480c | ||
|
|
c3d9830278 | ||
|
|
1b031303fc | ||
| d5ec878c3f | |||
|
|
68da2a7313 | ||
|
|
674e9c8679 | ||
|
|
0b45dbebb8 | ||
| 94377eed13 | |||
|
|
37dc0e4dad | ||
|
|
7a0501f3ce | ||
| 95533b39a2 | |||
|
|
3aeae3c273 | ||
| 6e6fc18cd8 | |||
| e90fdc5796 | |||
|
|
b9e1915f98 | ||
|
|
d080d9b23e | ||
|
|
d82329610d | ||
|
|
2b15221013 | ||
|
|
dc0eee51b9 | ||
|
|
a77df017d7 | ||
|
|
472cefe2ca | ||
|
|
4cb91d9c95 | ||
| 8c70edf172 | |||
| 57119c41da | |||
| b7014b03ee | |||
|
|
14a895bfc0 | ||
|
|
e346e7146e | ||
|
|
7718bc4ab0 | ||
|
|
4106b91afd | ||
|
|
5f87e1e817 | ||
| 000e3803dc | |||
|
|
25f8d5badb | ||
| 0ec8c05429 | |||
| 9472a28e5c | |||
|
|
1a2510264e | ||
|
|
c145034f84 | ||
| da58ff6466 | |||
| 71467e216d | |||
|
|
97fd207faf | ||
|
|
9916b78bb6 | ||
| f7ba919c6a | |||
| 2393149460 | |||
|
|
1e5d69bed5 | ||
|
|
2639862d95 | ||
| 5328524eed | |||
| c1c8ae1a91 | |||
|
|
00b2a50ddb | ||
| 1ade69bebe | |||
| 6f4a9e0238 | |||
| ff733e9981 | |||
| 1d30bb96a2 | |||
|
|
aa81a18d2c | ||
|
|
5f101e936a | ||
|
|
21d6651d1b | ||
|
|
b1ea12e70d | ||
|
|
a447c7470a | ||
|
|
43222b0299 | ||
|
|
54843c5417 | ||
|
|
d33daf1652 | ||
|
|
2dd336e3bc | ||
|
|
986b121df4 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -54,3 +54,4 @@ Assets/Editor/FYUtils
|
||||
|
||||
Assets/Editor/FYUtils.meta
|
||||
fbg.log
|
||||
.vsconfig
|
||||
@ -20,61 +20,32 @@ namespace BFEditor.Build
|
||||
}
|
||||
}
|
||||
|
||||
public static class BuildMode
|
||||
{
|
||||
public const string DEV = "dev";
|
||||
public const string TEST = "test";
|
||||
public const string PUBLISH = "publish";
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class BuildInfo
|
||||
{
|
||||
public string bundleName; // 包名
|
||||
public string version; // 版本号
|
||||
public string mode; // 渠道名_debug 或 渠道名_release
|
||||
public int version_code = 1; // 各自渠道的version_code
|
||||
public string mode; // 内网测试包,外网测试包,外网正式包
|
||||
public int versionCode = 1; // 各自渠道的version code
|
||||
public List<BulidGitInfo> git_info; // 打包的git信息
|
||||
public bool exportProject = false; // 是否只导出工程
|
||||
public bool onlyAssetBundle = false; // 是否只打ab包
|
||||
|
||||
[NonSerialized]
|
||||
public bool skipVersion = false; // 是否跳过版本校验
|
||||
|
||||
public bool IsGPChannel()
|
||||
{
|
||||
return bundleName == "com.combo.heroes.puzzle.rpg";
|
||||
}
|
||||
|
||||
public bool IsGPOfficial()
|
||||
{
|
||||
return bundleName == "com.combo.heroes.puzzle.rpg";
|
||||
}
|
||||
|
||||
// dev包使用mono编译,不会导出as工程
|
||||
public bool IsDevChannel()
|
||||
{
|
||||
return bundleName == "com.juzu.b6.dev" || bundleName == "com.juzu.b6.dev.android" ||
|
||||
bundleName == "com.juzu.b6.dev.ios";
|
||||
}
|
||||
|
||||
public bool IsReleaseChannel()
|
||||
{
|
||||
return !IsDevChannel();
|
||||
}
|
||||
|
||||
// 是否是内网release
|
||||
public bool IsLanRelease()
|
||||
{
|
||||
return bundleName == "com.juzu.b6.release.android" || bundleName == "com.juzu.b6.release.ios";
|
||||
}
|
||||
|
||||
public bool IsPublish()
|
||||
{
|
||||
return !IsDevChannel() && !IsLanRelease();
|
||||
return mode == BuildMode.PUBLISH;
|
||||
}
|
||||
|
||||
public bool IsIOSPlatform()
|
||||
{
|
||||
return bundleName.Contains("ios");
|
||||
}
|
||||
|
||||
public bool IsAndroidPlatform()
|
||||
{
|
||||
return !IsIOSPlatform();
|
||||
}
|
||||
|
||||
public string GetBundleName()
|
||||
{
|
||||
return bundleName;
|
||||
|
||||
@ -48,6 +48,12 @@ namespace BFEditor.Build
|
||||
return false;
|
||||
}
|
||||
|
||||
// 只打ab包
|
||||
if (buildInfo.onlyAssetBundle)
|
||||
{
|
||||
AssetDatabase.Refresh();
|
||||
return true;
|
||||
}
|
||||
// 删除不进包的多语言
|
||||
// if (!DeleteOverLanguageAb(buildInfo))
|
||||
// {
|
||||
@ -73,19 +79,10 @@ namespace BFEditor.Build
|
||||
watch.Start();
|
||||
|
||||
var result = false;
|
||||
|
||||
if (buildInfo.IsAndroidPlatform() && BuildAndroidUtils.BuildAndroidPlayer(buildInfo))
|
||||
if (BuildAndroidUtils.BuildAndroidPlayer(buildInfo))
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR_OSX
|
||||
if (buildInfo.IsIOSPlatform() && BuildIOSUtils.BuildIOSPlayer(buildInfo))
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (result)
|
||||
{
|
||||
watch.Stop();
|
||||
@ -140,8 +137,7 @@ namespace BFEditor.Build
|
||||
var watch = new System.Diagnostics.Stopwatch();
|
||||
watch.Start();
|
||||
|
||||
// var buildTarget = buildInfo.IsIOSPlatform() ? BuildTarget.iOS : BuildTarget.Android;
|
||||
var isRelease = buildInfo.IsReleaseChannel();
|
||||
var isRelease = true;
|
||||
Debug.Log("[bfinfo]开始打包资源, bundleName : " + buildInfo.bundleName + " version : " + buildInfo.version + " mode : " + buildInfo.mode);
|
||||
|
||||
// // 检查平台
|
||||
@ -197,7 +193,7 @@ namespace BFEditor.Build
|
||||
}
|
||||
|
||||
// 本地缓存ab
|
||||
if (buildInfo.IsReleaseChannel())
|
||||
if (buildInfo.IsPublish())
|
||||
{
|
||||
Debug.Log("[bfinfo]正在缓存assetbundles...");
|
||||
BFEditorUtils.CopyDirWithIgnore(outputPath, Path.Combine(AssetBundleCachePath, buildInfo.version), new List<string> { ".meta" });
|
||||
|
||||
@ -6,77 +6,116 @@ namespace BFEditor.Build
|
||||
public enum BFPlatformOptions
|
||||
{
|
||||
AndroidDev = 1,
|
||||
IOSDev,
|
||||
AndroidRelease,
|
||||
AndroidTest,
|
||||
AndroidGP,
|
||||
AndroidGPRU
|
||||
}
|
||||
|
||||
public class BuildProjectWindow : EditorWindow
|
||||
{
|
||||
private static int versionCode = 18;
|
||||
private static string versionName = "1.6.5";
|
||||
private static int VersionCode = 4;
|
||||
private static string VersionName = "1.2.10";
|
||||
private static int VersionCodeRU = 12;
|
||||
private static string VersionNameRU = "0.4.9";
|
||||
BFPlatformOptions platform = BFPlatformOptions.AndroidDev;
|
||||
const string ANDROID_DEV_PACKAGE_NAME = "com.juzu.b6.dev.android";
|
||||
const string ANDROID_RELEASE_PACKAGE_NAME = "com.juzu.b6.release.android";
|
||||
const string ANDROID_GP_PACKAGE_NAME = "com.combo.heroes.puzzle.rpg";
|
||||
const string IOS_PACKAGE_NAME = "com.juzu.b6.dev.ios";
|
||||
|
||||
const string ANDROID_GP_PACKAGE_NAME = "com.juzu.b6.dev.android";
|
||||
|
||||
public BuildProjectWindow()
|
||||
{
|
||||
titleContent = new GUIContent("打包");
|
||||
}
|
||||
{
|
||||
titleContent = new GUIContent("打包");
|
||||
}
|
||||
|
||||
private void OnEnable() { }
|
||||
|
||||
void OnGUI()
|
||||
{
|
||||
GUILayout.BeginVertical("box");
|
||||
|
||||
EditorGUILayout.LabelField("选择渠道");
|
||||
platform = (BFPlatformOptions)EditorGUILayout.EnumPopup("", platform);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.LabelField("版本: " + versionName);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
string packageName;
|
||||
string mode;
|
||||
string versionName = VersionName;
|
||||
int versionCode = VersionCode;
|
||||
bool skipVersion = false;
|
||||
string appType;
|
||||
if (platform == BFPlatformOptions.AndroidDev)
|
||||
{
|
||||
packageName = ANDROID_DEV_PACKAGE_NAME;
|
||||
packageName = ANDROID_GP_PACKAGE_NAME;
|
||||
skipVersion = true;
|
||||
mode = "dev_debug";
|
||||
mode = BuildMode.DEV;
|
||||
versionName = "0.1.0";
|
||||
versionCode = 1;
|
||||
appType = "内网测试包";
|
||||
}
|
||||
else if(platform == BFPlatformOptions.AndroidRelease)
|
||||
else if(platform == BFPlatformOptions.AndroidTest)
|
||||
{
|
||||
packageName = ANDROID_RELEASE_PACKAGE_NAME;
|
||||
mode = "release_release";
|
||||
packageName = ANDROID_GP_PACKAGE_NAME;
|
||||
mode = BuildMode.TEST;
|
||||
versionName = "0.1.0";
|
||||
versionCode = 1;
|
||||
appType = "外网测试包";
|
||||
}
|
||||
else if(platform == BFPlatformOptions.AndroidGP)
|
||||
{
|
||||
packageName = ANDROID_GP_PACKAGE_NAME;
|
||||
mode = "publish_release";
|
||||
mode = BuildMode.PUBLISH;
|
||||
appType = "外网正式包";
|
||||
}
|
||||
else
|
||||
{
|
||||
packageName = IOS_PACKAGE_NAME;
|
||||
mode = "dev_debug";
|
||||
packageName = ANDROID_GP_PACKAGE_NAME;
|
||||
skipVersion = true;
|
||||
mode = BuildMode.DEV;
|
||||
versionName = "0.1.0";
|
||||
versionCode = 1;
|
||||
appType = "内网测试包";
|
||||
}
|
||||
GUILayout.BeginVertical("box");
|
||||
EditorGUILayout.LabelField("选择");
|
||||
platform = (BFPlatformOptions)EditorGUILayout.EnumPopup("", platform);
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.LabelField("版本: " + versionName);
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.LabelField("包名: " + packageName);
|
||||
EditorGUILayout.LabelField("mode: " + mode);
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.LabelField(appType);
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
var buildInfo = new BuildInfo();
|
||||
buildInfo.version = versionName;
|
||||
buildInfo.versionCode = versionCode;
|
||||
buildInfo.mode = mode;
|
||||
buildInfo.bundleName = packageName;
|
||||
buildInfo.skipVersion = skipVersion;
|
||||
|
||||
if (GUILayout.Button("一键打包"))
|
||||
if (GUILayout.Button("一键APK"))
|
||||
{
|
||||
var buildInfo = new BuildInfo();
|
||||
buildInfo.version = versionName;
|
||||
buildInfo.version_code = versionCode;
|
||||
buildInfo.mode = mode;
|
||||
buildInfo.bundleName = packageName;
|
||||
buildInfo.skipVersion = skipVersion;
|
||||
buildInfo.exportProject = false;
|
||||
buildInfo.onlyAssetBundle = false;
|
||||
BuildProjectTools.BuildBFPlayer(buildInfo);
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.Space();
|
||||
|
||||
if (GUILayout.Button("仅导出工程"))
|
||||
{
|
||||
buildInfo.exportProject = true;
|
||||
buildInfo.onlyAssetBundle = false;
|
||||
BuildProjectTools.BuildBFPlayer(buildInfo);
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.Space();
|
||||
|
||||
if (GUILayout.Button("仅打ab包"))
|
||||
{
|
||||
buildInfo.exportProject = true;
|
||||
buildInfo.onlyAssetBundle = true;
|
||||
BuildProjectTools.BuildBFPlayer(buildInfo);
|
||||
}
|
||||
|
||||
|
||||
@ -77,25 +77,12 @@ namespace BFEditor.Build
|
||||
Directory.CreateDirectory(outputPath);
|
||||
}
|
||||
|
||||
AssetBundleManifest manifest;
|
||||
if (release)
|
||||
{
|
||||
manifest = BuildPipeline.BuildAssetBundles(outputPath, options |
|
||||
BuildAssetBundleOptions.StrictMode |
|
||||
BuildAssetBundleOptions.DisableLoadAssetByFileName |
|
||||
BuildAssetBundleOptions.DisableLoadAssetByFileNameWithExtension |
|
||||
BuildAssetBundleOptions.DeterministicAssetBundle,
|
||||
target);
|
||||
}
|
||||
else
|
||||
{
|
||||
manifest = BuildPipeline.BuildAssetBundles(outputPath, options |
|
||||
BuildAssetBundleOptions.StrictMode |
|
||||
BuildAssetBundleOptions.DisableLoadAssetByFileName |
|
||||
BuildAssetBundleOptions.DisableLoadAssetByFileNameWithExtension |
|
||||
BuildAssetBundleOptions.DeterministicAssetBundle,
|
||||
target);
|
||||
}
|
||||
AssetBundleManifest manifest = BuildPipeline.BuildAssetBundles(outputPath, options |
|
||||
BuildAssetBundleOptions.StrictMode |
|
||||
BuildAssetBundleOptions.DisableLoadAssetByFileName |
|
||||
BuildAssetBundleOptions.DisableLoadAssetByFileNameWithExtension |
|
||||
BuildAssetBundleOptions.DeterministicAssetBundle,
|
||||
target);
|
||||
|
||||
if (manifest == null)
|
||||
{
|
||||
@ -365,12 +352,12 @@ namespace BFEditor.Build
|
||||
SetProtoABName(Path.Combine(Application.dataPath, "proto"), index++ / total);
|
||||
SetSpineABName(Path.Combine(Application.dataPath, "arts", "spines"), index++ / total);
|
||||
SetFirstABName(Path.Combine(Application.dataPath, "first"), index++ / total);
|
||||
// SetTimelineABName(Path.Combine(Application.dataPath, "arts", "timeline"), 16f / total);
|
||||
// SetTimelineABName(Path.Combine(Application.dataPath, "arts", "timeline"), index++ / total);
|
||||
SetVideoABName(Path.Combine(Application.dataPath, "arts", "video"), index++ / total);
|
||||
// SetLanguageResABName(Resource.ResourceProcessConfig.LANGUAGE_PATH, 19f / total);
|
||||
// SetBakedatasABName(Path.Combine(Application.dataPath, "arts", "bakedatas"), 21f / total);
|
||||
// SetLightProbesABName(Path.Combine(Application.dataPath, "arts", "lightprobes"), 22f / total);
|
||||
// SetReflectionsABName(Path.Combine(Application.dataPath, "arts", "reflections"), 23f / total);
|
||||
// SetLanguageResABName(Resource.ResourceProcessConfig.LANGUAGE_PATH, index++ / total);
|
||||
// SetBakedatasABName(Path.Combine(Application.dataPath, "arts", "bakedatas"), index++ / total);
|
||||
// SetLightProbesABName(Path.Combine(Application.dataPath, "arts", "lightprobes"), index++ / total);
|
||||
// SetReflectionsABName(Path.Combine(Application.dataPath, "arts", "reflections"), index++ / total);
|
||||
|
||||
EditorUtility.ClearProgressBar();
|
||||
AssetDatabase.SaveAssets();
|
||||
@ -572,11 +559,11 @@ namespace BFEditor.Build
|
||||
{
|
||||
EditorUtility.DisplayProgressBar("提示", "正在设置spine ABName", progress);
|
||||
|
||||
var dirInfo = new DirectoryInfo(dirPath);
|
||||
var dirs = dirInfo.GetDirectories();
|
||||
for (var i = 0; i < dirs.Length; i++)
|
||||
string[] dirList = { "ui" , "characters" };
|
||||
for (var i = 0; i < dirList.Length; ++i)
|
||||
{
|
||||
SetABNameBySubDir(dirs[i]);
|
||||
var dirInfo = new DirectoryInfo(Path.Combine(dirPath, dirList[i]));
|
||||
SetABNameBySubDir(dirInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@ -596,6 +583,11 @@ namespace BFEditor.Build
|
||||
var dirInfo = new DirectoryInfo(Path.Combine(dirPath, dirList[i]));
|
||||
SetABNameBySubDir(dirInfo);
|
||||
}
|
||||
var dirInfo2 = new DirectoryInfo(Path.Combine(dirPath, "ui", "activity"));
|
||||
if (dirInfo2.Exists)
|
||||
{
|
||||
SetABNameBySubDir(dirInfo2);
|
||||
}
|
||||
}
|
||||
|
||||
static void SetBackgroundABName(string dirPath)
|
||||
|
||||
@ -3,12 +3,12 @@ using UnityEditor;
|
||||
using System.IO;
|
||||
using UnityEditor.Build.Reporting;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BFEditor.Build
|
||||
{
|
||||
{
|
||||
public static class BuildAndroidUtils
|
||||
{
|
||||
const string JAVA_HOME_ENVIRONMENT = "JAVA_HOME";
|
||||
@ -18,19 +18,19 @@ namespace BFEditor.Build
|
||||
const string GRADLE_PATH = "/Users/aoddabao/.gradle/wrapper/dists/gradle-5.6.4-all/ankdp27end7byghfw1q2sw75f/gradle-5.6.4/bin/gradle";
|
||||
const string BUGLY_APP_ID = "1eb4e5e560";
|
||||
const string BUGLY_APP_KEY = "99e249db-4eeb-440e-83e7-c2bd80e8b5e4";
|
||||
|
||||
|
||||
static Thread buglyUploadThread;
|
||||
static string ReleaseSOPath = Application.dataPath + "/../BFVersions/android/ub-release/src/main/jniLibs";
|
||||
static string BuglyPath = Application.dataPath + "/../Bugly";
|
||||
static string BuglySOPath = Application.dataPath + "/../Bugly/so";
|
||||
static string GradleExcuteProjectPath = Application.dataPath + "/../BFVersions/android/ub-release";
|
||||
static string DevAsProjectPath = Application.dataPath + "/../BFVersions/android/dz_dev";
|
||||
static string LanReleaseAsProjectPath = Application.dataPath + "/../BFVersions/android/dz_release";
|
||||
static string GoogleAsProjectPath = Application.dataPath + "/../BFVersions/android/dz_google_apk";
|
||||
static string GoogleCommonProjectPath = Application.dataPath + "/../BFVersions/android/google_common";
|
||||
static string GPAsProjectPath = Application.dataPath + "/../BFVersions/android/ub-gp"; // gp删档测试渠道
|
||||
static string GPOfficialAsProjectPath = Application.dataPath + "/../BFVersions/android/ub-google"; // gp正式渠道
|
||||
static string RuStoreProjectPath = Application.dataPath + "/../BFVersions/android/ru_store";
|
||||
static string RuProjectPath = Application.dataPath + "/../BFVersions/android/ru";
|
||||
static string GoogleServicesProjectPath = Application.dataPath + "/../BFVersions/android/google-services";
|
||||
static string PublishAsProjectPath = Application.dataPath + "/../BFVersions/android/publish_release";
|
||||
static string KeystoreFilePath = Application.dataPath + "/../BFVersions/android/keystore/dz_keystore.txt";
|
||||
static string SignShellPath = Application.dataPath + "/../BFFiles/androidkey";
|
||||
static string GpAlginShellPath = Application.dataPath + "/../BFFiles/androidkey";
|
||||
static HashSet<string> AABInPackageFileHashSet = new HashSet<string>()
|
||||
@ -38,12 +38,12 @@ namespace BFEditor.Build
|
||||
"bin",
|
||||
"UnityServicesProjectConfiguration.json"
|
||||
};
|
||||
|
||||
|
||||
static BuildAndroidUtils()
|
||||
{
|
||||
EnsureJavaHome();
|
||||
}
|
||||
|
||||
|
||||
public static void EnsureJavaHome()
|
||||
{
|
||||
// var javaHomeEnvironment = Environment.GetEnvironmentVariable(JAVA_HOME_ENVIRONMENT);
|
||||
@ -52,35 +52,44 @@ namespace BFEditor.Build
|
||||
// Environment.SetEnvironmentVariable(JAVA_HOME_ENVIRONMENT, JAVA_HOME_ENVIRONMENT_PATH);
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 打包android
|
||||
/// </summary>
|
||||
public static bool BuildAndroidPlayer(BuildInfo buildInfo)
|
||||
{
|
||||
var buildTarget = BuildTarget.Android;
|
||||
|
||||
|
||||
// 检查平台
|
||||
if (EditorUserBuildSettings.activeBuildTarget != buildTarget)
|
||||
{
|
||||
Debug.LogError("[bferror]当前没有在对应平台");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// 重新生成XLua
|
||||
CompileScriptsUtils.RegenerateXLuaCode(true);
|
||||
|
||||
|
||||
// 打包设置
|
||||
BuildSettings(buildInfo);
|
||||
|
||||
|
||||
// 开始打包
|
||||
var bpOptions = GetBuildOptions(buildInfo);
|
||||
var report = BuildPipeline.BuildPlayer(bpOptions);
|
||||
|
||||
// 打包成功
|
||||
|
||||
// 导出工程成功
|
||||
if (report.summary.result == BuildResult.Succeeded)
|
||||
{
|
||||
return BuildAndroidAPK(buildInfo);
|
||||
MergeProject(buildInfo, GoogleAsProjectPath);
|
||||
FixGradleVersion(buildInfo.versionCode, buildInfo.version);
|
||||
if (buildInfo.exportProject)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return BuildAPK(buildInfo);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -88,7 +97,7 @@ namespace BFEditor.Build
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 打包设置
|
||||
/// </summary>
|
||||
@ -96,45 +105,48 @@ namespace BFEditor.Build
|
||||
{
|
||||
// 设置bundleVersion
|
||||
PlayerSettings.bundleVersion = buildInfo.version;
|
||||
|
||||
|
||||
// 设置VersionCode
|
||||
PlayerSettings.Android.bundleVersionCode = buildInfo.version_code;
|
||||
|
||||
PlayerSettings.Android.bundleVersionCode = buildInfo.versionCode;
|
||||
|
||||
// 设置竖屏
|
||||
PlayerSettings.defaultInterfaceOrientation = UIOrientation.Portrait;
|
||||
PlayerSettings.allowedAutorotateToPortrait = false;
|
||||
PlayerSettings.allowedAutorotateToPortraitUpsideDown = false;
|
||||
PlayerSettings.allowedAutorotateToLandscapeLeft = false;
|
||||
PlayerSettings.allowedAutorotateToLandscapeRight = false;
|
||||
|
||||
|
||||
// 安卓构建目标CPU架构
|
||||
PlayerSettings.Android.targetArchitectures = AndroidArchitecture.ARMv7 | AndroidArchitecture.ARM64;
|
||||
|
||||
|
||||
// 强加Internet权限
|
||||
PlayerSettings.Android.forceInternetPermission = true;
|
||||
|
||||
|
||||
// 关闭启动动画
|
||||
PlayerSettings.SplashScreen.show = false;
|
||||
|
||||
|
||||
// 设置包名
|
||||
PlayerSettings.SetApplicationIdentifier(BuildTargetGroup.Android, buildInfo.bundleName);
|
||||
Debug.Log("[bfinfo]设置包名:" + buildInfo.bundleName);
|
||||
|
||||
|
||||
// 跳过版本控制
|
||||
var symbols = ANDROID_DEFINE_SYMBOLS;
|
||||
if (buildInfo.skipVersion)
|
||||
{
|
||||
symbols = symbols + ";SKIP_VERSION;";
|
||||
symbols = symbols + ";SKIP_VERSION";
|
||||
}
|
||||
if (buildInfo.mode == BuildMode.DEV)
|
||||
{
|
||||
symbols = symbols + ";BF_APP_DEV";
|
||||
}
|
||||
else if (buildInfo.mode == BuildMode.TEST)
|
||||
{
|
||||
symbols = symbols + ";BF_APP_TEST";
|
||||
}
|
||||
|
||||
PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android, symbols);
|
||||
Debug.Log("[bfinfo]设置defineSymbols: " + symbols);
|
||||
|
||||
// 是否是dev
|
||||
var development = buildInfo.IsDevChannel() ? true : false;
|
||||
EditorUserBuildSettings.development = development;
|
||||
|
||||
// 商品名称
|
||||
// 商品名称
|
||||
// 应用名
|
||||
if (buildInfo.IsPublish())
|
||||
{
|
||||
@ -142,20 +154,18 @@ namespace BFEditor.Build
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayerSettings.productName = development ? "b6-dev" : "b6-release";
|
||||
PlayerSettings.productName = "b6-dev";
|
||||
}
|
||||
// BuildType设置dev/release
|
||||
EditorUserBuildSettings.androidBuildType = development ? AndroidBuildType.Debug : AndroidBuildType.Release;
|
||||
|
||||
EditorUserBuildSettings.development = false;
|
||||
EditorUserBuildSettings.androidBuildType = AndroidBuildType.Release;
|
||||
|
||||
// 是否导出as工程
|
||||
// EditorUserBuildSettings.exportAsGoogleAndroidProject = development ? false : true;
|
||||
EditorUserBuildSettings.exportAsGoogleAndroidProject = true;
|
||||
|
||||
// dev使用Mono release使用IL2CPP
|
||||
var scriptImp = development ? ScriptingImplementation.Mono2x : ScriptingImplementation.IL2CPP;
|
||||
|
||||
var scriptImp = ScriptingImplementation.IL2CPP;
|
||||
PlayerSettings.SetScriptingBackend(BuildTargetGroup.Android, scriptImp);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取打包参数
|
||||
/// </summary>
|
||||
@ -164,43 +174,23 @@ namespace BFEditor.Build
|
||||
var bpOptions = new BuildPlayerOptions();
|
||||
bpOptions.scenes = AssetBundleUtils.GetBuildScenes();
|
||||
bpOptions.target = BuildTarget.Android;
|
||||
|
||||
// if (buildInfo.IsDevChannel())
|
||||
// {
|
||||
// bpOptions.locationPathName = GetDevApkPathName(buildInfo);
|
||||
// Debug.Log("[bfinfo]apk path : " + bpOptions.locationPathName);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// bpOptions.locationPathName = GetASProjectPathName();
|
||||
// Debug.Log("[bfinfo]asProject path : " + bpOptions.locationPathName);
|
||||
// }
|
||||
bpOptions.locationPathName = GetASProjectPathName(buildInfo);
|
||||
|
||||
BuildOptions options;
|
||||
if (buildInfo.IsReleaseChannel())
|
||||
{
|
||||
options = BuildOptions.None;
|
||||
}
|
||||
else
|
||||
{
|
||||
options = BuildOptions.Development;
|
||||
}
|
||||
|
||||
|
||||
BuildOptions options = BuildOptions.None;
|
||||
bpOptions.options = options;
|
||||
return bpOptions;
|
||||
}
|
||||
|
||||
|
||||
static string GetDevApkPathName(BuildInfo buildInfo)
|
||||
{
|
||||
var apkName = buildInfo.skipVersion ? "dz_dev_skip_version.apk" : "dz_dev_debug.apk";
|
||||
var path = Path.Combine(AS_PROJECT_PATH, apkName);
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
static string GetASProjectPathName(BuildInfo buildInfo)
|
||||
{
|
||||
var dir = Path.Combine(AS_PROJECT_PATH, buildInfo.mode);
|
||||
var dir = Path.Combine(AS_PROJECT_PATH, "publish_release");
|
||||
if (Directory.Exists(dir))
|
||||
{
|
||||
Directory.Delete(dir, true);
|
||||
@ -208,32 +198,53 @@ namespace BFEditor.Build
|
||||
return dir;
|
||||
}
|
||||
|
||||
static bool BuildAPK(BuildInfo buildInfo)
|
||||
static bool BuildAPK(BuildInfo buildInfo, bool isAAB = false)
|
||||
{
|
||||
if (buildInfo.IsGPChannel())
|
||||
{
|
||||
MergeGPToReleaseProject(buildInfo);
|
||||
FixGradleVersion(buildInfo.version_code, buildInfo.version);
|
||||
}
|
||||
|
||||
if (buildInfo.IsLanRelease())
|
||||
{
|
||||
AddBuglyParamsToReleaseProject();
|
||||
}
|
||||
|
||||
// 设置jdk环境变量
|
||||
string javaHomePath = System.Environment.GetEnvironmentVariable("JAVE_HOME");
|
||||
if (string.IsNullOrEmpty(javaHomePath))
|
||||
{
|
||||
Debug.LogError("[bferror] 找不到环境变量JAVE_HOME");
|
||||
return false;
|
||||
}
|
||||
var gradleFilePath = Path.Combine(PublishAsProjectPath, "gradle.properties");
|
||||
var gradleFileText = File.ReadAllText(gradleFilePath);
|
||||
if (!gradleFileText.Contains("org.gradle.java.home"))
|
||||
{
|
||||
gradleFileText = gradleFileText + "\norg.gradle.java.home=" + javaHomePath.Replace("\\", "/");
|
||||
}
|
||||
File.WriteAllText(gradleFilePath, gradleFileText);
|
||||
|
||||
// 设置密钥密码
|
||||
if (File.Exists(KeystoreFilePath))
|
||||
{
|
||||
var password = File.ReadAllText(KeystoreFilePath).Replace("\n", "").Replace("\r", "");
|
||||
var buildGradlePath = Path.Combine(PublishAsProjectPath, "launcher/build.gradle");
|
||||
var text = File.ReadAllText(buildGradlePath);
|
||||
var regex = new Regex("REPLACE_PASSWORD");
|
||||
text = regex.Replace(text, password);
|
||||
File.WriteAllText(buildGradlePath, text);
|
||||
}
|
||||
|
||||
Debug.Log("[bfinfo]正在buildApk...");
|
||||
var success = true;
|
||||
var args = "";
|
||||
if (buildInfo.IsReleaseChannel())
|
||||
{
|
||||
args += " assembleRelease";
|
||||
}
|
||||
else
|
||||
{
|
||||
args += " assembleDebug";
|
||||
}
|
||||
|
||||
BFEditorUtils.RunCommond(GRADLE_PATH, args, GradleExcuteProjectPath,
|
||||
var args = "assembleRelease";
|
||||
if (isAAB)
|
||||
{
|
||||
args = "bundleRelease";
|
||||
}
|
||||
string gradleHomePath = System.Environment.GetEnvironmentVariable("GRADLE_HOME");
|
||||
if (string.IsNullOrEmpty(gradleHomePath))
|
||||
{
|
||||
Debug.LogError("[bferror] 找不到环境变量GRADLE_HOME");
|
||||
return false;
|
||||
}
|
||||
#if UNITY_EDITOR_OSX
|
||||
var gradleCommondPath = Path.Combine(gradleHomePath, "gradle");
|
||||
#else
|
||||
var gradleCommondPath = Path.Combine(gradleHomePath, "gradle.bat");
|
||||
#endif
|
||||
BFEditorUtils.RunCommond(gradleCommondPath, args, PublishAsProjectPath,
|
||||
(msg) =>
|
||||
{
|
||||
},
|
||||
@ -245,80 +256,35 @@ namespace BFEditor.Build
|
||||
Debug.LogError("[bferror] " + errorMsg);
|
||||
}
|
||||
});
|
||||
|
||||
if (buildInfo.IsGPChannel())
|
||||
{
|
||||
// 尝试制作并上传bugly符号表 开新Thread不影响打包流程
|
||||
if (success)
|
||||
{
|
||||
CopySOAndUploadBuglySymbol(buildInfo.bundleName, buildInfo.version);
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool BuildAAB(BuildInfo buildInfo)
|
||||
{
|
||||
var result = true;
|
||||
if(buildInfo.IsGPChannel())
|
||||
{
|
||||
// MergeGPToReleaseProject(buildInfo);
|
||||
// FixGradleVersion(buildInfo.version_code, buildInfo.version);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool BuildAndroidAPK(BuildInfo buildInfo)
|
||||
{
|
||||
var result = true;
|
||||
if(buildInfo.IsDevChannel())
|
||||
{
|
||||
MergeProject(buildInfo, DevAsProjectPath);
|
||||
var dir = Path.Combine(Application.dataPath, "../", AS_PROJECT_PATH, buildInfo.mode);
|
||||
BFEditorUtils.RunCommond("gradle", " assembleDebug", dir, (msg) => {
|
||||
}, (errorMsg) => {
|
||||
Debug.LogError("[bferror] " + errorMsg);
|
||||
});
|
||||
}
|
||||
else if(buildInfo.IsLanRelease())
|
||||
{
|
||||
MergeProject(buildInfo, LanReleaseAsProjectPath);
|
||||
}
|
||||
else if(buildInfo.IsGPChannel())
|
||||
{
|
||||
MergeProject(buildInfo, GoogleAsProjectPath);
|
||||
FixGradleVersion(buildInfo.version_code, buildInfo.version);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 合并dev工程
|
||||
/// 合并工程
|
||||
/// </summary>
|
||||
static void MergeProject(BuildInfo buildInfo, String asProjectPath)
|
||||
{
|
||||
Debug.Log("[bfinfo]正在整合dev project...");
|
||||
Debug.Log("[bfinfo]正在整合 project...");
|
||||
|
||||
var dir = Path.Combine(Application.dataPath, "../", AS_PROJECT_PATH, buildInfo.mode);
|
||||
var dir = Path.Combine(Application.dataPath, "../", AS_PROJECT_PATH, "publish_release");
|
||||
|
||||
var javaPath = Path.Combine(dir, "unityLibrary/src/main/java");
|
||||
var manifestPath = Path.Combine(dir, "unityLibrary/src/main/AndroidManifest.xml");
|
||||
|
||||
// 老版本unity需要替换这个,2021之后的新版本不需要
|
||||
// 获取到unity打出的build-id
|
||||
var reader = new StreamReader(new FileStream(manifestPath, FileMode.Open));
|
||||
string buildIdLine;
|
||||
while ((buildIdLine = reader.ReadLine()) != null)
|
||||
{
|
||||
if (buildIdLine.Contains("unity.build-id"))
|
||||
{
|
||||
Debug.Log("[bfinfo]修正build-id: " + buildIdLine);
|
||||
break;
|
||||
}
|
||||
}
|
||||
reader.Close();
|
||||
reader.Dispose();
|
||||
// var reader = new StreamReader(new FileStream(manifestPath, FileMode.Open));
|
||||
// string buildIdLine;
|
||||
// while ((buildIdLine = reader.ReadLine()) != null)
|
||||
// {
|
||||
// if (buildIdLine.Contains("unity.build-id"))
|
||||
// {
|
||||
// Debug.Log("[bfinfo]修正build-id: " + buildIdLine);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// reader.Close();
|
||||
// reader.Dispose();
|
||||
|
||||
if (Directory.Exists(javaPath))
|
||||
{
|
||||
@ -326,71 +292,62 @@ namespace BFEditor.Build
|
||||
di.Delete(true);
|
||||
}
|
||||
|
||||
BFEditorUtils.CopyDir(GoogleCommonProjectPath, dir);
|
||||
// 获取到google_common复制过去的build.gradle和AndroidManifest
|
||||
var buildGradlePath = Path.Combine(dir, "launcher/build.gradle");
|
||||
var text = File.ReadAllText(buildGradlePath);
|
||||
var regex = new Regex("REPLACE_APPLICATION_ID");
|
||||
text = regex.Replace(text, buildInfo.bundleName);
|
||||
File.WriteAllText(buildGradlePath, text);
|
||||
// 如果是俄罗斯支付 则需要覆盖为俄罗斯相关文件
|
||||
// if (buildInfo.bundleName == BF.BFPlatform.ANDROID_GP_PACKAGE_NAME_RU)
|
||||
// {
|
||||
// BFEditorUtils.CopyDir(RuProjectPath, dir);
|
||||
// // 获取到build.gradle和AndroidManifest
|
||||
// var buildGradlePath = Path.Combine(dir, "launcher/build.gradle");
|
||||
// var text = File.ReadAllText(buildGradlePath);
|
||||
// var regex = new Regex("REPLACE_APPLICATION_ID");
|
||||
// text = regex.Replace(text, buildInfo.bundleName);
|
||||
// File.WriteAllText(buildGradlePath, text);
|
||||
|
||||
var androidManifestPath = Path.Combine(dir, "launcher/src/main/AndroidManifest.xml");
|
||||
text = File.ReadAllText(androidManifestPath);
|
||||
regex = new Regex("REPLACE_APPLICATION_ID");
|
||||
text = regex.Replace(text, buildInfo.bundleName);
|
||||
File.WriteAllText(androidManifestPath, text);
|
||||
// var androidManifestPath = Path.Combine(dir, "launcher/src/main/AndroidManifest.xml");
|
||||
// text = File.ReadAllText(androidManifestPath);
|
||||
// regex = new Regex("REPLACE_APPLICATION_ID");
|
||||
// text = regex.Replace(text, buildInfo.bundleName);
|
||||
// File.WriteAllText(androidManifestPath, text);
|
||||
|
||||
BFEditorUtils.CopyDir(asProjectPath, dir);
|
||||
// // 还有另一个AndroidManifest
|
||||
// androidManifestPath = Path.Combine(dir, "unityLibrary/src/main/AndroidManifest.xml");
|
||||
// text = File.ReadAllText(androidManifestPath);
|
||||
// regex = new Regex("REPLACE_APPLICATION_ID");
|
||||
// text = regex.Replace(text, buildInfo.bundleName);
|
||||
// File.WriteAllText(androidManifestPath, text);
|
||||
// }
|
||||
// // 否则使用通用谷歌
|
||||
// else
|
||||
// {
|
||||
BFEditorUtils.CopyDir(GoogleCommonProjectPath, dir);
|
||||
// 获取到google_common复制过去的build.gradle和AndroidManifest
|
||||
var buildGradlePath = Path.Combine(dir, "launcher/build.gradle");
|
||||
var text = File.ReadAllText(buildGradlePath);
|
||||
var regex = new Regex("REPLACE_APPLICATION_ID");
|
||||
text = regex.Replace(text, buildInfo.bundleName);
|
||||
File.WriteAllText(buildGradlePath, text);
|
||||
|
||||
text = File.ReadAllText(manifestPath);
|
||||
regex = new Regex("REPLACE_BUILD_ID");
|
||||
text = regex.Replace(text, buildIdLine);
|
||||
File.WriteAllText(manifestPath, text);
|
||||
}
|
||||
var androidManifestPath = Path.Combine(dir, "launcher/src/main/AndroidManifest.xml");
|
||||
text = File.ReadAllText(androidManifestPath);
|
||||
regex = new Regex("REPLACE_APPLICATION_ID");
|
||||
text = regex.Replace(text, buildInfo.bundleName);
|
||||
File.WriteAllText(androidManifestPath, text);
|
||||
|
||||
/// <summary>
|
||||
/// 合并gp工程
|
||||
/// </summary>
|
||||
static void MergeGPToReleaseProject(BuildInfo buildInfo)
|
||||
{
|
||||
Debug.Log("[bfinfo]正在整合gp渠道sdk...");
|
||||
|
||||
var javaPath = GradleExcuteProjectPath + "/src/main/java";
|
||||
var manifestPath = GradleExcuteProjectPath + "/src/main/AndroidManifest.xml";
|
||||
|
||||
// 获取到unity打出的build-id
|
||||
var reader = new StreamReader(new FileStream(manifestPath, FileMode.Open));
|
||||
string buildIdLine;
|
||||
while ((buildIdLine = reader.ReadLine()) != null)
|
||||
{
|
||||
if (buildIdLine.Contains("unity.build-id"))
|
||||
{
|
||||
Debug.Log("[bfinfo]修正build-id: " + buildIdLine);
|
||||
break;
|
||||
}
|
||||
}
|
||||
reader.Close();
|
||||
reader.Dispose();
|
||||
|
||||
if (Directory.Exists(javaPath))
|
||||
{
|
||||
var di = new DirectoryInfo(javaPath);
|
||||
di.Delete(true);
|
||||
}
|
||||
|
||||
if (buildInfo.IsGPOfficial())
|
||||
BFEditorUtils.CopyDir(asProjectPath, dir);
|
||||
// 还有dz_google_apk下的AndroidManifest
|
||||
androidManifestPath = Path.Combine(dir, "unityLibrary/src/main/AndroidManifest.xml");
|
||||
text = File.ReadAllText(androidManifestPath);
|
||||
regex = new Regex("REPLACE_APPLICATION_ID");
|
||||
text = regex.Replace(text, buildInfo.bundleName);
|
||||
File.WriteAllText(androidManifestPath, text);
|
||||
// }
|
||||
// 统一替换google-services文件
|
||||
var gsPath = Path.Combine(GoogleServicesProjectPath, Path.Combine(buildInfo.bundleName, "google-services.json"));
|
||||
if (File.Exists(gsPath))
|
||||
{
|
||||
BFEditorUtils.CopyDir(GPOfficialAsProjectPath, GradleExcuteProjectPath);
|
||||
var destFilePath = Path.Combine(dir, "launcher/google-services.json");
|
||||
File.Copy(gsPath, destFilePath, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
BFEditorUtils.CopyDir(GPAsProjectPath, GradleExcuteProjectPath);
|
||||
}
|
||||
|
||||
var text = File.ReadAllText(manifestPath);
|
||||
var regex = new Regex("REPLACE_BUILD_ID");
|
||||
text = regex.Replace(text, buildIdLine);
|
||||
File.WriteAllText(manifestPath, text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -413,7 +370,7 @@ namespace BFEditor.Build
|
||||
text2 = regex2.Replace(text2, string.Format("versionName '{0}'", versionName));
|
||||
File.WriteAllText(gradleFilePath2, text2);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 内网Release包接入Bugly
|
||||
/// </summary>
|
||||
@ -429,7 +386,7 @@ namespace BFEditor.Build
|
||||
"implementation 'com.tencent.bugly:crashreport:latest.release'\n" +
|
||||
"implementation 'com.tencent.bugly:nativecrashreport:latest.release'\n");
|
||||
File.WriteAllText(gradleFilePath, text);
|
||||
|
||||
|
||||
// 修改AndroidManifest.xml
|
||||
var manifestPath = GradleExcuteProjectPath + "/src/main/AndroidManifest.xml";
|
||||
text = File.ReadAllText(manifestPath);
|
||||
@ -442,7 +399,7 @@ namespace BFEditor.Build
|
||||
"<uses-permission android:name='android.permission.READ_LOGS' />\n" +
|
||||
"<uses-permission android:name='android.permission.POST_NOTIFICATIONS'/>\n");
|
||||
File.WriteAllText(manifestPath, text);
|
||||
|
||||
|
||||
// 修改UnityPlayerActivity.java
|
||||
var javaPath = GradleExcuteProjectPath + "/src/main/java/com/juzu/ub/release/android/UnityPlayerActivity.java";
|
||||
text = File.ReadAllText(javaPath);
|
||||
@ -458,7 +415,7 @@ namespace BFEditor.Build
|
||||
text = text.Insert(index + length, formatInsertString);
|
||||
File.WriteAllText(javaPath, text);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// release包加密后签名
|
||||
/// </summary>
|
||||
@ -477,7 +434,7 @@ namespace BFEditor.Build
|
||||
});
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// gp包对齐
|
||||
/// </summary>
|
||||
@ -524,7 +481,7 @@ namespace BFEditor.Build
|
||||
{
|
||||
// 将release的so复制到bugly文件下
|
||||
BFEditorUtils.CopyDir(ReleaseSOPath, BuglySOPath);
|
||||
|
||||
|
||||
// 开启Thread处理打包so和上传
|
||||
TryCloseUploadThread();
|
||||
var args = "bugly.sh" + " " + BUGLY_APP_ID + " " + BUGLY_APP_KEY + " " + bundleName + " " + version;
|
||||
@ -532,7 +489,7 @@ namespace BFEditor.Build
|
||||
buglyUploadThread.IsBackground = true;
|
||||
buglyUploadThread.Start();
|
||||
}
|
||||
|
||||
|
||||
static void UploadBuglySymbol(string args)
|
||||
{
|
||||
BFEditorUtils.RunCommond("sh", args, BuglyPath,
|
||||
@ -544,10 +501,10 @@ namespace BFEditor.Build
|
||||
{
|
||||
Debug.LogError("[bferror] UploadBuglySymbol: " + errorMsg);
|
||||
});
|
||||
|
||||
|
||||
TryCloseUploadThread();
|
||||
}
|
||||
|
||||
|
||||
static void TryCloseUploadThread()
|
||||
{
|
||||
if (buglyUploadThread != null)
|
||||
|
||||
@ -1,348 +1,348 @@
|
||||
#if UNITY_EDITOR_OSX
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Build.Reporting;
|
||||
using UnityEditor.iOS.Xcode;
|
||||
using System.IO;
|
||||
#endif
|
||||
// #if UNITY_EDITOR_OSX
|
||||
// using UnityEngine;
|
||||
// using UnityEditor;
|
||||
// using UnityEditor.Build.Reporting;
|
||||
// using UnityEditor.iOS.Xcode;
|
||||
// using System.IO;
|
||||
// #endif
|
||||
|
||||
namespace BFEditor.Build
|
||||
{
|
||||
public static class BuildIOSUtils
|
||||
{
|
||||
#if UNITY_EDITOR_OSX
|
||||
const string IOS_DEFINE_SYMBOLS = "THREAD_SAFE;USE_AB";
|
||||
const string DEV_XCODE_LOCAL_PATH = "BFVersions/ios/dev";
|
||||
const string RELEASE_XCODE_LOCAL_PATH = "BFVersions/ios/release";
|
||||
// namespace BFEditor.Build
|
||||
// {
|
||||
// public static class BuildIOSUtils
|
||||
// {
|
||||
// #if UNITY_EDITOR_OSX
|
||||
// const string IOS_DEFINE_SYMBOLS = "THREAD_SAFE;USE_AB";
|
||||
// const string DEV_XCODE_LOCAL_PATH = "BFVersions/ios/dev";
|
||||
// const string RELEASE_XCODE_LOCAL_PATH = "BFVersions/ios/release";
|
||||
|
||||
static string devXCodePath = Application.dataPath + "/../" + DEV_XCODE_LOCAL_PATH;
|
||||
static string releaseXCodePath = Application.dataPath + "/../" + RELEASE_XCODE_LOCAL_PATH;
|
||||
static string devOptionsPListPath = Application.dataPath + "/../" + "BFVersions/ios/exports/dev/ExportOptions.plist";
|
||||
static string releaseOptionsPListPath = Application.dataPath + "/../" + "BFVersions/ios/exports/release/ExportOptions.plist";
|
||||
static string publishOptionsPListPath = Application.dataPath + "/../" + "BFVersions/ios/exports/dis/ExportOptions.plist";
|
||||
// static string devXCodePath = Application.dataPath + "/../" + DEV_XCODE_LOCAL_PATH;
|
||||
// static string releaseXCodePath = Application.dataPath + "/../" + RELEASE_XCODE_LOCAL_PATH;
|
||||
// static string devOptionsPListPath = Application.dataPath + "/../" + "BFVersions/ios/exports/dev/ExportOptions.plist";
|
||||
// static string releaseOptionsPListPath = Application.dataPath + "/../" + "BFVersions/ios/exports/release/ExportOptions.plist";
|
||||
// static string publishOptionsPListPath = Application.dataPath + "/../" + "BFVersions/ios/exports/dis/ExportOptions.plist";
|
||||
|
||||
public static bool BuildIOSPlayer(BuildInfo buildInfo)
|
||||
{
|
||||
var buildTarget = BuildTarget.iOS;
|
||||
// public static bool BuildIOSPlayer(BuildInfo buildInfo)
|
||||
// {
|
||||
// var buildTarget = BuildTarget.iOS;
|
||||
|
||||
// 检查平台
|
||||
if (EditorUserBuildSettings.activeBuildTarget != buildTarget)
|
||||
{
|
||||
Debug.LogError("[bferror]当前没有在对应平台");
|
||||
return false;
|
||||
}
|
||||
// // 检查平台
|
||||
// if (EditorUserBuildSettings.activeBuildTarget != buildTarget)
|
||||
// {
|
||||
// Debug.LogError("[bferror]当前没有在对应平台");
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// 重新生成XLua
|
||||
CompileScriptsUtils.RegenerateXLuaCode(true);
|
||||
// // 重新生成XLua
|
||||
// CompileScriptsUtils.RegenerateXLuaCode(true);
|
||||
|
||||
// 打包设置
|
||||
BuildSettings(buildInfo);
|
||||
// // 打包设置
|
||||
// BuildSettings(buildInfo);
|
||||
|
||||
// 开始打包
|
||||
var bpOptions = GetBuildOptions(buildInfo);
|
||||
var report = BuildPipeline.BuildPlayer(bpOptions);
|
||||
if (report.summary.result == BuildResult.Succeeded)
|
||||
{
|
||||
return BuildIpaFromXCode(buildInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("[bferror]unity打包xcode失败");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// // 开始打包
|
||||
// var bpOptions = GetBuildOptions(buildInfo);
|
||||
// var report = BuildPipeline.BuildPlayer(bpOptions);
|
||||
// if (report.summary.result == BuildResult.Succeeded)
|
||||
// {
|
||||
// return BuildIpaFromXCode(buildInfo);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Debug.LogError("[bferror]unity打包xcode失败");
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// 打包设置
|
||||
/// </summary>
|
||||
static void BuildSettings(BuildInfo buildInfo)
|
||||
{
|
||||
// 设置bundleVersion
|
||||
PlayerSettings.bundleVersion = buildInfo.version;
|
||||
// /// <summary>
|
||||
// /// 打包设置
|
||||
// /// </summary>
|
||||
// static void BuildSettings(BuildInfo buildInfo)
|
||||
// {
|
||||
// // 设置bundleVersion
|
||||
// PlayerSettings.bundleVersion = buildInfo.version;
|
||||
|
||||
// 设置buildNumber
|
||||
PlayerSettings.iOS.buildNumber = buildInfo.version_code.ToString();
|
||||
// // 设置buildNumber
|
||||
// PlayerSettings.iOS.buildNumber = buildInfo.versionCode.ToString();
|
||||
|
||||
// 设置竖屏
|
||||
PlayerSettings.defaultInterfaceOrientation = UIOrientation.Portrait;
|
||||
PlayerSettings.allowedAutorotateToPortrait = false;
|
||||
PlayerSettings.allowedAutorotateToPortraitUpsideDown = false;
|
||||
PlayerSettings.allowedAutorotateToLandscapeLeft = false;
|
||||
PlayerSettings.allowedAutorotateToLandscapeRight = false;
|
||||
// // 设置竖屏
|
||||
// PlayerSettings.defaultInterfaceOrientation = UIOrientation.Portrait;
|
||||
// PlayerSettings.allowedAutorotateToPortrait = false;
|
||||
// PlayerSettings.allowedAutorotateToPortraitUpsideDown = false;
|
||||
// PlayerSettings.allowedAutorotateToLandscapeLeft = false;
|
||||
// PlayerSettings.allowedAutorotateToLandscapeRight = false;
|
||||
|
||||
// 允许Xcode根据appleDeveloperTeamID自动签署应用程序
|
||||
PlayerSettings.iOS.appleEnableAutomaticSigning = !buildInfo.IsPublish();
|
||||
// // 允许Xcode根据appleDeveloperTeamID自动签署应用程序
|
||||
// PlayerSettings.iOS.appleEnableAutomaticSigning = !buildInfo.IsPublish();
|
||||
|
||||
// 使用手动签名时iOS资源调配配置文件的类型,自动
|
||||
PlayerSettings.iOS.iOSManualProvisioningProfileType = buildInfo.IsPublish() ? ProvisioningProfileType.Distribution : ProvisioningProfileType.Automatic;
|
||||
// // 使用手动签名时iOS资源调配配置文件的类型,自动
|
||||
// PlayerSettings.iOS.iOSManualProvisioningProfileType = buildInfo.IsPublish() ? ProvisioningProfileType.Distribution : ProvisioningProfileType.Automatic;
|
||||
|
||||
// 关闭启动动画
|
||||
PlayerSettings.SplashScreen.show = false;
|
||||
// // 关闭启动动画
|
||||
// PlayerSettings.SplashScreen.show = false;
|
||||
|
||||
// 设置包名
|
||||
PlayerSettings.SetApplicationIdentifier(BuildTargetGroup.iOS, buildInfo.bundleName);
|
||||
Debug.Log("[bfinfo]设置包名:" + buildInfo.bundleName);
|
||||
// // 设置包名
|
||||
// PlayerSettings.SetApplicationIdentifier(BuildTargetGroup.iOS, buildInfo.bundleName);
|
||||
// Debug.Log("[bfinfo]设置包名:" + buildInfo.bundleName);
|
||||
|
||||
// 是否跳过版本控制
|
||||
var symbols = IOS_DEFINE_SYMBOLS;
|
||||
if (buildInfo.skipVersion)
|
||||
{
|
||||
symbols = symbols + ";SKIP_VERSION;";
|
||||
}
|
||||
// // 是否跳过版本控制
|
||||
// var symbols = IOS_DEFINE_SYMBOLS;
|
||||
// if (buildInfo.skipVersion)
|
||||
// {
|
||||
// symbols = symbols + ";SKIP_VERSION;";
|
||||
// }
|
||||
|
||||
|
||||
PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.iOS, symbols);
|
||||
Debug.Log("[bfinfo]设置defineSymbols: " + symbols);
|
||||
// PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.iOS, symbols);
|
||||
// Debug.Log("[bfinfo]设置defineSymbols: " + symbols);
|
||||
|
||||
// 是否是dev
|
||||
var development = buildInfo.IsDevChannel();
|
||||
EditorUserBuildSettings.development = development;
|
||||
// // 是否是dev
|
||||
// var development = buildInfo.IsDevChannel();
|
||||
// EditorUserBuildSettings.development = development;
|
||||
|
||||
// 商品名称
|
||||
if (buildInfo.IsPublish())
|
||||
{
|
||||
PlayerSettings.productName = "Heroic Expedition";
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayerSettings.productName = development ? "b6-dev" : "b6-release";
|
||||
}
|
||||
// // 商品名称
|
||||
// if (buildInfo.IsPublish())
|
||||
// {
|
||||
// PlayerSettings.productName = "Heroic Expedition";
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// PlayerSettings.productName = development ? "b6-dev" : "b6-release";
|
||||
// }
|
||||
|
||||
// BuildType设置dev/release
|
||||
EditorUserBuildSettings.iOSBuildConfigType = development ? iOSBuildType.Debug : iOSBuildType.Release;
|
||||
// // BuildType设置dev/release
|
||||
// EditorUserBuildSettings.iOSXcodeBuildConfig = development ? XcodeBuildConfig.Debug : XcodeBuildConfig.Release;
|
||||
|
||||
// 使用IL2CPP
|
||||
var scriptImp = ScriptingImplementation.IL2CPP;
|
||||
PlayerSettings.SetScriptingBackend(BuildTargetGroup.iOS, scriptImp);
|
||||
// // 使用IL2CPP
|
||||
// var scriptImp = ScriptingImplementation.IL2CPP;
|
||||
// PlayerSettings.SetScriptingBackend(BuildTargetGroup.iOS, scriptImp);
|
||||
|
||||
// 目标平台架构,目前支持ARM64
|
||||
PlayerSettings.SetArchitecture(BuildTargetGroup.iOS, 1);
|
||||
}
|
||||
// // 目标平台架构,目前支持ARM64
|
||||
// PlayerSettings.SetArchitecture(BuildTargetGroup.iOS, 1);
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// 获取打包参数
|
||||
/// </summary>
|
||||
static BuildPlayerOptions GetBuildOptions(BuildInfo buildInfo)
|
||||
{
|
||||
var bpOptions = new BuildPlayerOptions();
|
||||
bpOptions.scenes = AssetBundleUtils.GetBuildScenes();
|
||||
bpOptions.target = BuildTarget.iOS;
|
||||
// /// <summary>
|
||||
// /// 获取打包参数
|
||||
// /// </summary>
|
||||
// static BuildPlayerOptions GetBuildOptions(BuildInfo buildInfo)
|
||||
// {
|
||||
// var bpOptions = new BuildPlayerOptions();
|
||||
// bpOptions.scenes = AssetBundleUtils.GetBuildScenes();
|
||||
// bpOptions.target = BuildTarget.iOS;
|
||||
|
||||
var path = buildInfo.IsReleaseChannel() ? RELEASE_XCODE_LOCAL_PATH : DEV_XCODE_LOCAL_PATH;
|
||||
bpOptions.locationPathName = path;
|
||||
Debug.Log("[bfinfo]xcode path : " + path);
|
||||
var absolutePath = buildInfo.IsReleaseChannel() ? releaseXCodePath : devXCodePath;
|
||||
if (Directory.Exists(absolutePath))
|
||||
{
|
||||
Directory.Delete(absolutePath, true);
|
||||
}
|
||||
// var path = buildInfo.IsReleaseChannel() ? RELEASE_XCODE_LOCAL_PATH : DEV_XCODE_LOCAL_PATH;
|
||||
// bpOptions.locationPathName = path;
|
||||
// Debug.Log("[bfinfo]xcode path : " + path);
|
||||
// var absolutePath = buildInfo.IsReleaseChannel() ? releaseXCodePath : devXCodePath;
|
||||
// if (Directory.Exists(absolutePath))
|
||||
// {
|
||||
// Directory.Delete(absolutePath, true);
|
||||
// }
|
||||
|
||||
if (!buildInfo.IsPublish())
|
||||
{
|
||||
var options = BuildOptions.Development | BuildOptions.ConnectWithProfiler | BuildOptions.AllowDebugging;
|
||||
bpOptions.options = options;
|
||||
}
|
||||
return bpOptions;
|
||||
}
|
||||
// if (!buildInfo.IsPublish())
|
||||
// {
|
||||
// var options = BuildOptions.Development | BuildOptions.ConnectWithProfiler | BuildOptions.AllowDebugging;
|
||||
// bpOptions.options = options;
|
||||
// }
|
||||
// return bpOptions;
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// 打包ipa
|
||||
/// </summary>
|
||||
static bool BuildIpaFromXCode(BuildInfo buildInfo)
|
||||
{
|
||||
// 修改XCode设置
|
||||
FixXCodeProject(buildInfo);
|
||||
// /// <summary>
|
||||
// /// 打包ipa
|
||||
// /// </summary>
|
||||
// static bool BuildIpaFromXCode(BuildInfo buildInfo)
|
||||
// {
|
||||
// // 修改XCode设置
|
||||
// FixXCodeProject(buildInfo);
|
||||
|
||||
// 权限
|
||||
UnlockKeyChain();
|
||||
// // 权限
|
||||
// UnlockKeyChain();
|
||||
|
||||
// archive
|
||||
if (!Archive(buildInfo))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// // archive
|
||||
// if (!Archive(buildInfo))
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// 导出ipa
|
||||
if (!ExportIpa(buildInfo))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// // 导出ipa
|
||||
// if (!ExportIpa(buildInfo))
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
// return true;
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// xCode工程设置
|
||||
/// </summary>
|
||||
static void FixXCodeProject(BuildInfo buildInfo)
|
||||
{
|
||||
var isDev = buildInfo.IsDevChannel();
|
||||
var xCodeProjectPath = isDev ? devXCodePath : releaseXCodePath;
|
||||
// /// <summary>
|
||||
// /// xCode工程设置
|
||||
// /// </summary>
|
||||
// static void FixXCodeProject(BuildInfo buildInfo)
|
||||
// {
|
||||
// var isDev = buildInfo.IsDevChannel();
|
||||
// var xCodeProjectPath = isDev ? devXCodePath : releaseXCodePath;
|
||||
|
||||
var path = xCodeProjectPath + "/Unity-iPhone.xcodeproj/project.pbxproj";
|
||||
var pbxProject = new PBXProject();
|
||||
pbxProject.ReadFromFile(path);
|
||||
var targetGuid = pbxProject.TargetGuidByName("Unity-iPhone");
|
||||
pbxProject.AddBuildProperty(targetGuid, "OTHER_LDFLAGS", "-ObjC");
|
||||
pbxProject.SetBuildProperty(targetGuid, "ENABLE_BITCODE", "NO");
|
||||
pbxProject.SetBuildProperty(targetGuid, "ENABLE_BITCODE", "NO");
|
||||
pbxProject.SetBuildProperty(targetGuid, "DEVELOPMENT_TEAM", "49QQW8856Q");
|
||||
if (buildInfo.IsPublish())
|
||||
{
|
||||
pbxProject.SetBuildProperty(targetGuid, "PROVISIONING_PROFILE_SPECIFIER", "ub_appstore_dis");
|
||||
}
|
||||
// var path = xCodeProjectPath + "/Unity-iPhone.xcodeproj/project.pbxproj";
|
||||
// var pbxProject = new PBXProject();
|
||||
// pbxProject.ReadFromFile(path);
|
||||
// var targetGuid = pbxProject.TargetGuidByName("Unity-iPhone");
|
||||
// pbxProject.AddBuildProperty(targetGuid, "OTHER_LDFLAGS", "-ObjC");
|
||||
// pbxProject.SetBuildProperty(targetGuid, "ENABLE_BITCODE", "NO");
|
||||
// pbxProject.SetBuildProperty(targetGuid, "ENABLE_BITCODE", "NO");
|
||||
// pbxProject.SetBuildProperty(targetGuid, "DEVELOPMENT_TEAM", "49QQW8856Q");
|
||||
// if (buildInfo.IsPublish())
|
||||
// {
|
||||
// pbxProject.SetBuildProperty(targetGuid, "PROVISIONING_PROFILE_SPECIFIER", "ub_appstore_dis");
|
||||
// }
|
||||
|
||||
// 添加系统库
|
||||
AddSystemLibReferenceToProject(pbxProject, targetGuid, "libsqlite3.tbd");
|
||||
AddSystemLibReferenceToProject(pbxProject, targetGuid, "libz.1.tbd");
|
||||
AddSystemLibReferenceToProject(pbxProject, targetGuid, "libiconv.2.tbd");
|
||||
AddSystemLibReferenceToProject(pbxProject, targetGuid, "libresolv.9.tbd");
|
||||
// // 添加系统库
|
||||
// AddSystemLibReferenceToProject(pbxProject, targetGuid, "libsqlite3.tbd");
|
||||
// AddSystemLibReferenceToProject(pbxProject, targetGuid, "libz.1.tbd");
|
||||
// AddSystemLibReferenceToProject(pbxProject, targetGuid, "libiconv.2.tbd");
|
||||
// AddSystemLibReferenceToProject(pbxProject, targetGuid, "libresolv.9.tbd");
|
||||
|
||||
var pListPath = Path.Combine(xCodeProjectPath, "Info.plist");
|
||||
var pList = new PlistDocument();
|
||||
pList.ReadFromFile(pListPath);
|
||||
// var pListPath = Path.Combine(xCodeProjectPath, "Info.plist");
|
||||
// var pList = new PlistDocument();
|
||||
// pList.ReadFromFile(pListPath);
|
||||
|
||||
// 版本号
|
||||
var vKey = "CFBundleShortVersionString";
|
||||
var vValue = new PlistElementString(buildInfo.version);
|
||||
var pListRoot = pList.root;
|
||||
var rootDict = pListRoot.values;
|
||||
if (!rootDict.ContainsKey(vKey))
|
||||
{
|
||||
rootDict.Add(vKey, vValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
rootDict[vKey] = vValue;
|
||||
}
|
||||
// // 版本号
|
||||
// var vKey = "CFBundleShortVersionString";
|
||||
// var vValue = new PlistElementString(buildInfo.version);
|
||||
// var pListRoot = pList.root;
|
||||
// var rootDict = pListRoot.values;
|
||||
// if (!rootDict.ContainsKey(vKey))
|
||||
// {
|
||||
// rootDict.Add(vKey, vValue);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// rootDict[vKey] = vValue;
|
||||
// }
|
||||
|
||||
// VersionCode
|
||||
var vCodeKey = "CFBundleVersion";
|
||||
var vCodeValue = new PlistElementString(buildInfo.version_code.ToString());
|
||||
if (!rootDict.ContainsKey(vCodeKey))
|
||||
{
|
||||
rootDict.Add(vCodeKey, vCodeValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
rootDict[vCodeKey] = vCodeValue;
|
||||
}
|
||||
// // VersionCode
|
||||
// var vCodeKey = "CFBundleVersion";
|
||||
// var vCodeValue = new PlistElementString(buildInfo.versionCode.ToString());
|
||||
// if (!rootDict.ContainsKey(vCodeKey))
|
||||
// {
|
||||
// rootDict.Add(vCodeKey, vCodeValue);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// rootDict[vCodeKey] = vCodeValue;
|
||||
// }
|
||||
|
||||
// 数美SDK会使用位置,必须加入这个说明
|
||||
var localtionKey = "NSLocationWhenInUseUsageDescription";
|
||||
var localtionValue = new PlistElementString("We use your location to give you a better localization.");
|
||||
if (!rootDict.ContainsKey(localtionKey))
|
||||
{
|
||||
rootDict.Add(localtionKey, localtionValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
rootDict[localtionKey] = localtionValue;
|
||||
}
|
||||
// // 数美SDK会使用位置,必须加入这个说明
|
||||
// var localtionKey = "NSLocationWhenInUseUsageDescription";
|
||||
// var localtionValue = new PlistElementString("We use your location to give you a better localization.");
|
||||
// if (!rootDict.ContainsKey(localtionKey))
|
||||
// {
|
||||
// rootDict.Add(localtionKey, localtionValue);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// rootDict[localtionKey] = localtionValue;
|
||||
// }
|
||||
|
||||
// 提审提示缺少出口合规证明,这里直接设置为false即可
|
||||
var encryptionKey = "ITSAppUsesNonExemptEncryption";
|
||||
var encryptionValue = new PlistElementBoolean(false);
|
||||
if (!rootDict.ContainsKey(encryptionKey))
|
||||
{
|
||||
rootDict.Add(encryptionKey, encryptionValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
rootDict[encryptionKey] = encryptionValue;
|
||||
}
|
||||
// // 提审提示缺少出口合规证明,这里直接设置为false即可
|
||||
// var encryptionKey = "ITSAppUsesNonExemptEncryption";
|
||||
// var encryptionValue = new PlistElementBoolean(false);
|
||||
// if (!rootDict.ContainsKey(encryptionKey))
|
||||
// {
|
||||
// rootDict.Add(encryptionKey, encryptionValue);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// rootDict[encryptionKey] = encryptionValue;
|
||||
// }
|
||||
|
||||
pList.WriteToFile(pListPath);
|
||||
pbxProject.WriteToFile(path);
|
||||
}
|
||||
// pList.WriteToFile(pListPath);
|
||||
// pbxProject.WriteToFile(path);
|
||||
// }
|
||||
|
||||
//添加系统lib方法
|
||||
static void AddSystemLibReferenceToProject(PBXProject pbxProject, string targetGuid, string lib)
|
||||
{
|
||||
var fileGuid = pbxProject.AddFile("usr/lib/" + lib, "Frameworks/" + lib, PBXSourceTree.Sdk);
|
||||
pbxProject.AddFileToBuild(targetGuid, fileGuid);
|
||||
}
|
||||
// //添加系统lib方法
|
||||
// static void AddSystemLibReferenceToProject(PBXProject pbxProject, string targetGuid, string lib)
|
||||
// {
|
||||
// var fileGuid = pbxProject.AddFile("usr/lib/" + lib, "Frameworks/" + lib, PBXSourceTree.Sdk);
|
||||
// pbxProject.AddFileToBuild(targetGuid, fileGuid);
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Archive
|
||||
/// </summary>
|
||||
static bool Archive(BuildInfo buildInfo)
|
||||
{
|
||||
Debug.Log("[bfinfo]正在archive...");
|
||||
var result = true;
|
||||
var xCodeProjectPath = buildInfo.IsDevChannel() ? devXCodePath : releaseXCodePath;
|
||||
var archivePath = xCodeProjectPath + "/build/archive/Unity-iPhone.xcarchive";
|
||||
var args = string.Format("archive -scheme Unity-iPhone -configuration Release -archivePath {0}", archivePath);
|
||||
BFEditorUtils.RunCommond("xcodebuild", args, xCodeProjectPath,
|
||||
(info) =>
|
||||
{
|
||||
Debug.Log(info);
|
||||
},
|
||||
(error) =>
|
||||
{
|
||||
if (error.Contains("ARCHIVE FAILED")) // 失败标志
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
Debug.LogError("[bferror] " + error);
|
||||
}
|
||||
);
|
||||
// /// <summary>
|
||||
// /// Archive
|
||||
// /// </summary>
|
||||
// static bool Archive(BuildInfo buildInfo)
|
||||
// {
|
||||
// Debug.Log("[bfinfo]正在archive...");
|
||||
// var result = true;
|
||||
// var xCodeProjectPath = buildInfo.IsDevChannel() ? devXCodePath : releaseXCodePath;
|
||||
// var archivePath = xCodeProjectPath + "/build/archive/Unity-iPhone.xcarchive";
|
||||
// var args = string.Format("archive -scheme Unity-iPhone -configuration Release -archivePath {0}", archivePath);
|
||||
// BFEditorUtils.RunCommond("xcodebuild", args, xCodeProjectPath,
|
||||
// (info) =>
|
||||
// {
|
||||
// Debug.Log(info);
|
||||
// },
|
||||
// (error) =>
|
||||
// {
|
||||
// if (error.Contains("ARCHIVE FAILED")) // 失败标志
|
||||
// {
|
||||
// result = false;
|
||||
// }
|
||||
// Debug.LogError("[bferror] " + error);
|
||||
// }
|
||||
// );
|
||||
|
||||
return result;
|
||||
}
|
||||
// return result;
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// 导出ipa
|
||||
/// </summary>
|
||||
static bool ExportIpa(BuildInfo buildInfo)
|
||||
{
|
||||
Debug.Log("[bfinfo]正在导出ipa...");
|
||||
var result = false;
|
||||
var xCodeProjectPath = buildInfo.IsDevChannel() ? devXCodePath : releaseXCodePath;
|
||||
string exportPListPath;
|
||||
if (buildInfo.IsPublish())
|
||||
{
|
||||
exportPListPath = publishOptionsPListPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
exportPListPath = buildInfo.IsDevChannel() ? devOptionsPListPath : releaseOptionsPListPath;
|
||||
}
|
||||
var ipaPath = xCodeProjectPath + "/build/ipa";
|
||||
var archivePath = xCodeProjectPath + "/build/archive/Unity-iPhone.xcarchive";
|
||||
var args = string.Format("-exportArchive -archivePath {0} -exportPath {1} -exportOptionsPlist {2} -allowProvisioningUpdates", archivePath, ipaPath, exportPListPath);
|
||||
BFEditorUtils.RunCommond("xcodebuild", args, null,
|
||||
(info) =>
|
||||
{
|
||||
if(info.Contains("EXPORT SUCCEEDED"))
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
},
|
||||
(error) =>
|
||||
{
|
||||
}
|
||||
);
|
||||
// /// <summary>
|
||||
// /// 导出ipa
|
||||
// /// </summary>
|
||||
// static bool ExportIpa(BuildInfo buildInfo)
|
||||
// {
|
||||
// Debug.Log("[bfinfo]正在导出ipa...");
|
||||
// var result = false;
|
||||
// var xCodeProjectPath = buildInfo.IsDevChannel() ? devXCodePath : releaseXCodePath;
|
||||
// string exportPListPath;
|
||||
// if (buildInfo.IsPublish())
|
||||
// {
|
||||
// exportPListPath = publishOptionsPListPath;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// exportPListPath = buildInfo.IsDevChannel() ? devOptionsPListPath : releaseOptionsPListPath;
|
||||
// }
|
||||
// var ipaPath = xCodeProjectPath + "/build/ipa";
|
||||
// var archivePath = xCodeProjectPath + "/build/archive/Unity-iPhone.xcarchive";
|
||||
// var args = string.Format("-exportArchive -archivePath {0} -exportPath {1} -exportOptionsPlist {2} -allowProvisioningUpdates", archivePath, ipaPath, exportPListPath);
|
||||
// BFEditorUtils.RunCommond("xcodebuild", args, null,
|
||||
// (info) =>
|
||||
// {
|
||||
// if(info.Contains("EXPORT SUCCEEDED"))
|
||||
// {
|
||||
// result = true;
|
||||
// }
|
||||
// },
|
||||
// (error) =>
|
||||
// {
|
||||
// }
|
||||
// );
|
||||
|
||||
return result;
|
||||
}
|
||||
// return result;
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// 远程打包签名ipa时需要钥匙串权限
|
||||
/// </summary>
|
||||
static void UnlockKeyChain()
|
||||
{
|
||||
BFEditorUtils.RunCommond("security", "-v unlock-keychain -p '123456' /Users/aoddabao/Library/Keychains/login.keychain-db", null,
|
||||
(msg) =>
|
||||
{
|
||||
Debug.Log(msg);
|
||||
},
|
||||
(msg) =>
|
||||
{
|
||||
Debug.LogError(msg);
|
||||
}
|
||||
);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
// /// <summary>
|
||||
// /// 远程打包签名ipa时需要钥匙串权限
|
||||
// /// </summary>
|
||||
// static void UnlockKeyChain()
|
||||
// {
|
||||
// BFEditorUtils.RunCommond("security", "-v unlock-keychain -p '123456' /Users/aoddabao/Library/Keychains/login.keychain-db", null,
|
||||
// (msg) =>
|
||||
// {
|
||||
// Debug.Log(msg);
|
||||
// },
|
||||
// (msg) =>
|
||||
// {
|
||||
// Debug.LogError(msg);
|
||||
// }
|
||||
// );
|
||||
// }
|
||||
// #endif
|
||||
// }
|
||||
// }
|
||||
|
||||
@ -85,6 +85,9 @@ namespace BFEditor
|
||||
{
|
||||
//加载lua配置测试
|
||||
LuaEnv env = new LuaEnv();
|
||||
env.DoString(@"
|
||||
print('当前 Lua 版本: ' .. _VERSION) -- 输出 Lua 5.1
|
||||
");
|
||||
env.AddLoader((ref string scriptPath) =>
|
||||
{
|
||||
var text = LoadGameLuaScriptText(scriptPath, isDeveloper);
|
||||
@ -136,58 +139,58 @@ namespace BFEditor
|
||||
var configFileInfos = configDirInfo.GetFiles(suffix, SearchOption.TopDirectoryOnly);
|
||||
|
||||
// 检查棋盘文件格式
|
||||
checkBoard("chapter_board", env, sb);
|
||||
checkBoard("chapter_board_bossrush", env, sb);
|
||||
checkBoard("chapter_board_daily_challenge", env, sb);
|
||||
checkBoard("chapter_board_dungeon_armor", env, sb);
|
||||
checkBoard("chapter_board_dungeon_equip", env, sb);
|
||||
checkBoard("chapter_board_dungeon_gold", env, sb);
|
||||
checkBoard("chapter_board_dungeon_shards", env, sb);
|
||||
checkBoard("chapter_board_rune", env, sb);
|
||||
checkBoard("activity_pvp_board", env, sb);
|
||||
checkBoard("arena_board", env, sb);
|
||||
// checkBoard("chapter_board", env, sb);
|
||||
// checkBoard("chapter_board_bossrush", env, sb);
|
||||
// checkBoard("chapter_board_daily_challenge", env, sb);
|
||||
// checkBoard("chapter_board_dungeon_armor", env, sb);
|
||||
// checkBoard("chapter_board_dungeon_equip", env, sb);
|
||||
// checkBoard("chapter_board_dungeon_gold", env, sb);
|
||||
// checkBoard("chapter_board_dungeon_shards", env, sb);
|
||||
// checkBoard("chapter_board_rune", env, sb);
|
||||
// checkBoard("activity_pvp_board", env, sb);
|
||||
// checkBoard("arena_board", env, sb);
|
||||
|
||||
|
||||
// 检查monster
|
||||
string monsterConfigListLua = "{";
|
||||
foreach (var file in configFileInfos)
|
||||
{
|
||||
var fileName = file.Name.ToLower();
|
||||
if(fileName.Contains("monster_"))
|
||||
{
|
||||
monsterConfigListLua += "'" + fileName.Replace(".lua", "").Replace(".bytes", "") + "',";
|
||||
}
|
||||
}
|
||||
monsterConfigListLua += "}";
|
||||
var luaScriptString = "local ids = {}\n local MONSTER_LIST = " + monsterConfigListLua + "\n";
|
||||
luaScriptString += @"local str = {}
|
||||
for i, name in ipairs(MONSTER_LIST) do
|
||||
if name ~= 'monster_base' and name ~= 'monster_position' and name ~= 'monster_position_base' then
|
||||
local data = require('app/config/' .. name).data
|
||||
for k, v in pairs(data) do
|
||||
if ids[k] then
|
||||
table.insert(str, name .. '和' .. ids[k] .. '存在相同的mosnter id:' .. k)
|
||||
end
|
||||
ids[k] = name
|
||||
end
|
||||
end
|
||||
end
|
||||
if #str > 0 then
|
||||
return table.concat(str, '\n');
|
||||
end
|
||||
return ''";
|
||||
var resultStr = env.DoString(luaScriptString);
|
||||
if (resultStr.Length > 0)
|
||||
{
|
||||
foreach(var strObj in resultStr)
|
||||
{
|
||||
var str = Convert.ToString(strObj);
|
||||
if(!String.IsNullOrEmpty(str))
|
||||
{
|
||||
sb.Append(str + "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
// string monsterConfigListLua = "{";
|
||||
// foreach (var file in configFileInfos)
|
||||
// {
|
||||
// var fileName = file.Name.ToLower();
|
||||
// if(fileName.Contains("monster_"))
|
||||
// {
|
||||
// monsterConfigListLua += "'" + fileName.Replace(".lua", "").Replace(".bytes", "") + "',";
|
||||
// }
|
||||
// }
|
||||
// monsterConfigListLua += "}";
|
||||
// var luaScriptString = "local ids = {}\n local MONSTER_LIST = " + monsterConfigListLua + "\n";
|
||||
// luaScriptString += @"local str = {}
|
||||
// for i, name in ipairs(MONSTER_LIST) do
|
||||
// if name ~= 'monster_base' and name ~= 'monster_position' and name ~= 'monster_position_base' then
|
||||
// local data = require('app/config/' .. name).data
|
||||
// for k, v in pairs(data) do
|
||||
// if ids[k] then
|
||||
// table.insert(str, name .. '和' .. ids[k] .. '存在相同的mosnter id:' .. k)
|
||||
// end
|
||||
// ids[k] = name
|
||||
// end
|
||||
// end
|
||||
// end
|
||||
// if #str > 0 then
|
||||
// return table.concat(str, '\n');
|
||||
// end
|
||||
// return ''";
|
||||
// var resultStr = env.DoString(luaScriptString);
|
||||
// if (resultStr.Length > 0)
|
||||
// {
|
||||
// foreach(var strObj in resultStr)
|
||||
// {
|
||||
// var str = Convert.ToString(strObj);
|
||||
// if(!String.IsNullOrEmpty(str))
|
||||
// {
|
||||
// sb.Append(str + "\n");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// 检查怪物的坐标信息
|
||||
// var luaScriptString2 = @"local MONSTER_POSITION_KEY = { 'monster_1','monster_2','monster_3','monster_4','monster_5','monster_6','monster_7','monster_8','monster_9','monster_10','monster_11','monster_12'}
|
||||
// local list = {'enemy_id_1', 'enemy_id_2', 'enemy_id_3'}
|
||||
|
||||
@ -1,117 +1,117 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Experimental.SceneManagement;
|
||||
|
||||
namespace BFEditor.Resource
|
||||
{
|
||||
public class CheckRaycastTargetWindow : EditorWindow
|
||||
{
|
||||
ShowRaycast raycastHelper;
|
||||
RectTransform rt;
|
||||
Vector2 scrollPos;
|
||||
|
||||
CheckRaycastTargetWindow()
|
||||
{
|
||||
this.titleContent = new GUIContent("检查RaycastTarget");
|
||||
}
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
PrefabStage currentPrefabStage = PrefabStageUtility.GetCurrentPrefabStage();
|
||||
Transform tran;
|
||||
if (currentPrefabStage == null)
|
||||
tran = Selection.activeTransform;
|
||||
else
|
||||
tran = currentPrefabStage.prefabContentsRoot.transform;
|
||||
if (tran != null)
|
||||
rt = tran.GetComponent<RectTransform>();
|
||||
if (rt != null)
|
||||
{
|
||||
raycastHelper = rt.GetComponent<ShowRaycast>();
|
||||
if (raycastHelper == null)
|
||||
raycastHelper = rt.gameObject.AddComponent<ShowRaycast>();
|
||||
raycastHelper.SetEditorWindowMode(true);
|
||||
}
|
||||
}
|
||||
|
||||
void OnGUI()
|
||||
{
|
||||
GUILayout.BeginVertical();
|
||||
EditorGUI.BeginChangeCheck();
|
||||
rt = (RectTransform)EditorGUILayout.ObjectField("", rt, typeof(RectTransform), true, GUILayout.Width(200));
|
||||
GUILayout.Space(6);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
if (raycastHelper != null)
|
||||
DestroyImmediate(raycastHelper);
|
||||
if (rt != null)
|
||||
{
|
||||
raycastHelper = rt.GetComponent<ShowRaycast>();
|
||||
if (raycastHelper == null)
|
||||
raycastHelper = rt.gameObject.AddComponent<ShowRaycast>();
|
||||
raycastHelper.SetEditorWindowMode(true);
|
||||
}
|
||||
}
|
||||
if (raycastHelper != null)
|
||||
{
|
||||
GUILayout.Label(string.Format("raycastTarget组件一共有 {0} 个", raycastHelper.GetTotalCount()));
|
||||
GUILayout.Label("(红色)image " + raycastHelper.GetImageCount() +
|
||||
" (绿色)text " + raycastHelper.GetTextCount());
|
||||
GUILayout.Label("(黄色)emptyRaycast " + raycastHelper.GetEmptyCount() +
|
||||
" (蓝色)rawImage " + raycastHelper.GetRawImageCount());
|
||||
GUILayout.Space(6);
|
||||
scrollPos = GUILayout.BeginScrollView(scrollPos, GUILayout.Width(400), GUILayout.Height(270));
|
||||
List<string> pathList = raycastHelper.GetImagePathList();
|
||||
int i = 0;
|
||||
if (pathList.Count > 0)
|
||||
{
|
||||
GUILayout.Label("image路径:");
|
||||
for (; i < pathList.Count; i++)
|
||||
GUILayout.Label(pathList[i]);
|
||||
}
|
||||
pathList = raycastHelper.GetTextPathList();
|
||||
i = 0;
|
||||
if (pathList.Count > 0)
|
||||
{
|
||||
GUILayout.Label("text路径:");
|
||||
for (; i < pathList.Count; i++)
|
||||
GUILayout.Label(pathList[i]);
|
||||
}
|
||||
pathList = raycastHelper.GetEmptyPathList();
|
||||
i = 0;
|
||||
if (pathList.Count > 0)
|
||||
{
|
||||
GUILayout.Label("emptyRaycast路径:");
|
||||
for (; i < pathList.Count; i++)
|
||||
GUILayout.Label(pathList[i]);
|
||||
}
|
||||
pathList = raycastHelper.GetRawImagePathList();
|
||||
i = 0;
|
||||
if (pathList.Count > 0)
|
||||
{
|
||||
GUILayout.Label("rawImage路径:");
|
||||
for (; i < pathList.Count; i++)
|
||||
GUILayout.Label(pathList[i]);
|
||||
}
|
||||
GUILayout.EndScrollView();
|
||||
}
|
||||
GUILayout.EndVertical();
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
if (raycastHelper != null)
|
||||
DestroyImmediate(raycastHelper);
|
||||
}
|
||||
|
||||
//[MenuItem("资源工具/资源检查/检查RaycastTarget", false, 401)]
|
||||
public static void OpenWindow()
|
||||
{
|
||||
CheckRaycastTargetWindow window = (CheckRaycastTargetWindow)GetWindowWithRect(typeof(CheckRaycastTargetWindow),
|
||||
new Rect(Screen.width / 2, Screen.height / 2, 400, 400), true);
|
||||
window.Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
|
||||
namespace BFEditor.Resource
|
||||
{
|
||||
public class CheckRaycastTargetWindow : EditorWindow
|
||||
{
|
||||
ShowRaycast raycastHelper;
|
||||
RectTransform rt;
|
||||
Vector2 scrollPos;
|
||||
|
||||
CheckRaycastTargetWindow()
|
||||
{
|
||||
this.titleContent = new GUIContent("检查RaycastTarget");
|
||||
}
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
UnityEditor.SceneManagement.PrefabStage currentPrefabStage = UnityEditor.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage();
|
||||
Transform tran;
|
||||
if (currentPrefabStage == null)
|
||||
tran = Selection.activeTransform;
|
||||
else
|
||||
tran = currentPrefabStage.prefabContentsRoot.transform;
|
||||
if (tran != null)
|
||||
rt = tran.GetComponent<RectTransform>();
|
||||
if (rt != null)
|
||||
{
|
||||
raycastHelper = rt.GetComponent<ShowRaycast>();
|
||||
if (raycastHelper == null)
|
||||
raycastHelper = rt.gameObject.AddComponent<ShowRaycast>();
|
||||
raycastHelper.SetEditorWindowMode(true);
|
||||
}
|
||||
}
|
||||
|
||||
void OnGUI()
|
||||
{
|
||||
GUILayout.BeginVertical();
|
||||
EditorGUI.BeginChangeCheck();
|
||||
rt = (RectTransform)EditorGUILayout.ObjectField("", rt, typeof(RectTransform), true, GUILayout.Width(200));
|
||||
GUILayout.Space(6);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
if (raycastHelper != null)
|
||||
DestroyImmediate(raycastHelper);
|
||||
if (rt != null)
|
||||
{
|
||||
raycastHelper = rt.GetComponent<ShowRaycast>();
|
||||
if (raycastHelper == null)
|
||||
raycastHelper = rt.gameObject.AddComponent<ShowRaycast>();
|
||||
raycastHelper.SetEditorWindowMode(true);
|
||||
}
|
||||
}
|
||||
if (raycastHelper != null)
|
||||
{
|
||||
GUILayout.Label(string.Format("raycastTarget组件一共有 {0} 个", raycastHelper.GetTotalCount()));
|
||||
GUILayout.Label("(红色)image " + raycastHelper.GetImageCount() +
|
||||
" (绿色)text " + raycastHelper.GetTextCount());
|
||||
GUILayout.Label("(黄色)emptyRaycast " + raycastHelper.GetEmptyCount() +
|
||||
" (蓝色)rawImage " + raycastHelper.GetRawImageCount());
|
||||
GUILayout.Space(6);
|
||||
scrollPos = GUILayout.BeginScrollView(scrollPos, GUILayout.Width(400), GUILayout.Height(270));
|
||||
List<string> pathList = raycastHelper.GetImagePathList();
|
||||
int i = 0;
|
||||
if (pathList.Count > 0)
|
||||
{
|
||||
GUILayout.Label("image路径:");
|
||||
for (; i < pathList.Count; i++)
|
||||
GUILayout.Label(pathList[i]);
|
||||
}
|
||||
pathList = raycastHelper.GetTextPathList();
|
||||
i = 0;
|
||||
if (pathList.Count > 0)
|
||||
{
|
||||
GUILayout.Label("text路径:");
|
||||
for (; i < pathList.Count; i++)
|
||||
GUILayout.Label(pathList[i]);
|
||||
}
|
||||
pathList = raycastHelper.GetEmptyPathList();
|
||||
i = 0;
|
||||
if (pathList.Count > 0)
|
||||
{
|
||||
GUILayout.Label("emptyRaycast路径:");
|
||||
for (; i < pathList.Count; i++)
|
||||
GUILayout.Label(pathList[i]);
|
||||
}
|
||||
pathList = raycastHelper.GetRawImagePathList();
|
||||
i = 0;
|
||||
if (pathList.Count > 0)
|
||||
{
|
||||
GUILayout.Label("rawImage路径:");
|
||||
for (; i < pathList.Count; i++)
|
||||
GUILayout.Label(pathList[i]);
|
||||
}
|
||||
GUILayout.EndScrollView();
|
||||
}
|
||||
GUILayout.EndVertical();
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
if (raycastHelper != null)
|
||||
DestroyImmediate(raycastHelper);
|
||||
}
|
||||
|
||||
//[MenuItem("资源工具/资源检查/检查RaycastTarget", false, 401)]
|
||||
public static void OpenWindow()
|
||||
{
|
||||
CheckRaycastTargetWindow window = (CheckRaycastTargetWindow)GetWindowWithRect(typeof(CheckRaycastTargetWindow),
|
||||
new Rect(Screen.width / 2, Screen.height / 2, 400, 400), true);
|
||||
window.Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,206 +1,206 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using TMPro;
|
||||
using BFEditor.Resource;
|
||||
using BF;
|
||||
|
||||
namespace BFEditor
|
||||
{
|
||||
public class GameObjectEditer : Editor
|
||||
{
|
||||
static Material CustomUIDefault;
|
||||
|
||||
// 重写Text菜单,默认取消raycastTarget
|
||||
[MenuItem("GameObject/UI/Text", true)]
|
||||
static bool ValidateUITextMenu()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/Text", false)]
|
||||
static void CreateUIText()
|
||||
{
|
||||
GameObject go = new GameObject("Text", typeof(UnityEngine.UI.Text));
|
||||
UnityEngine.UI.Text text = go.GetComponent<UnityEngine.UI.Text>();
|
||||
text.raycastTarget = false;
|
||||
text.material = GetCustomDefaultUIMat();
|
||||
CheckAndSetUIParent(go.transform);
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/TextMeshPro - Text", true)]
|
||||
static bool ValidateUITextMeshProMenu()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/TextMeshPro - Text", false)]
|
||||
static void CreateUITextMeshPro()
|
||||
{
|
||||
Debug.LogError("请在UI/BF通用控件里创建Text");
|
||||
}
|
||||
|
||||
// 重写Image菜单,默认取消raycastTarget
|
||||
[MenuItem("GameObject/UI/Image", true)]
|
||||
static bool ValidateUIImageMenu()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/Image", false)]
|
||||
static void CreateUIImage()
|
||||
{
|
||||
GameObject go = new GameObject("Image", typeof(UnityEngine.UI.Image));
|
||||
UnityEngine.UI.Image image = go.GetComponent<UnityEngine.UI.Image>();
|
||||
image.raycastTarget = false;
|
||||
image.material = GetCustomDefaultUIMat();
|
||||
CheckAndSetUIParent(go.transform);
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/BFSlider", false)]
|
||||
static void CreateBFSlider()
|
||||
{
|
||||
GameObject go = new GameObject("BFSlider", typeof(BFSlider));
|
||||
BFSlider slider = go.GetComponent<BFSlider>();
|
||||
slider.raycastTarget = false;
|
||||
slider.material = GetCustomDefaultUIMat();
|
||||
CheckAndSetUIParent(go.transform);
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/Raw Image", true)]
|
||||
static bool ValidateUIRawImageMenu()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/Raw Image", false)]
|
||||
static void CreateUIRawImage()
|
||||
{
|
||||
GameObject go = new GameObject("RawImage", typeof(UnityEngine.UI.RawImage));
|
||||
UnityEngine.UI.RawImage image = go.GetComponent<UnityEngine.UI.RawImage>();
|
||||
image.raycastTarget = false;
|
||||
image.material = GetCustomDefaultUIMat();
|
||||
CheckAndSetUIParent(go.transform);
|
||||
}
|
||||
|
||||
static void CheckAndSetUIParent(Transform uiTransform)
|
||||
{
|
||||
if (Selection.activeTransform) // 当前有选择一个父节点
|
||||
{
|
||||
uiTransform.SetParent(Selection.activeTransform, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
var currentPrefabStage = UnityEditor.Experimental.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage();
|
||||
if (currentPrefabStage != null) //当前处于prefab编辑模式
|
||||
{
|
||||
var prefabRoot = currentPrefabStage.prefabContentsRoot;
|
||||
uiTransform.SetParent(prefabRoot.transform, false);
|
||||
}
|
||||
}
|
||||
Selection.activeTransform = uiTransform;
|
||||
}
|
||||
|
||||
static Material GetCustomDefaultUIMat()
|
||||
{
|
||||
if (CustomUIDefault == null)
|
||||
CustomUIDefault = AssetDatabase.LoadAssetAtPath<Material>(ResourceProcessConfig.CUSTOM_DEFAULT_UI_MAT_PATH);
|
||||
return CustomUIDefault;
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/Button", true)]
|
||||
static bool ValidateUIButtonMenu()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/Button", false)]
|
||||
static void CreateUIButton()
|
||||
{
|
||||
Debug.LogError("请在UI/BF通用控件里创建Button");
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/Button - TextMeshPro", true)]
|
||||
static bool ValidateUIButtonTMPMenu()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/Button - TextMeshPro", false)]
|
||||
static void CreateUIButtonTMP()
|
||||
{
|
||||
Debug.LogError("请在UI/BF通用控件里创建Button");
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/Text - TextMeshPro", true)]
|
||||
static bool ValidateUITextTMPMenu()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/Text - TextMeshPro", false)]
|
||||
static void CreateUITextTMP()
|
||||
{
|
||||
Debug.LogError("请在UI/BF通用控件里创建Text");
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/BF通用控件/Button")]
|
||||
static void CreateBFCommonButton()
|
||||
{
|
||||
GameObject go = new GameObject("Button", typeof(UnityEngine.UI.Image));
|
||||
UnityEngine.UI.Image image = go.GetComponent<UnityEngine.UI.Image>();
|
||||
image.material = GetCustomDefaultUIMat();
|
||||
go.AddComponent<BF.UITouchEvent>();
|
||||
CheckAndSetUIParent(go.transform);
|
||||
}
|
||||
|
||||
|
||||
[MenuItem("GameObject/UI/BF通用控件/Text")]
|
||||
static void CreateBFCommonText()
|
||||
{
|
||||
if (TMP_Settings.defaultFontAsset == null)
|
||||
{
|
||||
var tmpSettings = TMP_Settings.instance;
|
||||
var type = tmpSettings.GetType();
|
||||
var fontAssetField = type.GetField("m_defaultFontAsset", System.Reflection.BindingFlags.Instance |
|
||||
System.Reflection.BindingFlags.NonPublic);
|
||||
var fontAssets = AssetDatabase.LoadAssetAtPath<TMP_FontAsset>(ResourceProcessConfig.DEFAULT_TMP_FONTASSET_PATH);
|
||||
fontAssetField.SetValue(tmpSettings, fontAssets);
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
GameObject go = new GameObject("TextMeshPro", typeof(TMPro.TextMeshProUGUI));
|
||||
TMPro.TextMeshProUGUI textMeshPro = go.GetComponent<TMPro.TextMeshProUGUI>();
|
||||
textMeshPro.raycastTarget = false;
|
||||
var font = AssetDatabase.LoadAssetAtPath<TMP_FontAsset>(
|
||||
"Assets/arts/fonts/tmpfonts/default/tmpfont/font_sdf.asset");
|
||||
textMeshPro.font = font;
|
||||
textMeshPro.material = GetCustomDefaultUIMat();
|
||||
textMeshPro.enableWordWrapping = false;
|
||||
CheckAndSetUIParent(go.transform);
|
||||
|
||||
if (TMP_Settings.defaultFontAsset != null)
|
||||
{
|
||||
var tmpSettings = TMP_Settings.instance;
|
||||
var type = tmpSettings.GetType();
|
||||
var fontAssetField = type.GetField("m_defaultFontAsset", System.Reflection.BindingFlags.Instance |
|
||||
System.Reflection.BindingFlags.NonPublic);
|
||||
fontAssetField.SetValue(tmpSettings, null);
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/创建序列帧")]
|
||||
static void CreateFrameAnimation()
|
||||
{
|
||||
FrameAnimationTools.CreateFrameAnimation();
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/创建序列帧(父节点)")]
|
||||
static void CreateFrameAnimationInParent()
|
||||
{
|
||||
FrameAnimationTools.CreateFrameAnimation(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using TMPro;
|
||||
using BFEditor.Resource;
|
||||
using BF;
|
||||
|
||||
namespace BFEditor
|
||||
{
|
||||
public class GameObjectEditer : Editor
|
||||
{
|
||||
static Material CustomUIDefault;
|
||||
|
||||
// 重写Text菜单,默认取消raycastTarget
|
||||
[MenuItem("GameObject/UI/Text", true)]
|
||||
static bool ValidateUITextMenu()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/Text", false)]
|
||||
static void CreateUIText()
|
||||
{
|
||||
GameObject go = new GameObject("Text", typeof(UnityEngine.UI.Text));
|
||||
UnityEngine.UI.Text text = go.GetComponent<UnityEngine.UI.Text>();
|
||||
text.raycastTarget = false;
|
||||
text.material = GetCustomDefaultUIMat();
|
||||
CheckAndSetUIParent(go.transform);
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/TextMeshPro - Text", true)]
|
||||
static bool ValidateUITextMeshProMenu()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/TextMeshPro - Text", false)]
|
||||
static void CreateUITextMeshPro()
|
||||
{
|
||||
Debug.LogError("请在UI/BF通用控件里创建Text");
|
||||
}
|
||||
|
||||
// 重写Image菜单,默认取消raycastTarget
|
||||
[MenuItem("GameObject/UI/Image", true)]
|
||||
static bool ValidateUIImageMenu()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/Image", false)]
|
||||
static void CreateUIImage()
|
||||
{
|
||||
GameObject go = new GameObject("Image", typeof(UnityEngine.UI.Image));
|
||||
UnityEngine.UI.Image image = go.GetComponent<UnityEngine.UI.Image>();
|
||||
image.raycastTarget = false;
|
||||
image.material = GetCustomDefaultUIMat();
|
||||
CheckAndSetUIParent(go.transform);
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/BFSlider", false)]
|
||||
static void CreateBFSlider()
|
||||
{
|
||||
GameObject go = new GameObject("BFSlider", typeof(BFSlider));
|
||||
BFSlider slider = go.GetComponent<BFSlider>();
|
||||
slider.raycastTarget = false;
|
||||
slider.material = GetCustomDefaultUIMat();
|
||||
CheckAndSetUIParent(go.transform);
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/Raw Image", true)]
|
||||
static bool ValidateUIRawImageMenu()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/Raw Image", false)]
|
||||
static void CreateUIRawImage()
|
||||
{
|
||||
GameObject go = new GameObject("RawImage", typeof(UnityEngine.UI.RawImage));
|
||||
UnityEngine.UI.RawImage image = go.GetComponent<UnityEngine.UI.RawImage>();
|
||||
image.raycastTarget = false;
|
||||
image.material = GetCustomDefaultUIMat();
|
||||
CheckAndSetUIParent(go.transform);
|
||||
}
|
||||
|
||||
static void CheckAndSetUIParent(Transform uiTransform)
|
||||
{
|
||||
if (Selection.activeTransform) // 当前有选择一个父节点
|
||||
{
|
||||
uiTransform.SetParent(Selection.activeTransform, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
var currentPrefabStage = UnityEditor.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage();
|
||||
if (currentPrefabStage != null) //当前处于prefab编辑模式
|
||||
{
|
||||
var prefabRoot = currentPrefabStage.prefabContentsRoot;
|
||||
uiTransform.SetParent(prefabRoot.transform, false);
|
||||
}
|
||||
}
|
||||
Selection.activeTransform = uiTransform;
|
||||
}
|
||||
|
||||
static Material GetCustomDefaultUIMat()
|
||||
{
|
||||
if (CustomUIDefault == null)
|
||||
CustomUIDefault = AssetDatabase.LoadAssetAtPath<Material>(ResourceProcessConfig.CUSTOM_DEFAULT_UI_MAT_PATH);
|
||||
return CustomUIDefault;
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/Button", true)]
|
||||
static bool ValidateUIButtonMenu()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/Button", false)]
|
||||
static void CreateUIButton()
|
||||
{
|
||||
Debug.LogError("请在UI/BF通用控件里创建Button");
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/Button - TextMeshPro", true)]
|
||||
static bool ValidateUIButtonTMPMenu()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/Button - TextMeshPro", false)]
|
||||
static void CreateUIButtonTMP()
|
||||
{
|
||||
Debug.LogError("请在UI/BF通用控件里创建Button");
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/Text - TextMeshPro", true)]
|
||||
static bool ValidateUITextTMPMenu()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/Text - TextMeshPro", false)]
|
||||
static void CreateUITextTMP()
|
||||
{
|
||||
Debug.LogError("请在UI/BF通用控件里创建Text");
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/BF通用控件/Button")]
|
||||
static void CreateBFCommonButton()
|
||||
{
|
||||
GameObject go = new GameObject("Button", typeof(UnityEngine.UI.Image));
|
||||
UnityEngine.UI.Image image = go.GetComponent<UnityEngine.UI.Image>();
|
||||
image.material = GetCustomDefaultUIMat();
|
||||
go.AddComponent<BF.UITouchEvent>();
|
||||
CheckAndSetUIParent(go.transform);
|
||||
}
|
||||
|
||||
|
||||
[MenuItem("GameObject/UI/BF通用控件/Text")]
|
||||
static void CreateBFCommonText()
|
||||
{
|
||||
if (TMP_Settings.defaultFontAsset == null)
|
||||
{
|
||||
var tmpSettings = TMP_Settings.instance;
|
||||
var type = tmpSettings.GetType();
|
||||
var fontAssetField = type.GetField("m_defaultFontAsset", System.Reflection.BindingFlags.Instance |
|
||||
System.Reflection.BindingFlags.NonPublic);
|
||||
var fontAssets = AssetDatabase.LoadAssetAtPath<TMP_FontAsset>(ResourceProcessConfig.DEFAULT_TMP_FONTASSET_PATH);
|
||||
fontAssetField.SetValue(tmpSettings, fontAssets);
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
GameObject go = new GameObject("TextMeshPro", typeof(TMPro.TextMeshProUGUI));
|
||||
TMPro.TextMeshProUGUI textMeshPro = go.GetComponent<TMPro.TextMeshProUGUI>();
|
||||
textMeshPro.raycastTarget = false;
|
||||
var font = AssetDatabase.LoadAssetAtPath<TMP_FontAsset>(
|
||||
"Assets/arts/fonts/tmpfonts/default/tmpfont/font_sdf.asset");
|
||||
textMeshPro.font = font;
|
||||
textMeshPro.material = GetCustomDefaultUIMat();
|
||||
textMeshPro.enableWordWrapping = false;
|
||||
CheckAndSetUIParent(go.transform);
|
||||
|
||||
if (TMP_Settings.defaultFontAsset != null)
|
||||
{
|
||||
var tmpSettings = TMP_Settings.instance;
|
||||
var type = tmpSettings.GetType();
|
||||
var fontAssetField = type.GetField("m_defaultFontAsset", System.Reflection.BindingFlags.Instance |
|
||||
System.Reflection.BindingFlags.NonPublic);
|
||||
fontAssetField.SetValue(tmpSettings, null);
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/创建序列帧")]
|
||||
static void CreateFrameAnimation()
|
||||
{
|
||||
FrameAnimationTools.CreateFrameAnimation();
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/创建序列帧(父节点)")]
|
||||
static void CreateFrameAnimationInParent()
|
||||
{
|
||||
FrameAnimationTools.CreateFrameAnimation(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,93 +1,93 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using BFEditor.Build;
|
||||
|
||||
public class JenkinsAdapter {
|
||||
|
||||
/// <summary>
|
||||
/// 构建版本号
|
||||
/// </summary>
|
||||
private static string BuildVersion = (int.Parse(DateTime.Now.ToString("yyMMddHH"))).ToString();
|
||||
private static int versionCode = 10;
|
||||
private static string versionName = "1.4.0";
|
||||
|
||||
[MenuItem("Jenkins/JenkinsBuildIos")]
|
||||
public static void CommandLineBuildIos() {
|
||||
var buildInfo = new BuildInfo();
|
||||
buildInfo.version = versionName;
|
||||
buildInfo.mode = "publish_release";
|
||||
buildInfo.bundleName = "com.combo.heroes.puzzle.rpg";
|
||||
buildInfo.skipVersion = false;
|
||||
BuildProjectTools.BuildResources(buildInfo, Application.streamingAssetsPath, true);
|
||||
// 重新生成XLua
|
||||
CompileScriptsUtils.RegenerateXLuaCode(true);
|
||||
|
||||
// 设置版本号
|
||||
PlayerSettings.bundleVersion = buildInfo.version;
|
||||
//SDK要求
|
||||
PlayerSettings.iOS.targetOSVersionString = "12.0";
|
||||
//设置Build,每次需要增加
|
||||
PlayerSettings.iOS.buildNumber = versionCode.ToString();
|
||||
// 隐藏ios的横条
|
||||
PlayerSettings.iOS.hideHomeButton = false;
|
||||
// 禁止在所有边缘上延迟手势
|
||||
PlayerSettings.iOS.deferSystemGesturesMode = UnityEngine.iOS.SystemGestureDeferMode.All;
|
||||
// 设置竖屏
|
||||
PlayerSettings.defaultInterfaceOrientation = UIOrientation.Portrait;
|
||||
PlayerSettings.allowedAutorotateToPortrait = false;
|
||||
PlayerSettings.allowedAutorotateToPortraitUpsideDown = false;
|
||||
PlayerSettings.allowedAutorotateToLandscapeLeft = false;
|
||||
PlayerSettings.allowedAutorotateToLandscapeRight = false;
|
||||
// 关闭启动动画
|
||||
PlayerSettings.SplashScreen.show = false;
|
||||
// 设置包名
|
||||
PlayerSettings.SetApplicationIdentifier(BuildTargetGroup.iOS, buildInfo.bundleName);
|
||||
// 是否跳过版本控制
|
||||
var symbols = "THREAD_SAFE;USE_AB";
|
||||
if (buildInfo.skipVersion)
|
||||
{
|
||||
symbols = symbols + ";SKIP_VERSION;";
|
||||
}
|
||||
PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.iOS, symbols);
|
||||
// 商品名称
|
||||
PlayerSettings.productName = "Knights Combo";
|
||||
// BuildType设置dev/release
|
||||
EditorUserBuildSettings.iOSBuildConfigType = iOSBuildType.Release;
|
||||
EditorUserBuildSettings.development = false;
|
||||
// 使用IL2CPP
|
||||
var scriptImp = ScriptingImplementation.IL2CPP;
|
||||
PlayerSettings.SetScriptingBackend(BuildTargetGroup.iOS, scriptImp);
|
||||
// 目标平台架构,目前支持ARM64
|
||||
PlayerSettings.SetArchitecture(BuildTargetGroup.iOS, 1);
|
||||
|
||||
// 开始打包
|
||||
BuildPipeline.BuildPlayer(GetBuildScenes(), GetIosBuildPath(), BuildTarget.iOS, BuildOptions.None);
|
||||
Console.WriteLine("Build Complete Path:" + GetIosBuildPath());
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取build Setting 列表里的打勾场景
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static string[] GetBuildScenes() {
|
||||
List<string> names = new List<string>();
|
||||
|
||||
foreach (var x in EditorBuildSettings.scenes) {
|
||||
if (!x.enabled) continue;
|
||||
names.Add(x.path);
|
||||
}
|
||||
return names.ToArray();
|
||||
}
|
||||
|
||||
#region Get Build Path
|
||||
private static string GetIosBuildPath() {
|
||||
return "build/iOS";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using BFEditor.Build;
|
||||
|
||||
public class JenkinsAdapter {
|
||||
|
||||
/// <summary>
|
||||
/// 构建版本号
|
||||
/// </summary>
|
||||
private static string BuildVersion = (int.Parse(DateTime.Now.ToString("yyMMddHH"))).ToString();
|
||||
private static int versionCode = 10;
|
||||
private static string versionName = "1.4.0";
|
||||
|
||||
[MenuItem("Jenkins/JenkinsBuildIos")]
|
||||
public static void CommandLineBuildIos() {
|
||||
var buildInfo = new BuildInfo();
|
||||
buildInfo.version = versionName;
|
||||
buildInfo.mode = "publish_release";
|
||||
buildInfo.bundleName = "com.combo.heroes.puzzle.rpg";
|
||||
buildInfo.skipVersion = false;
|
||||
BuildProjectTools.BuildResources(buildInfo, Application.streamingAssetsPath, true);
|
||||
// 重新生成XLua
|
||||
CompileScriptsUtils.RegenerateXLuaCode(true);
|
||||
|
||||
// 设置版本号
|
||||
PlayerSettings.bundleVersion = buildInfo.version;
|
||||
//SDK要求
|
||||
PlayerSettings.iOS.targetOSVersionString = "12.0";
|
||||
//设置Build,每次需要增加
|
||||
PlayerSettings.iOS.buildNumber = versionCode.ToString();
|
||||
// 隐藏ios的横条
|
||||
PlayerSettings.iOS.hideHomeButton = false;
|
||||
// 禁止在所有边缘上延迟手势
|
||||
PlayerSettings.iOS.deferSystemGesturesMode = UnityEngine.iOS.SystemGestureDeferMode.All;
|
||||
// 设置竖屏
|
||||
PlayerSettings.defaultInterfaceOrientation = UIOrientation.Portrait;
|
||||
PlayerSettings.allowedAutorotateToPortrait = false;
|
||||
PlayerSettings.allowedAutorotateToPortraitUpsideDown = false;
|
||||
PlayerSettings.allowedAutorotateToLandscapeLeft = false;
|
||||
PlayerSettings.allowedAutorotateToLandscapeRight = false;
|
||||
// 关闭启动动画
|
||||
PlayerSettings.SplashScreen.show = false;
|
||||
// 设置包名
|
||||
PlayerSettings.SetApplicationIdentifier(BuildTargetGroup.iOS, buildInfo.bundleName);
|
||||
// 是否跳过版本控制
|
||||
var symbols = "THREAD_SAFE;USE_AB";
|
||||
if (buildInfo.skipVersion)
|
||||
{
|
||||
symbols = symbols + ";SKIP_VERSION;";
|
||||
}
|
||||
PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.iOS, symbols);
|
||||
// 商品名称
|
||||
PlayerSettings.productName = "Knights Combo";
|
||||
// BuildType设置dev/release
|
||||
EditorUserBuildSettings.iOSXcodeBuildConfig = XcodeBuildConfig.Release;
|
||||
EditorUserBuildSettings.development = false;
|
||||
// 使用IL2CPP
|
||||
var scriptImp = ScriptingImplementation.IL2CPP;
|
||||
PlayerSettings.SetScriptingBackend(BuildTargetGroup.iOS, scriptImp);
|
||||
// 目标平台架构,目前支持ARM64
|
||||
PlayerSettings.SetArchitecture(BuildTargetGroup.iOS, 1);
|
||||
|
||||
// 开始打包
|
||||
BuildPipeline.BuildPlayer(GetBuildScenes(), GetIosBuildPath(), BuildTarget.iOS, BuildOptions.None);
|
||||
Console.WriteLine("Build Complete Path:" + GetIosBuildPath());
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取build Setting 列表里的打勾场景
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static string[] GetBuildScenes() {
|
||||
List<string> names = new List<string>();
|
||||
|
||||
foreach (var x in EditorBuildSettings.scenes) {
|
||||
if (!x.enabled) continue;
|
||||
names.Add(x.path);
|
||||
}
|
||||
return names.ToArray();
|
||||
}
|
||||
|
||||
#region Get Build Path
|
||||
private static string GetIosBuildPath() {
|
||||
return "build/iOS";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -14,19 +14,26 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
defaultScale: 0.01
|
||||
defaultMix: 0.2
|
||||
defaultShader: BF/Spine/Skeleton
|
||||
defaultShader: Spine/Skeleton
|
||||
defaultZSpacing: 0
|
||||
defaultInstantiateLoop: 1
|
||||
defaultPhysicsPositionInheritance: {x: 1, y: 1}
|
||||
defaultPhysicsRotationInheritance: 1
|
||||
showHierarchyIcons: 1
|
||||
reloadAfterPlayMode: 1
|
||||
setTextureImporterSettings: 1
|
||||
textureSettingsReference: Assets/ThirdParty/Spine/Editor/spine-unity/Editor/ImporterPresets/PMATexturePreset.preset
|
||||
fixPrefabOverrideViaMeshFilter: 0
|
||||
removePrefabPreviewMeshes: 0
|
||||
blendModeMaterialMultiply: {fileID: 0}
|
||||
blendModeMaterialScreen: {fileID: 0}
|
||||
blendModeMaterialAdditive: {fileID: 0}
|
||||
atlasTxtImportWarning: 1
|
||||
textureImporterWarning: 1
|
||||
componentMaterialWarning: 1
|
||||
skeletonDataAssetNoFileError: 1
|
||||
autoReloadSceneSkeletons: 1
|
||||
handleScale: 1
|
||||
mecanimEventIncludeFolderName: 1
|
||||
timelineDefaultMixDuration: 0
|
||||
timelineUseBlendDuration: 1
|
||||
|
||||
@ -78,6 +78,7 @@ namespace BFEditor
|
||||
psi.RedirectStandardOutput = true; //由调用程序获取输出信息
|
||||
psi.RedirectStandardError = true; //重定向标准错误输出
|
||||
psi.CreateNoWindow = true; //不显示程序窗口
|
||||
psi.StandardOutputEncoding = System.Text.Encoding.UTF8; // 核心:指定UTF-8解码
|
||||
p.StartInfo = psi;
|
||||
p.Start();
|
||||
|
||||
|
||||
@ -23,7 +23,8 @@ namespace AudienceNetwork
|
||||
public partial class AdManager : BF.MonoSingleton<AdManager>
|
||||
{
|
||||
private const string Tag = "AdManager:";
|
||||
private const string Key = "9uHgeBwag3NXva9MC23ToO3q11Ve59bF1uwg4qGltdGmCQ7OSByFZ_3b1ZF7krMlkHQo5gXzIokVDsvg1rwbr-";
|
||||
// private const string Key = "9uHgeBwag3NXva9MC23ToO3q11Ve59bF1uwg4qGltdGmCQ7OSByFZ_3b1ZF7krMlkHQo5gXzIokVDsvg1rwbr-";
|
||||
private const string Key = "9uHgeBwag3NXva9MC23ToO3q11Ve59bF1uwg4qGltdGmCQ7OSByFZ_3b1ZF7krMlkHQo5gXzIokVDsvg1rwbr-11";
|
||||
string bannerAdUnitId = "YOUR_BANNER_AD_UNIT_ID"; // Retrieve the ID from your account
|
||||
string adInterstitialUnitId = "YOUR_AD_UNIT_ID";
|
||||
string adRewardUnitId = "e54f27e345da90df";
|
||||
|
||||
@ -9,9 +9,9 @@ namespace BF
|
||||
{
|
||||
public class BFThirdReportSDKManager : MonoBehaviour
|
||||
{
|
||||
private ThinkingAnalyticsSdk TASdk = new ThinkingAnalyticsSdk();
|
||||
private AppsFlyerSdk AFSdk = new AppsFlyerSdk();
|
||||
private bool isInitAFAdRevenue = false;
|
||||
// private ThinkingAnalyticsSdk TASdk = new ThinkingAnalyticsSdk();
|
||||
// private AppsFlyerSdk AFSdk = new AppsFlyerSdk();
|
||||
// private bool isInitAFAdRevenue = false;
|
||||
|
||||
void Start()
|
||||
{
|
||||
@ -21,147 +21,147 @@ namespace BF
|
||||
public void Init()
|
||||
{
|
||||
BFLog.Log("TASdk.Init");
|
||||
TASdk.Init();
|
||||
AFSdk.Init();
|
||||
// TASdk.Init();
|
||||
// AFSdk.Init();
|
||||
}
|
||||
|
||||
// 设置账户id
|
||||
public void SetThinkingAnalyticsAccountId(string id)
|
||||
{
|
||||
TASdk.SetAccountId(id);
|
||||
AFSdk.SetTaAccountId(id);
|
||||
// TASdk.SetAccountId(id);
|
||||
// AFSdk.SetTaAccountId(id);
|
||||
}
|
||||
|
||||
public void InitAppsFlyerAdRevenue()
|
||||
{
|
||||
if (isInitAFAdRevenue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
isInitAFAdRevenue = true;
|
||||
AppsFlyerAdRevenue.start();
|
||||
// if (isInitAFAdRevenue)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
// isInitAFAdRevenue = true;
|
||||
// AppsFlyerAdRevenue.start();
|
||||
}
|
||||
|
||||
// 清除账户id
|
||||
public void ClearThinkingAnalyticsAccountId()
|
||||
{
|
||||
TASdk.ClearAccountId();
|
||||
// TASdk.ClearAccountId();
|
||||
}
|
||||
|
||||
// 数数科技上报
|
||||
// lua端使用
|
||||
public void PostThinkingAnalyticsEvent(string eventName, string data = "")
|
||||
{
|
||||
if (string.IsNullOrEmpty(data))
|
||||
{
|
||||
TASdk.Track(eventName, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
var properties = JsonConvert.DeserializeObject<Dictionary<string, object>>(data);
|
||||
TASdk.Track(eventName, properties);
|
||||
}
|
||||
// if (string.IsNullOrEmpty(data))
|
||||
// {
|
||||
// TASdk.Track(eventName, null);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// var properties = JsonConvert.DeserializeObject<Dictionary<string, object>>(data);
|
||||
// TASdk.Track(eventName, properties);
|
||||
// }
|
||||
}
|
||||
|
||||
// 数数科技上报
|
||||
// c#端使用,只上报事件名
|
||||
public void PostThinkingAnalyticsEventName(string eventName)
|
||||
{
|
||||
TASdk.Track(eventName, null);
|
||||
// TASdk.Track(eventName, null);
|
||||
}
|
||||
|
||||
// 数数科技上报
|
||||
// c#端使用,上报事件名和参数
|
||||
public void PostThinkingAnalyticsEventProperties(string eventName, Dictionary<string, object> properties)
|
||||
{
|
||||
TASdk.Track(eventName, properties);
|
||||
// TASdk.Track(eventName, properties);
|
||||
}
|
||||
|
||||
public void PostAppsflyerEvent(string eventName, string data = "")
|
||||
{
|
||||
if (string.IsNullOrEmpty(data))
|
||||
{
|
||||
AFSdk.SendEvent(eventName, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
var properties = JsonConvert.DeserializeObject<Dictionary<string, string>>(data);
|
||||
AFSdk.SendEvent(eventName, properties);
|
||||
}
|
||||
// if (string.IsNullOrEmpty(data))
|
||||
// {
|
||||
// AFSdk.SendEvent(eventName, null);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// var properties = JsonConvert.DeserializeObject<Dictionary<string, string>>(data);
|
||||
// AFSdk.SendEvent(eventName, properties);
|
||||
// }
|
||||
}
|
||||
|
||||
public void PostFireBaseEvent(string eventName, string data = "")
|
||||
{
|
||||
if (string.IsNullOrEmpty(data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
BFMain.Instance.SDKMgr.BFNativeSDKMgr.LogEvent(eventName, data);
|
||||
}
|
||||
// if (string.IsNullOrEmpty(data))
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// BFMain.Instance.SDKMgr.BFNativeSDKMgr.LogEvent(eventName, data);
|
||||
// }
|
||||
}
|
||||
|
||||
// 设置账户id
|
||||
public void PostAdjustSimpleTrackEvent(string key)
|
||||
{
|
||||
AdjustEvent adjustEvent = new AdjustEvent(key);
|
||||
// BFLog.Log("PostAdjustSimpleTrackEvent");
|
||||
Adjust.trackEvent(adjustEvent);
|
||||
// AdjustEvent adjustEvent = new AdjustEvent(key);
|
||||
// // BFLog.Log("PostAdjustSimpleTrackEvent");
|
||||
// Adjust.trackEvent(adjustEvent);
|
||||
}
|
||||
|
||||
public void PostAdjustRevenueTrackEvent(string key, double currency, string currencyCode)
|
||||
{
|
||||
AdjustEvent adjustEvent = new AdjustEvent(key);
|
||||
adjustEvent.setRevenue(currency, currencyCode);
|
||||
// BFLog.Log("PostAdjustRevenueTrackEvent");
|
||||
Adjust.trackEvent(adjustEvent);
|
||||
// AdjustEvent adjustEvent = new AdjustEvent(key);
|
||||
// adjustEvent.setRevenue(currency, currencyCode);
|
||||
// // BFLog.Log("PostAdjustRevenueTrackEvent");
|
||||
// Adjust.trackEvent(adjustEvent);
|
||||
}
|
||||
|
||||
public void PostAdjustCallbackTrackEvent(string key, string data = "")
|
||||
{
|
||||
var properties = JsonConvert.DeserializeObject<Dictionary<string, string>>(data);
|
||||
AdjustEvent adjustEvent = new AdjustEvent(key);
|
||||
foreach (var item in properties)
|
||||
{
|
||||
adjustEvent.addCallbackParameter(item.Key, item.Value);
|
||||
}
|
||||
// BFLog.Log("PostAdjustCallbackTrackEvent");
|
||||
Adjust.trackEvent(adjustEvent);
|
||||
// var properties = JsonConvert.DeserializeObject<Dictionary<string, string>>(data);
|
||||
// AdjustEvent adjustEvent = new AdjustEvent(key);
|
||||
// foreach (var item in properties)
|
||||
// {
|
||||
// adjustEvent.addCallbackParameter(item.Key, item.Value);
|
||||
// }
|
||||
// // BFLog.Log("PostAdjustCallbackTrackEvent");
|
||||
// Adjust.trackEvent(adjustEvent);
|
||||
}
|
||||
|
||||
public void PostAdjustPartnerTrackEvent(string key, string data = "")
|
||||
{
|
||||
var properties = JsonConvert.DeserializeObject<Dictionary<string, string>>(data);
|
||||
AdjustEvent adjustEvent = new AdjustEvent(key);
|
||||
foreach (var item in properties)
|
||||
{
|
||||
adjustEvent.addPartnerParameter(item.Key, item.Value);
|
||||
}
|
||||
// BFLog.Log("PostAdjustPartnerTrackEvent");
|
||||
Adjust.trackEvent(adjustEvent);
|
||||
// var properties = JsonConvert.DeserializeObject<Dictionary<string, string>>(data);
|
||||
// AdjustEvent adjustEvent = new AdjustEvent(key);
|
||||
// foreach (var item in properties)
|
||||
// {
|
||||
// adjustEvent.addPartnerParameter(item.Key, item.Value);
|
||||
// }
|
||||
// // BFLog.Log("PostAdjustPartnerTrackEvent");
|
||||
// Adjust.trackEvent(adjustEvent);
|
||||
}
|
||||
|
||||
public void PostAdjustAdRevenueAppLovinMAX(double revenue, string networkName, string adUnitIdentifier, string placement)
|
||||
{
|
||||
var adRevenue = new AdjustAdRevenue(AdjustConfig.AdjustAdRevenueSourceAppLovinMAX);
|
||||
adRevenue.setRevenue(revenue, "USD");
|
||||
adRevenue.setAdRevenueNetwork(networkName);
|
||||
adRevenue.setAdRevenueUnit(adUnitIdentifier);
|
||||
adRevenue.setAdRevenuePlacement(placement);
|
||||
Adjust.trackAdRevenue(adRevenue);
|
||||
// var adRevenue = new AdjustAdRevenue(AdjustConfig.AdjustAdRevenueSourceAppLovinMAX);
|
||||
// adRevenue.setRevenue(revenue, "USD");
|
||||
// adRevenue.setAdRevenueNetwork(networkName);
|
||||
// adRevenue.setAdRevenueUnit(adUnitIdentifier);
|
||||
// adRevenue.setAdRevenuePlacement(placement);
|
||||
// Adjust.trackAdRevenue(adRevenue);
|
||||
}
|
||||
|
||||
public void AdjustSetDeviceToken(string token)
|
||||
{
|
||||
Adjust.setDeviceToken(token);
|
||||
// Adjust.setDeviceToken(token);
|
||||
}
|
||||
|
||||
public void LogAppsFlyerAdRevenue(int mediationNetwork, string monetizationNetwork, double eventRevenue, string data)
|
||||
{
|
||||
var properties = JsonConvert.DeserializeObject<Dictionary<string, string>>(data);
|
||||
var mediationNetworkType = (AppsFlyerAdRevenueMediationNetworkType)mediationNetwork;
|
||||
AppsFlyerAdRevenue.logAdRevenue(monetizationNetwork, mediationNetworkType, eventRevenue, "USD", properties);
|
||||
// var properties = JsonConvert.DeserializeObject<Dictionary<string, string>>(data);
|
||||
// var mediationNetworkType = (AppsFlyerAdRevenueMediationNetworkType)mediationNetwork;
|
||||
// AppsFlyerAdRevenue.logAdRevenue(monetizationNetwork, mediationNetworkType, eventRevenue, "USD", properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,7 +62,7 @@ namespace BF
|
||||
public BFPaySDKManager BFPaySDKMgr { get; private set; }
|
||||
public IAPManager IosPaySDKMgr { get; private set; }
|
||||
// public BFAdmobSDKManager BFAdmobSDKMgr { get; private set; }
|
||||
public BFIronSourceSDKManager BFIronSourceSDKMgr { get; private set; }
|
||||
// public BFIronSourceSDKManager BFIronSourceSDKMgr { get; private set; }
|
||||
public BFNativeSDKManager BFNativeSDKMgr { get; private set; }
|
||||
public BFThirdReportSDKManager BFThirdReportSDKMgr { get; private set; }
|
||||
|
||||
@ -91,12 +91,12 @@ namespace BF
|
||||
BFPaySDKMgr = sdkGo.AddComponent<BFPaySDKManager>();
|
||||
// 广告
|
||||
// BFAdmobSDKMgr = sdkGo.AddComponent<BFAdmobSDKManager>();
|
||||
BFIronSourceSDKMgr = sdkGo.AddComponent<BFIronSourceSDKManager>();
|
||||
// 三方上报
|
||||
// BFIronSourceSDKMgr = sdkGo.AddComponent<BFIronSourceSDKManager>();
|
||||
// // 三方上报
|
||||
BFThirdReportSDKMgr = sdkGo.AddComponent<BFThirdReportSDKManager>();
|
||||
// native交互管理
|
||||
BFNativeSDKMgr = sdkGo.AddComponent<BFNativeSDKManager>();
|
||||
IosPaySDKMgr = IAPManager.Instance;
|
||||
// IosPaySDKMgr = IAPManager.Instance;
|
||||
|
||||
GameObject.DontDestroyOnLoad(sdkGo);
|
||||
}
|
||||
|
||||
53
Assets/Scripts/Component/Battle/BattleControlBg.cs
Executable file
53
Assets/Scripts/Component/Battle/BattleControlBg.cs
Executable file
@ -0,0 +1,53 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BF
|
||||
{
|
||||
public class BattleControlBg : MonoBehaviour
|
||||
{
|
||||
public float speed = 0.0f;
|
||||
public float endX = 0.0f;
|
||||
public float resetX = 0.0f;
|
||||
public int type = 0;
|
||||
public bool canMove = true;
|
||||
|
||||
public void SetPositionByTime(float time)
|
||||
{
|
||||
var transformRect = GetComponent<RectTransform>();
|
||||
transformRect.anchoredPosition = new Vector2(transformRect.anchoredPosition.x + speed * time, transformRect.anchoredPosition.y);
|
||||
}
|
||||
|
||||
void FixedUpdate()
|
||||
{
|
||||
if (!canMove) return;
|
||||
var transformRect = GetComponent<RectTransform>();
|
||||
if (transformRect.anchoredPosition.x <= endX)
|
||||
{
|
||||
transformRect.anchoredPosition = new Vector2(resetX, transformRect.anchoredPosition.y);
|
||||
}
|
||||
// if (type == 1)
|
||||
// {
|
||||
// speed = BF.BFMain.Instance.BattleMgr.SceneSpeedC;
|
||||
// }
|
||||
// else if (type == 2)
|
||||
// {
|
||||
// speed = BF.BFMain.Instance.BattleMgr.SceneSpeedM;
|
||||
// }
|
||||
// else if (type == 3)
|
||||
// {
|
||||
// speed = BF.BFMain.Instance.BattleMgr.SceneSpeedF;
|
||||
// }
|
||||
// else if (type == 4)
|
||||
// {
|
||||
// speed = BF.BFMain.Instance.BattleMgr.SceneSpeedCould;
|
||||
// }
|
||||
// else if (type == 5)
|
||||
// {
|
||||
// speed = BF.BFMain.Instance.BattleMgr.SceneSpeedBg;
|
||||
// }
|
||||
// transform.Translate(speed * Time.fixedDeltaTime, 0.0f, 0.0f);
|
||||
transformRect.anchoredPosition = new Vector2(transformRect.anchoredPosition.x + speed * Time.fixedDeltaTime, transformRect.anchoredPosition.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/Component/Battle/BattleControlBg.cs.meta
Normal file
11
Assets/Scripts/Component/Battle/BattleControlBg.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1025633752bc248dc9665067e756f919
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -64,12 +64,12 @@ namespace BF
|
||||
|
||||
public partial class BFPlatform
|
||||
{
|
||||
const String LoginCenterURL = "https://entrance.bigfoot-studio.link";
|
||||
const String LoginCenterURL = "https://entrance.wdd817.link";
|
||||
static Dictionary<string, string> BFLoginCenterURLDict = new Dictionary<string, string>()
|
||||
{
|
||||
// dev
|
||||
{"com.juzu.b6.dev", "http://game.juzugame.com:3000"},
|
||||
{"com.juzu.b6.dev.android", "http://game.juzugame.com:3000"},
|
||||
{"com.juzu.b6.dev", "https://entrance.wdd817.link"},
|
||||
{"com.juzu.b6.dev.android", "http://8.137.93.107:3000"},
|
||||
{"com.juzu.b6.dev.ios", "http://game.juzugame.com:3000"},
|
||||
|
||||
// release
|
||||
@ -77,7 +77,7 @@ namespace BF
|
||||
{"com.juzu.b6.release.ios", "http://game.juzugame.com:3000"},
|
||||
|
||||
// gp
|
||||
{"com.combo.heroes.puzzle.rpg", "https://entrance.bigfoot-studio.link"},
|
||||
{"com.combo.heroes.puzzle.rpg", "http://8.137.93.107:3000"},
|
||||
};
|
||||
|
||||
//combine url解析的数据
|
||||
|
||||
@ -37,6 +37,20 @@ namespace BF
|
||||
public const bool SKIP_VERSION = false;
|
||||
#endif
|
||||
|
||||
#if BF_APP_DEV
|
||||
public const bool BF_APP_DEV = true;
|
||||
public const bool BF_APP_TEST = false;
|
||||
public const bool BF_APP_PUBLISH = false;
|
||||
#elif BF_APP_TEST
|
||||
public const bool BF_APP_DEV = false;
|
||||
public const bool BF_APP_TEST = true;
|
||||
public const bool BF_APP_PUBLISH = false;
|
||||
#else
|
||||
public const bool BF_APP_DEV = false;
|
||||
public const bool BF_APP_TEST = false;
|
||||
public const bool BF_APP_PUBLISH = true;
|
||||
#endif
|
||||
|
||||
public static char[] C_FREE_CHAR = new char[16] {
|
||||
(char)('g' ^ (0x29 - 0)),
|
||||
(char)('w' ^ (0x29 - 1)),
|
||||
|
||||
@ -1,108 +1,103 @@
|
||||
fileFormatVersion: 2
|
||||
guid: de1fb4dac677a6d45ae2ad12a49091c0
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 11
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 0
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 1
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: de1fb4dac677a6d45ae2ad12a49091c0
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 10
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -100
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: -1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
||||
@ -1,162 +1,162 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine;
|
||||
using Spine.Unity;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class SpineAnimationTesterTool : MonoBehaviour, IHasSkeletonDataAsset, IHasSkeletonComponent {
|
||||
|
||||
public SkeletonAnimation skeletonAnimation;
|
||||
public SkeletonDataAsset SkeletonDataAsset { get { return skeletonAnimation.SkeletonDataAsset; } }
|
||||
public ISkeletonComponent SkeletonComponent { get { return skeletonAnimation; } }
|
||||
|
||||
public bool useOverrideMixDuration;
|
||||
public float overrideMixDuration = 0.2f;
|
||||
|
||||
public bool useOverrideAttachmentThreshold = true;
|
||||
|
||||
[Range(0f, 1f)]
|
||||
public float attachmentThreshold = 0.5f;
|
||||
|
||||
public bool useOverrideDrawOrderThreshold;
|
||||
[Range(0f, 1f)]
|
||||
public float drawOrderThreshold = 0.5f;
|
||||
|
||||
[System.Serializable]
|
||||
public struct AnimationControl {
|
||||
[SpineAnimation]
|
||||
public string animationName;
|
||||
public bool loop;
|
||||
public KeyCode key;
|
||||
|
||||
[Space]
|
||||
public bool useCustomMixDuration;
|
||||
public float mixDuration;
|
||||
//public bool useChainToControl;
|
||||
//public int chainToControl;
|
||||
}
|
||||
[System.Serializable]
|
||||
public class ControlledTrack {
|
||||
public List<AnimationControl> controls = new List<AnimationControl>();
|
||||
}
|
||||
|
||||
[Space]
|
||||
public List<ControlledTrack> trackControls = new List<ControlledTrack>();
|
||||
|
||||
[Header("UI")]
|
||||
public UnityEngine.UI.Text boundAnimationsText;
|
||||
public UnityEngine.UI.Text skeletonNameText;
|
||||
|
||||
void OnValidate () {
|
||||
// Fill in the SkeletonData asset name
|
||||
if (skeletonNameText != null) {
|
||||
if (skeletonAnimation != null && skeletonAnimation.skeletonDataAsset != null) {
|
||||
skeletonNameText.text = SkeletonDataAsset.name.Replace("_SkeletonData", "");
|
||||
}
|
||||
}
|
||||
|
||||
// Fill in the control list.
|
||||
if (boundAnimationsText != null) {
|
||||
StringBuilder boundAnimationsStringBuilder = new StringBuilder();
|
||||
boundAnimationsStringBuilder.AppendLine("Animation Controls:");
|
||||
|
||||
for (int trackIndex = 0; trackIndex < trackControls.Count; trackIndex++) {
|
||||
|
||||
if (trackIndex > 0)
|
||||
boundAnimationsStringBuilder.AppendLine();
|
||||
|
||||
boundAnimationsStringBuilder.AppendFormat("---- Track {0} ---- \n", trackIndex);
|
||||
foreach (AnimationControl ba in trackControls[trackIndex].controls) {
|
||||
string animationName = ba.animationName;
|
||||
if (string.IsNullOrEmpty(animationName))
|
||||
animationName = "SetEmptyAnimation";
|
||||
|
||||
boundAnimationsStringBuilder.AppendFormat("[{0}] {1}\n", ba.key.ToString(), animationName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
boundAnimationsText.text = boundAnimationsStringBuilder.ToString();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Start () {
|
||||
if (useOverrideMixDuration) {
|
||||
skeletonAnimation.AnimationState.Data.DefaultMix = overrideMixDuration;
|
||||
}
|
||||
}
|
||||
|
||||
void Update () {
|
||||
AnimationState animationState = skeletonAnimation.AnimationState;
|
||||
|
||||
// For each track
|
||||
for (int trackIndex = 0; trackIndex < trackControls.Count; trackIndex++) {
|
||||
|
||||
// For each control in the track
|
||||
foreach (AnimationControl control in trackControls[trackIndex].controls) {
|
||||
|
||||
// Check each control, and play the appropriate animation.
|
||||
if (Input.GetKeyDown(control.key)) {
|
||||
TrackEntry trackEntry;
|
||||
if (!string.IsNullOrEmpty(control.animationName)) {
|
||||
trackEntry = animationState.SetAnimation(trackIndex, control.animationName, control.loop);
|
||||
|
||||
} else {
|
||||
float mix = control.useCustomMixDuration ? control.mixDuration : animationState.Data.DefaultMix;
|
||||
trackEntry = animationState.SetEmptyAnimation(trackIndex, mix);
|
||||
}
|
||||
|
||||
if (trackEntry != null) {
|
||||
if (control.useCustomMixDuration)
|
||||
trackEntry.MixDuration = control.mixDuration;
|
||||
|
||||
if (useOverrideAttachmentThreshold)
|
||||
trackEntry.AttachmentThreshold = attachmentThreshold;
|
||||
|
||||
if (useOverrideDrawOrderThreshold)
|
||||
trackEntry.DrawOrderThreshold = drawOrderThreshold;
|
||||
}
|
||||
|
||||
// Don't parse more than one animation per track.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine;
|
||||
using Spine.Unity;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class SpineAnimationTesterTool : MonoBehaviour, IHasSkeletonDataAsset, IHasSkeletonComponent {
|
||||
|
||||
public SkeletonAnimation skeletonAnimation;
|
||||
public SkeletonDataAsset SkeletonDataAsset { get { return skeletonAnimation.SkeletonDataAsset; } }
|
||||
public ISkeletonComponent SkeletonComponent { get { return skeletonAnimation; } }
|
||||
|
||||
public bool useOverrideMixDuration;
|
||||
public float overrideMixDuration = 0.2f;
|
||||
|
||||
public bool useOverrideAttachmentThreshold = true;
|
||||
|
||||
[Range(0f, 1f)]
|
||||
public float attachmentThreshold = 0.5f;
|
||||
|
||||
public bool useOverrideDrawOrderThreshold;
|
||||
[Range(0f, 1f)]
|
||||
public float drawOrderThreshold = 0.5f;
|
||||
|
||||
[System.Serializable]
|
||||
public struct AnimationControl {
|
||||
[SpineAnimation]
|
||||
public string animationName;
|
||||
public bool loop;
|
||||
public KeyCode key;
|
||||
|
||||
[Space]
|
||||
public bool useCustomMixDuration;
|
||||
public float mixDuration;
|
||||
//public bool useChainToControl;
|
||||
//public int chainToControl;
|
||||
}
|
||||
[System.Serializable]
|
||||
public class ControlledTrack {
|
||||
public List<AnimationControl> controls = new List<AnimationControl>();
|
||||
}
|
||||
|
||||
[Space]
|
||||
public List<ControlledTrack> trackControls = new List<ControlledTrack>();
|
||||
|
||||
[Header("UI")]
|
||||
public UnityEngine.UI.Text boundAnimationsText;
|
||||
public UnityEngine.UI.Text skeletonNameText;
|
||||
|
||||
void OnValidate () {
|
||||
// Fill in the SkeletonData asset name
|
||||
if (skeletonNameText != null) {
|
||||
if (skeletonAnimation != null && skeletonAnimation.skeletonDataAsset != null) {
|
||||
skeletonNameText.text = SkeletonDataAsset.name.Replace("_SkeletonData", "");
|
||||
}
|
||||
}
|
||||
|
||||
// Fill in the control list.
|
||||
if (boundAnimationsText != null) {
|
||||
StringBuilder boundAnimationsStringBuilder = new StringBuilder();
|
||||
boundAnimationsStringBuilder.AppendLine("Animation Controls:");
|
||||
|
||||
for (int trackIndex = 0; trackIndex < trackControls.Count; trackIndex++) {
|
||||
|
||||
if (trackIndex > 0)
|
||||
boundAnimationsStringBuilder.AppendLine();
|
||||
|
||||
boundAnimationsStringBuilder.AppendFormat("---- Track {0} ---- \n", trackIndex);
|
||||
foreach (AnimationControl ba in trackControls[trackIndex].controls) {
|
||||
string animationName = ba.animationName;
|
||||
if (string.IsNullOrEmpty(animationName))
|
||||
animationName = "SetEmptyAnimation";
|
||||
|
||||
boundAnimationsStringBuilder.AppendFormat("[{0}] {1}\n", ba.key.ToString(), animationName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
boundAnimationsText.text = boundAnimationsStringBuilder.ToString();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Start () {
|
||||
if (useOverrideMixDuration) {
|
||||
skeletonAnimation.AnimationState.Data.DefaultMix = overrideMixDuration;
|
||||
}
|
||||
}
|
||||
|
||||
void Update () {
|
||||
AnimationState animationState = skeletonAnimation.AnimationState;
|
||||
|
||||
// For each track
|
||||
for (int trackIndex = 0; trackIndex < trackControls.Count; trackIndex++) {
|
||||
|
||||
// For each control in the track
|
||||
foreach (AnimationControl control in trackControls[trackIndex].controls) {
|
||||
|
||||
// Check each control, and play the appropriate animation.
|
||||
if (Input.GetKeyDown(control.key)) {
|
||||
TrackEntry trackEntry;
|
||||
if (!string.IsNullOrEmpty(control.animationName)) {
|
||||
trackEntry = animationState.SetAnimation(trackIndex, control.animationName, control.loop);
|
||||
|
||||
} else {
|
||||
float mix = control.useCustomMixDuration ? control.mixDuration : animationState.Data.DefaultMix;
|
||||
trackEntry = animationState.SetEmptyAnimation(trackIndex, mix);
|
||||
}
|
||||
|
||||
if (trackEntry != null) {
|
||||
if (control.useCustomMixDuration)
|
||||
trackEntry.SetMixDuration(control.mixDuration, 0f); // use SetMixDuration(mixDuration, delay) to update delay correctly
|
||||
|
||||
if (useOverrideAttachmentThreshold)
|
||||
trackEntry.MixAttachmentThreshold = attachmentThreshold;
|
||||
|
||||
if (useOverrideDrawOrderThreshold)
|
||||
trackEntry.MixDrawOrderThreshold = drawOrderThreshold;
|
||||
}
|
||||
|
||||
// Don't parse more than one animation per track.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@ OcclusionCullingSettings:
|
||||
--- !u!104 &2
|
||||
RenderSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 8
|
||||
serializedVersion: 10
|
||||
m_Fog: 0
|
||||
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
|
||||
m_FogMode: 3
|
||||
@ -39,37 +39,33 @@ RenderSettings:
|
||||
m_CustomReflection: {fileID: 0}
|
||||
m_Sun: {fileID: 0}
|
||||
m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
m_UseRadianceAmbientProbe: 0
|
||||
--- !u!157 &3
|
||||
LightmapSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 11
|
||||
m_GIWorkflowMode: 1
|
||||
serializedVersion: 12
|
||||
m_GISettings:
|
||||
serializedVersion: 2
|
||||
m_BounceScale: 1
|
||||
m_IndirectOutputScale: 1
|
||||
m_AlbedoBoost: 1
|
||||
m_TemporalCoherenceThreshold: 1
|
||||
m_EnvironmentLightingMode: 0
|
||||
m_EnableBakedLightmaps: 0
|
||||
m_EnableRealtimeLightmaps: 0
|
||||
m_LightmapEditorSettings:
|
||||
serializedVersion: 9
|
||||
serializedVersion: 12
|
||||
m_Resolution: 2
|
||||
m_BakeResolution: 40
|
||||
m_TextureWidth: 1024
|
||||
m_TextureHeight: 1024
|
||||
m_AtlasSize: 1024
|
||||
m_AO: 0
|
||||
m_AOMaxDistance: 1
|
||||
m_CompAOExponent: 1
|
||||
m_CompAOExponentDirect: 0
|
||||
m_ExtractAmbientOcclusion: 0
|
||||
m_Padding: 2
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_LightmapsBakeMode: 1
|
||||
m_TextureCompression: 1
|
||||
m_FinalGather: 0
|
||||
m_FinalGatherFiltering: 1
|
||||
m_FinalGatherRayCount: 256
|
||||
m_ReflectionCompression: 2
|
||||
m_MixedBakeMode: 2
|
||||
m_BakeBackend: 0
|
||||
@ -77,23 +73,34 @@ LightmapSettings:
|
||||
m_PVRDirectSampleCount: 32
|
||||
m_PVRSampleCount: 500
|
||||
m_PVRBounces: 2
|
||||
m_PVRFiltering: 0
|
||||
m_PVRFilteringMode: 1
|
||||
m_PVREnvironmentSampleCount: 500
|
||||
m_PVREnvironmentReferencePointCount: 2048
|
||||
m_PVRFilteringMode: 2
|
||||
m_PVRDenoiserTypeDirect: 0
|
||||
m_PVRDenoiserTypeIndirect: 0
|
||||
m_PVRDenoiserTypeAO: 0
|
||||
m_PVRFilterTypeDirect: 0
|
||||
m_PVRFilterTypeIndirect: 0
|
||||
m_PVRFilterTypeAO: 0
|
||||
m_PVREnvironmentMIS: 0
|
||||
m_PVRCulling: 1
|
||||
m_PVRFilteringGaussRadiusDirect: 1
|
||||
m_PVRFilteringGaussRadiusIndirect: 5
|
||||
m_PVRFilteringGaussRadiusAO: 2
|
||||
m_PVRFilteringAtrousColorSigma: 1
|
||||
m_PVRFilteringAtrousNormalSigma: 1
|
||||
m_PVRFilteringAtrousPositionSigma: 1
|
||||
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
|
||||
m_PVRFilteringAtrousPositionSigmaIndirect: 2
|
||||
m_PVRFilteringAtrousPositionSigmaAO: 1
|
||||
m_ExportTrainingData: 0
|
||||
m_TrainingDataDestination: TrainingData
|
||||
m_LightProbeSampleCountMultiplier: 4
|
||||
m_LightingDataAsset: {fileID: 0}
|
||||
m_UseShadowmask: 1
|
||||
m_LightingSettings: {fileID: 1506007501}
|
||||
--- !u!196 &4
|
||||
NavMeshSettings:
|
||||
serializedVersion: 2
|
||||
m_ObjectHideFlags: 0
|
||||
m_BuildSettings:
|
||||
serializedVersion: 2
|
||||
serializedVersion: 3
|
||||
agentTypeID: 0
|
||||
agentRadius: 0.5
|
||||
agentHeight: 2
|
||||
@ -106,20 +113,25 @@ NavMeshSettings:
|
||||
cellSize: 0.16666667
|
||||
manualTileSize: 0
|
||||
tileSize: 256
|
||||
accuratePlacement: 0
|
||||
buildHeightMesh: 0
|
||||
maxJobWorkers: 0
|
||||
preserveTilesOutsideBounds: 0
|
||||
debug:
|
||||
m_Flags: 0
|
||||
m_NavMeshData: {fileID: 0}
|
||||
--- !u!1 &92207858
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
serializedVersion: 5
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 92207862}
|
||||
- component: {fileID: 92207861}
|
||||
- component: {fileID: 92207860}
|
||||
m_Layer: 5
|
||||
m_Name: 3 Canvas - Spawn SkeletonGraphic Sample
|
||||
m_Name: 2 Canvas - Spawn SkeletonGraphic Sample
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
@ -128,12 +140,13 @@ GameObject:
|
||||
--- !u!114 &92207860
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 92207858}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 1980459831, guid: f70555f144d8491a825f0804e09c671c, type: 3}
|
||||
m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_UiScaleMode: 1
|
||||
@ -146,11 +159,13 @@ MonoBehaviour:
|
||||
m_FallbackScreenDPI: 96
|
||||
m_DefaultSpriteDPI: 96
|
||||
m_DynamicPixelsPerUnit: 1
|
||||
m_PresetInfoIsWorld: 0
|
||||
--- !u!223 &92207861
|
||||
Canvas:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 92207858}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
@ -162,35 +177,122 @@ Canvas:
|
||||
m_OverrideSorting: 0
|
||||
m_OverridePixelPerfect: 0
|
||||
m_SortingBucketNormalizedSize: 0
|
||||
m_VertexColorAlwaysGammaSpace: 0
|
||||
m_AdditionalShaderChannelsFlag: 0
|
||||
m_UpdateRectTransformForStandalone: 0
|
||||
m_SortingLayerID: 0
|
||||
m_SortingOrder: 0
|
||||
m_TargetDisplay: 0
|
||||
--- !u!224 &92207862
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 92207858}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 0, y: 0, z: 0}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 1691562007}
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 3
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0, y: 0}
|
||||
--- !u!1 &191860306
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 191860307}
|
||||
- component: {fileID: 191860309}
|
||||
- component: {fileID: 191860308}
|
||||
m_Layer: 0
|
||||
m_Name: Canvas
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &191860307
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 191860306}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 0, y: 0, z: 0}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 1200587070}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0, y: 0}
|
||||
--- !u!114 &191860308
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 191860306}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_UiScaleMode: 1
|
||||
m_ReferencePixelsPerUnit: 100
|
||||
m_ScaleFactor: 1
|
||||
m_ReferenceResolution: {x: 1920, y: 1080}
|
||||
m_ScreenMatchMode: 0
|
||||
m_MatchWidthOrHeight: 0
|
||||
m_PhysicalUnit: 3
|
||||
m_FallbackScreenDPI: 96
|
||||
m_DefaultSpriteDPI: 96
|
||||
m_DynamicPixelsPerUnit: 1
|
||||
m_PresetInfoIsWorld: 0
|
||||
--- !u!223 &191860309
|
||||
Canvas:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 191860306}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_RenderMode: 0
|
||||
m_Camera: {fileID: 0}
|
||||
m_PlaneDistance: 100
|
||||
m_PixelPerfect: 0
|
||||
m_ReceivesEvents: 1
|
||||
m_OverrideSorting: 0
|
||||
m_OverridePixelPerfect: 0
|
||||
m_SortingBucketNormalizedSize: 0
|
||||
m_VertexColorAlwaysGammaSpace: 0
|
||||
m_AdditionalShaderChannelsFlag: 0
|
||||
m_UpdateRectTransformForStandalone: 0
|
||||
m_SortingLayerID: 0
|
||||
m_SortingOrder: 0
|
||||
m_TargetDisplay: 0
|
||||
--- !u!1 &433620963
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
serializedVersion: 5
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 433620968}
|
||||
- component: {fileID: 433620967}
|
||||
@ -206,27 +308,44 @@ GameObject:
|
||||
--- !u!81 &433620964
|
||||
AudioListener:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 433620963}
|
||||
m_Enabled: 1
|
||||
--- !u!124 &433620965
|
||||
Behaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 433620963}
|
||||
m_Enabled: 1
|
||||
--- !u!20 &433620967
|
||||
Camera:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 433620963}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 2
|
||||
m_ClearFlags: 1
|
||||
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
|
||||
m_projectionMatrixMode: 1
|
||||
m_GateFitMode: 2
|
||||
m_FOVAxisMode: 0
|
||||
m_Iso: 200
|
||||
m_ShutterSpeed: 0.005
|
||||
m_Aperture: 16
|
||||
m_FocusDistance: 10
|
||||
m_FocalLength: 50
|
||||
m_BladeCount: 5
|
||||
m_Curvature: {x: 2, y: 11}
|
||||
m_BarrelClipping: 0.25
|
||||
m_Anamorphism: 0
|
||||
m_SensorSize: {x: 36, y: 24}
|
||||
m_LensShift: {x: 0, y: 0}
|
||||
m_NormalizedViewPortRect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
@ -248,35 +367,38 @@ Camera:
|
||||
m_TargetEye: 3
|
||||
m_HDR: 1
|
||||
m_AllowMSAA: 1
|
||||
m_AllowDynamicResolution: 0
|
||||
m_ForceIntoRT: 0
|
||||
m_OcclusionCulling: 1
|
||||
m_StereoConvergence: 10
|
||||
m_StereoSeparation: 0.022
|
||||
m_StereoMirrorMode: 0
|
||||
--- !u!4 &433620968
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 433620963}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: -10}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &651278528
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
serializedVersion: 5
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 651278530}
|
||||
- component: {fileID: 651278529}
|
||||
m_Layer: 0
|
||||
m_Name: 2 RuntimeLoadFromExports
|
||||
m_Name: 3 RuntimeLoadFromExports
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
@ -285,8 +407,9 @@ GameObject:
|
||||
--- !u!114 &651278529
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 651278528}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
@ -297,27 +420,251 @@ MonoBehaviour:
|
||||
atlasText: {fileID: 4900000, guid: 5c0a5c36970a46e4d8378760ab4a4cfc, type: 3}
|
||||
textures:
|
||||
- {fileID: 2800000, guid: 49bb65eefe08e424bbf7a38bc98ec638, type: 3}
|
||||
materialPropertySource: {fileID: 2100000, guid: 1455e88fdb81ccc45bdeaedd657bad4d,
|
||||
type: 2}
|
||||
materialPropertySource: {fileID: 2100000, guid: 1455e88fdb81ccc45bdeaedd657bad4d, type: 2}
|
||||
delay: 0
|
||||
skinName:
|
||||
animationName:
|
||||
blendModeMaterials: 0
|
||||
applyAdditiveMaterial: 0
|
||||
blendModeTemplateMaterials:
|
||||
additiveTemplate: {fileID: 0}
|
||||
multiplyTemplate: {fileID: 0}
|
||||
screenTemplate: {fileID: 0}
|
||||
graphicBlendModeMaterials:
|
||||
additiveTemplate: {fileID: 0}
|
||||
multiplyTemplate: {fileID: 0}
|
||||
screenTemplate: {fileID: 0}
|
||||
skeletonGraphicMaterial: {fileID: 2100000, guid: b66cf7a186d13054989b33a5c90044e4, type: 2}
|
||||
--- !u!4 &651278530
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 651278528}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 1025308469}
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 2
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &1025308468
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1025308469}
|
||||
- component: {fileID: 1025308472}
|
||||
- component: {fileID: 1025308471}
|
||||
m_Layer: 0
|
||||
m_Name: Canvas
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &1025308469
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1025308468}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 0, y: 0, z: 0}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 651278530}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0, y: 0}
|
||||
--- !u!114 &1025308471
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1025308468}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_UiScaleMode: 1
|
||||
m_ReferencePixelsPerUnit: 100
|
||||
m_ScaleFactor: 1
|
||||
m_ReferenceResolution: {x: 1920, y: 1080}
|
||||
m_ScreenMatchMode: 0
|
||||
m_MatchWidthOrHeight: 0
|
||||
m_PhysicalUnit: 3
|
||||
m_FallbackScreenDPI: 96
|
||||
m_DefaultSpriteDPI: 96
|
||||
m_DynamicPixelsPerUnit: 1
|
||||
m_PresetInfoIsWorld: 0
|
||||
--- !u!223 &1025308472
|
||||
Canvas:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1025308468}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_RenderMode: 0
|
||||
m_Camera: {fileID: 0}
|
||||
m_PlaneDistance: 100
|
||||
m_PixelPerfect: 0
|
||||
m_ReceivesEvents: 1
|
||||
m_OverrideSorting: 0
|
||||
m_OverridePixelPerfect: 0
|
||||
m_SortingBucketNormalizedSize: 0
|
||||
m_VertexColorAlwaysGammaSpace: 0
|
||||
m_AdditionalShaderChannelsFlag: 0
|
||||
m_UpdateRectTransformForStandalone: 0
|
||||
m_SortingLayerID: 0
|
||||
m_SortingOrder: 0
|
||||
m_TargetDisplay: 0
|
||||
--- !u!1 &1200587068
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1200587070}
|
||||
- component: {fileID: 1200587069}
|
||||
m_Layer: 0
|
||||
m_Name: 4 Runtime BlendModes from Exports
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!114 &1200587069
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1200587068}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: bb0837af7345d504db63d0c662fd12dc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
skeletonJson: {fileID: 4900000, guid: 1a6f51aad0fef5a40aeedfeec5c0b8b2, type: 3}
|
||||
atlasText: {fileID: 4900000, guid: 188756a89517d7649a67fb53606220f5, type: 3}
|
||||
textures:
|
||||
- {fileID: 2800000, guid: dc1b9f9665c8aa74799404a1d2038e3d, type: 3}
|
||||
materialPropertySource: {fileID: 2100000, guid: 1455e88fdb81ccc45bdeaedd657bad4d, type: 2}
|
||||
delay: 0
|
||||
skinName:
|
||||
animationName:
|
||||
blendModeMaterials: 1
|
||||
applyAdditiveMaterial: 0
|
||||
blendModeTemplateMaterials:
|
||||
additiveTemplate: {fileID: 2100000, guid: 4deba332d47209e4780b3c5fcf0e3745, type: 2}
|
||||
multiplyTemplate: {fileID: 2100000, guid: 53bf0ab317d032d418cf1252d68f51df, type: 2}
|
||||
screenTemplate: {fileID: 2100000, guid: 73f0f46d3177c614baf0fa48d646a9be, type: 2}
|
||||
graphicBlendModeMaterials:
|
||||
additiveTemplate: {fileID: 2100000, guid: 2e8245019faeb8c43b75f9ca3ac8ee34, type: 2}
|
||||
multiplyTemplate: {fileID: 2100000, guid: e74a1f8978a7da348a721508d0d58834, type: 2}
|
||||
screenTemplate: {fileID: 2100000, guid: bab24c479f34eec45be6ea8595891569, type: 2}
|
||||
skeletonGraphicMaterial: {fileID: 2100000, guid: b66cf7a186d13054989b33a5c90044e4, type: 2}
|
||||
--- !u!4 &1200587070
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1200587068}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 191860307}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!850595691 &1506007501
|
||||
LightingSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Settings.lighting
|
||||
serializedVersion: 8
|
||||
m_EnableBakedLightmaps: 0
|
||||
m_EnableRealtimeLightmaps: 0
|
||||
m_RealtimeEnvironmentLighting: 1
|
||||
m_BounceScale: 1
|
||||
m_AlbedoBoost: 1
|
||||
m_IndirectOutputScale: 1
|
||||
m_UsingShadowmask: 1
|
||||
m_BakeBackend: 1
|
||||
m_LightmapMaxSize: 1024
|
||||
m_LightmapSizeFixed: 0
|
||||
m_UseMipmapLimits: 1
|
||||
m_BakeResolution: 40
|
||||
m_Padding: 2
|
||||
m_LightmapCompression: 3
|
||||
m_AO: 0
|
||||
m_AOMaxDistance: 1
|
||||
m_CompAOExponent: 1
|
||||
m_CompAOExponentDirect: 0
|
||||
m_ExtractAO: 0
|
||||
m_MixedBakeMode: 2
|
||||
m_LightmapsBakeMode: 1
|
||||
m_FilterMode: 1
|
||||
m_LightmapParameters: {fileID: 15204, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ExportTrainingData: 0
|
||||
m_TrainingDataDestination: TrainingData
|
||||
m_RealtimeResolution: 2
|
||||
m_ForceWhiteAlbedo: 0
|
||||
m_ForceUpdates: 0
|
||||
m_PVRCulling: 1
|
||||
m_PVRSampling: 1
|
||||
m_PVRDirectSampleCount: 32
|
||||
m_PVRSampleCount: 512
|
||||
m_PVREnvironmentSampleCount: 512
|
||||
m_PVREnvironmentReferencePointCount: 2048
|
||||
m_LightProbeSampleCountMultiplier: 4
|
||||
m_PVRBounces: 2
|
||||
m_PVRMinBounces: 2
|
||||
m_PVREnvironmentImportanceSampling: 0
|
||||
m_PVRFilteringMode: 2
|
||||
m_PVRDenoiserTypeDirect: 0
|
||||
m_PVRDenoiserTypeIndirect: 0
|
||||
m_PVRDenoiserTypeAO: 0
|
||||
m_PVRFilterTypeDirect: 0
|
||||
m_PVRFilterTypeIndirect: 0
|
||||
m_PVRFilterTypeAO: 0
|
||||
m_PVRFilteringGaussRadiusDirect: 1
|
||||
m_PVRFilteringGaussRadiusIndirect: 5
|
||||
m_PVRFilteringGaussRadiusAO: 2
|
||||
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
|
||||
m_PVRFilteringAtrousPositionSigmaIndirect: 2
|
||||
m_PVRFilteringAtrousPositionSigmaAO: 1
|
||||
m_RespectSceneVisibilityWhenBakingGI: 0
|
||||
--- !u!1 &1691562006
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
serializedVersion: 5
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1691562007}
|
||||
- component: {fileID: 1691562008}
|
||||
@ -331,15 +678,16 @@ GameObject:
|
||||
--- !u!224 &1691562007
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1691562006}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 92207862}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
@ -349,8 +697,9 @@ RectTransform:
|
||||
--- !u!114 &1691562008
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1691562006}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
@ -360,14 +709,14 @@ MonoBehaviour:
|
||||
skeletonDataAsset: {fileID: 11400000, guid: a467507a4ffb1d542a558739b2fede77, type: 2}
|
||||
startingAnimation: run
|
||||
startingSkin: base
|
||||
skeletonGraphicMaterial: {fileID: 2100000, guid: 1455e88fdb81ccc45bdeaedd657bad4d,
|
||||
type: 2}
|
||||
skeletonGraphicMaterial: {fileID: 2100000, guid: b66cf7a186d13054989b33a5c90044e4, type: 2}
|
||||
--- !u!1 &1807176298
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
serializedVersion: 5
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1807176300}
|
||||
- component: {fileID: 1807176299}
|
||||
@ -381,8 +730,9 @@ GameObject:
|
||||
--- !u!114 &1807176299
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1807176298}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
@ -395,13 +745,93 @@ MonoBehaviour:
|
||||
--- !u!4 &1807176300
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1807176298}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 1
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &1924218899
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1924218902}
|
||||
- component: {fileID: 1924218901}
|
||||
- component: {fileID: 1924218900}
|
||||
m_Layer: 0
|
||||
m_Name: EventSystem
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!114 &1924218900
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1924218899}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_SendPointerHoverToParent: 1
|
||||
m_HorizontalAxis: Horizontal
|
||||
m_VerticalAxis: Vertical
|
||||
m_SubmitButton: Submit
|
||||
m_CancelButton: Cancel
|
||||
m_InputActionsPerSecond: 10
|
||||
m_RepeatDelay: 0.5
|
||||
m_ForceModuleActive: 0
|
||||
--- !u!114 &1924218901
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1924218899}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_FirstSelected: {fileID: 0}
|
||||
m_sendNavigationEvents: 1
|
||||
m_DragThreshold: 10
|
||||
--- !u!4 &1924218902
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1924218899}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1660057539 &9223372036854775807
|
||||
SceneRoots:
|
||||
m_ObjectHideFlags: 0
|
||||
m_Roots:
|
||||
- {fileID: 433620968}
|
||||
- {fileID: 1807176300}
|
||||
- {fileID: 92207862}
|
||||
- {fileID: 651278530}
|
||||
- {fileID: 1200587070}
|
||||
- {fileID: 1924218902}
|
||||
|
||||
15770
Assets/ThirdParty/Spine Examples/Other Examples/Physics Constraints.unity
vendored
Normal file
15770
Assets/ThirdParty/Spine Examples/Other Examples/Physics Constraints.unity
vendored
Normal file
File diff suppressed because it is too large
Load Diff
7
Assets/ThirdParty/Spine Examples/Other Examples/Physics Constraints.unity.meta
vendored
Normal file
7
Assets/ThirdParty/Spine Examples/Other Examples/Physics Constraints.unity.meta
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e08ce2e2ca315ea4a8e8d3a90681a14c
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -151,6 +151,7 @@ RectTransform:
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 592567554}
|
||||
m_RootOrder: 1
|
||||
@ -256,6 +257,9 @@ MonoBehaviour:
|
||||
materialsInsideMask: []
|
||||
materialsOutsideMask: []
|
||||
disableRenderingOnOverride: 1
|
||||
physicsPositionInheritanceFactor: {x: 1, y: 1}
|
||||
physicsRotationInheritanceFactor: 1
|
||||
physicsMovementRelativeTo: {fileID: 0}
|
||||
updateTiming: 1
|
||||
unscaledTime: 0
|
||||
_animationName: run
|
||||
@ -272,6 +276,7 @@ MeshRenderer:
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
m_DynamicOccludee: 1
|
||||
m_StaticShadowCaster: 0
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
@ -320,6 +325,7 @@ Transform:
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: -7.83, y: 0, z: 5.66}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 3
|
||||
@ -352,6 +358,7 @@ RectTransform:
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 592567554}
|
||||
m_RootOrder: 2
|
||||
@ -434,6 +441,7 @@ RectTransform:
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 0, y: 0, z: 0}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 1911967440}
|
||||
- {fileID: 71621967}
|
||||
@ -489,6 +497,7 @@ Canvas:
|
||||
m_OverridePixelPerfect: 0
|
||||
m_SortingBucketNormalizedSize: 0
|
||||
m_AdditionalShaderChannelsFlag: 0
|
||||
m_UpdateRectTransformForStandalone: 0
|
||||
m_SortingLayerID: 0
|
||||
m_SortingOrder: 0
|
||||
m_TargetDisplay: 0
|
||||
@ -518,6 +527,7 @@ RectTransform:
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 1911967440}
|
||||
m_RootOrder: 0
|
||||
@ -554,6 +564,7 @@ Transform:
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: -3.7153435, y: -0.0017910004, z: 5.9292965}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 2
|
||||
@ -583,6 +594,7 @@ GameObject:
|
||||
m_Component:
|
||||
- component: {fileID: 1369381601}
|
||||
- component: {fileID: 1369381600}
|
||||
- component: {fileID: 1369381602}
|
||||
m_Layer: 0
|
||||
m_Name: Directional Light
|
||||
m_TagString: Untagged
|
||||
@ -662,10 +674,31 @@ Transform:
|
||||
m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261}
|
||||
m_LocalPosition: {x: 0, y: 3, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 1
|
||||
m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
|
||||
--- !u!114 &1369381602
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1369381599}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 474bcb49853aa07438625e644c072ee6, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Version: 1
|
||||
m_UsePipelineSettings: 1
|
||||
m_AdditionalLightsShadowResolutionTier: 2
|
||||
m_LightLayerMask: 1
|
||||
m_CustomShadowLayers: 0
|
||||
m_ShadowLayerMask: 1
|
||||
m_LightCookieSize: {x: 1, y: 1}
|
||||
m_LightCookieOffset: {x: 0, y: 0}
|
||||
--- !u!1 &1407691187
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -745,6 +778,7 @@ Transform:
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 4.8, z: -10}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
@ -811,6 +845,7 @@ Transform:
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 5
|
||||
@ -843,6 +878,7 @@ RectTransform:
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 592567554}
|
||||
m_RootOrder: 3
|
||||
@ -930,6 +966,7 @@ RectTransform:
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 592567554}
|
||||
m_RootOrder: 4
|
||||
@ -1019,9 +1056,10 @@ MonoBehaviour:
|
||||
color: {r: 1, g: 1, b: 1, a: 1}
|
||||
maxRenderTextureSize: 1024
|
||||
quad: {fileID: 0}
|
||||
quadMaterial: {fileID: 2100000, guid: 4c507f887c6274a44a603d96e0eabf2a, type: 2}
|
||||
renderTexture: {fileID: 0}
|
||||
targetCamera: {fileID: 0}
|
||||
quadMaterial: {fileID: 2100000, guid: 4c507f887c6274a44a603d96e0eabf2a, type: 2}
|
||||
shaderPasses: 00000000
|
||||
--- !u!114 &1786065615
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -1057,6 +1095,9 @@ MonoBehaviour:
|
||||
materialsInsideMask: []
|
||||
materialsOutsideMask: []
|
||||
disableRenderingOnOverride: 1
|
||||
physicsPositionInheritanceFactor: {x: 1, y: 1}
|
||||
physicsRotationInheritanceFactor: 1
|
||||
physicsMovementRelativeTo: {fileID: 0}
|
||||
updateTiming: 1
|
||||
unscaledTime: 0
|
||||
_animationName: run
|
||||
@ -1073,6 +1114,7 @@ MeshRenderer:
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
m_DynamicOccludee: 1
|
||||
m_StaticShadowCaster: 0
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
@ -1121,6 +1163,7 @@ Transform:
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 2.38, y: 0, z: 5.66}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 4
|
||||
@ -1164,6 +1207,7 @@ Transform:
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: -4.7074776, y: 0.042612553, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 592567554}
|
||||
m_Father: {fileID: 0}
|
||||
@ -1199,6 +1243,7 @@ RectTransform:
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 0.3, y: 0.3, z: 0.3}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 1089682727}
|
||||
m_Father: {fileID: 592567554}
|
||||
@ -1233,6 +1278,7 @@ MonoBehaviour:
|
||||
additiveMaterial: {fileID: 2100000, guid: 2e8245019faeb8c43b75f9ca3ac8ee34, type: 2}
|
||||
multiplyMaterial: {fileID: 2100000, guid: e74a1f8978a7da348a721508d0d58834, type: 2}
|
||||
screenMaterial: {fileID: 2100000, guid: bab24c479f34eec45be6ea8595891569, type: 2}
|
||||
m_SkeletonColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
initialSkinName: default
|
||||
initialFlipX: 0
|
||||
initialFlipY: 0
|
||||
@ -1240,6 +1286,14 @@ MonoBehaviour:
|
||||
startingLoop: 1
|
||||
timeScale: 1
|
||||
freeze: 0
|
||||
layoutScaleMode: 0
|
||||
referenceSize: {x: 2145.5999, y: 1302.059}
|
||||
referencePivot: {x: 0.63858336, y: 0.010301443}
|
||||
referencePivotOffset: {x: 1370.1444, y: 13.413086}
|
||||
referenceScale: 1
|
||||
rectTransformSize: {x: 2145.5999, y: 1302.059}
|
||||
rectTransformPivot: {x: 0, y: 0}
|
||||
editReferenceRect: 0
|
||||
updateWhenInvisible: 3
|
||||
allowMultipleCanvasRenderers: 0
|
||||
canvasRenderers: []
|
||||
@ -1247,16 +1301,20 @@ MonoBehaviour:
|
||||
enableSeparatorSlots: 0
|
||||
separatorParts: []
|
||||
updateSeparatorPartLocation: 1
|
||||
updateSeparatorPartScale: 0
|
||||
disableMeshAssignmentOnOverride: 1
|
||||
physicsPositionInheritanceFactor: {x: 1, y: 1}
|
||||
physicsRotationInheritanceFactor: 1
|
||||
physicsMovementRelativeTo: {fileID: 0}
|
||||
meshGenerator:
|
||||
settings:
|
||||
useClipping: 1
|
||||
zSpacing: 0
|
||||
pmaVertexColors: 1
|
||||
tintBlack: 0
|
||||
canvasGroupTintBlack: 0
|
||||
calculateTangents: 0
|
||||
canvasGroupCompatible: 0
|
||||
pmaVertexColors: 1
|
||||
addNormals: 0
|
||||
calculateTangents: 0
|
||||
immutableTriangles: 0
|
||||
updateTiming: 1
|
||||
unscaledTime: 0
|
||||
@ -1296,8 +1354,10 @@ MonoBehaviour:
|
||||
color: {r: 1, g: 1, b: 1, a: 1}
|
||||
maxRenderTextureSize: 1024
|
||||
quad: {fileID: 0}
|
||||
quadMaterial: {fileID: 2100000, guid: afeb0ae2ea2cda94796515bf8d1b3cb1, type: 2}
|
||||
renderTexture: {fileID: 0}
|
||||
targetCamera: {fileID: 0}
|
||||
shaderPasses: 00000000
|
||||
customRenderRect: {fileID: 1089682727}
|
||||
meshRendererMaterialForTexture:
|
||||
- texture: {fileID: 2800000, guid: 4ea2c33e839afb34c98f66e892b3b2d2, type: 3}
|
||||
|
||||
@ -1,71 +1,71 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class AttackSpineboy : MonoBehaviour {
|
||||
|
||||
public SkeletonAnimation spineboy;
|
||||
public SkeletonAnimation attackerSpineboy;
|
||||
public SpineGauge gauge;
|
||||
public Text healthText;
|
||||
|
||||
int currentHealth = 100;
|
||||
const int maxHealth = 100;
|
||||
|
||||
public AnimationReferenceAsset shoot, hit, idle, death;
|
||||
|
||||
public UnityEngine.Events.UnityEvent onAttack;
|
||||
|
||||
void Update () {
|
||||
if (Input.GetKeyDown(KeyCode.Space)) {
|
||||
currentHealth -= 10;
|
||||
healthText.text = currentHealth + "/" + maxHealth;
|
||||
|
||||
attackerSpineboy.AnimationState.SetAnimation(1, shoot, false);
|
||||
attackerSpineboy.AnimationState.AddEmptyAnimation(1, 0.5f, 2f);
|
||||
|
||||
if (currentHealth > 0) {
|
||||
spineboy.AnimationState.SetAnimation(0, hit, false);
|
||||
spineboy.AnimationState.AddAnimation(0, idle, true, 0);
|
||||
gauge.fillPercent = (float)currentHealth / (float)maxHealth;
|
||||
onAttack.Invoke();
|
||||
} else {
|
||||
if (currentHealth >= 0) {
|
||||
gauge.fillPercent = 0;
|
||||
spineboy.AnimationState.SetAnimation(0, death, false).TrackEnd = float.PositiveInfinity;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class AttackSpineboy : MonoBehaviour {
|
||||
|
||||
public SkeletonAnimation spineboy;
|
||||
public SkeletonAnimation attackerSpineboy;
|
||||
public SpineGauge gauge;
|
||||
public Text healthText;
|
||||
|
||||
int currentHealth = 100;
|
||||
const int maxHealth = 100;
|
||||
|
||||
public AnimationReferenceAsset shoot, hit, idle, death;
|
||||
|
||||
public UnityEngine.Events.UnityEvent onAttack;
|
||||
|
||||
void Update () {
|
||||
if (Input.GetKeyDown(KeyCode.Space)) {
|
||||
currentHealth -= 10;
|
||||
healthText.text = currentHealth + "/" + maxHealth;
|
||||
|
||||
attackerSpineboy.AnimationState.SetAnimation(1, shoot, false);
|
||||
attackerSpineboy.AnimationState.AddEmptyAnimation(1, 0.5f, 2f);
|
||||
|
||||
if (currentHealth > 0) {
|
||||
spineboy.AnimationState.SetAnimation(0, hit, false);
|
||||
spineboy.AnimationState.AddAnimation(0, idle, true, 0);
|
||||
gauge.fillPercent = (float)currentHealth / (float)maxHealth;
|
||||
onAttack.Invoke();
|
||||
} else {
|
||||
if (currentHealth >= 0) {
|
||||
gauge.fillPercent = 0;
|
||||
spineboy.AnimationState.SetAnimation(0, death, false).TrackEnd = float.PositiveInfinity;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,56 +1,56 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class DraggableTransform : MonoBehaviour {
|
||||
|
||||
Vector2 mousePreviousWorld, mouseDeltaWorld;
|
||||
Camera mainCamera;
|
||||
|
||||
void Start () {
|
||||
mainCamera = Camera.main;
|
||||
}
|
||||
|
||||
void Update () {
|
||||
Vector2 mouseCurrent = Input.mousePosition;
|
||||
Vector2 mouseCurrentWorld = mainCamera.ScreenToWorldPoint(new Vector3(mouseCurrent.x, mouseCurrent.y, -mainCamera.transform.position.z));
|
||||
|
||||
mouseDeltaWorld = mouseCurrentWorld - mousePreviousWorld;
|
||||
mousePreviousWorld = mouseCurrentWorld;
|
||||
}
|
||||
|
||||
void OnMouseDrag () {
|
||||
transform.Translate(mouseDeltaWorld);
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class DraggableTransform : MonoBehaviour {
|
||||
|
||||
Vector2 mousePreviousWorld, mouseDeltaWorld;
|
||||
Camera mainCamera;
|
||||
|
||||
void Start () {
|
||||
mainCamera = Camera.main;
|
||||
}
|
||||
|
||||
void Update () {
|
||||
Vector2 mouseCurrent = Input.mousePosition;
|
||||
Vector2 mouseCurrentWorld = mainCamera.ScreenToWorldPoint(new Vector3(mouseCurrent.x, mouseCurrent.y, -mainCamera.transform.position.z));
|
||||
|
||||
mouseDeltaWorld = mouseCurrentWorld - mousePreviousWorld;
|
||||
mousePreviousWorld = mouseCurrentWorld;
|
||||
}
|
||||
|
||||
void OnMouseDrag () {
|
||||
transform.Translate(mouseDeltaWorld);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,103 +1,103 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
// Contributed by: Mitch Thompson
|
||||
|
||||
using Spine.Unity;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class FootSoldierExample : MonoBehaviour {
|
||||
[SpineAnimation("Idle")]
|
||||
public string idleAnimation;
|
||||
|
||||
[SpineAnimation]
|
||||
public string attackAnimation;
|
||||
|
||||
[SpineAnimation]
|
||||
public string moveAnimation;
|
||||
|
||||
[SpineSlot]
|
||||
public string eyesSlot;
|
||||
|
||||
[SpineAttachment(currentSkinOnly: true, slotField: "eyesSlot")]
|
||||
public string eyesOpenAttachment;
|
||||
|
||||
[SpineAttachment(currentSkinOnly: true, slotField: "eyesSlot")]
|
||||
public string blinkAttachment;
|
||||
|
||||
[Range(0, 0.2f)]
|
||||
public float blinkDuration = 0.05f;
|
||||
|
||||
public KeyCode attackKey = KeyCode.Mouse0;
|
||||
public KeyCode rightKey = KeyCode.D;
|
||||
public KeyCode leftKey = KeyCode.A;
|
||||
|
||||
public float moveSpeed = 3;
|
||||
|
||||
SkeletonAnimation skeletonAnimation;
|
||||
|
||||
void Awake () {
|
||||
skeletonAnimation = GetComponent<SkeletonAnimation>();
|
||||
skeletonAnimation.OnRebuild += Apply;
|
||||
}
|
||||
|
||||
void Apply (SkeletonRenderer skeletonRenderer) {
|
||||
StartCoroutine(Blink());
|
||||
}
|
||||
|
||||
void Update () {
|
||||
if (Input.GetKey(attackKey)) {
|
||||
skeletonAnimation.AnimationName = attackAnimation;
|
||||
} else {
|
||||
if (Input.GetKey(rightKey)) {
|
||||
skeletonAnimation.AnimationName = moveAnimation;
|
||||
skeletonAnimation.Skeleton.ScaleX = 1;
|
||||
transform.Translate(moveSpeed * Time.deltaTime, 0, 0);
|
||||
} else if (Input.GetKey(leftKey)) {
|
||||
skeletonAnimation.AnimationName = moveAnimation;
|
||||
skeletonAnimation.Skeleton.ScaleX = -1;
|
||||
transform.Translate(-moveSpeed * Time.deltaTime, 0, 0);
|
||||
} else {
|
||||
skeletonAnimation.AnimationName = idleAnimation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator Blink () {
|
||||
while (true) {
|
||||
yield return new WaitForSeconds(Random.Range(0.25f, 3f));
|
||||
skeletonAnimation.Skeleton.SetAttachment(eyesSlot, blinkAttachment);
|
||||
yield return new WaitForSeconds(blinkDuration);
|
||||
skeletonAnimation.Skeleton.SetAttachment(eyesSlot, eyesOpenAttachment);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
// Contributed by: Mitch Thompson
|
||||
|
||||
using Spine.Unity;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class FootSoldierExample : MonoBehaviour {
|
||||
[SpineAnimation("Idle")]
|
||||
public string idleAnimation;
|
||||
|
||||
[SpineAnimation]
|
||||
public string attackAnimation;
|
||||
|
||||
[SpineAnimation]
|
||||
public string moveAnimation;
|
||||
|
||||
[SpineSlot]
|
||||
public string eyesSlot;
|
||||
|
||||
[SpineAttachment(currentSkinOnly: true, slotField: "eyesSlot")]
|
||||
public string eyesOpenAttachment;
|
||||
|
||||
[SpineAttachment(currentSkinOnly: true, slotField: "eyesSlot")]
|
||||
public string blinkAttachment;
|
||||
|
||||
[Range(0, 0.2f)]
|
||||
public float blinkDuration = 0.05f;
|
||||
|
||||
public KeyCode attackKey = KeyCode.Mouse0;
|
||||
public KeyCode rightKey = KeyCode.D;
|
||||
public KeyCode leftKey = KeyCode.A;
|
||||
|
||||
public float moveSpeed = 3;
|
||||
|
||||
SkeletonAnimation skeletonAnimation;
|
||||
|
||||
void Awake () {
|
||||
skeletonAnimation = GetComponent<SkeletonAnimation>();
|
||||
skeletonAnimation.OnRebuild += Apply;
|
||||
}
|
||||
|
||||
void Apply (SkeletonRenderer skeletonRenderer) {
|
||||
StartCoroutine(Blink());
|
||||
}
|
||||
|
||||
void Update () {
|
||||
if (Input.GetKey(attackKey)) {
|
||||
skeletonAnimation.AnimationName = attackAnimation;
|
||||
} else {
|
||||
if (Input.GetKey(rightKey)) {
|
||||
skeletonAnimation.AnimationName = moveAnimation;
|
||||
skeletonAnimation.Skeleton.ScaleX = 1;
|
||||
transform.Translate(moveSpeed * Time.deltaTime, 0, 0);
|
||||
} else if (Input.GetKey(leftKey)) {
|
||||
skeletonAnimation.AnimationName = moveAnimation;
|
||||
skeletonAnimation.Skeleton.ScaleX = -1;
|
||||
transform.Translate(-moveSpeed * Time.deltaTime, 0, 0);
|
||||
} else {
|
||||
skeletonAnimation.AnimationName = idleAnimation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator Blink () {
|
||||
while (true) {
|
||||
yield return new WaitForSeconds(Random.Range(0.25f, 3f));
|
||||
skeletonAnimation.Skeleton.SetAttachment(eyesSlot, blinkAttachment);
|
||||
yield return new WaitForSeconds(blinkDuration);
|
||||
skeletonAnimation.Skeleton.SetAttachment(eyesSlot, eyesOpenAttachment);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,220 +1,220 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
[RequireComponent(typeof(CharacterController))]
|
||||
public class BasicPlatformerController : MonoBehaviour {
|
||||
|
||||
public enum CharacterState {
|
||||
None,
|
||||
Idle,
|
||||
Walk,
|
||||
Run,
|
||||
Crouch,
|
||||
Rise,
|
||||
Fall,
|
||||
Attack
|
||||
}
|
||||
|
||||
[Header("Components")]
|
||||
public CharacterController controller;
|
||||
|
||||
[Header("Controls")]
|
||||
public string XAxis = "Horizontal";
|
||||
public string YAxis = "Vertical";
|
||||
public string JumpButton = "Jump";
|
||||
|
||||
[Header("Moving")]
|
||||
public float walkSpeed = 1.5f;
|
||||
public float runSpeed = 7f;
|
||||
public float gravityScale = 6.6f;
|
||||
|
||||
[Header("Jumping")]
|
||||
public float jumpSpeed = 25;
|
||||
public float minimumJumpDuration = 0.5f;
|
||||
public float jumpInterruptFactor = 0.5f;
|
||||
public float forceCrouchVelocity = 25;
|
||||
public float forceCrouchDuration = 0.5f;
|
||||
|
||||
[Header("Animation")]
|
||||
public SkeletonAnimationHandleExample animationHandle;
|
||||
|
||||
// Events
|
||||
public event UnityAction OnJump, OnLand, OnHardLand;
|
||||
|
||||
Vector2 input = default(Vector2);
|
||||
Vector3 velocity = default(Vector3);
|
||||
float minimumJumpEndTime = 0;
|
||||
float forceCrouchEndTime;
|
||||
bool wasGrounded = false;
|
||||
|
||||
CharacterState previousState, currentState;
|
||||
|
||||
void Update () {
|
||||
float dt = Time.deltaTime;
|
||||
bool isGrounded = controller.isGrounded;
|
||||
bool landed = !wasGrounded && isGrounded;
|
||||
|
||||
// Dummy input.
|
||||
input.x = Input.GetAxis(XAxis);
|
||||
input.y = Input.GetAxis(YAxis);
|
||||
bool inputJumpStop = Input.GetButtonUp(JumpButton);
|
||||
bool inputJumpStart = Input.GetButtonDown(JumpButton);
|
||||
bool doCrouch = (isGrounded && input.y < -0.5f) || (forceCrouchEndTime > Time.time);
|
||||
bool doJumpInterrupt = false;
|
||||
bool doJump = false;
|
||||
bool hardLand = false;
|
||||
|
||||
if (landed) {
|
||||
if (-velocity.y > forceCrouchVelocity) {
|
||||
hardLand = true;
|
||||
doCrouch = true;
|
||||
forceCrouchEndTime = Time.time + forceCrouchDuration;
|
||||
}
|
||||
}
|
||||
|
||||
if (!doCrouch) {
|
||||
if (isGrounded) {
|
||||
if (inputJumpStart) {
|
||||
doJump = true;
|
||||
}
|
||||
} else {
|
||||
doJumpInterrupt = inputJumpStop && Time.time < minimumJumpEndTime;
|
||||
}
|
||||
}
|
||||
|
||||
// Dummy physics and controller using UnityEngine.CharacterController.
|
||||
Vector3 gravityDeltaVelocity = Physics.gravity * gravityScale * dt;
|
||||
|
||||
if (doJump) {
|
||||
velocity.y = jumpSpeed;
|
||||
minimumJumpEndTime = Time.time + minimumJumpDuration;
|
||||
} else if (doJumpInterrupt) {
|
||||
if (velocity.y > 0)
|
||||
velocity.y *= jumpInterruptFactor;
|
||||
}
|
||||
|
||||
velocity.x = 0;
|
||||
if (!doCrouch) {
|
||||
if (input.x != 0) {
|
||||
velocity.x = Mathf.Abs(input.x) > 0.6f ? runSpeed : walkSpeed;
|
||||
velocity.x *= Mathf.Sign(input.x);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!isGrounded) {
|
||||
if (wasGrounded) {
|
||||
if (velocity.y < 0)
|
||||
velocity.y = 0;
|
||||
} else {
|
||||
velocity += gravityDeltaVelocity;
|
||||
}
|
||||
}
|
||||
controller.Move(velocity * dt);
|
||||
wasGrounded = isGrounded;
|
||||
|
||||
// Determine and store character state
|
||||
if (isGrounded) {
|
||||
if (doCrouch) {
|
||||
currentState = CharacterState.Crouch;
|
||||
} else {
|
||||
if (input.x == 0)
|
||||
currentState = CharacterState.Idle;
|
||||
else
|
||||
currentState = Mathf.Abs(input.x) > 0.6f ? CharacterState.Run : CharacterState.Walk;
|
||||
}
|
||||
} else {
|
||||
currentState = velocity.y > 0 ? CharacterState.Rise : CharacterState.Fall;
|
||||
}
|
||||
|
||||
bool stateChanged = previousState != currentState;
|
||||
previousState = currentState;
|
||||
|
||||
// Animation
|
||||
// Do not modify character parameters or state in this phase. Just read them.
|
||||
// Detect changes in state, and communicate with animation handle if it changes.
|
||||
if (stateChanged)
|
||||
HandleStateChanged();
|
||||
|
||||
if (input.x != 0)
|
||||
animationHandle.SetFlip(input.x);
|
||||
|
||||
// Fire events.
|
||||
if (doJump) {
|
||||
OnJump.Invoke();
|
||||
}
|
||||
if (landed) {
|
||||
if (hardLand) {
|
||||
OnHardLand.Invoke();
|
||||
} else {
|
||||
OnLand.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HandleStateChanged () {
|
||||
// When the state changes, notify the animation handle of the new state.
|
||||
string stateName = null;
|
||||
switch (currentState) {
|
||||
case CharacterState.Idle:
|
||||
stateName = "idle";
|
||||
break;
|
||||
case CharacterState.Walk:
|
||||
stateName = "walk";
|
||||
break;
|
||||
case CharacterState.Run:
|
||||
stateName = "run";
|
||||
break;
|
||||
case CharacterState.Crouch:
|
||||
stateName = "crouch";
|
||||
break;
|
||||
case CharacterState.Rise:
|
||||
stateName = "rise";
|
||||
break;
|
||||
case CharacterState.Fall:
|
||||
stateName = "fall";
|
||||
break;
|
||||
case CharacterState.Attack:
|
||||
stateName = "attack";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
animationHandle.PlayAnimationForState(stateName, 0);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
[RequireComponent(typeof(CharacterController))]
|
||||
public class BasicPlatformerController : MonoBehaviour {
|
||||
|
||||
public enum CharacterState {
|
||||
None,
|
||||
Idle,
|
||||
Walk,
|
||||
Run,
|
||||
Crouch,
|
||||
Rise,
|
||||
Fall,
|
||||
Attack
|
||||
}
|
||||
|
||||
[Header("Components")]
|
||||
public CharacterController controller;
|
||||
|
||||
[Header("Controls")]
|
||||
public string XAxis = "Horizontal";
|
||||
public string YAxis = "Vertical";
|
||||
public string JumpButton = "Jump";
|
||||
|
||||
[Header("Moving")]
|
||||
public float walkSpeed = 1.5f;
|
||||
public float runSpeed = 7f;
|
||||
public float gravityScale = 6.6f;
|
||||
|
||||
[Header("Jumping")]
|
||||
public float jumpSpeed = 25;
|
||||
public float minimumJumpDuration = 0.5f;
|
||||
public float jumpInterruptFactor = 0.5f;
|
||||
public float forceCrouchVelocity = 25;
|
||||
public float forceCrouchDuration = 0.5f;
|
||||
|
||||
[Header("Animation")]
|
||||
public SkeletonAnimationHandleExample animationHandle;
|
||||
|
||||
// Events
|
||||
public event UnityAction OnJump, OnLand, OnHardLand;
|
||||
|
||||
Vector2 input = default(Vector2);
|
||||
Vector3 velocity = default(Vector3);
|
||||
float minimumJumpEndTime = 0;
|
||||
float forceCrouchEndTime;
|
||||
bool wasGrounded = false;
|
||||
|
||||
CharacterState previousState, currentState;
|
||||
|
||||
void Update () {
|
||||
float dt = Time.deltaTime;
|
||||
bool isGrounded = controller.isGrounded;
|
||||
bool landed = !wasGrounded && isGrounded;
|
||||
|
||||
// Dummy input.
|
||||
input.x = Input.GetAxis(XAxis);
|
||||
input.y = Input.GetAxis(YAxis);
|
||||
bool inputJumpStop = Input.GetButtonUp(JumpButton);
|
||||
bool inputJumpStart = Input.GetButtonDown(JumpButton);
|
||||
bool doCrouch = (isGrounded && input.y < -0.5f) || (forceCrouchEndTime > Time.time);
|
||||
bool doJumpInterrupt = false;
|
||||
bool doJump = false;
|
||||
bool hardLand = false;
|
||||
|
||||
if (landed) {
|
||||
if (-velocity.y > forceCrouchVelocity) {
|
||||
hardLand = true;
|
||||
doCrouch = true;
|
||||
forceCrouchEndTime = Time.time + forceCrouchDuration;
|
||||
}
|
||||
}
|
||||
|
||||
if (!doCrouch) {
|
||||
if (isGrounded) {
|
||||
if (inputJumpStart) {
|
||||
doJump = true;
|
||||
}
|
||||
} else {
|
||||
doJumpInterrupt = inputJumpStop && Time.time < minimumJumpEndTime;
|
||||
}
|
||||
}
|
||||
|
||||
// Dummy physics and controller using UnityEngine.CharacterController.
|
||||
Vector3 gravityDeltaVelocity = Physics.gravity * gravityScale * dt;
|
||||
|
||||
if (doJump) {
|
||||
velocity.y = jumpSpeed;
|
||||
minimumJumpEndTime = Time.time + minimumJumpDuration;
|
||||
} else if (doJumpInterrupt) {
|
||||
if (velocity.y > 0)
|
||||
velocity.y *= jumpInterruptFactor;
|
||||
}
|
||||
|
||||
velocity.x = 0;
|
||||
if (!doCrouch) {
|
||||
if (input.x != 0) {
|
||||
velocity.x = Mathf.Abs(input.x) > 0.6f ? runSpeed : walkSpeed;
|
||||
velocity.x *= Mathf.Sign(input.x);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!isGrounded) {
|
||||
if (wasGrounded) {
|
||||
if (velocity.y < 0)
|
||||
velocity.y = 0;
|
||||
} else {
|
||||
velocity += gravityDeltaVelocity;
|
||||
}
|
||||
}
|
||||
controller.Move(velocity * dt);
|
||||
wasGrounded = isGrounded;
|
||||
|
||||
// Determine and store character state
|
||||
if (isGrounded) {
|
||||
if (doCrouch) {
|
||||
currentState = CharacterState.Crouch;
|
||||
} else {
|
||||
if (input.x == 0)
|
||||
currentState = CharacterState.Idle;
|
||||
else
|
||||
currentState = Mathf.Abs(input.x) > 0.6f ? CharacterState.Run : CharacterState.Walk;
|
||||
}
|
||||
} else {
|
||||
currentState = velocity.y > 0 ? CharacterState.Rise : CharacterState.Fall;
|
||||
}
|
||||
|
||||
bool stateChanged = previousState != currentState;
|
||||
previousState = currentState;
|
||||
|
||||
// Animation
|
||||
// Do not modify character parameters or state in this phase. Just read them.
|
||||
// Detect changes in state, and communicate with animation handle if it changes.
|
||||
if (stateChanged)
|
||||
HandleStateChanged();
|
||||
|
||||
if (input.x != 0)
|
||||
animationHandle.SetFlip(input.x);
|
||||
|
||||
// Fire events.
|
||||
if (doJump) {
|
||||
OnJump.Invoke();
|
||||
}
|
||||
if (landed) {
|
||||
if (hardLand) {
|
||||
OnHardLand.Invoke();
|
||||
} else {
|
||||
OnLand.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HandleStateChanged () {
|
||||
// When the state changes, notify the animation handle of the new state.
|
||||
string stateName = null;
|
||||
switch (currentState) {
|
||||
case CharacterState.Idle:
|
||||
stateName = "idle";
|
||||
break;
|
||||
case CharacterState.Walk:
|
||||
stateName = "walk";
|
||||
break;
|
||||
case CharacterState.Run:
|
||||
stateName = "run";
|
||||
break;
|
||||
case CharacterState.Crouch:
|
||||
stateName = "crouch";
|
||||
break;
|
||||
case CharacterState.Rise:
|
||||
stateName = "rise";
|
||||
break;
|
||||
case CharacterState.Fall:
|
||||
stateName = "fall";
|
||||
break;
|
||||
case CharacterState.Attack:
|
||||
stateName = "attack";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
animationHandle.PlayAnimationForState(stateName, 0);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,52 +1,52 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
// Contributed by: Mitch Thompson
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class ConstrainedCamera : MonoBehaviour {
|
||||
public Transform target;
|
||||
public Vector3 offset;
|
||||
public Vector3 min;
|
||||
public Vector3 max;
|
||||
public float smoothing = 5f;
|
||||
|
||||
// Update is called once per frame
|
||||
void LateUpdate () {
|
||||
Vector3 goalPoint = target.position + offset;
|
||||
goalPoint.x = Mathf.Clamp(goalPoint.x, min.x, max.x);
|
||||
goalPoint.y = Mathf.Clamp(goalPoint.y, min.y, max.y);
|
||||
goalPoint.z = Mathf.Clamp(goalPoint.z, min.z, max.z);
|
||||
|
||||
transform.position = Vector3.Lerp(transform.position, goalPoint, smoothing * Time.deltaTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
// Contributed by: Mitch Thompson
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class ConstrainedCamera : MonoBehaviour {
|
||||
public Transform target;
|
||||
public Vector3 offset;
|
||||
public Vector3 min;
|
||||
public Vector3 max;
|
||||
public float smoothing = 5f;
|
||||
|
||||
// Update is called once per frame
|
||||
void LateUpdate () {
|
||||
Vector3 goalPoint = target.position + offset;
|
||||
goalPoint.x = Mathf.Clamp(goalPoint.x, min.x, max.x);
|
||||
goalPoint.y = Mathf.Clamp(goalPoint.y, min.y, max.y);
|
||||
goalPoint.z = Mathf.Clamp(goalPoint.z, min.z, max.z);
|
||||
|
||||
transform.position = Vector3.Lerp(transform.position, goalPoint, smoothing * Time.deltaTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,66 +1,66 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class Raptor : MonoBehaviour {
|
||||
|
||||
#region Inspector
|
||||
public AnimationReferenceAsset walk;
|
||||
public AnimationReferenceAsset gungrab;
|
||||
public AnimationReferenceAsset gunkeep;
|
||||
#endregion
|
||||
|
||||
SkeletonAnimation skeletonAnimation;
|
||||
|
||||
void Start () {
|
||||
skeletonAnimation = GetComponent<SkeletonAnimation>();
|
||||
StartCoroutine(GunGrabRoutine());
|
||||
}
|
||||
|
||||
IEnumerator GunGrabRoutine () {
|
||||
// Play the walk animation on track 0.
|
||||
skeletonAnimation.AnimationState.SetAnimation(0, walk, true);
|
||||
|
||||
// Repeatedly play the gungrab and gunkeep animation on track 1.
|
||||
while (true) {
|
||||
yield return new WaitForSeconds(Random.Range(0.5f, 3f));
|
||||
skeletonAnimation.AnimationState.SetAnimation(1, gungrab, false);
|
||||
|
||||
yield return new WaitForSeconds(Random.Range(0.5f, 3f));
|
||||
skeletonAnimation.AnimationState.SetAnimation(1, gunkeep, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class Raptor : MonoBehaviour {
|
||||
|
||||
#region Inspector
|
||||
public AnimationReferenceAsset walk;
|
||||
public AnimationReferenceAsset gungrab;
|
||||
public AnimationReferenceAsset gunkeep;
|
||||
#endregion
|
||||
|
||||
SkeletonAnimation skeletonAnimation;
|
||||
|
||||
void Start () {
|
||||
skeletonAnimation = GetComponent<SkeletonAnimation>();
|
||||
StartCoroutine(GunGrabRoutine());
|
||||
}
|
||||
|
||||
IEnumerator GunGrabRoutine () {
|
||||
// Play the walk animation on track 0.
|
||||
skeletonAnimation.AnimationState.SetAnimation(0, walk, true);
|
||||
|
||||
// Repeatedly play the gungrab and gunkeep animation on track 1.
|
||||
while (true) {
|
||||
yield return new WaitForSeconds(Random.Range(0.5f, 3f));
|
||||
skeletonAnimation.AnimationState.SetAnimation(1, gungrab, false);
|
||||
|
||||
yield return new WaitForSeconds(Random.Range(0.5f, 3f));
|
||||
skeletonAnimation.AnimationState.SetAnimation(1, gunkeep, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,109 +1,109 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class SpineBeginnerTwo : MonoBehaviour {
|
||||
|
||||
#region Inspector
|
||||
// [SpineAnimation] attribute allows an Inspector dropdown of Spine animation names coming form SkeletonAnimation.
|
||||
[SpineAnimation]
|
||||
public string runAnimationName;
|
||||
|
||||
[SpineAnimation]
|
||||
public string idleAnimationName;
|
||||
|
||||
[SpineAnimation]
|
||||
public string walkAnimationName;
|
||||
|
||||
[SpineAnimation]
|
||||
public string shootAnimationName;
|
||||
|
||||
[Header("Transitions")]
|
||||
[SpineAnimation]
|
||||
public string idleTurnAnimationName;
|
||||
|
||||
[SpineAnimation]
|
||||
public string runToIdleAnimationName;
|
||||
|
||||
public float runWalkDuration = 1.5f;
|
||||
#endregion
|
||||
|
||||
SkeletonAnimation skeletonAnimation;
|
||||
|
||||
// Spine.AnimationState and Spine.Skeleton are not Unity-serialized objects. You will not see them as fields in the inspector.
|
||||
public Spine.AnimationState spineAnimationState;
|
||||
public Spine.Skeleton skeleton;
|
||||
|
||||
void Start () {
|
||||
// Make sure you get these AnimationState and Skeleton references in Start or Later.
|
||||
// Getting and using them in Awake is not guaranteed by default execution order.
|
||||
skeletonAnimation = GetComponent<SkeletonAnimation>();
|
||||
spineAnimationState = skeletonAnimation.AnimationState;
|
||||
skeleton = skeletonAnimation.Skeleton;
|
||||
|
||||
StartCoroutine(DoDemoRoutine());
|
||||
}
|
||||
|
||||
/// This is an infinitely repeating Unity Coroutine. Read the Unity documentation on Coroutines to learn more.
|
||||
IEnumerator DoDemoRoutine () {
|
||||
while (true) {
|
||||
// SetAnimation is the basic way to set an animation.
|
||||
// SetAnimation sets the animation and starts playing it from the beginning.
|
||||
// Common Mistake: If you keep calling it in Update, it will keep showing the first pose of the animation, do don't do that.
|
||||
|
||||
spineAnimationState.SetAnimation(0, walkAnimationName, true);
|
||||
yield return new WaitForSeconds(runWalkDuration);
|
||||
|
||||
spineAnimationState.SetAnimation(0, runAnimationName, true);
|
||||
yield return new WaitForSeconds(runWalkDuration);
|
||||
|
||||
// AddAnimation queues up an animation to play after the previous one ends.
|
||||
spineAnimationState.SetAnimation(0, runToIdleAnimationName, false);
|
||||
spineAnimationState.AddAnimation(0, idleAnimationName, true, 0);
|
||||
yield return new WaitForSeconds(1f);
|
||||
|
||||
skeleton.ScaleX = -1; // skeleton allows you to flip the skeleton.
|
||||
spineAnimationState.SetAnimation(0, idleTurnAnimationName, false);
|
||||
spineAnimationState.AddAnimation(0, idleAnimationName, true, 0);
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
skeleton.ScaleX = 1;
|
||||
spineAnimationState.SetAnimation(0, idleTurnAnimationName, false);
|
||||
spineAnimationState.AddAnimation(0, idleAnimationName, true, 0);
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class SpineBeginnerTwo : MonoBehaviour {
|
||||
|
||||
#region Inspector
|
||||
// [SpineAnimation] attribute allows an Inspector dropdown of Spine animation names coming form SkeletonAnimation.
|
||||
[SpineAnimation]
|
||||
public string runAnimationName;
|
||||
|
||||
[SpineAnimation]
|
||||
public string idleAnimationName;
|
||||
|
||||
[SpineAnimation]
|
||||
public string walkAnimationName;
|
||||
|
||||
[SpineAnimation]
|
||||
public string shootAnimationName;
|
||||
|
||||
[Header("Transitions")]
|
||||
[SpineAnimation]
|
||||
public string idleTurnAnimationName;
|
||||
|
||||
[SpineAnimation]
|
||||
public string runToIdleAnimationName;
|
||||
|
||||
public float runWalkDuration = 1.5f;
|
||||
#endregion
|
||||
|
||||
SkeletonAnimation skeletonAnimation;
|
||||
|
||||
// Spine.AnimationState and Spine.Skeleton are not Unity-serialized objects. You will not see them as fields in the inspector.
|
||||
public Spine.AnimationState spineAnimationState;
|
||||
public Spine.Skeleton skeleton;
|
||||
|
||||
void Start () {
|
||||
// Make sure you get these AnimationState and Skeleton references in Start or Later.
|
||||
// Getting and using them in Awake is not guaranteed by default execution order.
|
||||
skeletonAnimation = GetComponent<SkeletonAnimation>();
|
||||
spineAnimationState = skeletonAnimation.AnimationState;
|
||||
skeleton = skeletonAnimation.Skeleton;
|
||||
|
||||
StartCoroutine(DoDemoRoutine());
|
||||
}
|
||||
|
||||
/// This is an infinitely repeating Unity Coroutine. Read the Unity documentation on Coroutines to learn more.
|
||||
IEnumerator DoDemoRoutine () {
|
||||
while (true) {
|
||||
// SetAnimation is the basic way to set an animation.
|
||||
// SetAnimation sets the animation and starts playing it from the beginning.
|
||||
// Common Mistake: If you keep calling it in Update, it will keep showing the first pose of the animation, do don't do that.
|
||||
|
||||
spineAnimationState.SetAnimation(0, walkAnimationName, true);
|
||||
yield return new WaitForSeconds(runWalkDuration);
|
||||
|
||||
spineAnimationState.SetAnimation(0, runAnimationName, true);
|
||||
yield return new WaitForSeconds(runWalkDuration);
|
||||
|
||||
// AddAnimation queues up an animation to play after the previous one ends.
|
||||
spineAnimationState.SetAnimation(0, runToIdleAnimationName, false);
|
||||
spineAnimationState.AddAnimation(0, idleAnimationName, true, 0);
|
||||
yield return new WaitForSeconds(1f);
|
||||
|
||||
skeleton.ScaleX = -1; // skeleton allows you to flip the skeleton.
|
||||
spineAnimationState.SetAnimation(0, idleTurnAnimationName, false);
|
||||
spineAnimationState.AddAnimation(0, idleAnimationName, true, 0);
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
skeleton.ScaleX = 1;
|
||||
spineAnimationState.SetAnimation(0, idleTurnAnimationName, false);
|
||||
spineAnimationState.AddAnimation(0, idleAnimationName, true, 0);
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,52 +1,52 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class SpineBlinkPlayer : MonoBehaviour {
|
||||
const int BlinkTrack = 1;
|
||||
|
||||
public AnimationReferenceAsset blinkAnimation;
|
||||
public float minimumDelay = 0.15f;
|
||||
public float maximumDelay = 3f;
|
||||
|
||||
IEnumerator Start () {
|
||||
SkeletonAnimation skeletonAnimation = GetComponent<SkeletonAnimation>();
|
||||
if (skeletonAnimation == null) yield break;
|
||||
while (true) {
|
||||
skeletonAnimation.AnimationState.SetAnimation(SpineBlinkPlayer.BlinkTrack, blinkAnimation, false);
|
||||
yield return new WaitForSeconds(Random.Range(minimumDelay, maximumDelay));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class SpineBlinkPlayer : MonoBehaviour {
|
||||
const int BlinkTrack = 1;
|
||||
|
||||
public AnimationReferenceAsset blinkAnimation;
|
||||
public float minimumDelay = 0.15f;
|
||||
public float maximumDelay = 3f;
|
||||
|
||||
IEnumerator Start () {
|
||||
SkeletonAnimation skeletonAnimation = GetComponent<SkeletonAnimation>();
|
||||
if (skeletonAnimation == null) yield break;
|
||||
while (true) {
|
||||
skeletonAnimation.AnimationState.SetAnimation(SpineBlinkPlayer.BlinkTrack, blinkAnimation, false);
|
||||
yield return new WaitForSeconds(Random.Range(minimumDelay, maximumDelay));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,68 +1,68 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class SpineboyBeginnerInput : MonoBehaviour {
|
||||
#region Inspector
|
||||
public string horizontalAxis = "Horizontal";
|
||||
public string attackButton = "Fire1";
|
||||
public string aimButton = "Fire2";
|
||||
public string jumpButton = "Jump";
|
||||
|
||||
public SpineboyBeginnerModel model;
|
||||
|
||||
void OnValidate () {
|
||||
if (model == null)
|
||||
model = GetComponent<SpineboyBeginnerModel>();
|
||||
}
|
||||
#endregion
|
||||
|
||||
void Update () {
|
||||
if (model == null) return;
|
||||
|
||||
float currentHorizontal = Input.GetAxisRaw(horizontalAxis);
|
||||
model.TryMove(currentHorizontal);
|
||||
|
||||
if (Input.GetButton(attackButton))
|
||||
model.TryShoot();
|
||||
|
||||
if (Input.GetButtonDown(aimButton))
|
||||
model.StartAim();
|
||||
if (Input.GetButtonUp(aimButton))
|
||||
model.StopAim();
|
||||
|
||||
if (Input.GetButtonDown(jumpButton))
|
||||
model.TryJump();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class SpineboyBeginnerInput : MonoBehaviour {
|
||||
#region Inspector
|
||||
public string horizontalAxis = "Horizontal";
|
||||
public string attackButton = "Fire1";
|
||||
public string aimButton = "Fire2";
|
||||
public string jumpButton = "Jump";
|
||||
|
||||
public SpineboyBeginnerModel model;
|
||||
|
||||
void OnValidate () {
|
||||
if (model == null)
|
||||
model = GetComponent<SpineboyBeginnerModel>();
|
||||
}
|
||||
#endregion
|
||||
|
||||
void Update () {
|
||||
if (model == null) return;
|
||||
|
||||
float currentHorizontal = Input.GetAxisRaw(horizontalAxis);
|
||||
model.TryMove(currentHorizontal);
|
||||
|
||||
if (Input.GetButton(attackButton))
|
||||
model.TryShoot();
|
||||
|
||||
if (Input.GetButtonDown(aimButton))
|
||||
model.StartAim();
|
||||
if (Input.GetButtonUp(aimButton))
|
||||
model.StopAim();
|
||||
|
||||
if (Input.GetButtonDown(jumpButton))
|
||||
model.TryJump();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,124 +1,124 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
[SelectionBase]
|
||||
public class SpineboyBeginnerModel : MonoBehaviour {
|
||||
|
||||
#region Inspector
|
||||
[Header("Current State")]
|
||||
public SpineBeginnerBodyState state;
|
||||
public bool facingLeft;
|
||||
[Range(-1f, 1f)]
|
||||
public float currentSpeed;
|
||||
|
||||
[Header("Balance")]
|
||||
public float shootInterval = 0.12f;
|
||||
#endregion
|
||||
|
||||
float lastShootTime;
|
||||
public event System.Action ShootEvent; // Lets other scripts know when Spineboy is shooting. Check C# Documentation to learn more about events and delegates.
|
||||
public event System.Action StartAimEvent; // Lets other scripts know when Spineboy is aiming.
|
||||
public event System.Action StopAimEvent; // Lets other scripts know when Spineboy is no longer aiming.
|
||||
|
||||
#region API
|
||||
public void TryJump () {
|
||||
StartCoroutine(JumpRoutine());
|
||||
}
|
||||
|
||||
public void TryShoot () {
|
||||
float currentTime = Time.time;
|
||||
|
||||
if (currentTime - lastShootTime > shootInterval) {
|
||||
lastShootTime = currentTime;
|
||||
if (ShootEvent != null) ShootEvent(); // Fire the "ShootEvent" event.
|
||||
}
|
||||
}
|
||||
|
||||
public void StartAim () {
|
||||
if (StartAimEvent != null) StartAimEvent(); // Fire the "StartAimEvent" event.
|
||||
}
|
||||
|
||||
public void StopAim () {
|
||||
if (StopAimEvent != null) StopAimEvent(); // Fire the "StopAimEvent" event.
|
||||
}
|
||||
|
||||
public void TryMove (float speed) {
|
||||
currentSpeed = speed; // show the "speed" in the Inspector.
|
||||
|
||||
if (speed != 0) {
|
||||
bool speedIsNegative = (speed < 0f);
|
||||
facingLeft = speedIsNegative; // Change facing direction whenever speed is not 0.
|
||||
}
|
||||
|
||||
if (state != SpineBeginnerBodyState.Jumping) {
|
||||
state = (speed == 0) ? SpineBeginnerBodyState.Idle : SpineBeginnerBodyState.Running;
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
IEnumerator JumpRoutine () {
|
||||
if (state == SpineBeginnerBodyState.Jumping) yield break; // Don't jump when already jumping.
|
||||
|
||||
state = SpineBeginnerBodyState.Jumping;
|
||||
|
||||
// Fake jumping.
|
||||
{
|
||||
Vector3 pos = transform.localPosition;
|
||||
const float jumpTime = 1.2f;
|
||||
const float half = jumpTime * 0.5f;
|
||||
const float jumpPower = 20f;
|
||||
for (float t = 0; t < half; t += Time.deltaTime) {
|
||||
float d = jumpPower * (half - t);
|
||||
transform.Translate((d * Time.deltaTime) * Vector3.up);
|
||||
yield return null;
|
||||
}
|
||||
for (float t = 0; t < half; t += Time.deltaTime) {
|
||||
float d = jumpPower * t;
|
||||
transform.Translate((d * Time.deltaTime) * Vector3.down);
|
||||
yield return null;
|
||||
}
|
||||
transform.localPosition = pos;
|
||||
}
|
||||
|
||||
state = SpineBeginnerBodyState.Idle;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public enum SpineBeginnerBodyState {
|
||||
Idle,
|
||||
Running,
|
||||
Jumping
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
[SelectionBase]
|
||||
public class SpineboyBeginnerModel : MonoBehaviour {
|
||||
|
||||
#region Inspector
|
||||
[Header("Current State")]
|
||||
public SpineBeginnerBodyState state;
|
||||
public bool facingLeft;
|
||||
[Range(-1f, 1f)]
|
||||
public float currentSpeed;
|
||||
|
||||
[Header("Balance")]
|
||||
public float shootInterval = 0.12f;
|
||||
#endregion
|
||||
|
||||
float lastShootTime;
|
||||
public event System.Action ShootEvent; // Lets other scripts know when Spineboy is shooting. Check C# Documentation to learn more about events and delegates.
|
||||
public event System.Action StartAimEvent; // Lets other scripts know when Spineboy is aiming.
|
||||
public event System.Action StopAimEvent; // Lets other scripts know when Spineboy is no longer aiming.
|
||||
|
||||
#region API
|
||||
public void TryJump () {
|
||||
StartCoroutine(JumpRoutine());
|
||||
}
|
||||
|
||||
public void TryShoot () {
|
||||
float currentTime = Time.time;
|
||||
|
||||
if (currentTime - lastShootTime > shootInterval) {
|
||||
lastShootTime = currentTime;
|
||||
if (ShootEvent != null) ShootEvent(); // Fire the "ShootEvent" event.
|
||||
}
|
||||
}
|
||||
|
||||
public void StartAim () {
|
||||
if (StartAimEvent != null) StartAimEvent(); // Fire the "StartAimEvent" event.
|
||||
}
|
||||
|
||||
public void StopAim () {
|
||||
if (StopAimEvent != null) StopAimEvent(); // Fire the "StopAimEvent" event.
|
||||
}
|
||||
|
||||
public void TryMove (float speed) {
|
||||
currentSpeed = speed; // show the "speed" in the Inspector.
|
||||
|
||||
if (speed != 0) {
|
||||
bool speedIsNegative = (speed < 0f);
|
||||
facingLeft = speedIsNegative; // Change facing direction whenever speed is not 0.
|
||||
}
|
||||
|
||||
if (state != SpineBeginnerBodyState.Jumping) {
|
||||
state = (speed == 0) ? SpineBeginnerBodyState.Idle : SpineBeginnerBodyState.Running;
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
IEnumerator JumpRoutine () {
|
||||
if (state == SpineBeginnerBodyState.Jumping) yield break; // Don't jump when already jumping.
|
||||
|
||||
state = SpineBeginnerBodyState.Jumping;
|
||||
|
||||
// Fake jumping.
|
||||
{
|
||||
Vector3 pos = transform.localPosition;
|
||||
const float jumpTime = 1.2f;
|
||||
const float half = jumpTime * 0.5f;
|
||||
const float jumpPower = 20f;
|
||||
for (float t = 0; t < half; t += Time.deltaTime) {
|
||||
float d = jumpPower * (half - t);
|
||||
transform.Translate((d * Time.deltaTime) * Vector3.up);
|
||||
yield return null;
|
||||
}
|
||||
for (float t = 0; t < half; t += Time.deltaTime) {
|
||||
float d = jumpPower * t;
|
||||
transform.Translate((d * Time.deltaTime) * Vector3.down);
|
||||
yield return null;
|
||||
}
|
||||
transform.localPosition = pos;
|
||||
}
|
||||
|
||||
state = SpineBeginnerBodyState.Idle;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public enum SpineBeginnerBodyState {
|
||||
Idle,
|
||||
Running,
|
||||
Jumping
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,167 +1,167 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class SpineboyBeginnerView : MonoBehaviour {
|
||||
|
||||
#region Inspector
|
||||
[Header("Components")]
|
||||
public SpineboyBeginnerModel model;
|
||||
public SkeletonAnimation skeletonAnimation;
|
||||
|
||||
public AnimationReferenceAsset run, idle, aim, shoot, jump;
|
||||
public EventDataReferenceAsset footstepEvent;
|
||||
|
||||
[Header("Audio")]
|
||||
public float footstepPitchOffset = 0.2f;
|
||||
public float gunsoundPitchOffset = 0.13f;
|
||||
public AudioSource footstepSource, gunSource, jumpSource;
|
||||
|
||||
[Header("Effects")]
|
||||
public ParticleSystem gunParticles;
|
||||
#endregion
|
||||
|
||||
SpineBeginnerBodyState previousViewState;
|
||||
|
||||
void Start () {
|
||||
if (skeletonAnimation == null) return;
|
||||
model.ShootEvent += PlayShoot;
|
||||
model.StartAimEvent += StartPlayingAim;
|
||||
model.StopAimEvent += StopPlayingAim;
|
||||
skeletonAnimation.AnimationState.Event += HandleEvent;
|
||||
}
|
||||
|
||||
void HandleEvent (Spine.TrackEntry trackEntry, Spine.Event e) {
|
||||
if (e.Data == footstepEvent.EventData)
|
||||
PlayFootstepSound();
|
||||
}
|
||||
|
||||
void Update () {
|
||||
if (skeletonAnimation == null) return;
|
||||
if (model == null) return;
|
||||
|
||||
if ((skeletonAnimation.skeleton.ScaleX < 0) != model.facingLeft) { // Detect changes in model.facingLeft
|
||||
Turn(model.facingLeft);
|
||||
}
|
||||
|
||||
// Detect changes in model.state
|
||||
SpineBeginnerBodyState currentModelState = model.state;
|
||||
|
||||
if (previousViewState != currentModelState) {
|
||||
PlayNewStableAnimation();
|
||||
}
|
||||
|
||||
previousViewState = currentModelState;
|
||||
}
|
||||
|
||||
void PlayNewStableAnimation () {
|
||||
SpineBeginnerBodyState newModelState = model.state;
|
||||
Animation nextAnimation;
|
||||
|
||||
// Add conditionals to not interrupt transient animations.
|
||||
|
||||
if (previousViewState == SpineBeginnerBodyState.Jumping && newModelState != SpineBeginnerBodyState.Jumping) {
|
||||
PlayFootstepSound();
|
||||
}
|
||||
|
||||
if (newModelState == SpineBeginnerBodyState.Jumping) {
|
||||
jumpSource.Play();
|
||||
nextAnimation = jump;
|
||||
} else {
|
||||
if (newModelState == SpineBeginnerBodyState.Running) {
|
||||
nextAnimation = run;
|
||||
} else {
|
||||
nextAnimation = idle;
|
||||
}
|
||||
}
|
||||
|
||||
skeletonAnimation.AnimationState.SetAnimation(0, nextAnimation, true);
|
||||
}
|
||||
|
||||
void PlayFootstepSound () {
|
||||
footstepSource.Play();
|
||||
footstepSource.pitch = GetRandomPitch(footstepPitchOffset);
|
||||
}
|
||||
|
||||
[ContextMenu("Check Tracks")]
|
||||
void CheckTracks () {
|
||||
AnimationState state = skeletonAnimation.AnimationState;
|
||||
Debug.Log(state.GetCurrent(0));
|
||||
Debug.Log(state.GetCurrent(1));
|
||||
}
|
||||
|
||||
#region Transient Actions
|
||||
public void PlayShoot () {
|
||||
// Play the shoot animation on track 1.
|
||||
TrackEntry shootTrack = skeletonAnimation.AnimationState.SetAnimation(1, shoot, false);
|
||||
shootTrack.AttachmentThreshold = 1f;
|
||||
shootTrack.MixDuration = 0f;
|
||||
skeletonAnimation.state.AddEmptyAnimation(1, 0.5f, 0.1f);
|
||||
|
||||
// Play the aim animation on track 2 to aim at the mouse target.
|
||||
TrackEntry aimTrack = skeletonAnimation.AnimationState.SetAnimation(2, aim, false);
|
||||
aimTrack.AttachmentThreshold = 1f;
|
||||
aimTrack.MixDuration = 0f;
|
||||
skeletonAnimation.state.AddEmptyAnimation(2, 0.5f, 0.1f);
|
||||
|
||||
gunSource.pitch = GetRandomPitch(gunsoundPitchOffset);
|
||||
gunSource.Play();
|
||||
//gunParticles.randomSeed = (uint)Random.Range(0, 100);
|
||||
gunParticles.Play();
|
||||
}
|
||||
|
||||
public void StartPlayingAim () {
|
||||
// Play the aim animation on track 2 to aim at the mouse target.
|
||||
TrackEntry aimTrack = skeletonAnimation.AnimationState.SetAnimation(2, aim, true);
|
||||
aimTrack.AttachmentThreshold = 1f;
|
||||
aimTrack.MixDuration = 0f;
|
||||
}
|
||||
|
||||
public void StopPlayingAim () {
|
||||
skeletonAnimation.state.AddEmptyAnimation(2, 0.5f, 0.1f);
|
||||
}
|
||||
|
||||
public void Turn (bool facingLeft) {
|
||||
skeletonAnimation.Skeleton.ScaleX = facingLeft ? -1f : 1f;
|
||||
// Maybe play a transient turning animation too, then call ChangeStableAnimation.
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Utility
|
||||
public float GetRandomPitch (float maxPitchOffset) {
|
||||
return 1f + Random.Range(-maxPitchOffset, maxPitchOffset);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class SpineboyBeginnerView : MonoBehaviour {
|
||||
|
||||
#region Inspector
|
||||
[Header("Components")]
|
||||
public SpineboyBeginnerModel model;
|
||||
public SkeletonAnimation skeletonAnimation;
|
||||
|
||||
public AnimationReferenceAsset run, idle, aim, shoot, jump;
|
||||
public EventDataReferenceAsset footstepEvent;
|
||||
|
||||
[Header("Audio")]
|
||||
public float footstepPitchOffset = 0.2f;
|
||||
public float gunsoundPitchOffset = 0.13f;
|
||||
public AudioSource footstepSource, gunSource, jumpSource;
|
||||
|
||||
[Header("Effects")]
|
||||
public ParticleSystem gunParticles;
|
||||
#endregion
|
||||
|
||||
SpineBeginnerBodyState previousViewState;
|
||||
|
||||
void Start () {
|
||||
if (skeletonAnimation == null) return;
|
||||
model.ShootEvent += PlayShoot;
|
||||
model.StartAimEvent += StartPlayingAim;
|
||||
model.StopAimEvent += StopPlayingAim;
|
||||
skeletonAnimation.AnimationState.Event += HandleEvent;
|
||||
}
|
||||
|
||||
void HandleEvent (Spine.TrackEntry trackEntry, Spine.Event e) {
|
||||
if (e.Data == footstepEvent.EventData)
|
||||
PlayFootstepSound();
|
||||
}
|
||||
|
||||
void Update () {
|
||||
if (skeletonAnimation == null) return;
|
||||
if (model == null) return;
|
||||
|
||||
if ((skeletonAnimation.skeleton.ScaleX < 0) != model.facingLeft) { // Detect changes in model.facingLeft
|
||||
Turn(model.facingLeft);
|
||||
}
|
||||
|
||||
// Detect changes in model.state
|
||||
SpineBeginnerBodyState currentModelState = model.state;
|
||||
|
||||
if (previousViewState != currentModelState) {
|
||||
PlayNewStableAnimation();
|
||||
}
|
||||
|
||||
previousViewState = currentModelState;
|
||||
}
|
||||
|
||||
void PlayNewStableAnimation () {
|
||||
SpineBeginnerBodyState newModelState = model.state;
|
||||
Animation nextAnimation;
|
||||
|
||||
// Add conditionals to not interrupt transient animations.
|
||||
|
||||
if (previousViewState == SpineBeginnerBodyState.Jumping && newModelState != SpineBeginnerBodyState.Jumping) {
|
||||
PlayFootstepSound();
|
||||
}
|
||||
|
||||
if (newModelState == SpineBeginnerBodyState.Jumping) {
|
||||
jumpSource.Play();
|
||||
nextAnimation = jump;
|
||||
} else {
|
||||
if (newModelState == SpineBeginnerBodyState.Running) {
|
||||
nextAnimation = run;
|
||||
} else {
|
||||
nextAnimation = idle;
|
||||
}
|
||||
}
|
||||
|
||||
skeletonAnimation.AnimationState.SetAnimation(0, nextAnimation, true);
|
||||
}
|
||||
|
||||
void PlayFootstepSound () {
|
||||
footstepSource.Play();
|
||||
footstepSource.pitch = GetRandomPitch(footstepPitchOffset);
|
||||
}
|
||||
|
||||
[ContextMenu("Check Tracks")]
|
||||
void CheckTracks () {
|
||||
AnimationState state = skeletonAnimation.AnimationState;
|
||||
Debug.Log(state.GetCurrent(0));
|
||||
Debug.Log(state.GetCurrent(1));
|
||||
}
|
||||
|
||||
#region Transient Actions
|
||||
public void PlayShoot () {
|
||||
// Play the shoot animation on track 1.
|
||||
TrackEntry shootTrack = skeletonAnimation.AnimationState.SetAnimation(1, shoot, false);
|
||||
shootTrack.MixAttachmentThreshold = 1f;
|
||||
shootTrack.SetMixDuration(0f, 0f);
|
||||
skeletonAnimation.state.AddEmptyAnimation(1, 0.5f, 0.1f);
|
||||
|
||||
// Play the aim animation on track 2 to aim at the mouse target.
|
||||
TrackEntry aimTrack = skeletonAnimation.AnimationState.SetAnimation(2, aim, false);
|
||||
aimTrack.MixAttachmentThreshold = 1f;
|
||||
aimTrack.SetMixDuration(0f, 0f);
|
||||
skeletonAnimation.state.AddEmptyAnimation(2, 0.5f, 0.1f);
|
||||
|
||||
gunSource.pitch = GetRandomPitch(gunsoundPitchOffset);
|
||||
gunSource.Play();
|
||||
//gunParticles.randomSeed = (uint)Random.Range(0, 100);
|
||||
gunParticles.Play();
|
||||
}
|
||||
|
||||
public void StartPlayingAim () {
|
||||
// Play the aim animation on track 2 to aim at the mouse target.
|
||||
TrackEntry aimTrack = skeletonAnimation.AnimationState.SetAnimation(2, aim, true);
|
||||
aimTrack.MixAttachmentThreshold = 1f;
|
||||
aimTrack.SetMixDuration(0f, 0f); // use SetMixDuration(mixDuration, delay) to update delay correctly
|
||||
}
|
||||
|
||||
public void StopPlayingAim () {
|
||||
skeletonAnimation.state.AddEmptyAnimation(2, 0.5f, 0.1f);
|
||||
}
|
||||
|
||||
public void Turn (bool facingLeft) {
|
||||
skeletonAnimation.Skeleton.ScaleX = facingLeft ? -1f : 1f;
|
||||
// Maybe play a transient turning animation too, then call ChangeStableAnimation.
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Utility
|
||||
public float GetRandomPitch (float maxPitchOffset) {
|
||||
return 1f + Random.Range(-maxPitchOffset, maxPitchOffset);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
167
Assets/ThirdParty/Spine Examples/Scripts/Getting Started Scripts/SpineboyBeginnerViewGraphic.cs
vendored
Normal file
167
Assets/ThirdParty/Spine Examples/Scripts/Getting Started Scripts/SpineboyBeginnerViewGraphic.cs
vendored
Normal file
@ -0,0 +1,167 @@
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class SpineboyBeginnerViewGraphic : MonoBehaviour {
|
||||
|
||||
#region Inspector
|
||||
[Header("Components")]
|
||||
public SpineboyBeginnerModel model;
|
||||
public SkeletonGraphic skeletonGraphic;
|
||||
|
||||
public AnimationReferenceAsset run, idle, aim, shoot, jump;
|
||||
public EventDataReferenceAsset footstepEvent;
|
||||
|
||||
[Header("Audio")]
|
||||
public float footstepPitchOffset = 0.2f;
|
||||
public float gunsoundPitchOffset = 0.13f;
|
||||
public AudioSource footstepSource, gunSource, jumpSource;
|
||||
|
||||
[Header("Effects")]
|
||||
public ParticleSystem gunParticles;
|
||||
#endregion
|
||||
|
||||
SpineBeginnerBodyState previousViewState;
|
||||
|
||||
void Start () {
|
||||
if (skeletonGraphic == null) return;
|
||||
model.ShootEvent += PlayShoot;
|
||||
model.StartAimEvent += StartPlayingAim;
|
||||
model.StopAimEvent += StopPlayingAim;
|
||||
skeletonGraphic.AnimationState.Event += HandleEvent;
|
||||
}
|
||||
|
||||
void HandleEvent (Spine.TrackEntry trackEntry, Spine.Event e) {
|
||||
if (e.Data == footstepEvent.EventData)
|
||||
PlayFootstepSound();
|
||||
}
|
||||
|
||||
void Update () {
|
||||
if (skeletonGraphic == null) return;
|
||||
if (model == null) return;
|
||||
|
||||
if ((skeletonGraphic.Skeleton.ScaleX < 0) != model.facingLeft) { // Detect changes in model.facingLeft
|
||||
Turn(model.facingLeft);
|
||||
}
|
||||
|
||||
// Detect changes in model.state
|
||||
SpineBeginnerBodyState currentModelState = model.state;
|
||||
|
||||
if (previousViewState != currentModelState) {
|
||||
PlayNewStableAnimation();
|
||||
}
|
||||
|
||||
previousViewState = currentModelState;
|
||||
}
|
||||
|
||||
void PlayNewStableAnimation () {
|
||||
SpineBeginnerBodyState newModelState = model.state;
|
||||
Animation nextAnimation;
|
||||
|
||||
// Add conditionals to not interrupt transient animations.
|
||||
|
||||
if (previousViewState == SpineBeginnerBodyState.Jumping && newModelState != SpineBeginnerBodyState.Jumping) {
|
||||
PlayFootstepSound();
|
||||
}
|
||||
|
||||
if (newModelState == SpineBeginnerBodyState.Jumping) {
|
||||
jumpSource.Play();
|
||||
nextAnimation = jump;
|
||||
} else {
|
||||
if (newModelState == SpineBeginnerBodyState.Running) {
|
||||
nextAnimation = run;
|
||||
} else {
|
||||
nextAnimation = idle;
|
||||
}
|
||||
}
|
||||
|
||||
skeletonGraphic.AnimationState.SetAnimation(0, nextAnimation, true);
|
||||
}
|
||||
|
||||
void PlayFootstepSound () {
|
||||
footstepSource.Play();
|
||||
footstepSource.pitch = GetRandomPitch(footstepPitchOffset);
|
||||
}
|
||||
|
||||
[ContextMenu("Check Tracks")]
|
||||
void CheckTracks () {
|
||||
AnimationState state = skeletonGraphic.AnimationState;
|
||||
Debug.Log(state.GetCurrent(0));
|
||||
Debug.Log(state.GetCurrent(1));
|
||||
}
|
||||
|
||||
#region Transient Actions
|
||||
public void PlayShoot () {
|
||||
// Play the shoot animation on track 1.
|
||||
TrackEntry shootTrack = skeletonGraphic.AnimationState.SetAnimation(1, shoot, false);
|
||||
shootTrack.MixAttachmentThreshold = 1f;
|
||||
shootTrack.SetMixDuration(0f, 0f);
|
||||
skeletonGraphic.AnimationState.AddEmptyAnimation(1, 0.5f, 0.1f);
|
||||
|
||||
// Play the aim animation on track 2 to aim at the mouse target.
|
||||
TrackEntry aimTrack = skeletonGraphic.AnimationState.SetAnimation(2, aim, false);
|
||||
aimTrack.MixAttachmentThreshold = 1f;
|
||||
aimTrack.SetMixDuration(0f, 0f);
|
||||
skeletonGraphic.AnimationState.AddEmptyAnimation(2, 0.5f, 0.1f);
|
||||
|
||||
gunSource.pitch = GetRandomPitch(gunsoundPitchOffset);
|
||||
gunSource.Play();
|
||||
//gunParticles.randomSeed = (uint)Random.Range(0, 100);
|
||||
gunParticles.Play();
|
||||
}
|
||||
|
||||
public void StartPlayingAim () {
|
||||
// Play the aim animation on track 2 to aim at the mouse target.
|
||||
TrackEntry aimTrack = skeletonGraphic.AnimationState.SetAnimation(2, aim, true);
|
||||
aimTrack.MixAttachmentThreshold = 1f;
|
||||
aimTrack.SetMixDuration(0f, 0f); // use SetMixDuration(mixDuration, delay) to update delay correctly
|
||||
}
|
||||
|
||||
public void StopPlayingAim () {
|
||||
skeletonGraphic.AnimationState.AddEmptyAnimation(2, 0.5f, 0.1f);
|
||||
}
|
||||
|
||||
public void Turn (bool facingLeft) {
|
||||
skeletonGraphic.Skeleton.ScaleX = facingLeft ? -1f : 1f;
|
||||
// Maybe play a transient turning animation too, then call ChangeStableAnimation.
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Utility
|
||||
public float GetRandomPitch (float maxPitchOffset) {
|
||||
return 1f + Random.Range(-maxPitchOffset, maxPitchOffset);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 795971ea6ab1f214eac09ad8814226e6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -1,61 +1,61 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class SpineboyTargetController : MonoBehaviour {
|
||||
|
||||
public SkeletonAnimation skeletonAnimation;
|
||||
|
||||
[SpineBone(dataField: "skeletonAnimation")]
|
||||
public string boneName;
|
||||
public Camera cam;
|
||||
|
||||
Bone bone;
|
||||
|
||||
void OnValidate () {
|
||||
if (skeletonAnimation == null) skeletonAnimation = GetComponent<SkeletonAnimation>();
|
||||
}
|
||||
|
||||
void Start () {
|
||||
bone = skeletonAnimation.Skeleton.FindBone(boneName);
|
||||
}
|
||||
|
||||
void Update () {
|
||||
Vector3 mousePosition = Input.mousePosition;
|
||||
Vector3 worldMousePosition = cam.ScreenToWorldPoint(mousePosition);
|
||||
Vector3 skeletonSpacePoint = skeletonAnimation.transform.InverseTransformPoint(worldMousePosition);
|
||||
skeletonSpacePoint.x *= skeletonAnimation.Skeleton.ScaleX;
|
||||
skeletonSpacePoint.y *= skeletonAnimation.Skeleton.ScaleY;
|
||||
bone.SetLocalPosition(skeletonSpacePoint);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class SpineboyTargetController : MonoBehaviour {
|
||||
|
||||
public SkeletonAnimation skeletonAnimation;
|
||||
|
||||
[SpineBone(dataField: "skeletonAnimation")]
|
||||
public string boneName;
|
||||
public Camera cam;
|
||||
|
||||
Bone bone;
|
||||
|
||||
void OnValidate () {
|
||||
if (skeletonAnimation == null) skeletonAnimation = GetComponent<SkeletonAnimation>();
|
||||
}
|
||||
|
||||
void Start () {
|
||||
bone = skeletonAnimation.Skeleton.FindBone(boneName);
|
||||
}
|
||||
|
||||
void Update () {
|
||||
Vector3 mousePosition = Input.mousePosition;
|
||||
Vector3 worldMousePosition = cam.ScreenToWorldPoint(mousePosition);
|
||||
Vector3 skeletonSpacePoint = skeletonAnimation.transform.InverseTransformPoint(worldMousePosition);
|
||||
skeletonSpacePoint.x *= skeletonAnimation.Skeleton.ScaleX;
|
||||
skeletonSpacePoint.y *= skeletonAnimation.Skeleton.ScaleY;
|
||||
bone.SetLocalPosition(skeletonSpacePoint);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,64 @@
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class SpineboyTargetControllerGraphic : MonoBehaviour {
|
||||
|
||||
public SkeletonGraphic skeletonGraphic;
|
||||
|
||||
[SpineBone(dataField: "skeletonGraphic")]
|
||||
public string boneName;
|
||||
public Camera cam;
|
||||
public Canvas canvas;
|
||||
|
||||
Bone bone;
|
||||
|
||||
void OnValidate () {
|
||||
if (skeletonGraphic == null) skeletonGraphic = GetComponent<SkeletonGraphic>();
|
||||
}
|
||||
|
||||
void Start () {
|
||||
bone = skeletonGraphic.Skeleton.FindBone(boneName);
|
||||
}
|
||||
|
||||
void Update () {
|
||||
Vector3 mousePosition = Input.mousePosition;
|
||||
Vector2 localRectPosition;
|
||||
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
||||
skeletonGraphic.rectTransform, mousePosition, null, out localRectPosition);
|
||||
Vector3 skeletonSpacePoint = localRectPosition / skeletonGraphic.MeshScale;
|
||||
skeletonSpacePoint.x *= skeletonGraphic.Skeleton.ScaleX;
|
||||
skeletonSpacePoint.y *= skeletonGraphic.Skeleton.ScaleY;
|
||||
bone.SetLocalPosition(skeletonSpacePoint);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e58811512f2bea64988af3798e27f1d8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -1,64 +1,64 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
// This is an example of how you could store animation transitions for use in your animation system.
|
||||
// More ideally, this would be stored in a ScriptableObject in asset form rather than in a MonoBehaviour.
|
||||
public sealed class TransitionDictionaryExample : MonoBehaviour {
|
||||
|
||||
[System.Serializable]
|
||||
public struct SerializedEntry {
|
||||
public AnimationReferenceAsset from;
|
||||
public AnimationReferenceAsset to;
|
||||
public AnimationReferenceAsset transition;
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
List<SerializedEntry> transitions = new List<SerializedEntry>();
|
||||
readonly Dictionary<AnimationStateData.AnimationPair, Animation> dictionary = new Dictionary<AnimationStateData.AnimationPair, Animation>();
|
||||
|
||||
void Start () {
|
||||
dictionary.Clear();
|
||||
foreach (SerializedEntry e in transitions) {
|
||||
dictionary.Add(new AnimationStateData.AnimationPair(e.from.Animation, e.to.Animation), e.transition.Animation);
|
||||
}
|
||||
}
|
||||
|
||||
public Animation GetTransition (Animation from, Animation to) {
|
||||
Animation result;
|
||||
dictionary.TryGetValue(new AnimationStateData.AnimationPair(from, to), out result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
// This is an example of how you could store animation transitions for use in your animation system.
|
||||
// More ideally, this would be stored in a ScriptableObject in asset form rather than in a MonoBehaviour.
|
||||
public sealed class TransitionDictionaryExample : MonoBehaviour {
|
||||
|
||||
[System.Serializable]
|
||||
public struct SerializedEntry {
|
||||
public AnimationReferenceAsset from;
|
||||
public AnimationReferenceAsset to;
|
||||
public AnimationReferenceAsset transition;
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
List<SerializedEntry> transitions = new List<SerializedEntry>();
|
||||
readonly Dictionary<AnimationStateData.AnimationPair, Animation> dictionary = new Dictionary<AnimationStateData.AnimationPair, Animation>();
|
||||
|
||||
void Start () {
|
||||
dictionary.Clear();
|
||||
foreach (SerializedEntry e in transitions) {
|
||||
dictionary.Add(new AnimationStateData.AnimationPair(e.from.Animation, e.to.Animation), e.transition.Animation);
|
||||
}
|
||||
}
|
||||
|
||||
public Animation GetTransition (Animation from, Animation to) {
|
||||
Animation result;
|
||||
dictionary.TryGetValue(new AnimationStateData.AnimationPair(from, to), out result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
134
Assets/ThirdParty/Spine Examples/Scripts/Goblins.cs
vendored
134
Assets/ThirdParty/Spine Examples/Scripts/Goblins.cs
vendored
@ -1,67 +1,67 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine;
|
||||
using Spine.Unity;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class Goblins : MonoBehaviour {
|
||||
SkeletonAnimation skeletonAnimation;
|
||||
Bone headBone;
|
||||
bool girlSkin;
|
||||
|
||||
[Range(-360, 360)]
|
||||
public float extraRotation;
|
||||
|
||||
public void Start () {
|
||||
skeletonAnimation = GetComponent<SkeletonAnimation>();
|
||||
headBone = skeletonAnimation.Skeleton.FindBone("head");
|
||||
skeletonAnimation.UpdateLocal += UpdateLocal;
|
||||
}
|
||||
|
||||
// This is called after the animation is applied to the skeleton and can be used to adjust the bones dynamically.
|
||||
public void UpdateLocal (ISkeletonAnimation skeletonRenderer) {
|
||||
headBone.Rotation += extraRotation;
|
||||
}
|
||||
|
||||
public void OnMouseDown () {
|
||||
skeletonAnimation.Skeleton.SetSkin(girlSkin ? "goblin" : "goblingirl");
|
||||
skeletonAnimation.Skeleton.SetSlotsToSetupPose();
|
||||
|
||||
girlSkin = !girlSkin;
|
||||
|
||||
if (girlSkin) {
|
||||
skeletonAnimation.Skeleton.SetAttachment("right-hand-item", null);
|
||||
skeletonAnimation.Skeleton.SetAttachment("left-hand-item", "spear");
|
||||
} else
|
||||
skeletonAnimation.Skeleton.SetAttachment("left-hand-item", "dagger");
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine;
|
||||
using Spine.Unity;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class Goblins : MonoBehaviour {
|
||||
SkeletonAnimation skeletonAnimation;
|
||||
Bone headBone;
|
||||
bool girlSkin;
|
||||
|
||||
[Range(-360, 360)]
|
||||
public float extraRotation;
|
||||
|
||||
public void Start () {
|
||||
skeletonAnimation = GetComponent<SkeletonAnimation>();
|
||||
headBone = skeletonAnimation.Skeleton.FindBone("head");
|
||||
skeletonAnimation.UpdateLocal += UpdateLocal;
|
||||
}
|
||||
|
||||
// This is called after the animation is applied to the skeleton and can be used to adjust the bones dynamically.
|
||||
public void UpdateLocal (ISkeletonAnimation skeletonRenderer) {
|
||||
headBone.Rotation += extraRotation;
|
||||
}
|
||||
|
||||
public void OnMouseDown () {
|
||||
skeletonAnimation.Skeleton.SetSkin(girlSkin ? "goblin" : "goblingirl");
|
||||
skeletonAnimation.Skeleton.SetSlotsToSetupPose();
|
||||
|
||||
girlSkin = !girlSkin;
|
||||
|
||||
if (girlSkin) {
|
||||
skeletonAnimation.Skeleton.SetAttachment("right-hand-item", null);
|
||||
skeletonAnimation.Skeleton.SetAttachment("left-hand-item", "spear");
|
||||
} else
|
||||
skeletonAnimation.Skeleton.SetAttachment("left-hand-item", "dagger");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,83 +1,83 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class HandleEventWithAudioExample : MonoBehaviour {
|
||||
|
||||
public SkeletonAnimation skeletonAnimation;
|
||||
[SpineEvent(dataField: "skeletonAnimation", fallbackToTextField: true)]
|
||||
public string eventName;
|
||||
|
||||
[Space]
|
||||
public AudioSource audioSource;
|
||||
public AudioClip audioClip;
|
||||
public float basePitch = 1f;
|
||||
public float randomPitchOffset = 0.1f;
|
||||
|
||||
[Space]
|
||||
public bool logDebugMessage = false;
|
||||
|
||||
Spine.EventData eventData;
|
||||
|
||||
void OnValidate () {
|
||||
if (skeletonAnimation == null) GetComponent<SkeletonAnimation>();
|
||||
if (audioSource == null) GetComponent<AudioSource>();
|
||||
}
|
||||
|
||||
void Start () {
|
||||
if (audioSource == null) return;
|
||||
if (skeletonAnimation == null) return;
|
||||
skeletonAnimation.Initialize(false);
|
||||
if (!skeletonAnimation.valid) return;
|
||||
|
||||
eventData = skeletonAnimation.Skeleton.Data.FindEvent(eventName);
|
||||
skeletonAnimation.AnimationState.Event += HandleAnimationStateEvent;
|
||||
}
|
||||
|
||||
private void HandleAnimationStateEvent (TrackEntry trackEntry, Event e) {
|
||||
if (logDebugMessage) Debug.Log("Event fired! " + e.Data.Name);
|
||||
//bool eventMatch = string.Equals(e.Data.Name, eventName, System.StringComparison.Ordinal); // Testing recommendation: String compare.
|
||||
bool eventMatch = (eventData == e.Data); // Performance recommendation: Match cached reference instead of string.
|
||||
if (eventMatch) {
|
||||
Play();
|
||||
}
|
||||
}
|
||||
|
||||
public void Play () {
|
||||
audioSource.pitch = basePitch + Random.Range(-randomPitchOffset, randomPitchOffset);
|
||||
audioSource.clip = audioClip;
|
||||
audioSource.Play();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class HandleEventWithAudioExample : MonoBehaviour {
|
||||
|
||||
public SkeletonAnimation skeletonAnimation;
|
||||
[SpineEvent(dataField: "skeletonAnimation", fallbackToTextField: true)]
|
||||
public string eventName;
|
||||
|
||||
[Space]
|
||||
public AudioSource audioSource;
|
||||
public AudioClip audioClip;
|
||||
public float basePitch = 1f;
|
||||
public float randomPitchOffset = 0.1f;
|
||||
|
||||
[Space]
|
||||
public bool logDebugMessage = false;
|
||||
|
||||
Spine.EventData eventData;
|
||||
|
||||
void OnValidate () {
|
||||
if (skeletonAnimation == null) GetComponent<SkeletonAnimation>();
|
||||
if (audioSource == null) GetComponent<AudioSource>();
|
||||
}
|
||||
|
||||
void Start () {
|
||||
if (audioSource == null) return;
|
||||
if (skeletonAnimation == null) return;
|
||||
skeletonAnimation.Initialize(false);
|
||||
if (!skeletonAnimation.valid) return;
|
||||
|
||||
eventData = skeletonAnimation.Skeleton.Data.FindEvent(eventName);
|
||||
skeletonAnimation.AnimationState.Event += HandleAnimationStateEvent;
|
||||
}
|
||||
|
||||
private void HandleAnimationStateEvent (TrackEntry trackEntry, Event e) {
|
||||
if (logDebugMessage) Debug.Log("Event fired! " + e.Data.Name);
|
||||
//bool eventMatch = string.Equals(e.Data.Name, eventName, System.StringComparison.Ordinal); // Testing recommendation: String compare.
|
||||
bool eventMatch = (eventData == e.Data); // Performance recommendation: Match cached reference instead of string.
|
||||
if (eventMatch) {
|
||||
Play();
|
||||
}
|
||||
}
|
||||
|
||||
public void Play () {
|
||||
audioSource.pitch = basePitch + Random.Range(-randomPitchOffset, randomPitchOffset);
|
||||
audioSource.clip = audioClip;
|
||||
audioSource.Play();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,47 +1,47 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class HeroEffectsHandlerExample : MonoBehaviour {
|
||||
public BasicPlatformerController eventSource;
|
||||
public UnityEvent OnJump, OnLand, OnHardLand;
|
||||
|
||||
public void Awake () {
|
||||
if (eventSource == null)
|
||||
return;
|
||||
|
||||
eventSource.OnLand += OnLand.Invoke;
|
||||
eventSource.OnJump += OnJump.Invoke;
|
||||
eventSource.OnHardLand += OnHardLand.Invoke;
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class HeroEffectsHandlerExample : MonoBehaviour {
|
||||
public BasicPlatformerController eventSource;
|
||||
public UnityEvent OnJump, OnLand, OnHardLand;
|
||||
|
||||
public void Awake () {
|
||||
if (eventSource == null)
|
||||
return;
|
||||
|
||||
eventSource.OnLand += OnLand.Invoke;
|
||||
eventSource.OnJump += OnJump.Invoke;
|
||||
eventSource.OnHardLand += OnHardLand.Invoke;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,77 +1,77 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class HurtFlashEffect : MonoBehaviour {
|
||||
|
||||
const int DefaultFlashCount = 3;
|
||||
|
||||
public int flashCount = DefaultFlashCount;
|
||||
public Color flashColor = Color.white;
|
||||
[Range(1f / 120f, 1f / 15f)]
|
||||
public float interval = 1f / 60f;
|
||||
public string fillPhaseProperty = "_FillPhase";
|
||||
public string fillColorProperty = "_FillColor";
|
||||
|
||||
MaterialPropertyBlock mpb;
|
||||
MeshRenderer meshRenderer;
|
||||
|
||||
public void Flash () {
|
||||
if (mpb == null) mpb = new MaterialPropertyBlock();
|
||||
if (meshRenderer == null) meshRenderer = GetComponent<MeshRenderer>();
|
||||
meshRenderer.GetPropertyBlock(mpb);
|
||||
|
||||
StartCoroutine(FlashRoutine());
|
||||
}
|
||||
|
||||
IEnumerator FlashRoutine () {
|
||||
if (flashCount < 0) flashCount = DefaultFlashCount;
|
||||
int fillPhase = Shader.PropertyToID(fillPhaseProperty);
|
||||
int fillColor = Shader.PropertyToID(fillColorProperty);
|
||||
|
||||
WaitForSeconds wait = new WaitForSeconds(interval);
|
||||
|
||||
for (int i = 0; i < flashCount; i++) {
|
||||
mpb.SetColor(fillColor, flashColor);
|
||||
mpb.SetFloat(fillPhase, 1f);
|
||||
meshRenderer.SetPropertyBlock(mpb);
|
||||
yield return wait;
|
||||
|
||||
mpb.SetFloat(fillPhase, 0f);
|
||||
meshRenderer.SetPropertyBlock(mpb);
|
||||
yield return wait;
|
||||
}
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class HurtFlashEffect : MonoBehaviour {
|
||||
|
||||
const int DefaultFlashCount = 3;
|
||||
|
||||
public int flashCount = DefaultFlashCount;
|
||||
public Color flashColor = Color.white;
|
||||
[Range(1f / 120f, 1f / 15f)]
|
||||
public float interval = 1f / 60f;
|
||||
public string fillPhaseProperty = "_FillPhase";
|
||||
public string fillColorProperty = "_FillColor";
|
||||
|
||||
MaterialPropertyBlock mpb;
|
||||
MeshRenderer meshRenderer;
|
||||
|
||||
public void Flash () {
|
||||
if (mpb == null) mpb = new MaterialPropertyBlock();
|
||||
if (meshRenderer == null) meshRenderer = GetComponent<MeshRenderer>();
|
||||
meshRenderer.GetPropertyBlock(mpb);
|
||||
|
||||
StartCoroutine(FlashRoutine());
|
||||
}
|
||||
|
||||
IEnumerator FlashRoutine () {
|
||||
if (flashCount < 0) flashCount = DefaultFlashCount;
|
||||
int fillPhase = Shader.PropertyToID(fillPhaseProperty);
|
||||
int fillColor = Shader.PropertyToID(fillColorProperty);
|
||||
|
||||
WaitForSeconds wait = new WaitForSeconds(interval);
|
||||
|
||||
for (int i = 0; i < flashCount; i++) {
|
||||
mpb.SetColor(fillColor, flashColor);
|
||||
mpb.SetFloat(fillPhase, 1f);
|
||||
meshRenderer.SetPropertyBlock(mpb);
|
||||
yield return wait;
|
||||
|
||||
mpb.SetFloat(fillPhase, 0f);
|
||||
meshRenderer.SetPropertyBlock(mpb);
|
||||
yield return wait;
|
||||
}
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,62 +1,62 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class MaterialPropertyBlockExample : MonoBehaviour {
|
||||
|
||||
public float timeInterval = 1f;
|
||||
public Gradient randomColors = new Gradient();
|
||||
public string colorPropertyName = "_FillColor";
|
||||
|
||||
MaterialPropertyBlock mpb;
|
||||
float timeToNextColor = 0;
|
||||
|
||||
void Start () {
|
||||
mpb = new MaterialPropertyBlock();
|
||||
}
|
||||
|
||||
void Update () {
|
||||
if (timeToNextColor <= 0) {
|
||||
timeToNextColor = timeInterval;
|
||||
|
||||
Color newColor = randomColors.Evaluate(UnityEngine.Random.value);
|
||||
mpb.SetColor(colorPropertyName, newColor);
|
||||
GetComponent<MeshRenderer>().SetPropertyBlock(mpb);
|
||||
}
|
||||
|
||||
timeToNextColor -= Time.deltaTime;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class MaterialPropertyBlockExample : MonoBehaviour {
|
||||
|
||||
public float timeInterval = 1f;
|
||||
public Gradient randomColors = new Gradient();
|
||||
public string colorPropertyName = "_FillColor";
|
||||
|
||||
MaterialPropertyBlock mpb;
|
||||
float timeToNextColor = 0;
|
||||
|
||||
void Start () {
|
||||
mpb = new MaterialPropertyBlock();
|
||||
}
|
||||
|
||||
void Update () {
|
||||
if (timeToNextColor <= 0) {
|
||||
timeToNextColor = timeInterval;
|
||||
|
||||
Color newColor = randomColors.Evaluate(UnityEngine.Random.value);
|
||||
mpb.SetColor(colorPropertyName, newColor);
|
||||
GetComponent<MeshRenderer>().SetPropertyBlock(mpb);
|
||||
}
|
||||
|
||||
timeToNextColor -= Time.deltaTime;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,82 +1,82 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class MaterialReplacementExample : MonoBehaviour {
|
||||
|
||||
public Material originalMaterial;
|
||||
public Material replacementMaterial;
|
||||
public bool replacementEnabled = true;
|
||||
public SkeletonAnimation skeletonAnimation;
|
||||
|
||||
[Space]
|
||||
public string phasePropertyName = "_FillPhase";
|
||||
[Range(0f, 1f)] public float phase = 1f;
|
||||
|
||||
bool previousEnabled;
|
||||
MaterialPropertyBlock mpb;
|
||||
|
||||
void Start () {
|
||||
// Use the code below to programmatically query the original material.
|
||||
// Note: using MeshRenderer.material will fail since it creates an instance copy of the Material,
|
||||
// MeshRenderer.sharedMaterial might also fail when called too early or when no Attachments
|
||||
// are visible in the initial first frame.
|
||||
if (originalMaterial == null)
|
||||
originalMaterial = skeletonAnimation.SkeletonDataAsset.atlasAssets[0].PrimaryMaterial;
|
||||
|
||||
previousEnabled = replacementEnabled;
|
||||
SetReplacementEnabled(replacementEnabled);
|
||||
mpb = new MaterialPropertyBlock();
|
||||
}
|
||||
|
||||
void Update () {
|
||||
mpb.SetFloat(phasePropertyName, phase);
|
||||
GetComponent<MeshRenderer>().SetPropertyBlock(mpb);
|
||||
|
||||
if (previousEnabled != replacementEnabled)
|
||||
SetReplacementEnabled(replacementEnabled);
|
||||
|
||||
previousEnabled = replacementEnabled;
|
||||
|
||||
}
|
||||
|
||||
void SetReplacementEnabled (bool active) {
|
||||
if (replacementEnabled) {
|
||||
skeletonAnimation.CustomMaterialOverride[originalMaterial] = replacementMaterial;
|
||||
} else {
|
||||
skeletonAnimation.CustomMaterialOverride.Remove(originalMaterial);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class MaterialReplacementExample : MonoBehaviour {
|
||||
|
||||
public Material originalMaterial;
|
||||
public Material replacementMaterial;
|
||||
public bool replacementEnabled = true;
|
||||
public SkeletonAnimation skeletonAnimation;
|
||||
|
||||
[Space]
|
||||
public string phasePropertyName = "_FillPhase";
|
||||
[Range(0f, 1f)] public float phase = 1f;
|
||||
|
||||
bool previousEnabled;
|
||||
MaterialPropertyBlock mpb;
|
||||
|
||||
void Start () {
|
||||
// Use the code below to programmatically query the original material.
|
||||
// Note: using MeshRenderer.material will fail since it creates an instance copy of the Material,
|
||||
// MeshRenderer.sharedMaterial might also fail when called too early or when no Attachments
|
||||
// are visible in the initial first frame.
|
||||
if (originalMaterial == null)
|
||||
originalMaterial = skeletonAnimation.SkeletonDataAsset.atlasAssets[0].PrimaryMaterial;
|
||||
|
||||
previousEnabled = replacementEnabled;
|
||||
SetReplacementEnabled(replacementEnabled);
|
||||
mpb = new MaterialPropertyBlock();
|
||||
}
|
||||
|
||||
void Update () {
|
||||
mpb.SetFloat(phasePropertyName, phase);
|
||||
GetComponent<MeshRenderer>().SetPropertyBlock(mpb);
|
||||
|
||||
if (previousEnabled != replacementEnabled)
|
||||
SetReplacementEnabled(replacementEnabled);
|
||||
|
||||
previousEnabled = replacementEnabled;
|
||||
|
||||
}
|
||||
|
||||
void SetReplacementEnabled (bool active) {
|
||||
if (replacementEnabled) {
|
||||
skeletonAnimation.CustomMaterialOverride[originalMaterial] = replacementMaterial;
|
||||
} else {
|
||||
skeletonAnimation.CustomMaterialOverride.Remove(originalMaterial);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,104 +1,104 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class DummyMecanimControllerExample : MonoBehaviour {
|
||||
|
||||
public Animator logicAnimator;
|
||||
public SkeletonAnimationHandleExample animationHandle;
|
||||
|
||||
[Header("Controls")]
|
||||
public KeyCode walkButton = KeyCode.LeftShift;
|
||||
public KeyCode jumpButton = KeyCode.Space;
|
||||
|
||||
[Header("Animator Properties")]
|
||||
public string horizontalSpeedProperty = "Speed";
|
||||
public string verticalSpeedProperty = "VerticalSpeed";
|
||||
public string groundedProperty = "Grounded";
|
||||
|
||||
[Header("Fake Physics")]
|
||||
public float jumpDuration = 1.5f;
|
||||
public Vector2 speed;
|
||||
public bool isGrounded;
|
||||
|
||||
void Awake () {
|
||||
isGrounded = true;
|
||||
}
|
||||
|
||||
void Update () {
|
||||
float x = Input.GetAxisRaw("Horizontal");
|
||||
if (Input.GetKey(walkButton)) {
|
||||
x *= 0.4f;
|
||||
}
|
||||
|
||||
speed.x = x;
|
||||
|
||||
// Flip skeleton.
|
||||
if (x != 0) {
|
||||
animationHandle.SetFlip(x);
|
||||
}
|
||||
|
||||
if (Input.GetKeyDown(jumpButton)) {
|
||||
if (isGrounded)
|
||||
StartCoroutine(FakeJump());
|
||||
}
|
||||
|
||||
logicAnimator.SetFloat(horizontalSpeedProperty, Mathf.Abs(speed.x));
|
||||
logicAnimator.SetFloat(verticalSpeedProperty, speed.y);
|
||||
logicAnimator.SetBool(groundedProperty, isGrounded);
|
||||
}
|
||||
|
||||
IEnumerator FakeJump () {
|
||||
// Rise
|
||||
isGrounded = false;
|
||||
speed.y = 10f;
|
||||
float durationLeft = jumpDuration * 0.5f;
|
||||
while (durationLeft > 0) {
|
||||
durationLeft -= Time.deltaTime;
|
||||
if (!Input.GetKey(jumpButton)) break;
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// Fall
|
||||
speed.y = -10f;
|
||||
float fallDuration = (jumpDuration * 0.5f) - durationLeft;
|
||||
yield return new WaitForSeconds(fallDuration);
|
||||
|
||||
// Land
|
||||
speed.y = 0f;
|
||||
isGrounded = true;
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class DummyMecanimControllerExample : MonoBehaviour {
|
||||
|
||||
public Animator logicAnimator;
|
||||
public SkeletonAnimationHandleExample animationHandle;
|
||||
|
||||
[Header("Controls")]
|
||||
public KeyCode walkButton = KeyCode.LeftShift;
|
||||
public KeyCode jumpButton = KeyCode.Space;
|
||||
|
||||
[Header("Animator Properties")]
|
||||
public string horizontalSpeedProperty = "Speed";
|
||||
public string verticalSpeedProperty = "VerticalSpeed";
|
||||
public string groundedProperty = "Grounded";
|
||||
|
||||
[Header("Fake Physics")]
|
||||
public float jumpDuration = 1.5f;
|
||||
public Vector2 speed;
|
||||
public bool isGrounded;
|
||||
|
||||
void Awake () {
|
||||
isGrounded = true;
|
||||
}
|
||||
|
||||
void Update () {
|
||||
float x = Input.GetAxisRaw("Horizontal");
|
||||
if (Input.GetKey(walkButton)) {
|
||||
x *= 0.4f;
|
||||
}
|
||||
|
||||
speed.x = x;
|
||||
|
||||
// Flip skeleton.
|
||||
if (x != 0) {
|
||||
animationHandle.SetFlip(x);
|
||||
}
|
||||
|
||||
if (Input.GetKeyDown(jumpButton)) {
|
||||
if (isGrounded)
|
||||
StartCoroutine(FakeJump());
|
||||
}
|
||||
|
||||
logicAnimator.SetFloat(horizontalSpeedProperty, Mathf.Abs(speed.x));
|
||||
logicAnimator.SetFloat(verticalSpeedProperty, speed.y);
|
||||
logicAnimator.SetBool(groundedProperty, isGrounded);
|
||||
}
|
||||
|
||||
IEnumerator FakeJump () {
|
||||
// Rise
|
||||
isGrounded = false;
|
||||
speed.y = 10f;
|
||||
float durationLeft = jumpDuration * 0.5f;
|
||||
while (durationLeft > 0) {
|
||||
durationLeft -= Time.deltaTime;
|
||||
if (!Input.GetKey(jumpButton)) break;
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// Fall
|
||||
speed.y = -10f;
|
||||
float fallDuration = (jumpDuration * 0.5f) - durationLeft;
|
||||
yield return new WaitForSeconds(fallDuration);
|
||||
|
||||
// Land
|
||||
speed.y = 0f;
|
||||
isGrounded = true;
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,51 +1,51 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
// This StateMachineBehaviour handles sending the Mecanim state information to the component that handles playing the Spine animations.
|
||||
public class MecanimToAnimationHandleExample : StateMachineBehaviour {
|
||||
SkeletonAnimationHandleExample animationHandle;
|
||||
bool initialized;
|
||||
|
||||
override public void OnStateEnter (Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
|
||||
if (!initialized) {
|
||||
animationHandle = animator.GetComponent<SkeletonAnimationHandleExample>();
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
animationHandle.PlayAnimationForState(stateInfo.shortNameHash, layerIndex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
// This StateMachineBehaviour handles sending the Mecanim state information to the component that handles playing the Spine animations.
|
||||
public class MecanimToAnimationHandleExample : StateMachineBehaviour {
|
||||
SkeletonAnimationHandleExample animationHandle;
|
||||
bool initialized;
|
||||
|
||||
override public void OnStateEnter (Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
|
||||
if (!initialized) {
|
||||
animationHandle = animator.GetComponent<SkeletonAnimationHandleExample>();
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
animationHandle.PlayAnimationForState(stateInfo.shortNameHash, layerIndex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,164 +1,164 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
// This is an example of an animation handle. This is implemented with strings as state names.
|
||||
// Strings can serve as the identifier when Mecanim is used as the state machine and state source.
|
||||
// If you don't use Mecanim, using custom ScriptableObjects may be a more efficient way to store information about the state and its connection with specific Spine animations.
|
||||
|
||||
// This animation handle implementation also comes with a dummy implementation of transition-handling.
|
||||
public class SkeletonAnimationHandleExample : MonoBehaviour {
|
||||
public SkeletonAnimation skeletonAnimation;
|
||||
public List<StateNameToAnimationReference> statesAndAnimations = new List<StateNameToAnimationReference>();
|
||||
public List<AnimationTransition> transitions = new List<AnimationTransition>(); // Alternately, an AnimationPair-Animation Dictionary (commented out) can be used for more efficient lookups.
|
||||
|
||||
[System.Serializable]
|
||||
public class StateNameToAnimationReference {
|
||||
public string stateName;
|
||||
public AnimationReferenceAsset animation;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class AnimationTransition {
|
||||
public AnimationReferenceAsset from;
|
||||
public AnimationReferenceAsset to;
|
||||
public AnimationReferenceAsset transition;
|
||||
}
|
||||
|
||||
//readonly Dictionary<Spine.AnimationStateData.AnimationPair, Spine.Animation> transitionDictionary = new Dictionary<AnimationStateData.AnimationPair, Animation>(Spine.AnimationStateData.AnimationPairComparer.Instance);
|
||||
|
||||
public Spine.Animation TargetAnimation { get; private set; }
|
||||
|
||||
void Awake () {
|
||||
// Initialize AnimationReferenceAssets
|
||||
foreach (StateNameToAnimationReference entry in statesAndAnimations) {
|
||||
entry.animation.Initialize();
|
||||
}
|
||||
foreach (AnimationTransition entry in transitions) {
|
||||
entry.from.Initialize();
|
||||
entry.to.Initialize();
|
||||
entry.transition.Initialize();
|
||||
}
|
||||
|
||||
// Build Dictionary
|
||||
//foreach (AnimationTransition entry in transitions) {
|
||||
// transitionDictionary.Add(new AnimationStateData.AnimationPair(entry.from.Animation, entry.to.Animation), entry.transition.Animation);
|
||||
//}
|
||||
}
|
||||
|
||||
/// <summary>Sets the horizontal flip state of the skeleton based on a nonzero float. If negative, the skeleton is flipped. If positive, the skeleton is not flipped.</summary>
|
||||
public void SetFlip (float horizontal) {
|
||||
if (horizontal != 0) {
|
||||
skeletonAnimation.Skeleton.ScaleX = horizontal > 0 ? 1f : -1f;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Plays an animation based on the state name.</summary>
|
||||
public void PlayAnimationForState (string stateShortName, int layerIndex) {
|
||||
PlayAnimationForState(StringToHash(stateShortName), layerIndex);
|
||||
}
|
||||
|
||||
/// <summary>Plays an animation based on the hash of the state name.</summary>
|
||||
public void PlayAnimationForState (int shortNameHash, int layerIndex) {
|
||||
Animation foundAnimation = GetAnimationForState(shortNameHash);
|
||||
if (foundAnimation == null)
|
||||
return;
|
||||
|
||||
PlayNewAnimation(foundAnimation, layerIndex);
|
||||
}
|
||||
|
||||
/// <summary>Gets a Spine Animation based on the state name.</summary>
|
||||
public Spine.Animation GetAnimationForState (string stateShortName) {
|
||||
return GetAnimationForState(StringToHash(stateShortName));
|
||||
}
|
||||
|
||||
/// <summary>Gets a Spine Animation based on the hash of the state name.</summary>
|
||||
public Spine.Animation GetAnimationForState (int shortNameHash) {
|
||||
StateNameToAnimationReference foundState = statesAndAnimations.Find(entry => StringToHash(entry.stateName) == shortNameHash);
|
||||
return (foundState == null) ? null : foundState.animation;
|
||||
}
|
||||
|
||||
/// <summary>Play an animation. If a transition animation is defined, the transition is played before the target animation being passed.</summary>
|
||||
public void PlayNewAnimation (Spine.Animation target, int layerIndex) {
|
||||
Spine.Animation transition = null;
|
||||
Spine.Animation current = null;
|
||||
|
||||
current = GetCurrentAnimation(layerIndex);
|
||||
if (current != null)
|
||||
transition = TryGetTransition(current, target);
|
||||
|
||||
if (transition != null) {
|
||||
skeletonAnimation.AnimationState.SetAnimation(layerIndex, transition, false);
|
||||
skeletonAnimation.AnimationState.AddAnimation(layerIndex, target, true, 0f);
|
||||
} else {
|
||||
skeletonAnimation.AnimationState.SetAnimation(layerIndex, target, true);
|
||||
}
|
||||
|
||||
this.TargetAnimation = target;
|
||||
}
|
||||
|
||||
/// <summary>Play a non-looping animation once then continue playing the state animation.</summary>
|
||||
public void PlayOneShot (Spine.Animation oneShot, int layerIndex) {
|
||||
AnimationState state = skeletonAnimation.AnimationState;
|
||||
state.SetAnimation(0, oneShot, false);
|
||||
|
||||
Animation transition = TryGetTransition(oneShot, TargetAnimation);
|
||||
if (transition != null)
|
||||
state.AddAnimation(0, transition, false, 0f);
|
||||
|
||||
state.AddAnimation(0, this.TargetAnimation, true, 0f);
|
||||
}
|
||||
|
||||
Spine.Animation TryGetTransition (Spine.Animation from, Spine.Animation to) {
|
||||
foreach (AnimationTransition transition in transitions) {
|
||||
if (transition.from.Animation == from && transition.to.Animation == to) {
|
||||
return transition.transition.Animation;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
//Spine.Animation foundTransition = null;
|
||||
//transitionDictionary.TryGetValue(new AnimationStateData.AnimationPair(from, to), out foundTransition);
|
||||
//return foundTransition;
|
||||
}
|
||||
|
||||
Spine.Animation GetCurrentAnimation (int layerIndex) {
|
||||
TrackEntry currentTrackEntry = skeletonAnimation.AnimationState.GetCurrent(layerIndex);
|
||||
return (currentTrackEntry != null) ? currentTrackEntry.Animation : null;
|
||||
}
|
||||
|
||||
int StringToHash (string s) {
|
||||
return Animator.StringToHash(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
// This is an example of an animation handle. This is implemented with strings as state names.
|
||||
// Strings can serve as the identifier when Mecanim is used as the state machine and state source.
|
||||
// If you don't use Mecanim, using custom ScriptableObjects may be a more efficient way to store information about the state and its connection with specific Spine animations.
|
||||
|
||||
// This animation handle implementation also comes with a dummy implementation of transition-handling.
|
||||
public class SkeletonAnimationHandleExample : MonoBehaviour {
|
||||
public SkeletonAnimation skeletonAnimation;
|
||||
public List<StateNameToAnimationReference> statesAndAnimations = new List<StateNameToAnimationReference>();
|
||||
public List<AnimationTransition> transitions = new List<AnimationTransition>(); // Alternately, an AnimationPair-Animation Dictionary (commented out) can be used for more efficient lookups.
|
||||
|
||||
[System.Serializable]
|
||||
public class StateNameToAnimationReference {
|
||||
public string stateName;
|
||||
public AnimationReferenceAsset animation;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class AnimationTransition {
|
||||
public AnimationReferenceAsset from;
|
||||
public AnimationReferenceAsset to;
|
||||
public AnimationReferenceAsset transition;
|
||||
}
|
||||
|
||||
//readonly Dictionary<Spine.AnimationStateData.AnimationPair, Spine.Animation> transitionDictionary = new Dictionary<AnimationStateData.AnimationPair, Animation>(Spine.AnimationStateData.AnimationPairComparer.Instance);
|
||||
|
||||
public Spine.Animation TargetAnimation { get; private set; }
|
||||
|
||||
void Awake () {
|
||||
// Initialize AnimationReferenceAssets
|
||||
foreach (StateNameToAnimationReference entry in statesAndAnimations) {
|
||||
entry.animation.Initialize();
|
||||
}
|
||||
foreach (AnimationTransition entry in transitions) {
|
||||
entry.from.Initialize();
|
||||
entry.to.Initialize();
|
||||
entry.transition.Initialize();
|
||||
}
|
||||
|
||||
// Build Dictionary
|
||||
//foreach (AnimationTransition entry in transitions) {
|
||||
// transitionDictionary.Add(new AnimationStateData.AnimationPair(entry.from.Animation, entry.to.Animation), entry.transition.Animation);
|
||||
//}
|
||||
}
|
||||
|
||||
/// <summary>Sets the horizontal flip state of the skeleton based on a nonzero float. If negative, the skeleton is flipped. If positive, the skeleton is not flipped.</summary>
|
||||
public void SetFlip (float horizontal) {
|
||||
if (horizontal != 0) {
|
||||
skeletonAnimation.Skeleton.ScaleX = horizontal > 0 ? 1f : -1f;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Plays an animation based on the state name.</summary>
|
||||
public void PlayAnimationForState (string stateShortName, int layerIndex) {
|
||||
PlayAnimationForState(StringToHash(stateShortName), layerIndex);
|
||||
}
|
||||
|
||||
/// <summary>Plays an animation based on the hash of the state name.</summary>
|
||||
public void PlayAnimationForState (int shortNameHash, int layerIndex) {
|
||||
Animation foundAnimation = GetAnimationForState(shortNameHash);
|
||||
if (foundAnimation == null)
|
||||
return;
|
||||
|
||||
PlayNewAnimation(foundAnimation, layerIndex);
|
||||
}
|
||||
|
||||
/// <summary>Gets a Spine Animation based on the state name.</summary>
|
||||
public Spine.Animation GetAnimationForState (string stateShortName) {
|
||||
return GetAnimationForState(StringToHash(stateShortName));
|
||||
}
|
||||
|
||||
/// <summary>Gets a Spine Animation based on the hash of the state name.</summary>
|
||||
public Spine.Animation GetAnimationForState (int shortNameHash) {
|
||||
StateNameToAnimationReference foundState = statesAndAnimations.Find(entry => StringToHash(entry.stateName) == shortNameHash);
|
||||
return (foundState == null) ? null : foundState.animation;
|
||||
}
|
||||
|
||||
/// <summary>Play an animation. If a transition animation is defined, the transition is played before the target animation being passed.</summary>
|
||||
public void PlayNewAnimation (Spine.Animation target, int layerIndex) {
|
||||
Spine.Animation transition = null;
|
||||
Spine.Animation current = null;
|
||||
|
||||
current = GetCurrentAnimation(layerIndex);
|
||||
if (current != null)
|
||||
transition = TryGetTransition(current, target);
|
||||
|
||||
if (transition != null) {
|
||||
skeletonAnimation.AnimationState.SetAnimation(layerIndex, transition, false);
|
||||
skeletonAnimation.AnimationState.AddAnimation(layerIndex, target, true, 0f);
|
||||
} else {
|
||||
skeletonAnimation.AnimationState.SetAnimation(layerIndex, target, true);
|
||||
}
|
||||
|
||||
this.TargetAnimation = target;
|
||||
}
|
||||
|
||||
/// <summary>Play a non-looping animation once then continue playing the state animation.</summary>
|
||||
public void PlayOneShot (Spine.Animation oneShot, int layerIndex) {
|
||||
AnimationState state = skeletonAnimation.AnimationState;
|
||||
state.SetAnimation(0, oneShot, false);
|
||||
|
||||
Animation transition = TryGetTransition(oneShot, TargetAnimation);
|
||||
if (transition != null)
|
||||
state.AddAnimation(0, transition, false, 0f);
|
||||
|
||||
state.AddAnimation(0, this.TargetAnimation, true, 0f);
|
||||
}
|
||||
|
||||
Spine.Animation TryGetTransition (Spine.Animation from, Spine.Animation to) {
|
||||
foreach (AnimationTransition transition in transitions) {
|
||||
if (transition.from.Animation == from && transition.to.Animation == to) {
|
||||
return transition.transition.Animation;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
//Spine.Animation foundTransition = null;
|
||||
//transitionDictionary.TryGetValue(new AnimationStateData.AnimationPair(from, to), out foundTransition);
|
||||
//return foundTransition;
|
||||
}
|
||||
|
||||
Spine.Animation GetCurrentAnimation (int layerIndex) {
|
||||
TrackEntry currentTrackEntry = skeletonAnimation.AnimationState.GetCurrent(layerIndex);
|
||||
return (currentTrackEntry != null) ? currentTrackEntry.Animation : null;
|
||||
}
|
||||
|
||||
int StringToHash (string s) {
|
||||
return Animator.StringToHash(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,237 +1,237 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine;
|
||||
using Spine.Unity;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
//[CreateAssetMenu(menuName = "Spine/SkeletonData Modifiers/Animation Match", order = 200)]
|
||||
public class AnimationMatchModifierAsset : SkeletonDataModifierAsset {
|
||||
|
||||
public bool matchAllAnimations = true;
|
||||
|
||||
public override void Apply (SkeletonData skeletonData) {
|
||||
if (matchAllAnimations)
|
||||
AnimationTools.MatchAnimationTimelines(skeletonData.Animations, skeletonData);
|
||||
}
|
||||
|
||||
public static class AnimationTools {
|
||||
|
||||
#region Filler Timelines
|
||||
/// <summary>
|
||||
/// Matches the animation timelines across the given set of animations.
|
||||
/// This allows unkeyed properties to assume setup pose when animations are naively mixed using Animation.Apply.
|
||||
/// </summary>
|
||||
/// <param name="animations">An enumerable collection animations whose timelines will be matched.</param>
|
||||
/// <param name="skeletonData">The SkeletonData where the animations belong.</param>
|
||||
public static void MatchAnimationTimelines (IEnumerable<Spine.Animation> animations, SkeletonData skeletonData) {
|
||||
if (animations == null) return;
|
||||
if (skeletonData == null) throw new System.ArgumentNullException("skeletonData", "Timelines can't be matched without a SkeletonData source.");
|
||||
|
||||
// Build a reference collection of timelines to match
|
||||
// and a collection of dummy timelines that can be used to fill-in missing items.
|
||||
Dictionary<string, Timeline> timelineDictionary = new Dictionary<string, Spine.Timeline>();
|
||||
foreach (Animation animation in animations) {
|
||||
foreach (Timeline timeline in animation.Timelines) {
|
||||
if (timeline is EventTimeline) continue;
|
||||
|
||||
foreach (string propertyId in timeline.PropertyIds) {
|
||||
if (!timelineDictionary.ContainsKey(propertyId)) {
|
||||
timelineDictionary.Add(propertyId, GetFillerTimeline(timeline, skeletonData));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
List<string> idsToMatch = new List<string>(timelineDictionary.Keys);
|
||||
|
||||
// For each animation in the list, check for and add missing timelines.
|
||||
HashSet<string> currentAnimationIDs = new HashSet<string>();
|
||||
foreach (Animation animation in animations) {
|
||||
currentAnimationIDs.Clear();
|
||||
foreach (Timeline timeline in animation.Timelines) {
|
||||
if (timeline is EventTimeline) continue;
|
||||
foreach (string propertyId in timeline.PropertyIds) {
|
||||
currentAnimationIDs.Add(propertyId);
|
||||
}
|
||||
}
|
||||
|
||||
ExposedList<Timeline> animationTimelines = animation.Timelines;
|
||||
foreach (string propertyId in idsToMatch) {
|
||||
if (!currentAnimationIDs.Contains(propertyId))
|
||||
animationTimelines.Add(timelineDictionary[propertyId]);
|
||||
}
|
||||
}
|
||||
|
||||
// These are locals, but sometimes Unity's GC does weird stuff. So let's clean up.
|
||||
timelineDictionary.Clear();
|
||||
timelineDictionary = null;
|
||||
idsToMatch.Clear();
|
||||
idsToMatch = null;
|
||||
currentAnimationIDs.Clear();
|
||||
currentAnimationIDs = null;
|
||||
}
|
||||
|
||||
static Timeline GetFillerTimeline (Timeline timeline, SkeletonData skeletonData) {
|
||||
if (timeline is RotateTimeline)
|
||||
return GetFillerTimeline((RotateTimeline)timeline, skeletonData);
|
||||
if (timeline is TranslateTimeline)
|
||||
return GetFillerTimeline((TranslateTimeline)timeline, skeletonData);
|
||||
if (timeline is ScaleTimeline)
|
||||
return GetFillerTimeline((ScaleTimeline)timeline, skeletonData);
|
||||
if (timeline is ShearTimeline)
|
||||
return GetFillerTimeline((ShearTimeline)timeline, skeletonData);
|
||||
if (timeline is AttachmentTimeline)
|
||||
return GetFillerTimeline((AttachmentTimeline)timeline, skeletonData);
|
||||
if (timeline is RGBATimeline)
|
||||
return GetFillerTimeline((RGBATimeline)timeline, skeletonData);
|
||||
if (timeline is RGBA2Timeline)
|
||||
return GetFillerTimeline((RGBA2Timeline)timeline, skeletonData);
|
||||
if (timeline is DeformTimeline)
|
||||
return GetFillerTimeline((DeformTimeline)timeline, skeletonData);
|
||||
if (timeline is DrawOrderTimeline)
|
||||
return GetFillerTimeline((DrawOrderTimeline)timeline, skeletonData);
|
||||
if (timeline is IkConstraintTimeline)
|
||||
return GetFillerTimeline((IkConstraintTimeline)timeline, skeletonData);
|
||||
if (timeline is TransformConstraintTimeline)
|
||||
return GetFillerTimeline((TransformConstraintTimeline)timeline, skeletonData);
|
||||
if (timeline is PathConstraintPositionTimeline)
|
||||
return GetFillerTimeline((PathConstraintPositionTimeline)timeline, skeletonData);
|
||||
if (timeline is PathConstraintSpacingTimeline)
|
||||
return GetFillerTimeline((PathConstraintSpacingTimeline)timeline, skeletonData);
|
||||
if (timeline is PathConstraintMixTimeline)
|
||||
return GetFillerTimeline((PathConstraintMixTimeline)timeline, skeletonData);
|
||||
return null;
|
||||
}
|
||||
|
||||
static RotateTimeline GetFillerTimeline (RotateTimeline timeline, SkeletonData skeletonData) {
|
||||
RotateTimeline t = new RotateTimeline(1, 0, timeline.BoneIndex);
|
||||
t.SetFrame(0, 0, 0);
|
||||
return t;
|
||||
}
|
||||
|
||||
static TranslateTimeline GetFillerTimeline (TranslateTimeline timeline, SkeletonData skeletonData) {
|
||||
TranslateTimeline t = new TranslateTimeline(1, 0, timeline.BoneIndex);
|
||||
t.SetFrame(0, 0, 0, 0);
|
||||
return t;
|
||||
}
|
||||
|
||||
static ScaleTimeline GetFillerTimeline (ScaleTimeline timeline, SkeletonData skeletonData) {
|
||||
ScaleTimeline t = new ScaleTimeline(1, 0, timeline.BoneIndex);
|
||||
t.SetFrame(0, 0, 0, 0);
|
||||
return t;
|
||||
}
|
||||
|
||||
static ShearTimeline GetFillerTimeline (ShearTimeline timeline, SkeletonData skeletonData) {
|
||||
ShearTimeline t = new ShearTimeline(1, 0, timeline.BoneIndex);
|
||||
t.SetFrame(0, 0, 0, 0);
|
||||
return t;
|
||||
}
|
||||
|
||||
static AttachmentTimeline GetFillerTimeline (AttachmentTimeline timeline, SkeletonData skeletonData) {
|
||||
AttachmentTimeline t = new AttachmentTimeline(1, timeline.SlotIndex);
|
||||
SlotData slotData = skeletonData.Slots.Items[t.SlotIndex];
|
||||
t.SetFrame(0, 0, slotData.AttachmentName);
|
||||
return t;
|
||||
}
|
||||
|
||||
static RGBATimeline GetFillerTimeline (RGBATimeline timeline, SkeletonData skeletonData) {
|
||||
RGBATimeline t = new RGBATimeline(1, 0, timeline.SlotIndex);
|
||||
SlotData slotData = skeletonData.Slots.Items[t.SlotIndex];
|
||||
t.SetFrame(0, 0, slotData.R, slotData.G, slotData.B, slotData.A);
|
||||
return t;
|
||||
}
|
||||
|
||||
static RGBA2Timeline GetFillerTimeline (RGBA2Timeline timeline, SkeletonData skeletonData) {
|
||||
RGBA2Timeline t = new RGBA2Timeline(1, 0, timeline.SlotIndex);
|
||||
SlotData slotData = skeletonData.Slots.Items[t.SlotIndex];
|
||||
t.SetFrame(0, 0, slotData.R, slotData.G, slotData.B, slotData.A, slotData.R2, slotData.G2, slotData.B2);
|
||||
return t;
|
||||
}
|
||||
|
||||
static DeformTimeline GetFillerTimeline (DeformTimeline timeline, SkeletonData skeletonData) {
|
||||
DeformTimeline t = new DeformTimeline(1, 0, timeline.SlotIndex, timeline.Attachment);
|
||||
if (t.Attachment.IsWeighted()) {
|
||||
t.SetFrame(0, 0, new float[t.Attachment.Vertices.Length]);
|
||||
} else {
|
||||
t.SetFrame(0, 0, t.Attachment.Vertices.Clone() as float[]);
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static DrawOrderTimeline GetFillerTimeline (DrawOrderTimeline timeline, SkeletonData skeletonData) {
|
||||
DrawOrderTimeline t = new DrawOrderTimeline(1);
|
||||
t.SetFrame(0, 0, null); // null means use setup pose in DrawOrderTimeline.Apply.
|
||||
return t;
|
||||
}
|
||||
|
||||
static IkConstraintTimeline GetFillerTimeline (IkConstraintTimeline timeline, SkeletonData skeletonData) {
|
||||
IkConstraintTimeline t = new IkConstraintTimeline(1, 0, timeline.IkConstraintIndex);
|
||||
IkConstraintData ikConstraintData = skeletonData.IkConstraints.Items[timeline.IkConstraintIndex];
|
||||
t.SetFrame(0, 0, ikConstraintData.Mix, ikConstraintData.Softness, ikConstraintData.BendDirection, ikConstraintData.Compress, ikConstraintData.Stretch);
|
||||
return t;
|
||||
}
|
||||
|
||||
static TransformConstraintTimeline GetFillerTimeline (TransformConstraintTimeline timeline, SkeletonData skeletonData) {
|
||||
TransformConstraintTimeline t = new TransformConstraintTimeline(1, 0, timeline.TransformConstraintIndex);
|
||||
TransformConstraintData data = skeletonData.TransformConstraints.Items[timeline.TransformConstraintIndex];
|
||||
t.SetFrame(0, 0, data.MixRotate, data.MixX, data.MixY, data.MixScaleX, data.MixScaleY, data.MixShearY);
|
||||
return t;
|
||||
}
|
||||
|
||||
static PathConstraintPositionTimeline GetFillerTimeline (PathConstraintPositionTimeline timeline, SkeletonData skeletonData) {
|
||||
PathConstraintPositionTimeline t = new PathConstraintPositionTimeline(1, 0, timeline.PathConstraintIndex);
|
||||
PathConstraintData data = skeletonData.PathConstraints.Items[timeline.PathConstraintIndex];
|
||||
t.SetFrame(0, 0, data.Position);
|
||||
return t;
|
||||
}
|
||||
|
||||
static PathConstraintSpacingTimeline GetFillerTimeline (PathConstraintSpacingTimeline timeline, SkeletonData skeletonData) {
|
||||
PathConstraintSpacingTimeline t = new PathConstraintSpacingTimeline(1, 0, timeline.PathConstraintIndex);
|
||||
PathConstraintData data = skeletonData.PathConstraints.Items[timeline.PathConstraintIndex];
|
||||
t.SetFrame(0, 0, data.Spacing);
|
||||
return t;
|
||||
}
|
||||
|
||||
static PathConstraintMixTimeline GetFillerTimeline (PathConstraintMixTimeline timeline, SkeletonData skeletonData) {
|
||||
PathConstraintMixTimeline t = new PathConstraintMixTimeline(1, 0, timeline.PathConstraintIndex);
|
||||
PathConstraintData data = skeletonData.PathConstraints.Items[timeline.PathConstraintIndex];
|
||||
t.SetFrame(0, 0, data.RotateMix, data.MixX, data.MixY);
|
||||
return t;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine;
|
||||
using Spine.Unity;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
//[CreateAssetMenu(menuName = "Spine/SkeletonData Modifiers/Animation Match", order = 200)]
|
||||
public class AnimationMatchModifierAsset : SkeletonDataModifierAsset {
|
||||
|
||||
public bool matchAllAnimations = true;
|
||||
|
||||
public override void Apply (SkeletonData skeletonData) {
|
||||
if (matchAllAnimations)
|
||||
AnimationTools.MatchAnimationTimelines(skeletonData.Animations, skeletonData);
|
||||
}
|
||||
|
||||
public static class AnimationTools {
|
||||
|
||||
#region Filler Timelines
|
||||
/// <summary>
|
||||
/// Matches the animation timelines across the given set of animations.
|
||||
/// This allows unkeyed properties to assume setup pose when animations are naively mixed using Animation.Apply.
|
||||
/// </summary>
|
||||
/// <param name="animations">An enumerable collection animations whose timelines will be matched.</param>
|
||||
/// <param name="skeletonData">The SkeletonData where the animations belong.</param>
|
||||
public static void MatchAnimationTimelines (IEnumerable<Spine.Animation> animations, SkeletonData skeletonData) {
|
||||
if (animations == null) return;
|
||||
if (skeletonData == null) throw new System.ArgumentNullException("skeletonData", "Timelines can't be matched without a SkeletonData source.");
|
||||
|
||||
// Build a reference collection of timelines to match
|
||||
// and a collection of dummy timelines that can be used to fill-in missing items.
|
||||
Dictionary<string, Timeline> timelineDictionary = new Dictionary<string, Spine.Timeline>();
|
||||
foreach (Animation animation in animations) {
|
||||
foreach (Timeline timeline in animation.Timelines) {
|
||||
if (timeline is EventTimeline) continue;
|
||||
|
||||
foreach (string propertyId in timeline.PropertyIds) {
|
||||
if (!timelineDictionary.ContainsKey(propertyId)) {
|
||||
timelineDictionary.Add(propertyId, GetFillerTimeline(timeline, skeletonData));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
List<string> idsToMatch = new List<string>(timelineDictionary.Keys);
|
||||
|
||||
// For each animation in the list, check for and add missing timelines.
|
||||
HashSet<string> currentAnimationIDs = new HashSet<string>();
|
||||
foreach (Animation animation in animations) {
|
||||
currentAnimationIDs.Clear();
|
||||
foreach (Timeline timeline in animation.Timelines) {
|
||||
if (timeline is EventTimeline) continue;
|
||||
foreach (string propertyId in timeline.PropertyIds) {
|
||||
currentAnimationIDs.Add(propertyId);
|
||||
}
|
||||
}
|
||||
|
||||
ExposedList<Timeline> animationTimelines = animation.Timelines;
|
||||
foreach (string propertyId in idsToMatch) {
|
||||
if (!currentAnimationIDs.Contains(propertyId))
|
||||
animationTimelines.Add(timelineDictionary[propertyId]);
|
||||
}
|
||||
}
|
||||
|
||||
// These are locals, but sometimes Unity's GC does weird stuff. So let's clean up.
|
||||
timelineDictionary.Clear();
|
||||
timelineDictionary = null;
|
||||
idsToMatch.Clear();
|
||||
idsToMatch = null;
|
||||
currentAnimationIDs.Clear();
|
||||
currentAnimationIDs = null;
|
||||
}
|
||||
|
||||
static Timeline GetFillerTimeline (Timeline timeline, SkeletonData skeletonData) {
|
||||
if (timeline is RotateTimeline)
|
||||
return GetFillerTimeline((RotateTimeline)timeline, skeletonData);
|
||||
if (timeline is TranslateTimeline)
|
||||
return GetFillerTimeline((TranslateTimeline)timeline, skeletonData);
|
||||
if (timeline is ScaleTimeline)
|
||||
return GetFillerTimeline((ScaleTimeline)timeline, skeletonData);
|
||||
if (timeline is ShearTimeline)
|
||||
return GetFillerTimeline((ShearTimeline)timeline, skeletonData);
|
||||
if (timeline is AttachmentTimeline)
|
||||
return GetFillerTimeline((AttachmentTimeline)timeline, skeletonData);
|
||||
if (timeline is RGBATimeline)
|
||||
return GetFillerTimeline((RGBATimeline)timeline, skeletonData);
|
||||
if (timeline is RGBA2Timeline)
|
||||
return GetFillerTimeline((RGBA2Timeline)timeline, skeletonData);
|
||||
if (timeline is DeformTimeline)
|
||||
return GetFillerTimeline((DeformTimeline)timeline, skeletonData);
|
||||
if (timeline is DrawOrderTimeline)
|
||||
return GetFillerTimeline((DrawOrderTimeline)timeline, skeletonData);
|
||||
if (timeline is IkConstraintTimeline)
|
||||
return GetFillerTimeline((IkConstraintTimeline)timeline, skeletonData);
|
||||
if (timeline is TransformConstraintTimeline)
|
||||
return GetFillerTimeline((TransformConstraintTimeline)timeline, skeletonData);
|
||||
if (timeline is PathConstraintPositionTimeline)
|
||||
return GetFillerTimeline((PathConstraintPositionTimeline)timeline, skeletonData);
|
||||
if (timeline is PathConstraintSpacingTimeline)
|
||||
return GetFillerTimeline((PathConstraintSpacingTimeline)timeline, skeletonData);
|
||||
if (timeline is PathConstraintMixTimeline)
|
||||
return GetFillerTimeline((PathConstraintMixTimeline)timeline, skeletonData);
|
||||
return null;
|
||||
}
|
||||
|
||||
static RotateTimeline GetFillerTimeline (RotateTimeline timeline, SkeletonData skeletonData) {
|
||||
RotateTimeline t = new RotateTimeline(1, 0, timeline.BoneIndex);
|
||||
t.SetFrame(0, 0, 0);
|
||||
return t;
|
||||
}
|
||||
|
||||
static TranslateTimeline GetFillerTimeline (TranslateTimeline timeline, SkeletonData skeletonData) {
|
||||
TranslateTimeline t = new TranslateTimeline(1, 0, timeline.BoneIndex);
|
||||
t.SetFrame(0, 0, 0, 0);
|
||||
return t;
|
||||
}
|
||||
|
||||
static ScaleTimeline GetFillerTimeline (ScaleTimeline timeline, SkeletonData skeletonData) {
|
||||
ScaleTimeline t = new ScaleTimeline(1, 0, timeline.BoneIndex);
|
||||
t.SetFrame(0, 0, 0, 0);
|
||||
return t;
|
||||
}
|
||||
|
||||
static ShearTimeline GetFillerTimeline (ShearTimeline timeline, SkeletonData skeletonData) {
|
||||
ShearTimeline t = new ShearTimeline(1, 0, timeline.BoneIndex);
|
||||
t.SetFrame(0, 0, 0, 0);
|
||||
return t;
|
||||
}
|
||||
|
||||
static AttachmentTimeline GetFillerTimeline (AttachmentTimeline timeline, SkeletonData skeletonData) {
|
||||
AttachmentTimeline t = new AttachmentTimeline(1, timeline.SlotIndex);
|
||||
SlotData slotData = skeletonData.Slots.Items[t.SlotIndex];
|
||||
t.SetFrame(0, 0, slotData.AttachmentName);
|
||||
return t;
|
||||
}
|
||||
|
||||
static RGBATimeline GetFillerTimeline (RGBATimeline timeline, SkeletonData skeletonData) {
|
||||
RGBATimeline t = new RGBATimeline(1, 0, timeline.SlotIndex);
|
||||
SlotData slotData = skeletonData.Slots.Items[t.SlotIndex];
|
||||
t.SetFrame(0, 0, slotData.R, slotData.G, slotData.B, slotData.A);
|
||||
return t;
|
||||
}
|
||||
|
||||
static RGBA2Timeline GetFillerTimeline (RGBA2Timeline timeline, SkeletonData skeletonData) {
|
||||
RGBA2Timeline t = new RGBA2Timeline(1, 0, timeline.SlotIndex);
|
||||
SlotData slotData = skeletonData.Slots.Items[t.SlotIndex];
|
||||
t.SetFrame(0, 0, slotData.R, slotData.G, slotData.B, slotData.A, slotData.R2, slotData.G2, slotData.B2);
|
||||
return t;
|
||||
}
|
||||
|
||||
static DeformTimeline GetFillerTimeline (DeformTimeline timeline, SkeletonData skeletonData) {
|
||||
DeformTimeline t = new DeformTimeline(1, 0, timeline.SlotIndex, timeline.Attachment);
|
||||
if (t.Attachment.IsWeighted()) {
|
||||
t.SetFrame(0, 0, new float[t.Attachment.Vertices.Length]);
|
||||
} else {
|
||||
t.SetFrame(0, 0, t.Attachment.Vertices.Clone() as float[]);
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static DrawOrderTimeline GetFillerTimeline (DrawOrderTimeline timeline, SkeletonData skeletonData) {
|
||||
DrawOrderTimeline t = new DrawOrderTimeline(1);
|
||||
t.SetFrame(0, 0, null); // null means use setup pose in DrawOrderTimeline.Apply.
|
||||
return t;
|
||||
}
|
||||
|
||||
static IkConstraintTimeline GetFillerTimeline (IkConstraintTimeline timeline, SkeletonData skeletonData) {
|
||||
IkConstraintTimeline t = new IkConstraintTimeline(1, 0, timeline.IkConstraintIndex);
|
||||
IkConstraintData ikConstraintData = skeletonData.IkConstraints.Items[timeline.IkConstraintIndex];
|
||||
t.SetFrame(0, 0, ikConstraintData.Mix, ikConstraintData.Softness, ikConstraintData.BendDirection, ikConstraintData.Compress, ikConstraintData.Stretch);
|
||||
return t;
|
||||
}
|
||||
|
||||
static TransformConstraintTimeline GetFillerTimeline (TransformConstraintTimeline timeline, SkeletonData skeletonData) {
|
||||
TransformConstraintTimeline t = new TransformConstraintTimeline(1, 0, timeline.TransformConstraintIndex);
|
||||
TransformConstraintData data = skeletonData.TransformConstraints.Items[timeline.TransformConstraintIndex];
|
||||
t.SetFrame(0, 0, data.MixRotate, data.MixX, data.MixY, data.MixScaleX, data.MixScaleY, data.MixShearY);
|
||||
return t;
|
||||
}
|
||||
|
||||
static PathConstraintPositionTimeline GetFillerTimeline (PathConstraintPositionTimeline timeline, SkeletonData skeletonData) {
|
||||
PathConstraintPositionTimeline t = new PathConstraintPositionTimeline(1, 0, timeline.PathConstraintIndex);
|
||||
PathConstraintData data = skeletonData.PathConstraints.Items[timeline.PathConstraintIndex];
|
||||
t.SetFrame(0, 0, data.Position);
|
||||
return t;
|
||||
}
|
||||
|
||||
static PathConstraintSpacingTimeline GetFillerTimeline (PathConstraintSpacingTimeline timeline, SkeletonData skeletonData) {
|
||||
PathConstraintSpacingTimeline t = new PathConstraintSpacingTimeline(1, 0, timeline.PathConstraintIndex);
|
||||
PathConstraintData data = skeletonData.PathConstraints.Items[timeline.PathConstraintIndex];
|
||||
t.SetFrame(0, 0, data.Spacing);
|
||||
return t;
|
||||
}
|
||||
|
||||
static PathConstraintMixTimeline GetFillerTimeline (PathConstraintMixTimeline timeline, SkeletonData skeletonData) {
|
||||
PathConstraintMixTimeline t = new PathConstraintMixTimeline(1, 0, timeline.PathConstraintIndex);
|
||||
PathConstraintData data = skeletonData.PathConstraints.Items[timeline.PathConstraintIndex];
|
||||
t.SetFrame(0, 0, data.RotateMix, data.MixX, data.MixY);
|
||||
return t;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,41 +1,41 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class EquipAssetExample : ScriptableObject {
|
||||
public EquipSystemExample.EquipType equipType;
|
||||
public Sprite sprite;
|
||||
public string description;
|
||||
public int yourStats;
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class EquipAssetExample : ScriptableObject {
|
||||
public EquipSystemExample.EquipType equipType;
|
||||
public Sprite sprite;
|
||||
public string description;
|
||||
public int yourStats;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,60 +1,60 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class EquipButtonExample : MonoBehaviour {
|
||||
public EquipAssetExample asset;
|
||||
public EquipSystemExample equipSystem;
|
||||
public Image inventoryImage;
|
||||
|
||||
void OnValidate () {
|
||||
MatchImage();
|
||||
}
|
||||
|
||||
void MatchImage () {
|
||||
if (inventoryImage != null)
|
||||
inventoryImage.sprite = asset.sprite;
|
||||
}
|
||||
|
||||
void Start () {
|
||||
MatchImage();
|
||||
|
||||
Button button = GetComponent<Button>();
|
||||
button.onClick.AddListener(
|
||||
delegate { equipSystem.Equip(asset); }
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class EquipButtonExample : MonoBehaviour {
|
||||
public EquipAssetExample asset;
|
||||
public EquipSystemExample equipSystem;
|
||||
public Image inventoryImage;
|
||||
|
||||
void OnValidate () {
|
||||
MatchImage();
|
||||
}
|
||||
|
||||
void MatchImage () {
|
||||
if (inventoryImage != null)
|
||||
inventoryImage.sprite = asset.sprite;
|
||||
}
|
||||
|
||||
void Start () {
|
||||
MatchImage();
|
||||
|
||||
Button button = GetComponent<Button>();
|
||||
button.onClick.AddListener(
|
||||
delegate { equipSystem.Equip(asset); }
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,107 +1,107 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity.AttachmentTools;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class EquipSystemExample : MonoBehaviour, IHasSkeletonDataAsset {
|
||||
|
||||
// Implementing IHasSkeletonDataAsset allows Spine attribute drawers to automatically detect this component as a skeleton data source.
|
||||
public SkeletonDataAsset skeletonDataAsset;
|
||||
SkeletonDataAsset IHasSkeletonDataAsset.SkeletonDataAsset { get { return this.skeletonDataAsset; } }
|
||||
|
||||
public Material sourceMaterial;
|
||||
public bool applyPMA = true;
|
||||
public List<EquipHook> equippables = new List<EquipHook>();
|
||||
|
||||
public EquipsVisualsComponentExample target;
|
||||
public Dictionary<EquipAssetExample, Attachment> cachedAttachments = new Dictionary<EquipAssetExample, Attachment>();
|
||||
|
||||
[System.Serializable]
|
||||
public class EquipHook {
|
||||
public EquipType type;
|
||||
[SpineSlot]
|
||||
public string slot;
|
||||
[SpineSkin]
|
||||
public string templateSkin;
|
||||
[SpineAttachment(skinField: "templateSkin")]
|
||||
public string templateAttachment;
|
||||
}
|
||||
|
||||
public enum EquipType {
|
||||
Gun,
|
||||
Goggles
|
||||
}
|
||||
|
||||
public void Equip (EquipAssetExample asset) {
|
||||
EquipType equipType = asset.equipType;
|
||||
EquipHook howToEquip = equippables.Find(x => x.type == equipType);
|
||||
|
||||
SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(true);
|
||||
int slotIndex = skeletonData.FindSlot(howToEquip.slot).Index;
|
||||
Attachment attachment = GenerateAttachmentFromEquipAsset(asset, slotIndex, howToEquip.templateSkin, howToEquip.templateAttachment);
|
||||
target.Equip(slotIndex, howToEquip.templateAttachment, attachment);
|
||||
}
|
||||
|
||||
Attachment GenerateAttachmentFromEquipAsset (EquipAssetExample asset, int slotIndex, string templateSkinName, string templateAttachmentName) {
|
||||
Attachment attachment;
|
||||
cachedAttachments.TryGetValue(asset, out attachment);
|
||||
|
||||
if (attachment == null) {
|
||||
SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(true);
|
||||
Skin templateSkin = skeletonData.FindSkin(templateSkinName);
|
||||
Attachment templateAttachment = templateSkin.GetAttachment(slotIndex, templateAttachmentName);
|
||||
attachment = templateAttachment.GetRemappedClone(asset.sprite, sourceMaterial, premultiplyAlpha: this.applyPMA);
|
||||
// Note: Each call to `GetRemappedClone()` with parameter `premultiplyAlpha` set to `true` creates
|
||||
// a cached Texture copy which can be cleared by calling AtlasUtilities.ClearCache() as shown in the method below.
|
||||
|
||||
cachedAttachments.Add(asset, attachment); // Cache this value for next time this asset is used.
|
||||
}
|
||||
|
||||
return attachment;
|
||||
}
|
||||
|
||||
public void Done () {
|
||||
target.OptimizeSkin();
|
||||
// `GetRepackedSkin()` and each call to `GetRemappedClone()` with parameter `premultiplyAlpha` set to `true`
|
||||
// creates cached Texture copies which can be cleared by calling AtlasUtilities.ClearCache().
|
||||
// You can optionally clear the textures cache after multiple repack operations.
|
||||
// Just be aware that while this cleanup frees up memory, it is also a costly operation
|
||||
// and will likely cause a spike in the framerate.
|
||||
|
||||
//AtlasUtilities.ClearCache();
|
||||
//Resources.UnloadUnusedAssets();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity.AttachmentTools;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class EquipSystemExample : MonoBehaviour, IHasSkeletonDataAsset {
|
||||
|
||||
// Implementing IHasSkeletonDataAsset allows Spine attribute drawers to automatically detect this component as a skeleton data source.
|
||||
public SkeletonDataAsset skeletonDataAsset;
|
||||
SkeletonDataAsset IHasSkeletonDataAsset.SkeletonDataAsset { get { return this.skeletonDataAsset; } }
|
||||
|
||||
public Material sourceMaterial;
|
||||
public bool applyPMA = true;
|
||||
public List<EquipHook> equippables = new List<EquipHook>();
|
||||
|
||||
public EquipsVisualsComponentExample target;
|
||||
public Dictionary<EquipAssetExample, Attachment> cachedAttachments = new Dictionary<EquipAssetExample, Attachment>();
|
||||
|
||||
[System.Serializable]
|
||||
public class EquipHook {
|
||||
public EquipType type;
|
||||
[SpineSlot]
|
||||
public string slot;
|
||||
[SpineSkin]
|
||||
public string templateSkin;
|
||||
[SpineAttachment(skinField: "templateSkin")]
|
||||
public string templateAttachment;
|
||||
}
|
||||
|
||||
public enum EquipType {
|
||||
Gun,
|
||||
Goggles
|
||||
}
|
||||
|
||||
public void Equip (EquipAssetExample asset) {
|
||||
EquipType equipType = asset.equipType;
|
||||
EquipHook howToEquip = equippables.Find(x => x.type == equipType);
|
||||
|
||||
SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(true);
|
||||
int slotIndex = skeletonData.FindSlot(howToEquip.slot).Index;
|
||||
Attachment attachment = GenerateAttachmentFromEquipAsset(asset, slotIndex, howToEquip.templateSkin, howToEquip.templateAttachment);
|
||||
target.Equip(slotIndex, howToEquip.templateAttachment, attachment);
|
||||
}
|
||||
|
||||
Attachment GenerateAttachmentFromEquipAsset (EquipAssetExample asset, int slotIndex, string templateSkinName, string templateAttachmentName) {
|
||||
Attachment attachment;
|
||||
cachedAttachments.TryGetValue(asset, out attachment);
|
||||
|
||||
if (attachment == null) {
|
||||
SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(true);
|
||||
Skin templateSkin = skeletonData.FindSkin(templateSkinName);
|
||||
Attachment templateAttachment = templateSkin.GetAttachment(slotIndex, templateAttachmentName);
|
||||
attachment = templateAttachment.GetRemappedClone(asset.sprite, sourceMaterial, premultiplyAlpha: this.applyPMA);
|
||||
// Note: Each call to `GetRemappedClone()` with parameter `premultiplyAlpha` set to `true` creates
|
||||
// a cached Texture copy which can be cleared by calling AtlasUtilities.ClearCache() as shown in the method below.
|
||||
|
||||
cachedAttachments.Add(asset, attachment); // Cache this value for next time this asset is used.
|
||||
}
|
||||
|
||||
return attachment;
|
||||
}
|
||||
|
||||
public void Done () {
|
||||
target.OptimizeSkin();
|
||||
// `GetRepackedSkin()` and each call to `GetRemappedClone()` with parameter `premultiplyAlpha` set to `true`
|
||||
// creates cached Texture copies which can be cleared by calling AtlasUtilities.ClearCache().
|
||||
// You can optionally clear the textures cache after multiple repack operations.
|
||||
// Just be aware that while this cleanup frees up memory, it is also a costly operation
|
||||
// and will likely cause a spike in the framerate.
|
||||
|
||||
//AtlasUtilities.ClearCache();
|
||||
//Resources.UnloadUnusedAssets();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,100 +1,100 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity.AttachmentTools;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class EquipsVisualsComponentExample : MonoBehaviour {
|
||||
|
||||
public SkeletonAnimation skeletonAnimation;
|
||||
|
||||
[SpineSkin]
|
||||
public string templateSkinName;
|
||||
|
||||
Spine.Skin equipsSkin;
|
||||
Spine.Skin collectedSkin;
|
||||
|
||||
public Material runtimeMaterial;
|
||||
public Texture2D runtimeAtlas;
|
||||
|
||||
void Start () {
|
||||
equipsSkin = new Skin("Equips");
|
||||
|
||||
// OPTIONAL: Add all the attachments from the template skin.
|
||||
Skin templateSkin = skeletonAnimation.Skeleton.Data.FindSkin(templateSkinName);
|
||||
if (templateSkin != null)
|
||||
equipsSkin.AddSkin(templateSkin);
|
||||
|
||||
skeletonAnimation.Skeleton.Skin = equipsSkin;
|
||||
RefreshSkeletonAttachments();
|
||||
}
|
||||
|
||||
public void Equip (int slotIndex, string attachmentName, Attachment attachment) {
|
||||
equipsSkin.SetAttachment(slotIndex, attachmentName, attachment);
|
||||
skeletonAnimation.Skeleton.SetSkin(equipsSkin);
|
||||
RefreshSkeletonAttachments();
|
||||
}
|
||||
|
||||
public void OptimizeSkin () {
|
||||
// 1. Collect all the attachments of all active skins.
|
||||
collectedSkin = collectedSkin ?? new Skin("Collected skin");
|
||||
collectedSkin.Clear();
|
||||
collectedSkin.AddSkin(skeletonAnimation.Skeleton.Data.DefaultSkin);
|
||||
collectedSkin.AddSkin(equipsSkin);
|
||||
|
||||
// 2. Create a repacked skin.
|
||||
// Note: materials and textures returned by GetRepackedSkin() behave like 'new Texture2D()' and need to be destroyed
|
||||
if (runtimeMaterial)
|
||||
Destroy(runtimeMaterial);
|
||||
if (runtimeAtlas)
|
||||
Destroy(runtimeAtlas);
|
||||
Skin repackedSkin = collectedSkin.GetRepackedSkin("Repacked skin", skeletonAnimation.SkeletonDataAsset.atlasAssets[0].PrimaryMaterial,
|
||||
out runtimeMaterial, out runtimeAtlas, maxAtlasSize: 1024, clearCache: false);
|
||||
collectedSkin.Clear();
|
||||
|
||||
// You can optionally clear the textures cache after each ore multiple repack operations are done.
|
||||
//AtlasUtilities.ClearCache();
|
||||
//Resources.UnloadUnusedAssets();
|
||||
|
||||
// 3. Use the repacked skin.
|
||||
skeletonAnimation.Skeleton.Skin = repackedSkin;
|
||||
RefreshSkeletonAttachments();
|
||||
}
|
||||
|
||||
void RefreshSkeletonAttachments () {
|
||||
skeletonAnimation.Skeleton.SetSlotsToSetupPose();
|
||||
skeletonAnimation.AnimationState.Apply(skeletonAnimation.Skeleton); //skeletonAnimation.Update(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity.AttachmentTools;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class EquipsVisualsComponentExample : MonoBehaviour {
|
||||
|
||||
public SkeletonAnimation skeletonAnimation;
|
||||
|
||||
[SpineSkin]
|
||||
public string templateSkinName;
|
||||
|
||||
Spine.Skin equipsSkin;
|
||||
Spine.Skin collectedSkin;
|
||||
|
||||
public Material runtimeMaterial;
|
||||
public Texture2D runtimeAtlas;
|
||||
|
||||
void Start () {
|
||||
equipsSkin = new Skin("Equips");
|
||||
|
||||
// OPTIONAL: Add all the attachments from the template skin.
|
||||
Skin templateSkin = skeletonAnimation.Skeleton.Data.FindSkin(templateSkinName);
|
||||
if (templateSkin != null)
|
||||
equipsSkin.AddSkin(templateSkin);
|
||||
|
||||
skeletonAnimation.Skeleton.Skin = equipsSkin;
|
||||
RefreshSkeletonAttachments();
|
||||
}
|
||||
|
||||
public void Equip (int slotIndex, string attachmentName, Attachment attachment) {
|
||||
equipsSkin.SetAttachment(slotIndex, attachmentName, attachment);
|
||||
skeletonAnimation.Skeleton.SetSkin(equipsSkin);
|
||||
RefreshSkeletonAttachments();
|
||||
}
|
||||
|
||||
public void OptimizeSkin () {
|
||||
// 1. Collect all the attachments of all active skins.
|
||||
collectedSkin = collectedSkin ?? new Skin("Collected skin");
|
||||
collectedSkin.Clear();
|
||||
collectedSkin.AddSkin(skeletonAnimation.Skeleton.Data.DefaultSkin);
|
||||
collectedSkin.AddSkin(equipsSkin);
|
||||
|
||||
// 2. Create a repacked skin.
|
||||
// Note: materials and textures returned by GetRepackedSkin() behave like 'new Texture2D()' and need to be destroyed
|
||||
if (runtimeMaterial)
|
||||
Destroy(runtimeMaterial);
|
||||
if (runtimeAtlas)
|
||||
Destroy(runtimeAtlas);
|
||||
Skin repackedSkin = collectedSkin.GetRepackedSkin("Repacked skin", skeletonAnimation.SkeletonDataAsset.atlasAssets[0].PrimaryMaterial,
|
||||
out runtimeMaterial, out runtimeAtlas, maxAtlasSize: 1024, clearCache: false);
|
||||
collectedSkin.Clear();
|
||||
|
||||
// You can optionally clear the textures cache after each ore multiple repack operations are done.
|
||||
//AtlasUtilities.ClearCache();
|
||||
//Resources.UnloadUnusedAssets();
|
||||
|
||||
// 3. Use the repacked skin.
|
||||
skeletonAnimation.Skeleton.Skin = repackedSkin;
|
||||
RefreshSkeletonAttachments();
|
||||
}
|
||||
|
||||
void RefreshSkeletonAttachments () {
|
||||
skeletonAnimation.Skeleton.SetSlotsToSetupPose();
|
||||
skeletonAnimation.AnimationState.Apply(skeletonAnimation.Skeleton); //skeletonAnimation.Update(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,50 +1,50 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class MixAndMatchSkinsButtonExample : MonoBehaviour {
|
||||
|
||||
public SkeletonDataAsset skeletonDataAsset;
|
||||
public MixAndMatchSkinsExample skinsSystem;
|
||||
|
||||
[SpineSkin(dataField: "skeletonDataAsset")] public string itemSkin;
|
||||
public MixAndMatchSkinsExample.ItemType itemType;
|
||||
|
||||
void Start () {
|
||||
Button button = GetComponent<Button>();
|
||||
button.onClick.AddListener(
|
||||
delegate { skinsSystem.Equip(itemSkin, itemType); }
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class MixAndMatchSkinsButtonExample : MonoBehaviour {
|
||||
|
||||
public SkeletonDataAsset skeletonDataAsset;
|
||||
public MixAndMatchSkinsExample skinsSystem;
|
||||
|
||||
[SpineSkin(dataField: "skeletonDataAsset")] public string itemSkin;
|
||||
public MixAndMatchSkinsExample.ItemType itemType;
|
||||
|
||||
void Start () {
|
||||
Button button = GetComponent<Button>();
|
||||
button.onClick.AddListener(
|
||||
delegate { skinsSystem.Equip(itemSkin, itemType); }
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,195 +1,195 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity.AttachmentTools;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
public class MixAndMatchSkinsExample : MonoBehaviour {
|
||||
|
||||
// character skins
|
||||
[SpineSkin] public string baseSkin = "skin-base";
|
||||
[SpineSkin] public string eyelidsSkin = "eyelids/girly";
|
||||
|
||||
// here we use arrays of strings to be able to cycle between them easily.
|
||||
[SpineSkin] public string[] hairSkins = { "hair/brown", "hair/blue", "hair/pink", "hair/short-red", "hair/long-blue-with-scarf" };
|
||||
public int activeHairIndex = 0;
|
||||
[SpineSkin] public string[] eyesSkins = { "eyes/violet", "eyes/green", "eyes/yellow" };
|
||||
public int activeEyesIndex = 0;
|
||||
[SpineSkin] public string[] noseSkins = { "nose/short", "nose/long" };
|
||||
public int activeNoseIndex = 0;
|
||||
|
||||
// equipment skins
|
||||
public enum ItemType {
|
||||
Cloth,
|
||||
Pants,
|
||||
Bag,
|
||||
Hat
|
||||
}
|
||||
[SpineSkin] public string clothesSkin = "clothes/hoodie-orange";
|
||||
[SpineSkin] public string pantsSkin = "legs/pants-jeans";
|
||||
[SpineSkin] public string bagSkin = "";
|
||||
[SpineSkin] public string hatSkin = "accessories/hat-red-yellow";
|
||||
|
||||
SkeletonAnimation skeletonAnimation;
|
||||
// This "naked body" skin will likely change only once upon character creation,
|
||||
// so we store this combined set of non-equipment Skins for later re-use.
|
||||
Skin characterSkin;
|
||||
|
||||
// for repacking the skin to a new atlas texture
|
||||
public Material runtimeMaterial;
|
||||
public Texture2D runtimeAtlas;
|
||||
|
||||
void Awake () {
|
||||
skeletonAnimation = this.GetComponent<SkeletonAnimation>();
|
||||
}
|
||||
|
||||
void Start () {
|
||||
UpdateCharacterSkin();
|
||||
UpdateCombinedSkin();
|
||||
}
|
||||
|
||||
public void NextHairSkin () {
|
||||
activeHairIndex = (activeHairIndex + 1) % hairSkins.Length;
|
||||
UpdateCharacterSkin();
|
||||
UpdateCombinedSkin();
|
||||
}
|
||||
|
||||
public void PrevHairSkin () {
|
||||
activeHairIndex = (activeHairIndex + hairSkins.Length - 1) % hairSkins.Length;
|
||||
UpdateCharacterSkin();
|
||||
UpdateCombinedSkin();
|
||||
}
|
||||
|
||||
public void NextEyesSkin () {
|
||||
activeEyesIndex = (activeEyesIndex + 1) % eyesSkins.Length;
|
||||
UpdateCharacterSkin();
|
||||
UpdateCombinedSkin();
|
||||
}
|
||||
|
||||
public void PrevEyesSkin () {
|
||||
activeEyesIndex = (activeEyesIndex + eyesSkins.Length - 1) % eyesSkins.Length;
|
||||
UpdateCharacterSkin();
|
||||
UpdateCombinedSkin();
|
||||
}
|
||||
|
||||
public void NextNoseSkin () {
|
||||
activeNoseIndex = (activeNoseIndex + 1) % noseSkins.Length;
|
||||
UpdateCharacterSkin();
|
||||
UpdateCombinedSkin();
|
||||
}
|
||||
|
||||
public void PrevNoseSkin () {
|
||||
activeNoseIndex = (activeNoseIndex + noseSkins.Length - 1) % noseSkins.Length;
|
||||
UpdateCharacterSkin();
|
||||
UpdateCombinedSkin();
|
||||
}
|
||||
|
||||
public void Equip (string itemSkin, ItemType itemType) {
|
||||
switch (itemType) {
|
||||
case ItemType.Cloth:
|
||||
clothesSkin = itemSkin;
|
||||
break;
|
||||
case ItemType.Pants:
|
||||
pantsSkin = itemSkin;
|
||||
break;
|
||||
case ItemType.Bag:
|
||||
bagSkin = itemSkin;
|
||||
break;
|
||||
case ItemType.Hat:
|
||||
hatSkin = itemSkin;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
UpdateCombinedSkin();
|
||||
}
|
||||
|
||||
public void OptimizeSkin () {
|
||||
// Create a repacked skin.
|
||||
Skin previousSkin = skeletonAnimation.Skeleton.Skin;
|
||||
// Note: materials and textures returned by GetRepackedSkin() behave like 'new Texture2D()' and need to be destroyed
|
||||
if (runtimeMaterial)
|
||||
Destroy(runtimeMaterial);
|
||||
if (runtimeAtlas)
|
||||
Destroy(runtimeAtlas);
|
||||
Skin repackedSkin = previousSkin.GetRepackedSkin("Repacked skin", skeletonAnimation.SkeletonDataAsset.atlasAssets[0].PrimaryMaterial, out runtimeMaterial, out runtimeAtlas);
|
||||
previousSkin.Clear();
|
||||
|
||||
// Use the repacked skin.
|
||||
skeletonAnimation.Skeleton.Skin = repackedSkin;
|
||||
skeletonAnimation.Skeleton.SetSlotsToSetupPose();
|
||||
skeletonAnimation.AnimationState.Apply(skeletonAnimation.Skeleton);
|
||||
|
||||
// `GetRepackedSkin()` and each call to `GetRemappedClone()` with parameter `premultiplyAlpha` set to `true`
|
||||
// cache necessarily created Texture copies which can be cleared by calling AtlasUtilities.ClearCache().
|
||||
// You can optionally clear the textures cache after multiple repack operations.
|
||||
// Just be aware that while this cleanup frees up memory, it is also a costly operation
|
||||
// and will likely cause a spike in the framerate.
|
||||
AtlasUtilities.ClearCache();
|
||||
Resources.UnloadUnusedAssets();
|
||||
}
|
||||
|
||||
void UpdateCharacterSkin () {
|
||||
Skeleton skeleton = skeletonAnimation.Skeleton;
|
||||
SkeletonData skeletonData = skeleton.Data;
|
||||
characterSkin = new Skin("character-base");
|
||||
// Note that the result Skin returned by calls to skeletonData.FindSkin()
|
||||
// could be cached once in Start() instead of searching for the same skin
|
||||
// every time. For demonstration purposes we keep it simple here.
|
||||
characterSkin.AddSkin(skeletonData.FindSkin(baseSkin));
|
||||
characterSkin.AddSkin(skeletonData.FindSkin(noseSkins[activeNoseIndex]));
|
||||
characterSkin.AddSkin(skeletonData.FindSkin(eyelidsSkin));
|
||||
characterSkin.AddSkin(skeletonData.FindSkin(eyesSkins[activeEyesIndex]));
|
||||
characterSkin.AddSkin(skeletonData.FindSkin(hairSkins[activeHairIndex]));
|
||||
}
|
||||
|
||||
void AddEquipmentSkinsTo (Skin combinedSkin) {
|
||||
Skeleton skeleton = skeletonAnimation.Skeleton;
|
||||
SkeletonData skeletonData = skeleton.Data;
|
||||
combinedSkin.AddSkin(skeletonData.FindSkin(clothesSkin));
|
||||
combinedSkin.AddSkin(skeletonData.FindSkin(pantsSkin));
|
||||
if (!string.IsNullOrEmpty(bagSkin)) combinedSkin.AddSkin(skeletonData.FindSkin(bagSkin));
|
||||
if (!string.IsNullOrEmpty(hatSkin)) combinedSkin.AddSkin(skeletonData.FindSkin(hatSkin));
|
||||
}
|
||||
|
||||
void UpdateCombinedSkin () {
|
||||
Skeleton skeleton = skeletonAnimation.Skeleton;
|
||||
Skin resultCombinedSkin = new Skin("character-combined");
|
||||
|
||||
resultCombinedSkin.AddSkin(characterSkin);
|
||||
AddEquipmentSkinsTo(resultCombinedSkin);
|
||||
|
||||
skeleton.SetSkin(resultCombinedSkin);
|
||||
skeleton.SetSlotsToSetupPose();
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity.AttachmentTools;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
public class MixAndMatchSkinsExample : MonoBehaviour {
|
||||
|
||||
// character skins
|
||||
[SpineSkin] public string baseSkin = "skin-base";
|
||||
[SpineSkin] public string eyelidsSkin = "eyelids/girly";
|
||||
|
||||
// here we use arrays of strings to be able to cycle between them easily.
|
||||
[SpineSkin] public string[] hairSkins = { "hair/brown", "hair/blue", "hair/pink", "hair/short-red", "hair/long-blue-with-scarf" };
|
||||
public int activeHairIndex = 0;
|
||||
[SpineSkin] public string[] eyesSkins = { "eyes/violet", "eyes/green", "eyes/yellow" };
|
||||
public int activeEyesIndex = 0;
|
||||
[SpineSkin] public string[] noseSkins = { "nose/short", "nose/long" };
|
||||
public int activeNoseIndex = 0;
|
||||
|
||||
// equipment skins
|
||||
public enum ItemType {
|
||||
Cloth,
|
||||
Pants,
|
||||
Bag,
|
||||
Hat
|
||||
}
|
||||
[SpineSkin] public string clothesSkin = "clothes/hoodie-orange";
|
||||
[SpineSkin] public string pantsSkin = "legs/pants-jeans";
|
||||
[SpineSkin] public string bagSkin = "";
|
||||
[SpineSkin] public string hatSkin = "accessories/hat-red-yellow";
|
||||
|
||||
SkeletonAnimation skeletonAnimation;
|
||||
// This "naked body" skin will likely change only once upon character creation,
|
||||
// so we store this combined set of non-equipment Skins for later re-use.
|
||||
Skin characterSkin;
|
||||
|
||||
// for repacking the skin to a new atlas texture
|
||||
public Material runtimeMaterial;
|
||||
public Texture2D runtimeAtlas;
|
||||
|
||||
void Awake () {
|
||||
skeletonAnimation = this.GetComponent<SkeletonAnimation>();
|
||||
}
|
||||
|
||||
void Start () {
|
||||
UpdateCharacterSkin();
|
||||
UpdateCombinedSkin();
|
||||
}
|
||||
|
||||
public void NextHairSkin () {
|
||||
activeHairIndex = (activeHairIndex + 1) % hairSkins.Length;
|
||||
UpdateCharacterSkin();
|
||||
UpdateCombinedSkin();
|
||||
}
|
||||
|
||||
public void PrevHairSkin () {
|
||||
activeHairIndex = (activeHairIndex + hairSkins.Length - 1) % hairSkins.Length;
|
||||
UpdateCharacterSkin();
|
||||
UpdateCombinedSkin();
|
||||
}
|
||||
|
||||
public void NextEyesSkin () {
|
||||
activeEyesIndex = (activeEyesIndex + 1) % eyesSkins.Length;
|
||||
UpdateCharacterSkin();
|
||||
UpdateCombinedSkin();
|
||||
}
|
||||
|
||||
public void PrevEyesSkin () {
|
||||
activeEyesIndex = (activeEyesIndex + eyesSkins.Length - 1) % eyesSkins.Length;
|
||||
UpdateCharacterSkin();
|
||||
UpdateCombinedSkin();
|
||||
}
|
||||
|
||||
public void NextNoseSkin () {
|
||||
activeNoseIndex = (activeNoseIndex + 1) % noseSkins.Length;
|
||||
UpdateCharacterSkin();
|
||||
UpdateCombinedSkin();
|
||||
}
|
||||
|
||||
public void PrevNoseSkin () {
|
||||
activeNoseIndex = (activeNoseIndex + noseSkins.Length - 1) % noseSkins.Length;
|
||||
UpdateCharacterSkin();
|
||||
UpdateCombinedSkin();
|
||||
}
|
||||
|
||||
public void Equip (string itemSkin, ItemType itemType) {
|
||||
switch (itemType) {
|
||||
case ItemType.Cloth:
|
||||
clothesSkin = itemSkin;
|
||||
break;
|
||||
case ItemType.Pants:
|
||||
pantsSkin = itemSkin;
|
||||
break;
|
||||
case ItemType.Bag:
|
||||
bagSkin = itemSkin;
|
||||
break;
|
||||
case ItemType.Hat:
|
||||
hatSkin = itemSkin;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
UpdateCombinedSkin();
|
||||
}
|
||||
|
||||
public void OptimizeSkin () {
|
||||
// Create a repacked skin.
|
||||
Skin previousSkin = skeletonAnimation.Skeleton.Skin;
|
||||
// Note: materials and textures returned by GetRepackedSkin() behave like 'new Texture2D()' and need to be destroyed
|
||||
if (runtimeMaterial)
|
||||
Destroy(runtimeMaterial);
|
||||
if (runtimeAtlas)
|
||||
Destroy(runtimeAtlas);
|
||||
Skin repackedSkin = previousSkin.GetRepackedSkin("Repacked skin", skeletonAnimation.SkeletonDataAsset.atlasAssets[0].PrimaryMaterial, out runtimeMaterial, out runtimeAtlas);
|
||||
previousSkin.Clear();
|
||||
|
||||
// Use the repacked skin.
|
||||
skeletonAnimation.Skeleton.Skin = repackedSkin;
|
||||
skeletonAnimation.Skeleton.SetSlotsToSetupPose();
|
||||
skeletonAnimation.AnimationState.Apply(skeletonAnimation.Skeleton);
|
||||
|
||||
// `GetRepackedSkin()` and each call to `GetRemappedClone()` with parameter `premultiplyAlpha` set to `true`
|
||||
// cache necessarily created Texture copies which can be cleared by calling AtlasUtilities.ClearCache().
|
||||
// You can optionally clear the textures cache after multiple repack operations.
|
||||
// Just be aware that while this cleanup frees up memory, it is also a costly operation
|
||||
// and will likely cause a spike in the framerate.
|
||||
AtlasUtilities.ClearCache();
|
||||
Resources.UnloadUnusedAssets();
|
||||
}
|
||||
|
||||
void UpdateCharacterSkin () {
|
||||
Skeleton skeleton = skeletonAnimation.Skeleton;
|
||||
SkeletonData skeletonData = skeleton.Data;
|
||||
characterSkin = new Skin("character-base");
|
||||
// Note that the result Skin returned by calls to skeletonData.FindSkin()
|
||||
// could be cached once in Start() instead of searching for the same skin
|
||||
// every time. For demonstration purposes we keep it simple here.
|
||||
characterSkin.AddSkin(skeletonData.FindSkin(baseSkin));
|
||||
characterSkin.AddSkin(skeletonData.FindSkin(noseSkins[activeNoseIndex]));
|
||||
characterSkin.AddSkin(skeletonData.FindSkin(eyelidsSkin));
|
||||
characterSkin.AddSkin(skeletonData.FindSkin(eyesSkins[activeEyesIndex]));
|
||||
characterSkin.AddSkin(skeletonData.FindSkin(hairSkins[activeHairIndex]));
|
||||
}
|
||||
|
||||
void AddEquipmentSkinsTo (Skin combinedSkin) {
|
||||
Skeleton skeleton = skeletonAnimation.Skeleton;
|
||||
SkeletonData skeletonData = skeleton.Data;
|
||||
combinedSkin.AddSkin(skeletonData.FindSkin(clothesSkin));
|
||||
combinedSkin.AddSkin(skeletonData.FindSkin(pantsSkin));
|
||||
if (!string.IsNullOrEmpty(bagSkin)) combinedSkin.AddSkin(skeletonData.FindSkin(bagSkin));
|
||||
if (!string.IsNullOrEmpty(hatSkin)) combinedSkin.AddSkin(skeletonData.FindSkin(hatSkin));
|
||||
}
|
||||
|
||||
void UpdateCombinedSkin () {
|
||||
Skeleton skeleton = skeletonAnimation.Skeleton;
|
||||
Skin resultCombinedSkin = new Skin("character-combined");
|
||||
|
||||
resultCombinedSkin.AddSkin(characterSkin);
|
||||
AddEquipmentSkinsTo(resultCombinedSkin);
|
||||
|
||||
skeleton.SetSkin(resultCombinedSkin);
|
||||
skeleton.SetSlotsToSetupPose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,151 +1,151 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity.AttachmentTools;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
// This is an example script that shows you how to change images on your skeleton using UnityEngine.Sprites.
|
||||
public class MixAndMatch : MonoBehaviour {
|
||||
|
||||
#region Inspector
|
||||
[SpineSkin]
|
||||
public string templateAttachmentsSkin = "base";
|
||||
public Material sourceMaterial; // This will be used as the basis for shader and material property settings.
|
||||
|
||||
[Header("Visor")]
|
||||
public Sprite visorSprite;
|
||||
[SpineSlot] public string visorSlot;
|
||||
[SpineAttachment(slotField: "visorSlot", skinField: "baseSkinName")] public string visorKey = "goggles";
|
||||
|
||||
[Header("Gun")]
|
||||
public Sprite gunSprite;
|
||||
[SpineSlot] public string gunSlot;
|
||||
[SpineAttachment(slotField: "gunSlot", skinField: "baseSkinName")] public string gunKey = "gun";
|
||||
|
||||
[Header("Runtime Repack")]
|
||||
public bool repack = true;
|
||||
public BoundingBoxFollower bbFollower;
|
||||
|
||||
[Header("Do not assign")]
|
||||
public Texture2D runtimeAtlas;
|
||||
public Material runtimeMaterial;
|
||||
#endregion
|
||||
|
||||
Skin customSkin;
|
||||
|
||||
void OnValidate () {
|
||||
if (sourceMaterial == null) {
|
||||
SkeletonAnimation skeletonAnimation = GetComponent<SkeletonAnimation>();
|
||||
if (skeletonAnimation != null)
|
||||
sourceMaterial = skeletonAnimation.SkeletonDataAsset.atlasAssets[0].PrimaryMaterial;
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator Start () {
|
||||
yield return new WaitForSeconds(1f); // Delay for one second before applying. For testing.
|
||||
Apply();
|
||||
}
|
||||
|
||||
void Apply () {
|
||||
SkeletonAnimation skeletonAnimation = GetComponent<SkeletonAnimation>();
|
||||
Skeleton skeleton = skeletonAnimation.Skeleton;
|
||||
|
||||
// STEP 0: PREPARE SKINS
|
||||
// Let's prepare a new skin to be our custom skin with equips/customizations. We get a clone so our original skins are unaffected.
|
||||
customSkin = customSkin ?? new Skin("custom skin"); // This requires that all customizations are done with skin placeholders defined in Spine.
|
||||
Skin templateSkin = skeleton.Data.FindSkin(templateAttachmentsSkin);
|
||||
|
||||
// STEP 1: "EQUIP" ITEMS USING SPRITES
|
||||
// STEP 1.1 Find the original/template attachment.
|
||||
// Step 1.2 Get a clone of the original/template attachment.
|
||||
// Step 1.3 Apply the Sprite image to the clone.
|
||||
// Step 1.4 Add the remapped clone to the new custom skin.
|
||||
|
||||
// Let's do this for the visor.
|
||||
int visorSlotIndex = skeleton.Data.FindSlot(visorSlot).Index; // You can access GetAttachment and SetAttachment via string, but caching the slotIndex is faster.
|
||||
Attachment templateAttachment = templateSkin.GetAttachment(visorSlotIndex, visorKey); // STEP 1.1
|
||||
|
||||
// Note: Each call to `GetRemappedClone()` with parameter `premultiplyAlpha` set to `true` creates
|
||||
// a cached Texture copy which can be cleared by calling AtlasUtilities.ClearCache() as done in the method below.
|
||||
Attachment newAttachment = templateAttachment.GetRemappedClone(visorSprite, sourceMaterial, pivotShiftsMeshUVCoords: false); // STEP 1.2 - 1.3
|
||||
customSkin.SetAttachment(visorSlotIndex, visorKey, newAttachment); // STEP 1.4
|
||||
|
||||
// And now for the gun.
|
||||
int gunSlotIndex = skeleton.Data.FindSlot(gunSlot).Index;
|
||||
Attachment templateGun = templateSkin.GetAttachment(gunSlotIndex, gunKey); // STEP 1.1
|
||||
Attachment newGun = templateGun.GetRemappedClone(gunSprite, sourceMaterial, pivotShiftsMeshUVCoords: false); // STEP 1.2 - 1.3
|
||||
if (newGun != null) customSkin.SetAttachment(gunSlotIndex, gunKey, newGun); // STEP 1.4
|
||||
|
||||
// customSkin.RemoveAttachment(gunSlotIndex, gunKey); // To remove an item.
|
||||
// customSkin.Clear()
|
||||
// Use skin.Clear() To remove all customizations.
|
||||
// Customizations will fall back to the value in the default skin if it was defined there.
|
||||
// To prevent fallback from happening, make sure the key is not defined in the default skin.
|
||||
|
||||
// STEP 3: APPLY AND CLEAN UP.
|
||||
// Recommended, preferably at level-load-time: REPACK THE CUSTOM SKIN TO MINIMIZE DRAW CALLS
|
||||
// IMPORTANT NOTE: the GetRepackedSkin() operation is expensive - if multiple characters
|
||||
// need to call it every few seconds the overhead will outweigh the draw call benefits.
|
||||
//
|
||||
// Repacking requires that you set all source textures/sprites/atlases to be Read/Write enabled in the inspector.
|
||||
// Combine all the attachment sources into one skin. Usually this means the default skin and the custom skin.
|
||||
// call Skin.GetRepackedSkin to get a cloned skin with cloned attachments that all use one texture.
|
||||
if (repack) {
|
||||
Skin repackedSkin = new Skin("repacked skin");
|
||||
repackedSkin.AddSkin(skeleton.Data.DefaultSkin); // Include the "default" skin. (everything outside of skin placeholders)
|
||||
repackedSkin.AddSkin(customSkin); // Include your new custom skin.
|
||||
|
||||
// Note: materials and textures returned by GetRepackedSkin() behave like 'new Texture2D()' and need to be destroyed
|
||||
if (runtimeMaterial)
|
||||
Destroy(runtimeMaterial);
|
||||
if (runtimeAtlas)
|
||||
Destroy(runtimeAtlas);
|
||||
repackedSkin = repackedSkin.GetRepackedSkin("repacked skin", sourceMaterial, out runtimeMaterial, out runtimeAtlas); // Pack all the items in the skin.
|
||||
skeleton.SetSkin(repackedSkin); // Assign the repacked skin to your Skeleton.
|
||||
if (bbFollower != null) bbFollower.Initialize(true);
|
||||
} else {
|
||||
skeleton.SetSkin(customSkin); // Just use the custom skin directly.
|
||||
}
|
||||
|
||||
skeleton.SetSlotsToSetupPose(); // Use the pose from setup pose.
|
||||
skeletonAnimation.Update(0); // Use the pose in the currently active animation.
|
||||
|
||||
// `GetRepackedSkin()` and each call to `GetRemappedClone()` with parameter `premultiplyAlpha` set to `true`
|
||||
// cache necessarily created Texture copies which can be cleared by calling AtlasUtilities.ClearCache().
|
||||
// You can optionally clear the textures cache after multiple repack operations.
|
||||
// Just be aware that while this cleanup frees up memory, it is also a costly operation
|
||||
// and will likely cause a spike in the framerate.
|
||||
AtlasUtilities.ClearCache();
|
||||
Resources.UnloadUnusedAssets();
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity.AttachmentTools;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
// This is an example script that shows you how to change images on your skeleton using UnityEngine.Sprites.
|
||||
public class MixAndMatch : MonoBehaviour {
|
||||
|
||||
#region Inspector
|
||||
[SpineSkin]
|
||||
public string templateAttachmentsSkin = "base";
|
||||
public Material sourceMaterial; // This will be used as the basis for shader and material property settings.
|
||||
|
||||
[Header("Visor")]
|
||||
public Sprite visorSprite;
|
||||
[SpineSlot] public string visorSlot;
|
||||
[SpineAttachment(slotField: "visorSlot", skinField: "baseSkinName")] public string visorKey = "goggles";
|
||||
|
||||
[Header("Gun")]
|
||||
public Sprite gunSprite;
|
||||
[SpineSlot] public string gunSlot;
|
||||
[SpineAttachment(slotField: "gunSlot", skinField: "baseSkinName")] public string gunKey = "gun";
|
||||
|
||||
[Header("Runtime Repack")]
|
||||
public bool repack = true;
|
||||
public BoundingBoxFollower bbFollower;
|
||||
|
||||
[Header("Do not assign")]
|
||||
public Texture2D runtimeAtlas;
|
||||
public Material runtimeMaterial;
|
||||
#endregion
|
||||
|
||||
Skin customSkin;
|
||||
|
||||
void OnValidate () {
|
||||
if (sourceMaterial == null) {
|
||||
SkeletonAnimation skeletonAnimation = GetComponent<SkeletonAnimation>();
|
||||
if (skeletonAnimation != null)
|
||||
sourceMaterial = skeletonAnimation.SkeletonDataAsset.atlasAssets[0].PrimaryMaterial;
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator Start () {
|
||||
yield return new WaitForSeconds(1f); // Delay for one second before applying. For testing.
|
||||
Apply();
|
||||
}
|
||||
|
||||
void Apply () {
|
||||
SkeletonAnimation skeletonAnimation = GetComponent<SkeletonAnimation>();
|
||||
Skeleton skeleton = skeletonAnimation.Skeleton;
|
||||
|
||||
// STEP 0: PREPARE SKINS
|
||||
// Let's prepare a new skin to be our custom skin with equips/customizations. We get a clone so our original skins are unaffected.
|
||||
customSkin = customSkin ?? new Skin("custom skin"); // This requires that all customizations are done with skin placeholders defined in Spine.
|
||||
Skin templateSkin = skeleton.Data.FindSkin(templateAttachmentsSkin);
|
||||
|
||||
// STEP 1: "EQUIP" ITEMS USING SPRITES
|
||||
// STEP 1.1 Find the original/template attachment.
|
||||
// Step 1.2 Get a clone of the original/template attachment.
|
||||
// Step 1.3 Apply the Sprite image to the clone.
|
||||
// Step 1.4 Add the remapped clone to the new custom skin.
|
||||
|
||||
// Let's do this for the visor.
|
||||
int visorSlotIndex = skeleton.Data.FindSlot(visorSlot).Index; // You can access GetAttachment and SetAttachment via string, but caching the slotIndex is faster.
|
||||
Attachment templateAttachment = templateSkin.GetAttachment(visorSlotIndex, visorKey); // STEP 1.1
|
||||
|
||||
// Note: Each call to `GetRemappedClone()` with parameter `premultiplyAlpha` set to `true` creates
|
||||
// a cached Texture copy which can be cleared by calling AtlasUtilities.ClearCache() as done in the method below.
|
||||
Attachment newAttachment = templateAttachment.GetRemappedClone(visorSprite, sourceMaterial, pivotShiftsMeshUVCoords: false); // STEP 1.2 - 1.3
|
||||
customSkin.SetAttachment(visorSlotIndex, visorKey, newAttachment); // STEP 1.4
|
||||
|
||||
// And now for the gun.
|
||||
int gunSlotIndex = skeleton.Data.FindSlot(gunSlot).Index;
|
||||
Attachment templateGun = templateSkin.GetAttachment(gunSlotIndex, gunKey); // STEP 1.1
|
||||
Attachment newGun = templateGun.GetRemappedClone(gunSprite, sourceMaterial, pivotShiftsMeshUVCoords: false); // STEP 1.2 - 1.3
|
||||
if (newGun != null) customSkin.SetAttachment(gunSlotIndex, gunKey, newGun); // STEP 1.4
|
||||
|
||||
// customSkin.RemoveAttachment(gunSlotIndex, gunKey); // To remove an item.
|
||||
// customSkin.Clear()
|
||||
// Use skin.Clear() To remove all customizations.
|
||||
// Customizations will fall back to the value in the default skin if it was defined there.
|
||||
// To prevent fallback from happening, make sure the key is not defined in the default skin.
|
||||
|
||||
// STEP 3: APPLY AND CLEAN UP.
|
||||
// Recommended, preferably at level-load-time: REPACK THE CUSTOM SKIN TO MINIMIZE DRAW CALLS
|
||||
// IMPORTANT NOTE: the GetRepackedSkin() operation is expensive - if multiple characters
|
||||
// need to call it every few seconds the overhead will outweigh the draw call benefits.
|
||||
//
|
||||
// Repacking requires that you set all source textures/sprites/atlases to be Read/Write enabled in the inspector.
|
||||
// Combine all the attachment sources into one skin. Usually this means the default skin and the custom skin.
|
||||
// call Skin.GetRepackedSkin to get a cloned skin with cloned attachments that all use one texture.
|
||||
if (repack) {
|
||||
Skin repackedSkin = new Skin("repacked skin");
|
||||
repackedSkin.AddSkin(skeleton.Data.DefaultSkin); // Include the "default" skin. (everything outside of skin placeholders)
|
||||
repackedSkin.AddSkin(customSkin); // Include your new custom skin.
|
||||
|
||||
// Note: materials and textures returned by GetRepackedSkin() behave like 'new Texture2D()' and need to be destroyed
|
||||
if (runtimeMaterial)
|
||||
Destroy(runtimeMaterial);
|
||||
if (runtimeAtlas)
|
||||
Destroy(runtimeAtlas);
|
||||
repackedSkin = repackedSkin.GetRepackedSkin("repacked skin", sourceMaterial, out runtimeMaterial, out runtimeAtlas); // Pack all the items in the skin.
|
||||
skeleton.SetSkin(repackedSkin); // Assign the repacked skin to your Skeleton.
|
||||
if (bbFollower != null) bbFollower.Initialize(true);
|
||||
} else {
|
||||
skeleton.SetSkin(customSkin); // Just use the custom skin directly.
|
||||
}
|
||||
|
||||
skeleton.SetSlotsToSetupPose(); // Use the pose from setup pose.
|
||||
skeletonAnimation.Update(0); // Use the pose in the currently active animation.
|
||||
|
||||
// `GetRepackedSkin()` and each call to `GetRemappedClone()` with parameter `premultiplyAlpha` set to `true`
|
||||
// cache necessarily created Texture copies which can be cleared by calling AtlasUtilities.ClearCache().
|
||||
// You can optionally clear the textures cache after multiple repack operations.
|
||||
// Just be aware that while this cleanup frees up memory, it is also a costly operation
|
||||
// and will likely cause a spike in the framerate.
|
||||
AtlasUtilities.ClearCache();
|
||||
Resources.UnloadUnusedAssets();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,150 +1,150 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity.AttachmentTools;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
// This is an example script that shows you how to change images on your skeleton using UnityEngine.Sprites.
|
||||
public class MixAndMatchGraphic : MonoBehaviour {
|
||||
|
||||
#region Inspector
|
||||
[SpineSkin]
|
||||
public string baseSkinName = "base";
|
||||
public Material sourceMaterial; // This will be used as the basis for shader and material property settings.
|
||||
|
||||
[Header("Visor")]
|
||||
public Sprite visorSprite;
|
||||
[SpineSlot] public string visorSlot;
|
||||
[SpineAttachment(slotField: "visorSlot", skinField: "baseSkinName")] public string visorKey = "goggles";
|
||||
|
||||
[Header("Gun")]
|
||||
public Sprite gunSprite;
|
||||
[SpineSlot] public string gunSlot;
|
||||
[SpineAttachment(slotField: "gunSlot", skinField: "baseSkinName")] public string gunKey = "gun";
|
||||
|
||||
[Header("Runtime Repack Required!!")]
|
||||
public bool repack = true;
|
||||
|
||||
[Header("Do not assign")]
|
||||
public Texture2D runtimeAtlas;
|
||||
public Material runtimeMaterial;
|
||||
#endregion
|
||||
|
||||
Skin customSkin;
|
||||
|
||||
void OnValidate () {
|
||||
if (sourceMaterial == null) {
|
||||
SkeletonGraphic skeletonGraphic = GetComponent<SkeletonGraphic>();
|
||||
if (skeletonGraphic != null)
|
||||
sourceMaterial = skeletonGraphic.SkeletonDataAsset.atlasAssets[0].PrimaryMaterial;
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator Start () {
|
||||
yield return new WaitForSeconds(1f); // Delay for 1 second. For testing.
|
||||
Apply();
|
||||
}
|
||||
|
||||
[ContextMenu("Apply")]
|
||||
void Apply () {
|
||||
SkeletonGraphic skeletonGraphic = GetComponent<SkeletonGraphic>();
|
||||
Skeleton skeleton = skeletonGraphic.Skeleton;
|
||||
|
||||
// STEP 0: PREPARE SKINS
|
||||
// Let's prepare a new skin to be our custom skin with equips/customizations. We get a clone so our original skins are unaffected.
|
||||
customSkin = customSkin ?? new Skin("custom skin"); // This requires that all customizations are done with skin placeholders defined in Spine.
|
||||
|
||||
// Next let's get the skin that contains our source attachments. These are the attachments that
|
||||
Skin baseSkin = skeleton.Data.FindSkin(baseSkinName);
|
||||
|
||||
// STEP 1: "EQUIP" ITEMS USING SPRITES
|
||||
// STEP 1.1 Find the original attachment.
|
||||
// Step 1.2 Get a clone of the original attachment.
|
||||
// Step 1.3 Apply the Sprite image to it.
|
||||
// Step 1.4 Add the remapped clone to the new custom skin.
|
||||
|
||||
// Let's do this for the visor.
|
||||
int visorSlotIndex = skeleton.Data.FindSlot(visorSlot).Index; // You can access GetAttachment and SetAttachment via string, but caching the slotIndex is faster.
|
||||
Attachment baseAttachment = baseSkin.GetAttachment(visorSlotIndex, visorKey); // STEP 1.1
|
||||
|
||||
// Note: Each call to `GetRemappedClone()` with parameter `premultiplyAlpha` set to `true` creates
|
||||
// a cached Texture copy which can be cleared by calling AtlasUtilities.ClearCache() as done below.
|
||||
Attachment newAttachment = baseAttachment.GetRemappedClone(visorSprite, sourceMaterial); // STEP 1.2 - 1.3
|
||||
customSkin.SetAttachment(visorSlotIndex, visorKey, newAttachment); // STEP 1.4
|
||||
|
||||
// And now for the gun.
|
||||
int gunSlotIndex = skeleton.Data.FindSlot(gunSlot).Index;
|
||||
Attachment baseGun = baseSkin.GetAttachment(gunSlotIndex, gunKey); // STEP 1.1
|
||||
Attachment newGun = baseGun.GetRemappedClone(gunSprite, sourceMaterial); // STEP 1.2 - 1.3
|
||||
if (newGun != null) customSkin.SetAttachment(gunSlotIndex, gunKey, newGun); // STEP 1.4
|
||||
|
||||
// customSkin.RemoveAttachment(gunSlotIndex, gunKey); // To remove an item.
|
||||
// customSkin.Clear()
|
||||
// Use skin.Clear() To remove all customizations.
|
||||
// Customizations will fall back to the value in the default skin if it was defined there.
|
||||
// To prevent fallback from happening, make sure the key is not defined in the default skin.
|
||||
|
||||
// STEP 3: APPLY AND CLEAN UP.
|
||||
// Recommended: REPACK THE CUSTOM SKIN TO MINIMIZE DRAW CALLS
|
||||
// Repacking requires that you set all source textures/sprites/atlases to be Read/Write enabled in the inspector.
|
||||
// Combine all the attachment sources into one skin. Usually this means the default skin and the custom skin.
|
||||
// call Skin.GetRepackedSkin to get a cloned skin with cloned attachments that all use one texture.
|
||||
if (repack) {
|
||||
Skin repackedSkin = new Skin("repacked skin");
|
||||
repackedSkin.AddSkin(skeleton.Data.DefaultSkin);
|
||||
repackedSkin.AddSkin(customSkin);
|
||||
// Note: materials and textures returned by GetRepackedSkin() behave like 'new Texture2D()' and need to be destroyed
|
||||
if (runtimeMaterial)
|
||||
Destroy(runtimeMaterial);
|
||||
if (runtimeAtlas)
|
||||
Destroy(runtimeAtlas);
|
||||
repackedSkin = repackedSkin.GetRepackedSkin("repacked skin", sourceMaterial, out runtimeMaterial, out runtimeAtlas);
|
||||
skeleton.SetSkin(repackedSkin);
|
||||
} else {
|
||||
skeleton.SetSkin(customSkin);
|
||||
}
|
||||
|
||||
//skeleton.SetSlotsToSetupPose();
|
||||
skeleton.SetToSetupPose();
|
||||
skeletonGraphic.Update(0);
|
||||
skeletonGraphic.OverrideTexture = runtimeAtlas;
|
||||
|
||||
// `GetRepackedSkin()` and each call to `GetRemappedClone()` with parameter `premultiplyAlpha` set to `true`
|
||||
// cache necessarily created Texture copies which can be cleared by calling AtlasUtilities.ClearCache().
|
||||
// You can optionally clear the textures cache after multiple repack operations.
|
||||
// Just be aware that while this cleanup frees up memory, it is also a costly operation
|
||||
// and will likely cause a spike in the framerate.
|
||||
AtlasUtilities.ClearCache();
|
||||
Resources.UnloadUnusedAssets();
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity.AttachmentTools;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
// This is an example script that shows you how to change images on your skeleton using UnityEngine.Sprites.
|
||||
public class MixAndMatchGraphic : MonoBehaviour {
|
||||
|
||||
#region Inspector
|
||||
[SpineSkin]
|
||||
public string baseSkinName = "base";
|
||||
public Material sourceMaterial; // This will be used as the basis for shader and material property settings.
|
||||
|
||||
[Header("Visor")]
|
||||
public Sprite visorSprite;
|
||||
[SpineSlot] public string visorSlot;
|
||||
[SpineAttachment(slotField: "visorSlot", skinField: "baseSkinName")] public string visorKey = "goggles";
|
||||
|
||||
[Header("Gun")]
|
||||
public Sprite gunSprite;
|
||||
[SpineSlot] public string gunSlot;
|
||||
[SpineAttachment(slotField: "gunSlot", skinField: "baseSkinName")] public string gunKey = "gun";
|
||||
|
||||
[Header("Runtime Repack Required!!")]
|
||||
public bool repack = true;
|
||||
|
||||
[Header("Do not assign")]
|
||||
public Texture2D runtimeAtlas;
|
||||
public Material runtimeMaterial;
|
||||
#endregion
|
||||
|
||||
Skin customSkin;
|
||||
|
||||
void OnValidate () {
|
||||
if (sourceMaterial == null) {
|
||||
SkeletonGraphic skeletonGraphic = GetComponent<SkeletonGraphic>();
|
||||
if (skeletonGraphic != null)
|
||||
sourceMaterial = skeletonGraphic.SkeletonDataAsset.atlasAssets[0].PrimaryMaterial;
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator Start () {
|
||||
yield return new WaitForSeconds(1f); // Delay for 1 second. For testing.
|
||||
Apply();
|
||||
}
|
||||
|
||||
[ContextMenu("Apply")]
|
||||
void Apply () {
|
||||
SkeletonGraphic skeletonGraphic = GetComponent<SkeletonGraphic>();
|
||||
Skeleton skeleton = skeletonGraphic.Skeleton;
|
||||
|
||||
// STEP 0: PREPARE SKINS
|
||||
// Let's prepare a new skin to be our custom skin with equips/customizations. We get a clone so our original skins are unaffected.
|
||||
customSkin = customSkin ?? new Skin("custom skin"); // This requires that all customizations are done with skin placeholders defined in Spine.
|
||||
|
||||
// Next let's get the skin that contains our source attachments. These are the attachments that
|
||||
Skin baseSkin = skeleton.Data.FindSkin(baseSkinName);
|
||||
|
||||
// STEP 1: "EQUIP" ITEMS USING SPRITES
|
||||
// STEP 1.1 Find the original attachment.
|
||||
// Step 1.2 Get a clone of the original attachment.
|
||||
// Step 1.3 Apply the Sprite image to it.
|
||||
// Step 1.4 Add the remapped clone to the new custom skin.
|
||||
|
||||
// Let's do this for the visor.
|
||||
int visorSlotIndex = skeleton.Data.FindSlot(visorSlot).Index; // You can access GetAttachment and SetAttachment via string, but caching the slotIndex is faster.
|
||||
Attachment baseAttachment = baseSkin.GetAttachment(visorSlotIndex, visorKey); // STEP 1.1
|
||||
|
||||
// Note: Each call to `GetRemappedClone()` with parameter `premultiplyAlpha` set to `true` creates
|
||||
// a cached Texture copy which can be cleared by calling AtlasUtilities.ClearCache() as done below.
|
||||
Attachment newAttachment = baseAttachment.GetRemappedClone(visorSprite, sourceMaterial); // STEP 1.2 - 1.3
|
||||
customSkin.SetAttachment(visorSlotIndex, visorKey, newAttachment); // STEP 1.4
|
||||
|
||||
// And now for the gun.
|
||||
int gunSlotIndex = skeleton.Data.FindSlot(gunSlot).Index;
|
||||
Attachment baseGun = baseSkin.GetAttachment(gunSlotIndex, gunKey); // STEP 1.1
|
||||
Attachment newGun = baseGun.GetRemappedClone(gunSprite, sourceMaterial); // STEP 1.2 - 1.3
|
||||
if (newGun != null) customSkin.SetAttachment(gunSlotIndex, gunKey, newGun); // STEP 1.4
|
||||
|
||||
// customSkin.RemoveAttachment(gunSlotIndex, gunKey); // To remove an item.
|
||||
// customSkin.Clear()
|
||||
// Use skin.Clear() To remove all customizations.
|
||||
// Customizations will fall back to the value in the default skin if it was defined there.
|
||||
// To prevent fallback from happening, make sure the key is not defined in the default skin.
|
||||
|
||||
// STEP 3: APPLY AND CLEAN UP.
|
||||
// Recommended: REPACK THE CUSTOM SKIN TO MINIMIZE DRAW CALLS
|
||||
// Repacking requires that you set all source textures/sprites/atlases to be Read/Write enabled in the inspector.
|
||||
// Combine all the attachment sources into one skin. Usually this means the default skin and the custom skin.
|
||||
// call Skin.GetRepackedSkin to get a cloned skin with cloned attachments that all use one texture.
|
||||
if (repack) {
|
||||
Skin repackedSkin = new Skin("repacked skin");
|
||||
repackedSkin.AddSkin(skeleton.Data.DefaultSkin);
|
||||
repackedSkin.AddSkin(customSkin);
|
||||
// Note: materials and textures returned by GetRepackedSkin() behave like 'new Texture2D()' and need to be destroyed
|
||||
if (runtimeMaterial)
|
||||
Destroy(runtimeMaterial);
|
||||
if (runtimeAtlas)
|
||||
Destroy(runtimeAtlas);
|
||||
repackedSkin = repackedSkin.GetRepackedSkin("repacked skin", sourceMaterial, out runtimeMaterial, out runtimeAtlas);
|
||||
skeleton.SetSkin(repackedSkin);
|
||||
} else {
|
||||
skeleton.SetSkin(customSkin);
|
||||
}
|
||||
|
||||
//skeleton.SetSlotsToSetupPose();
|
||||
skeleton.SetToSetupPose();
|
||||
skeletonGraphic.Update(0);
|
||||
skeletonGraphic.OverrideTexture = runtimeAtlas;
|
||||
|
||||
// `GetRepackedSkin()` and each call to `GetRemappedClone()` with parameter `premultiplyAlpha` set to `true`
|
||||
// cache necessarily created Texture copies which can be cleared by calling AtlasUtilities.ClearCache().
|
||||
// You can optionally clear the textures cache after multiple repack operations.
|
||||
// Just be aware that while this cleanup frees up memory, it is also a costly operation
|
||||
// and will likely cause a spike in the framerate.
|
||||
AtlasUtilities.ClearCache();
|
||||
Resources.UnloadUnusedAssets();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,102 +1,102 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class RaggedySpineboy : MonoBehaviour {
|
||||
|
||||
public LayerMask groundMask;
|
||||
public float restoreDuration = 0.5f;
|
||||
public Vector2 launchVelocity = new Vector2(50, 100);
|
||||
|
||||
Spine.Unity.Examples.SkeletonRagdoll2D ragdoll;
|
||||
Collider2D naturalCollider;
|
||||
|
||||
void Start () {
|
||||
ragdoll = GetComponent<Spine.Unity.Examples.SkeletonRagdoll2D>();
|
||||
naturalCollider = GetComponent<Collider2D>();
|
||||
}
|
||||
|
||||
void AddRigidbody () {
|
||||
Rigidbody2D rb = gameObject.AddComponent<Rigidbody2D>();
|
||||
rb.freezeRotation = true;
|
||||
naturalCollider.enabled = true;
|
||||
}
|
||||
|
||||
void RemoveRigidbody () {
|
||||
Destroy(GetComponent<Rigidbody2D>());
|
||||
naturalCollider.enabled = false;
|
||||
}
|
||||
|
||||
void OnMouseUp () {
|
||||
if (naturalCollider.enabled)
|
||||
Launch();
|
||||
}
|
||||
|
||||
void Launch () {
|
||||
RemoveRigidbody();
|
||||
ragdoll.Apply();
|
||||
ragdoll.RootRigidbody.velocity = new Vector2(Random.Range(-launchVelocity.x, launchVelocity.x), launchVelocity.y);
|
||||
StartCoroutine(WaitUntilStopped());
|
||||
}
|
||||
|
||||
IEnumerator Restore () {
|
||||
Vector3 estimatedPos = ragdoll.EstimatedSkeletonPosition;
|
||||
Vector3 rbPosition = ragdoll.RootRigidbody.position;
|
||||
|
||||
Vector3 skeletonPoint = estimatedPos;
|
||||
RaycastHit2D hit = Physics2D.Raycast((Vector2)rbPosition, (Vector2)(estimatedPos - rbPosition), Vector3.Distance(estimatedPos, rbPosition), groundMask);
|
||||
if (hit.collider != null)
|
||||
skeletonPoint = hit.point;
|
||||
|
||||
ragdoll.RootRigidbody.isKinematic = true;
|
||||
ragdoll.SetSkeletonPosition(skeletonPoint);
|
||||
|
||||
yield return ragdoll.SmoothMix(0, restoreDuration);
|
||||
ragdoll.Remove();
|
||||
|
||||
AddRigidbody();
|
||||
}
|
||||
|
||||
IEnumerator WaitUntilStopped () {
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
|
||||
float t = 0;
|
||||
while (t < 0.5f) {
|
||||
t = (ragdoll.RootRigidbody.velocity.magnitude > 0.09f) ? 0 : t + Time.deltaTime;
|
||||
yield return null;
|
||||
}
|
||||
|
||||
StartCoroutine(Restore());
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class RaggedySpineboy : MonoBehaviour {
|
||||
|
||||
public LayerMask groundMask;
|
||||
public float restoreDuration = 0.5f;
|
||||
public Vector2 launchVelocity = new Vector2(50, 100);
|
||||
|
||||
Spine.Unity.Examples.SkeletonRagdoll2D ragdoll;
|
||||
Collider2D naturalCollider;
|
||||
|
||||
void Start () {
|
||||
ragdoll = GetComponent<Spine.Unity.Examples.SkeletonRagdoll2D>();
|
||||
naturalCollider = GetComponent<Collider2D>();
|
||||
}
|
||||
|
||||
void AddRigidbody () {
|
||||
Rigidbody2D rb = gameObject.AddComponent<Rigidbody2D>();
|
||||
rb.freezeRotation = true;
|
||||
naturalCollider.enabled = true;
|
||||
}
|
||||
|
||||
void RemoveRigidbody () {
|
||||
Destroy(GetComponent<Rigidbody2D>());
|
||||
naturalCollider.enabled = false;
|
||||
}
|
||||
|
||||
void OnMouseUp () {
|
||||
if (naturalCollider.enabled)
|
||||
Launch();
|
||||
}
|
||||
|
||||
void Launch () {
|
||||
RemoveRigidbody();
|
||||
ragdoll.Apply();
|
||||
ragdoll.RootRigidbody.velocity = new Vector2(Random.Range(-launchVelocity.x, launchVelocity.x), launchVelocity.y);
|
||||
StartCoroutine(WaitUntilStopped());
|
||||
}
|
||||
|
||||
IEnumerator Restore () {
|
||||
Vector3 estimatedPos = ragdoll.EstimatedSkeletonPosition;
|
||||
Vector3 rbPosition = ragdoll.RootRigidbody.position;
|
||||
|
||||
Vector3 skeletonPoint = estimatedPos;
|
||||
RaycastHit2D hit = Physics2D.Raycast((Vector2)rbPosition, (Vector2)(estimatedPos - rbPosition), Vector3.Distance(estimatedPos, rbPosition), groundMask);
|
||||
if (hit.collider != null)
|
||||
skeletonPoint = hit.point;
|
||||
|
||||
ragdoll.RootRigidbody.isKinematic = true;
|
||||
ragdoll.SetSkeletonPosition(skeletonPoint);
|
||||
|
||||
yield return ragdoll.SmoothMix(0, restoreDuration);
|
||||
ragdoll.Remove();
|
||||
|
||||
AddRigidbody();
|
||||
}
|
||||
|
||||
IEnumerator WaitUntilStopped () {
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
|
||||
float t = 0;
|
||||
while (t < 0.5f) {
|
||||
t = (ragdoll.RootRigidbody.velocity.magnitude > 0.09f) ? 0 : t + Time.deltaTime;
|
||||
yield return null;
|
||||
}
|
||||
|
||||
StartCoroutine(Restore());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,44 +1,44 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
public class ReloadSceneOnKeyDown : MonoBehaviour {
|
||||
|
||||
public KeyCode reloadKey = KeyCode.R;
|
||||
|
||||
void Update () {
|
||||
if (Input.GetKeyDown(reloadKey))
|
||||
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex, LoadSceneMode.Single);
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
public class ReloadSceneOnKeyDown : MonoBehaviour {
|
||||
|
||||
public KeyCode reloadKey = KeyCode.R;
|
||||
|
||||
void Update () {
|
||||
if (Input.GetKeyDown(reloadKey))
|
||||
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex, LoadSceneMode.Single);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,92 +1,92 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2022, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
#define HAS_VECTOR_INT
|
||||
#endif
|
||||
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class RenderTextureFadeoutExample : MonoBehaviour {
|
||||
|
||||
public SkeletonRenderTextureFadeout renderTextureFadeout;
|
||||
public SkeletonRenderTextureFadeout renderTextureFadeoutCanvas;
|
||||
public SkeletonRenderer normalSkeletonRenderer;
|
||||
|
||||
float fadeoutSeconds = 2.0f;
|
||||
float fadeoutSecondsRemaining;
|
||||
|
||||
IEnumerator Start () {
|
||||
while (true) {
|
||||
StartFadeoutBad();
|
||||
StartFadeoutGood(renderTextureFadeout);
|
||||
StartFadeoutGood(renderTextureFadeoutCanvas);
|
||||
yield return new WaitForSeconds(fadeoutSeconds + 1.0f);
|
||||
}
|
||||
}
|
||||
void Update () {
|
||||
UpdateBadFadeOutAlpha();
|
||||
}
|
||||
|
||||
void UpdateBadFadeOutAlpha () {
|
||||
if (fadeoutSecondsRemaining == 0)
|
||||
return;
|
||||
|
||||
fadeoutSecondsRemaining -= Time.deltaTime;
|
||||
if (fadeoutSecondsRemaining <= 0) {
|
||||
fadeoutSecondsRemaining = 0;
|
||||
return;
|
||||
}
|
||||
float fadeoutAlpha = fadeoutSecondsRemaining / fadeoutSeconds;
|
||||
|
||||
// changing transparency at a MeshRenderer does not yield the desired effect
|
||||
// due to overlapping attachment meshes.
|
||||
normalSkeletonRenderer.Skeleton.SetColor(new Color(1, 1, 1, fadeoutAlpha));
|
||||
}
|
||||
|
||||
void StartFadeoutBad () {
|
||||
fadeoutSecondsRemaining = fadeoutSeconds;
|
||||
}
|
||||
|
||||
void StartFadeoutGood (SkeletonRenderTextureFadeout fadeoutComponent) {
|
||||
fadeoutComponent.gameObject.SetActive(true);
|
||||
// enabling the SkeletonRenderTextureFadeout component starts the fadeout.
|
||||
fadeoutComponent.enabled = true;
|
||||
fadeoutComponent.OnFadeoutComplete -= DisableGameObject;
|
||||
fadeoutComponent.OnFadeoutComplete += DisableGameObject;
|
||||
}
|
||||
|
||||
void DisableGameObject (SkeletonRenderTextureFadeout target) {
|
||||
target.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
#define HAS_VECTOR_INT
|
||||
#endif
|
||||
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class RenderTextureFadeoutExample : MonoBehaviour {
|
||||
|
||||
public SkeletonRenderTextureFadeout renderTextureFadeout;
|
||||
public SkeletonRenderTextureFadeout renderTextureFadeoutCanvas;
|
||||
public SkeletonRenderer normalSkeletonRenderer;
|
||||
|
||||
float fadeoutSeconds = 2.0f;
|
||||
float fadeoutSecondsRemaining;
|
||||
|
||||
IEnumerator Start () {
|
||||
while (true) {
|
||||
StartFadeoutBad();
|
||||
StartFadeoutGood(renderTextureFadeout);
|
||||
StartFadeoutGood(renderTextureFadeoutCanvas);
|
||||
yield return new WaitForSeconds(fadeoutSeconds + 1.0f);
|
||||
}
|
||||
}
|
||||
void Update () {
|
||||
UpdateBadFadeOutAlpha();
|
||||
}
|
||||
|
||||
void UpdateBadFadeOutAlpha () {
|
||||
if (fadeoutSecondsRemaining == 0)
|
||||
return;
|
||||
|
||||
fadeoutSecondsRemaining -= Time.deltaTime;
|
||||
if (fadeoutSecondsRemaining <= 0) {
|
||||
fadeoutSecondsRemaining = 0;
|
||||
return;
|
||||
}
|
||||
float fadeoutAlpha = fadeoutSecondsRemaining / fadeoutSeconds;
|
||||
|
||||
// changing transparency at a MeshRenderer does not yield the desired effect
|
||||
// due to overlapping attachment meshes.
|
||||
normalSkeletonRenderer.Skeleton.SetColor(new Color(1, 1, 1, fadeoutAlpha));
|
||||
}
|
||||
|
||||
void StartFadeoutBad () {
|
||||
fadeoutSecondsRemaining = fadeoutSeconds;
|
||||
}
|
||||
|
||||
void StartFadeoutGood (SkeletonRenderTextureFadeout fadeoutComponent) {
|
||||
fadeoutComponent.gameObject.SetActive(true);
|
||||
// enabling the SkeletonRenderTextureFadeout component starts the fadeout.
|
||||
fadeoutComponent.enabled = true;
|
||||
fadeoutComponent.OnFadeoutComplete -= DisableGameObject;
|
||||
fadeoutComponent.OnFadeoutComplete += DisableGameObject;
|
||||
}
|
||||
|
||||
void DisableGameObject (SkeletonRenderTextureFadeout target) {
|
||||
target.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,41 +1,41 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class Rotator : MonoBehaviour {
|
||||
public Vector3 direction = new Vector3(0, 0, 1f);
|
||||
public float speed = 1f;
|
||||
|
||||
void Update () {
|
||||
transform.Rotate(direction * (speed * Time.deltaTime * 100f));
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class Rotator : MonoBehaviour {
|
||||
public Vector3 direction = new Vector3(0, 0, 1f);
|
||||
public float speed = 1f;
|
||||
|
||||
void Update () {
|
||||
transform.Rotate(direction * (speed * Time.deltaTime * 100f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,77 +1,120 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class RuntimeLoadFromExportsExample : MonoBehaviour {
|
||||
|
||||
public TextAsset skeletonJson;
|
||||
public TextAsset atlasText;
|
||||
public Texture2D[] textures;
|
||||
public Material materialPropertySource;
|
||||
|
||||
public float delay = 0;
|
||||
public string skinName;
|
||||
public string animationName;
|
||||
|
||||
SpineAtlasAsset runtimeAtlasAsset;
|
||||
SkeletonDataAsset runtimeSkeletonDataAsset;
|
||||
SkeletonAnimation runtimeSkeletonAnimation;
|
||||
|
||||
void CreateRuntimeAssetsAndGameObject () {
|
||||
// 1. Create the AtlasAsset (needs atlas text asset and textures, and materials/shader);
|
||||
// 2. Create SkeletonDataAsset (needs json or binary asset file, and an AtlasAsset)
|
||||
// 3. Create SkeletonAnimation (needs a valid SkeletonDataAsset)
|
||||
|
||||
runtimeAtlasAsset = SpineAtlasAsset.CreateRuntimeInstance(atlasText, textures, materialPropertySource, true);
|
||||
runtimeSkeletonDataAsset = SkeletonDataAsset.CreateRuntimeInstance(skeletonJson, runtimeAtlasAsset, true);
|
||||
}
|
||||
|
||||
IEnumerator Start () {
|
||||
CreateRuntimeAssetsAndGameObject();
|
||||
if (delay > 0) {
|
||||
runtimeSkeletonDataAsset.GetSkeletonData(false); // preload
|
||||
yield return new WaitForSeconds(delay);
|
||||
}
|
||||
runtimeSkeletonAnimation = SkeletonAnimation.NewSkeletonAnimationGameObject(runtimeSkeletonDataAsset);
|
||||
|
||||
// additional initialization
|
||||
runtimeSkeletonAnimation.Initialize(false);
|
||||
if (skinName != "")
|
||||
runtimeSkeletonAnimation.Skeleton.SetSkin(skinName);
|
||||
runtimeSkeletonAnimation.Skeleton.SetSlotsToSetupPose();
|
||||
if (animationName != "")
|
||||
runtimeSkeletonAnimation.AnimationState.SetAnimation(0, animationName, true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class RuntimeLoadFromExportsExample : MonoBehaviour {
|
||||
|
||||
public TextAsset skeletonJson;
|
||||
public TextAsset atlasText;
|
||||
public Texture2D[] textures;
|
||||
public Material materialPropertySource;
|
||||
|
||||
public float delay = 0;
|
||||
public string skinName;
|
||||
public string animationName;
|
||||
|
||||
SpineAtlasAsset runtimeAtlasAsset;
|
||||
SkeletonDataAsset runtimeSkeletonDataAsset;
|
||||
SkeletonAnimation runtimeSkeletonAnimation;
|
||||
SkeletonGraphic runtimeSkeletonGraphic;
|
||||
|
||||
public bool blendModeMaterials = false;
|
||||
public bool applyAdditiveMaterial = false;
|
||||
public BlendModeMaterials.TemplateMaterials blendModeTemplateMaterials;
|
||||
public BlendModeMaterials.TemplateMaterials graphicBlendModeMaterials;
|
||||
public Material skeletonGraphicMaterial;
|
||||
|
||||
void CreateRuntimeAssetsAndGameObject () {
|
||||
// 1. Create the AtlasAsset (needs atlas text asset and textures, and materials/shader);
|
||||
// 2. Create SkeletonDataAsset (needs json or binary asset file, and an AtlasAsset)
|
||||
// 2.1 Optional: Setup blend mode materials at SkeletonDataAsset. Only required if the skeleton
|
||||
// uses blend modes which require blend mode materials.
|
||||
// 3.a Create SkeletonAnimation (needs a valid SkeletonDataAsset)
|
||||
// 3.b Create SkeletonGraphic (needs a valid SkeletonDataAsset)
|
||||
|
||||
runtimeAtlasAsset = SpineAtlasAsset.CreateRuntimeInstance(atlasText, textures, materialPropertySource, true, null, true);
|
||||
runtimeSkeletonDataAsset = SkeletonDataAsset.CreateRuntimeInstance(skeletonJson, runtimeAtlasAsset, true);
|
||||
if (blendModeMaterials)
|
||||
runtimeSkeletonDataAsset.SetupRuntimeBlendModeMaterials(
|
||||
applyAdditiveMaterial, blendModeTemplateMaterials);
|
||||
}
|
||||
|
||||
IEnumerator Start () {
|
||||
CreateRuntimeAssetsAndGameObject();
|
||||
if (delay > 0) {
|
||||
runtimeSkeletonDataAsset.GetSkeletonData(false); // preload
|
||||
yield return new WaitForSeconds(delay);
|
||||
}
|
||||
InstantiateSkeletonAnimation();
|
||||
|
||||
InstantiateSkeletonGraphic();
|
||||
}
|
||||
|
||||
void InstantiateSkeletonAnimation () {
|
||||
runtimeSkeletonAnimation = SkeletonAnimation.NewSkeletonAnimationGameObject(runtimeSkeletonDataAsset);
|
||||
runtimeSkeletonAnimation.transform.parent = transform;
|
||||
runtimeSkeletonAnimation.name = "SkeletonAnimation Instance";
|
||||
|
||||
// additional initialization
|
||||
runtimeSkeletonAnimation.Initialize(false);
|
||||
if (skinName != "")
|
||||
runtimeSkeletonAnimation.Skeleton.SetSkin(skinName);
|
||||
runtimeSkeletonAnimation.Skeleton.SetSlotsToSetupPose();
|
||||
if (animationName != "")
|
||||
runtimeSkeletonAnimation.AnimationState.SetAnimation(0, animationName, true);
|
||||
}
|
||||
|
||||
void InstantiateSkeletonGraphic () {
|
||||
Canvas canvas = this.GetComponentInChildren<Canvas>();
|
||||
Transform parent = canvas.transform;
|
||||
|
||||
runtimeSkeletonGraphic = SkeletonGraphic.NewSkeletonGraphicGameObject(runtimeSkeletonDataAsset, parent, skeletonGraphicMaterial);
|
||||
runtimeSkeletonGraphic.name = "SkeletonGraphic Instance";
|
||||
|
||||
if (blendModeMaterials) {
|
||||
runtimeSkeletonGraphic.allowMultipleCanvasRenderers = true;
|
||||
runtimeSkeletonGraphic.additiveMaterial = graphicBlendModeMaterials.additiveTemplate;
|
||||
runtimeSkeletonGraphic.multiplyMaterial = graphicBlendModeMaterials.multiplyTemplate;
|
||||
runtimeSkeletonGraphic.screenMaterial = graphicBlendModeMaterials.screenTemplate;
|
||||
}
|
||||
|
||||
// additional initialization
|
||||
runtimeSkeletonGraphic.Initialize(false);
|
||||
if (skinName != "")
|
||||
runtimeSkeletonGraphic.Skeleton.SetSkin(skinName);
|
||||
runtimeSkeletonGraphic.Skeleton.SetSlotsToSetupPose();
|
||||
if (animationName != "")
|
||||
runtimeSkeletonGraphic.AnimationState.SetAnimation(0, animationName, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,91 +1,91 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine;
|
||||
using Spine.Unity;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class BoneLocalOverride : MonoBehaviour {
|
||||
[SpineBone]
|
||||
public string boneName;
|
||||
|
||||
[Space]
|
||||
[Range(0, 1)] public float alpha = 1;
|
||||
|
||||
[Space]
|
||||
public bool overridePosition = true;
|
||||
public Vector2 localPosition;
|
||||
|
||||
[Space]
|
||||
public bool overrideRotation = true;
|
||||
[Range(0, 360)] public float rotation = 0;
|
||||
|
||||
ISkeletonAnimation spineComponent;
|
||||
Bone bone;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
void OnValidate () {
|
||||
if (Application.isPlaying) return;
|
||||
if (spineComponent == null) spineComponent = GetComponent<ISkeletonAnimation>();
|
||||
if (spineComponent.IsNullOrDestroyed()) return;
|
||||
if (bone != null) bone.SetToSetupPose();
|
||||
OverrideLocal(spineComponent);
|
||||
}
|
||||
#endif
|
||||
|
||||
void Awake () {
|
||||
spineComponent = GetComponent<ISkeletonAnimation>();
|
||||
if (spineComponent == null) { this.enabled = false; return; }
|
||||
spineComponent.UpdateLocal += OverrideLocal;
|
||||
|
||||
if (bone == null) { this.enabled = false; return; }
|
||||
}
|
||||
|
||||
void OverrideLocal (ISkeletonAnimation animated) {
|
||||
if (bone == null || bone.Data.Name != boneName) {
|
||||
if (string.IsNullOrEmpty(boneName)) return;
|
||||
bone = spineComponent.Skeleton.FindBone(boneName);
|
||||
if (bone == null) {
|
||||
Debug.LogFormat("Cannot find bone: '{0}'", boneName);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (overridePosition) {
|
||||
bone.X = Mathf.Lerp(bone.X, localPosition.x, alpha);
|
||||
bone.Y = Mathf.Lerp(bone.Y, localPosition.y, alpha);
|
||||
}
|
||||
|
||||
if (overrideRotation)
|
||||
bone.Rotation = Mathf.Lerp(bone.Rotation, rotation, alpha);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine;
|
||||
using Spine.Unity;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class BoneLocalOverride : MonoBehaviour {
|
||||
[SpineBone]
|
||||
public string boneName;
|
||||
|
||||
[Space]
|
||||
[Range(0, 1)] public float alpha = 1;
|
||||
|
||||
[Space]
|
||||
public bool overridePosition = true;
|
||||
public Vector2 localPosition;
|
||||
|
||||
[Space]
|
||||
public bool overrideRotation = true;
|
||||
[Range(0, 360)] public float rotation = 0;
|
||||
|
||||
ISkeletonAnimation spineComponent;
|
||||
Bone bone;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
void OnValidate () {
|
||||
if (Application.isPlaying) return;
|
||||
if (spineComponent == null) spineComponent = GetComponent<ISkeletonAnimation>();
|
||||
if (spineComponent.IsNullOrDestroyed()) return;
|
||||
if (bone != null) bone.SetToSetupPose();
|
||||
OverrideLocal(spineComponent);
|
||||
}
|
||||
#endif
|
||||
|
||||
void Awake () {
|
||||
spineComponent = GetComponent<ISkeletonAnimation>();
|
||||
if (spineComponent == null) { this.enabled = false; return; }
|
||||
spineComponent.UpdateLocal += OverrideLocal;
|
||||
|
||||
if (bone == null) { this.enabled = false; return; }
|
||||
}
|
||||
|
||||
void OverrideLocal (ISkeletonAnimation animated) {
|
||||
if (bone == null || bone.Data.Name != boneName) {
|
||||
if (string.IsNullOrEmpty(boneName)) return;
|
||||
bone = spineComponent.Skeleton.FindBone(boneName);
|
||||
if (bone == null) {
|
||||
Debug.LogFormat("Cannot find bone: '{0}'", boneName);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (overridePosition) {
|
||||
bone.X = Mathf.Lerp(bone.X, localPosition.x, alpha);
|
||||
bone.Y = Mathf.Lerp(bone.Y, localPosition.y, alpha);
|
||||
}
|
||||
|
||||
if (overrideRotation)
|
||||
bone.Rotation = Mathf.Lerp(bone.Rotation, rotation, alpha);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,62 +1,62 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity.AttachmentTools;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class CombinedSkin : MonoBehaviour {
|
||||
[SpineSkin]
|
||||
public List<string> skinsToCombine;
|
||||
|
||||
Skin combinedSkin;
|
||||
|
||||
void Start () {
|
||||
ISkeletonComponent skeletonComponent = GetComponent<ISkeletonComponent>();
|
||||
if (skeletonComponent == null) return;
|
||||
Skeleton skeleton = skeletonComponent.Skeleton;
|
||||
if (skeleton == null) return;
|
||||
|
||||
combinedSkin = combinedSkin ?? new Skin("combined");
|
||||
combinedSkin.Clear();
|
||||
foreach (string skinName in skinsToCombine) {
|
||||
Skin skin = skeleton.Data.FindSkin(skinName);
|
||||
if (skin != null) combinedSkin.AddSkin(skin);
|
||||
}
|
||||
|
||||
skeleton.SetSkin(combinedSkin);
|
||||
skeleton.SetToSetupPose();
|
||||
IAnimationStateComponent animationStateComponent = skeletonComponent as IAnimationStateComponent;
|
||||
if (animationStateComponent != null) animationStateComponent.AnimationState.Apply(skeleton);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity.AttachmentTools;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class CombinedSkin : MonoBehaviour {
|
||||
[SpineSkin]
|
||||
public List<string> skinsToCombine;
|
||||
|
||||
Skin combinedSkin;
|
||||
|
||||
void Start () {
|
||||
ISkeletonComponent skeletonComponent = GetComponent<ISkeletonComponent>();
|
||||
if (skeletonComponent == null) return;
|
||||
Skeleton skeleton = skeletonComponent.Skeleton;
|
||||
if (skeleton == null) return;
|
||||
|
||||
combinedSkin = combinedSkin ?? new Skin("combined");
|
||||
combinedSkin.Clear();
|
||||
foreach (string skinName in skinsToCombine) {
|
||||
Skin skin = skeleton.Data.FindSkin(skinName);
|
||||
if (skin != null) combinedSkin.AddSkin(skin);
|
||||
}
|
||||
|
||||
skeleton.SetSkin(combinedSkin);
|
||||
skeleton.SetToSetupPose();
|
||||
IAnimationStateComponent animationStateComponent = skeletonComponent as IAnimationStateComponent;
|
||||
if (animationStateComponent != null) animationStateComponent.AnimationState.Apply(skeleton);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,201 +1,201 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
// Contributed by: Mitch Thompson
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
[RequireComponent(typeof(SkeletonRenderer))]
|
||||
public class SkeletonGhost : MonoBehaviour {
|
||||
// Internal Settings
|
||||
const HideFlags GhostHideFlags = HideFlags.HideInHierarchy;
|
||||
const string GhostingShaderName = "Spine/Special/SkeletonGhost";
|
||||
|
||||
[Header("Animation")]
|
||||
public bool ghostingEnabled = true;
|
||||
[Tooltip("The time between invididual ghost pieces being spawned.")]
|
||||
[UnityEngine.Serialization.FormerlySerializedAs("spawnRate")]
|
||||
public float spawnInterval = 1f / 30f;
|
||||
[Tooltip("Maximum number of ghosts that can exist at a time. If the fade speed is not fast enough, the oldest ghost will immediately disappear to enforce the maximum number.")]
|
||||
public int maximumGhosts = 10;
|
||||
public float fadeSpeed = 10;
|
||||
|
||||
[Header("Rendering")]
|
||||
public Shader ghostShader;
|
||||
public Color32 color = new Color32(0xFF, 0xFF, 0xFF, 0x00); // default for additive.
|
||||
[Tooltip("Remember to set color alpha to 0 if Additive is true")]
|
||||
public bool additive = true;
|
||||
[Tooltip("0 is Color and Alpha, 1 is Alpha only.")]
|
||||
[Range(0, 1)]
|
||||
public float textureFade = 1;
|
||||
|
||||
[Header("Sorting")]
|
||||
public bool sortWithDistanceOnly;
|
||||
public float zOffset = 0f;
|
||||
|
||||
float nextSpawnTime;
|
||||
SkeletonGhostRenderer[] pool;
|
||||
int poolIndex = 0;
|
||||
SkeletonRenderer skeletonRenderer;
|
||||
MeshRenderer meshRenderer;
|
||||
MeshFilter meshFilter;
|
||||
|
||||
readonly Dictionary<Material, Material> materialTable = new Dictionary<Material, Material>();
|
||||
|
||||
void Start () {
|
||||
Initialize(false);
|
||||
}
|
||||
|
||||
public void Initialize (bool overwrite) {
|
||||
if (pool == null || overwrite) {
|
||||
if (ghostShader == null)
|
||||
ghostShader = Shader.Find(GhostingShaderName);
|
||||
|
||||
skeletonRenderer = GetComponent<SkeletonRenderer>();
|
||||
meshFilter = GetComponent<MeshFilter>();
|
||||
meshRenderer = GetComponent<MeshRenderer>();
|
||||
nextSpawnTime = Time.time + spawnInterval;
|
||||
pool = new SkeletonGhostRenderer[maximumGhosts];
|
||||
for (int i = 0; i < maximumGhosts; i++) {
|
||||
GameObject go = new GameObject(gameObject.name + " Ghost", typeof(SkeletonGhostRenderer));
|
||||
pool[i] = go.GetComponent<SkeletonGhostRenderer>();
|
||||
go.SetActive(false);
|
||||
go.hideFlags = GhostHideFlags;
|
||||
}
|
||||
|
||||
IAnimationStateComponent skeletonAnimation = skeletonRenderer as Spine.Unity.IAnimationStateComponent;
|
||||
if (skeletonAnimation != null)
|
||||
skeletonAnimation.AnimationState.Event += OnEvent;
|
||||
}
|
||||
}
|
||||
|
||||
//SkeletonAnimation
|
||||
/*
|
||||
* Int Value: 0 sets ghostingEnabled to false, 1 sets ghostingEnabled to true
|
||||
* Float Value: Values greater than 0 set the spawnRate equal the float value
|
||||
* String Value: Pass RGBA hex color values in to set the color property. IE: "A0FF8BFF"
|
||||
*/
|
||||
void OnEvent (Spine.TrackEntry trackEntry, Spine.Event e) {
|
||||
if (e.Data.Name.Equals("Ghosting", System.StringComparison.Ordinal)) {
|
||||
ghostingEnabled = e.Int > 0;
|
||||
if (e.Float > 0)
|
||||
spawnInterval = e.Float;
|
||||
|
||||
if (!string.IsNullOrEmpty(e.String))
|
||||
this.color = HexToColor(e.String);
|
||||
}
|
||||
}
|
||||
|
||||
//SkeletonAnimator
|
||||
//SkeletonAnimator or Mecanim based animations only support toggling ghostingEnabled. Be sure not to set anything other than the Int param in Spine or String will take priority.
|
||||
void Ghosting (float val) {
|
||||
ghostingEnabled = val > 0;
|
||||
}
|
||||
|
||||
void Update () {
|
||||
if (!ghostingEnabled || poolIndex >= pool.Length)
|
||||
return;
|
||||
|
||||
if (Time.time >= nextSpawnTime) {
|
||||
GameObject go = pool[poolIndex].gameObject;
|
||||
|
||||
Material[] materials = meshRenderer.sharedMaterials;
|
||||
for (int i = 0; i < materials.Length; i++) {
|
||||
Material originalMat = materials[i];
|
||||
Material ghostMat;
|
||||
if (!materialTable.ContainsKey(originalMat)) {
|
||||
ghostMat = new Material(originalMat) {
|
||||
shader = ghostShader,
|
||||
color = Color.white
|
||||
};
|
||||
|
||||
if (ghostMat.HasProperty("_TextureFade"))
|
||||
ghostMat.SetFloat("_TextureFade", textureFade);
|
||||
|
||||
materialTable.Add(originalMat, ghostMat);
|
||||
} else {
|
||||
ghostMat = materialTable[originalMat];
|
||||
}
|
||||
|
||||
materials[i] = ghostMat;
|
||||
}
|
||||
|
||||
Transform goTransform = go.transform;
|
||||
goTransform.parent = transform;
|
||||
|
||||
pool[poolIndex].Initialize(meshFilter.sharedMesh, materials, color, additive, fadeSpeed, meshRenderer.sortingLayerID, (sortWithDistanceOnly) ? meshRenderer.sortingOrder : meshRenderer.sortingOrder - 1);
|
||||
|
||||
goTransform.localPosition = new Vector3(0f, 0f, zOffset);
|
||||
goTransform.localRotation = Quaternion.identity;
|
||||
goTransform.localScale = Vector3.one;
|
||||
|
||||
goTransform.parent = null;
|
||||
|
||||
poolIndex++;
|
||||
|
||||
if (poolIndex == pool.Length)
|
||||
poolIndex = 0;
|
||||
|
||||
nextSpawnTime = Time.time + spawnInterval;
|
||||
}
|
||||
}
|
||||
|
||||
void OnDestroy () {
|
||||
if (pool != null) {
|
||||
for (int i = 0; i < maximumGhosts; i++)
|
||||
if (pool[i] != null) pool[i].Cleanup();
|
||||
}
|
||||
|
||||
foreach (Material mat in materialTable.Values)
|
||||
Destroy(mat);
|
||||
}
|
||||
|
||||
// based on UnifyWiki http://wiki.unity3d.com/index.php?title=HexConverter
|
||||
static Color32 HexToColor (string hex) {
|
||||
const System.Globalization.NumberStyles HexNumber = System.Globalization.NumberStyles.HexNumber;
|
||||
|
||||
if (hex.Length < 6)
|
||||
return Color.magenta;
|
||||
|
||||
hex = hex.Replace("#", "");
|
||||
byte r = byte.Parse(hex.Substring(0, 2), HexNumber);
|
||||
byte g = byte.Parse(hex.Substring(2, 2), HexNumber);
|
||||
byte b = byte.Parse(hex.Substring(4, 2), HexNumber);
|
||||
byte a = 0xFF;
|
||||
if (hex.Length == 8)
|
||||
a = byte.Parse(hex.Substring(6, 2), HexNumber);
|
||||
|
||||
return new Color32(r, g, b, a);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
// Contributed by: Mitch Thompson
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
[RequireComponent(typeof(SkeletonRenderer))]
|
||||
public class SkeletonGhost : MonoBehaviour {
|
||||
// Internal Settings
|
||||
const HideFlags GhostHideFlags = HideFlags.HideInHierarchy;
|
||||
const string GhostingShaderName = "Spine/Special/SkeletonGhost";
|
||||
|
||||
[Header("Animation")]
|
||||
public bool ghostingEnabled = true;
|
||||
[Tooltip("The time between invididual ghost pieces being spawned.")]
|
||||
[UnityEngine.Serialization.FormerlySerializedAs("spawnRate")]
|
||||
public float spawnInterval = 1f / 30f;
|
||||
[Tooltip("Maximum number of ghosts that can exist at a time. If the fade speed is not fast enough, the oldest ghost will immediately disappear to enforce the maximum number.")]
|
||||
public int maximumGhosts = 10;
|
||||
public float fadeSpeed = 10;
|
||||
|
||||
[Header("Rendering")]
|
||||
public Shader ghostShader;
|
||||
public Color32 color = new Color32(0xFF, 0xFF, 0xFF, 0x00); // default for additive.
|
||||
[Tooltip("Remember to set color alpha to 0 if Additive is true")]
|
||||
public bool additive = true;
|
||||
[Tooltip("0 is Color and Alpha, 1 is Alpha only.")]
|
||||
[Range(0, 1)]
|
||||
public float textureFade = 1;
|
||||
|
||||
[Header("Sorting")]
|
||||
public bool sortWithDistanceOnly;
|
||||
public float zOffset = 0f;
|
||||
|
||||
float nextSpawnTime;
|
||||
SkeletonGhostRenderer[] pool;
|
||||
int poolIndex = 0;
|
||||
SkeletonRenderer skeletonRenderer;
|
||||
MeshRenderer meshRenderer;
|
||||
MeshFilter meshFilter;
|
||||
|
||||
readonly Dictionary<Material, Material> materialTable = new Dictionary<Material, Material>();
|
||||
|
||||
void Start () {
|
||||
Initialize(false);
|
||||
}
|
||||
|
||||
public void Initialize (bool overwrite) {
|
||||
if (pool == null || overwrite) {
|
||||
if (ghostShader == null)
|
||||
ghostShader = Shader.Find(GhostingShaderName);
|
||||
|
||||
skeletonRenderer = GetComponent<SkeletonRenderer>();
|
||||
meshFilter = GetComponent<MeshFilter>();
|
||||
meshRenderer = GetComponent<MeshRenderer>();
|
||||
nextSpawnTime = Time.time + spawnInterval;
|
||||
pool = new SkeletonGhostRenderer[maximumGhosts];
|
||||
for (int i = 0; i < maximumGhosts; i++) {
|
||||
GameObject go = new GameObject(gameObject.name + " Ghost", typeof(SkeletonGhostRenderer));
|
||||
pool[i] = go.GetComponent<SkeletonGhostRenderer>();
|
||||
go.SetActive(false);
|
||||
go.hideFlags = GhostHideFlags;
|
||||
}
|
||||
|
||||
IAnimationStateComponent skeletonAnimation = skeletonRenderer as Spine.Unity.IAnimationStateComponent;
|
||||
if (skeletonAnimation != null)
|
||||
skeletonAnimation.AnimationState.Event += OnEvent;
|
||||
}
|
||||
}
|
||||
|
||||
//SkeletonAnimation
|
||||
/*
|
||||
* Int Value: 0 sets ghostingEnabled to false, 1 sets ghostingEnabled to true
|
||||
* Float Value: Values greater than 0 set the spawnRate equal the float value
|
||||
* String Value: Pass RGBA hex color values in to set the color property. IE: "A0FF8BFF"
|
||||
*/
|
||||
void OnEvent (Spine.TrackEntry trackEntry, Spine.Event e) {
|
||||
if (e.Data.Name.Equals("Ghosting", System.StringComparison.Ordinal)) {
|
||||
ghostingEnabled = e.Int > 0;
|
||||
if (e.Float > 0)
|
||||
spawnInterval = e.Float;
|
||||
|
||||
if (!string.IsNullOrEmpty(e.String))
|
||||
this.color = HexToColor(e.String);
|
||||
}
|
||||
}
|
||||
|
||||
//SkeletonAnimator
|
||||
//SkeletonAnimator or Mecanim based animations only support toggling ghostingEnabled. Be sure not to set anything other than the Int param in Spine or String will take priority.
|
||||
void Ghosting (float val) {
|
||||
ghostingEnabled = val > 0;
|
||||
}
|
||||
|
||||
void Update () {
|
||||
if (!ghostingEnabled || poolIndex >= pool.Length)
|
||||
return;
|
||||
|
||||
if (Time.time >= nextSpawnTime) {
|
||||
GameObject go = pool[poolIndex].gameObject;
|
||||
|
||||
Material[] materials = meshRenderer.sharedMaterials;
|
||||
for (int i = 0; i < materials.Length; i++) {
|
||||
Material originalMat = materials[i];
|
||||
Material ghostMat;
|
||||
if (!materialTable.ContainsKey(originalMat)) {
|
||||
ghostMat = new Material(originalMat) {
|
||||
shader = ghostShader,
|
||||
color = Color.white
|
||||
};
|
||||
|
||||
if (ghostMat.HasProperty("_TextureFade"))
|
||||
ghostMat.SetFloat("_TextureFade", textureFade);
|
||||
|
||||
materialTable.Add(originalMat, ghostMat);
|
||||
} else {
|
||||
ghostMat = materialTable[originalMat];
|
||||
}
|
||||
|
||||
materials[i] = ghostMat;
|
||||
}
|
||||
|
||||
Transform goTransform = go.transform;
|
||||
goTransform.parent = transform;
|
||||
|
||||
pool[poolIndex].Initialize(meshFilter.sharedMesh, materials, color, additive, fadeSpeed, meshRenderer.sortingLayerID, (sortWithDistanceOnly) ? meshRenderer.sortingOrder : meshRenderer.sortingOrder - 1);
|
||||
|
||||
goTransform.localPosition = new Vector3(0f, 0f, zOffset);
|
||||
goTransform.localRotation = Quaternion.identity;
|
||||
goTransform.localScale = Vector3.one;
|
||||
|
||||
goTransform.parent = null;
|
||||
|
||||
poolIndex++;
|
||||
|
||||
if (poolIndex == pool.Length)
|
||||
poolIndex = 0;
|
||||
|
||||
nextSpawnTime = Time.time + spawnInterval;
|
||||
}
|
||||
}
|
||||
|
||||
void OnDestroy () {
|
||||
if (pool != null) {
|
||||
for (int i = 0; i < maximumGhosts; i++)
|
||||
if (pool[i] != null) pool[i].Cleanup();
|
||||
}
|
||||
|
||||
foreach (Material mat in materialTable.Values)
|
||||
Destroy(mat);
|
||||
}
|
||||
|
||||
// based on UnifyWiki http://wiki.unity3d.com/index.php?title=HexConverter
|
||||
static Color32 HexToColor (string hex) {
|
||||
const System.Globalization.NumberStyles HexNumber = System.Globalization.NumberStyles.HexNumber;
|
||||
|
||||
if (hex.Length < 6)
|
||||
return Color.magenta;
|
||||
|
||||
hex = hex.Replace("#", "");
|
||||
byte r = byte.Parse(hex.Substring(0, 2), HexNumber);
|
||||
byte g = byte.Parse(hex.Substring(2, 2), HexNumber);
|
||||
byte b = byte.Parse(hex.Substring(4, 2), HexNumber);
|
||||
byte a = 0xFF;
|
||||
if (hex.Length == 8)
|
||||
a = byte.Parse(hex.Substring(6, 2), HexNumber);
|
||||
|
||||
return new Color32(r, g, b, a);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,128 +1,128 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
// Contributed by: Mitch Thompson
|
||||
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class SkeletonGhostRenderer : MonoBehaviour {
|
||||
static readonly Color32 TransparentBlack = new Color32(0, 0, 0, 0);
|
||||
const string colorPropertyName = "_Color";
|
||||
|
||||
float fadeSpeed = 10;
|
||||
Color32 startColor;
|
||||
MeshFilter meshFilter;
|
||||
MeshRenderer meshRenderer;
|
||||
|
||||
MaterialPropertyBlock mpb;
|
||||
int colorId;
|
||||
|
||||
void Awake () {
|
||||
meshRenderer = gameObject.AddComponent<MeshRenderer>();
|
||||
meshFilter = gameObject.AddComponent<MeshFilter>();
|
||||
|
||||
colorId = Shader.PropertyToID(colorPropertyName);
|
||||
mpb = new MaterialPropertyBlock();
|
||||
}
|
||||
|
||||
public void Initialize (Mesh mesh, Material[] materials, Color32 color, bool additive, float speed, int sortingLayerID, int sortingOrder) {
|
||||
StopAllCoroutines();
|
||||
|
||||
gameObject.SetActive(true);
|
||||
meshRenderer.sharedMaterials = materials;
|
||||
meshRenderer.sortingLayerID = sortingLayerID;
|
||||
meshRenderer.sortingOrder = sortingOrder;
|
||||
meshFilter.sharedMesh = Instantiate(mesh);
|
||||
startColor = color;
|
||||
mpb.SetColor(colorId, color);
|
||||
meshRenderer.SetPropertyBlock(mpb);
|
||||
|
||||
fadeSpeed = speed;
|
||||
|
||||
if (additive)
|
||||
StartCoroutine(FadeAdditive());
|
||||
else
|
||||
StartCoroutine(Fade());
|
||||
}
|
||||
|
||||
IEnumerator Fade () {
|
||||
Color32 c = startColor;
|
||||
Color32 black = SkeletonGhostRenderer.TransparentBlack;
|
||||
|
||||
float t = 1f;
|
||||
for (float hardTimeLimit = 5f; hardTimeLimit > 0; hardTimeLimit -= Time.deltaTime) {
|
||||
c = Color32.Lerp(black, startColor, t);
|
||||
mpb.SetColor(colorId, c);
|
||||
meshRenderer.SetPropertyBlock(mpb);
|
||||
|
||||
t = Mathf.Lerp(t, 0, Time.deltaTime * fadeSpeed);
|
||||
if (t <= 0)
|
||||
break;
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
Destroy(meshFilter.sharedMesh);
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
IEnumerator FadeAdditive () {
|
||||
Color32 c = startColor;
|
||||
Color32 black = SkeletonGhostRenderer.TransparentBlack;
|
||||
|
||||
float t = 1f;
|
||||
|
||||
for (float hardTimeLimit = 5f; hardTimeLimit > 0; hardTimeLimit -= Time.deltaTime) {
|
||||
c = Color32.Lerp(black, startColor, t);
|
||||
mpb.SetColor(colorId, c);
|
||||
meshRenderer.SetPropertyBlock(mpb);
|
||||
|
||||
t = Mathf.Lerp(t, 0, Time.deltaTime * fadeSpeed);
|
||||
if (t <= 0)
|
||||
break;
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
Destroy(meshFilter.sharedMesh);
|
||||
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
public void Cleanup () {
|
||||
if (meshFilter != null && meshFilter.sharedMesh != null)
|
||||
Destroy(meshFilter.sharedMesh);
|
||||
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
// Contributed by: Mitch Thompson
|
||||
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class SkeletonGhostRenderer : MonoBehaviour {
|
||||
static readonly Color32 TransparentBlack = new Color32(0, 0, 0, 0);
|
||||
const string colorPropertyName = "_Color";
|
||||
|
||||
float fadeSpeed = 10;
|
||||
Color32 startColor;
|
||||
MeshFilter meshFilter;
|
||||
MeshRenderer meshRenderer;
|
||||
|
||||
MaterialPropertyBlock mpb;
|
||||
int colorId;
|
||||
|
||||
void Awake () {
|
||||
meshRenderer = gameObject.AddComponent<MeshRenderer>();
|
||||
meshFilter = gameObject.AddComponent<MeshFilter>();
|
||||
|
||||
colorId = Shader.PropertyToID(colorPropertyName);
|
||||
mpb = new MaterialPropertyBlock();
|
||||
}
|
||||
|
||||
public void Initialize (Mesh mesh, Material[] materials, Color32 color, bool additive, float speed, int sortingLayerID, int sortingOrder) {
|
||||
StopAllCoroutines();
|
||||
|
||||
gameObject.SetActive(true);
|
||||
meshRenderer.sharedMaterials = materials;
|
||||
meshRenderer.sortingLayerID = sortingLayerID;
|
||||
meshRenderer.sortingOrder = sortingOrder;
|
||||
meshFilter.sharedMesh = Instantiate(mesh);
|
||||
startColor = color;
|
||||
mpb.SetColor(colorId, color);
|
||||
meshRenderer.SetPropertyBlock(mpb);
|
||||
|
||||
fadeSpeed = speed;
|
||||
|
||||
if (additive)
|
||||
StartCoroutine(FadeAdditive());
|
||||
else
|
||||
StartCoroutine(Fade());
|
||||
}
|
||||
|
||||
IEnumerator Fade () {
|
||||
Color32 c = startColor;
|
||||
Color32 black = SkeletonGhostRenderer.TransparentBlack;
|
||||
|
||||
float t = 1f;
|
||||
for (float hardTimeLimit = 5f; hardTimeLimit > 0; hardTimeLimit -= Time.deltaTime) {
|
||||
c = Color32.Lerp(black, startColor, t);
|
||||
mpb.SetColor(colorId, c);
|
||||
meshRenderer.SetPropertyBlock(mpb);
|
||||
|
||||
t = Mathf.Lerp(t, 0, Time.deltaTime * fadeSpeed);
|
||||
if (t <= 0)
|
||||
break;
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
Destroy(meshFilter.sharedMesh);
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
IEnumerator FadeAdditive () {
|
||||
Color32 c = startColor;
|
||||
Color32 black = SkeletonGhostRenderer.TransparentBlack;
|
||||
|
||||
float t = 1f;
|
||||
|
||||
for (float hardTimeLimit = 5f; hardTimeLimit > 0; hardTimeLimit -= Time.deltaTime) {
|
||||
c = Color32.Lerp(black, startColor, t);
|
||||
mpb.SetColor(colorId, c);
|
||||
meshRenderer.SetPropertyBlock(mpb);
|
||||
|
||||
t = Mathf.Lerp(t, 0, Time.deltaTime * fadeSpeed);
|
||||
if (t <= 0)
|
||||
break;
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
Destroy(meshFilter.sharedMesh);
|
||||
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
public void Cleanup () {
|
||||
if (meshFilter != null && meshFilter.sharedMesh != null)
|
||||
Destroy(meshFilter.sharedMesh);
|
||||
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,81 +1,81 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine;
|
||||
using Spine.Unity.AttachmentTools;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
/// <summary>
|
||||
/// Example code for a component that replaces the default attachment of a slot with an image from a Spine atlas.</summary>
|
||||
public class AtlasRegionAttacher : MonoBehaviour {
|
||||
|
||||
[System.Serializable]
|
||||
public class SlotRegionPair {
|
||||
[SpineSlot] public string slot;
|
||||
[SpineAtlasRegion] public string region;
|
||||
}
|
||||
|
||||
[SerializeField] protected SpineAtlasAsset atlasAsset;
|
||||
[SerializeField] protected bool inheritProperties = true;
|
||||
[SerializeField] protected List<SlotRegionPair> attachments = new List<SlotRegionPair>();
|
||||
|
||||
Atlas atlas;
|
||||
|
||||
void Awake () {
|
||||
SkeletonRenderer skeletonRenderer = GetComponent<SkeletonRenderer>();
|
||||
skeletonRenderer.OnRebuild += Apply;
|
||||
if (skeletonRenderer.valid) Apply(skeletonRenderer);
|
||||
}
|
||||
|
||||
void Apply (SkeletonRenderer skeletonRenderer) {
|
||||
if (!this.enabled) return;
|
||||
|
||||
atlas = atlasAsset.GetAtlas();
|
||||
if (atlas == null) return;
|
||||
float scale = skeletonRenderer.skeletonDataAsset.scale;
|
||||
|
||||
foreach (SlotRegionPair entry in attachments) {
|
||||
Slot slot = skeletonRenderer.Skeleton.FindSlot(entry.slot);
|
||||
Attachment originalAttachment = slot.Attachment;
|
||||
AtlasRegion region = atlas.FindRegion(entry.region);
|
||||
|
||||
if (region == null) {
|
||||
slot.Attachment = null;
|
||||
} else if (inheritProperties && originalAttachment != null) {
|
||||
slot.Attachment = originalAttachment.GetRemappedClone(region, true, true, scale);
|
||||
} else {
|
||||
RegionAttachment newRegionAttachment = region.ToRegionAttachment(region.name, scale);
|
||||
slot.Attachment = newRegionAttachment;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine;
|
||||
using Spine.Unity.AttachmentTools;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
/// <summary>
|
||||
/// Example code for a component that replaces the default attachment of a slot with an image from a Spine atlas.</summary>
|
||||
public class AtlasRegionAttacher : MonoBehaviour {
|
||||
|
||||
[System.Serializable]
|
||||
public class SlotRegionPair {
|
||||
[SpineSlot] public string slot;
|
||||
[SpineAtlasRegion] public string region;
|
||||
}
|
||||
|
||||
[SerializeField] protected SpineAtlasAsset atlasAsset;
|
||||
[SerializeField] protected bool inheritProperties = true;
|
||||
[SerializeField] protected List<SlotRegionPair> attachments = new List<SlotRegionPair>();
|
||||
|
||||
Atlas atlas;
|
||||
|
||||
void Awake () {
|
||||
SkeletonRenderer skeletonRenderer = GetComponent<SkeletonRenderer>();
|
||||
skeletonRenderer.OnRebuild += Apply;
|
||||
if (skeletonRenderer.valid) Apply(skeletonRenderer);
|
||||
}
|
||||
|
||||
void Apply (SkeletonRenderer skeletonRenderer) {
|
||||
if (!this.enabled) return;
|
||||
|
||||
atlas = atlasAsset.GetAtlas();
|
||||
if (atlas == null) return;
|
||||
float scale = skeletonRenderer.skeletonDataAsset.scale;
|
||||
|
||||
foreach (SlotRegionPair entry in attachments) {
|
||||
Slot slot = skeletonRenderer.Skeleton.FindSlot(entry.slot);
|
||||
Attachment originalAttachment = slot.Attachment;
|
||||
AtlasRegion region = atlas.FindRegion(entry.region);
|
||||
|
||||
if (region == null) {
|
||||
slot.Attachment = null;
|
||||
} else if (inheritProperties && originalAttachment != null) {
|
||||
slot.Attachment = originalAttachment.GetRemappedClone(region, true, true, scale);
|
||||
} else {
|
||||
RegionAttachment newRegionAttachment = region.ToRegionAttachment(region.name, scale);
|
||||
slot.Attachment = newRegionAttachment;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,184 +1,184 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
// Original Contribution by: Mitch Thompson
|
||||
|
||||
using Spine.Unity.AttachmentTools;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class SpriteAttacher : MonoBehaviour {
|
||||
public const string DefaultPMAShader = "Spine/Skeleton";
|
||||
public const string DefaultStraightAlphaShader = "Sprites/Default";
|
||||
|
||||
#region Inspector
|
||||
public bool attachOnStart = true;
|
||||
public bool overrideAnimation = true;
|
||||
public Sprite sprite;
|
||||
[SpineSlot] public string slot;
|
||||
#endregion
|
||||
|
||||
#if UNITY_EDITOR
|
||||
void OnValidate () {
|
||||
ISkeletonComponent skeletonComponent = GetComponent<ISkeletonComponent>();
|
||||
SkeletonRenderer skeletonRenderer = skeletonComponent as SkeletonRenderer;
|
||||
bool applyPMA;
|
||||
|
||||
if (skeletonRenderer != null) {
|
||||
applyPMA = skeletonRenderer.pmaVertexColors;
|
||||
} else {
|
||||
SkeletonGraphic skeletonGraphic = skeletonComponent as SkeletonGraphic;
|
||||
applyPMA = skeletonGraphic != null && skeletonGraphic.MeshGenerator.settings.pmaVertexColors;
|
||||
}
|
||||
|
||||
if (applyPMA) {
|
||||
try {
|
||||
if (sprite == null)
|
||||
return;
|
||||
sprite.texture.GetPixel(0, 0);
|
||||
} catch (UnityException e) {
|
||||
Debug.LogFormat("Texture of {0} ({1}) is not read/write enabled. SpriteAttacher requires this in order to work with a SkeletonRenderer that renders premultiplied alpha. Please check the texture settings.", sprite.name, sprite.texture.name);
|
||||
UnityEditor.EditorGUIUtility.PingObject(sprite.texture);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
RegionAttachment attachment;
|
||||
Slot spineSlot;
|
||||
bool applyPMA;
|
||||
|
||||
static Dictionary<Texture, AtlasPage> atlasPageCache;
|
||||
static AtlasPage GetPageFor (Texture texture, Shader shader) {
|
||||
if (atlasPageCache == null) atlasPageCache = new Dictionary<Texture, AtlasPage>();
|
||||
AtlasPage atlasPage;
|
||||
atlasPageCache.TryGetValue(texture, out atlasPage);
|
||||
if (atlasPage == null) {
|
||||
Material newMaterial = new Material(shader);
|
||||
atlasPage = newMaterial.ToSpineAtlasPage();
|
||||
atlasPageCache[texture] = atlasPage;
|
||||
}
|
||||
return atlasPage;
|
||||
}
|
||||
|
||||
void Start () {
|
||||
// Initialize slot and attachment references.
|
||||
Initialize(false);
|
||||
|
||||
if (attachOnStart)
|
||||
Attach();
|
||||
}
|
||||
|
||||
void AnimationOverrideSpriteAttach (ISkeletonAnimation animated) {
|
||||
if (overrideAnimation && isActiveAndEnabled)
|
||||
Attach();
|
||||
}
|
||||
|
||||
public void Initialize (bool overwrite = true) {
|
||||
if (overwrite || attachment == null) {
|
||||
// Get the applyPMA value.
|
||||
ISkeletonComponent skeletonComponent = GetComponent<ISkeletonComponent>();
|
||||
SkeletonRenderer skeletonRenderer = skeletonComponent as SkeletonRenderer;
|
||||
if (skeletonRenderer != null)
|
||||
this.applyPMA = skeletonRenderer.pmaVertexColors;
|
||||
else {
|
||||
SkeletonGraphic skeletonGraphic = skeletonComponent as SkeletonGraphic;
|
||||
if (skeletonGraphic != null)
|
||||
this.applyPMA = skeletonGraphic.MeshGenerator.settings.pmaVertexColors;
|
||||
}
|
||||
|
||||
// Subscribe to UpdateComplete to override animation keys.
|
||||
if (overrideAnimation) {
|
||||
ISkeletonAnimation animatedSkeleton = skeletonComponent as ISkeletonAnimation;
|
||||
if (animatedSkeleton != null) {
|
||||
animatedSkeleton.UpdateComplete -= AnimationOverrideSpriteAttach;
|
||||
animatedSkeleton.UpdateComplete += AnimationOverrideSpriteAttach;
|
||||
}
|
||||
}
|
||||
|
||||
spineSlot = spineSlot ?? skeletonComponent.Skeleton.FindSlot(slot);
|
||||
Shader attachmentShader = applyPMA ? Shader.Find(DefaultPMAShader) : Shader.Find(DefaultStraightAlphaShader);
|
||||
if (sprite == null)
|
||||
attachment = null;
|
||||
else
|
||||
attachment = applyPMA ? sprite.ToRegionAttachmentPMAClone(attachmentShader) : sprite.ToRegionAttachment(SpriteAttacher.GetPageFor(sprite.texture, attachmentShader));
|
||||
}
|
||||
}
|
||||
|
||||
void OnDestroy () {
|
||||
ISkeletonAnimation animatedSkeleton = GetComponent<ISkeletonAnimation>();
|
||||
if (animatedSkeleton != null)
|
||||
animatedSkeleton.UpdateComplete -= AnimationOverrideSpriteAttach;
|
||||
}
|
||||
|
||||
/// <summary>Update the slot's attachment to the Attachment generated from the sprite.</summary>
|
||||
public void Attach () {
|
||||
if (spineSlot != null)
|
||||
spineSlot.Attachment = attachment;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static class SpriteAttachmentExtensions {
|
||||
[System.Obsolete]
|
||||
public static RegionAttachment AttachUnitySprite (this Skeleton skeleton, string slotName, Sprite sprite, string shaderName = SpriteAttacher.DefaultPMAShader, bool applyPMA = true, float rotation = 0f) {
|
||||
return skeleton.AttachUnitySprite(slotName, sprite, Shader.Find(shaderName), applyPMA, rotation: rotation);
|
||||
}
|
||||
|
||||
[System.Obsolete]
|
||||
public static RegionAttachment AddUnitySprite (this SkeletonData skeletonData, string slotName, Sprite sprite, string skinName = "", string shaderName = SpriteAttacher.DefaultPMAShader, bool applyPMA = true, float rotation = 0f) {
|
||||
return skeletonData.AddUnitySprite(slotName, sprite, skinName, Shader.Find(shaderName), applyPMA, rotation: rotation);
|
||||
}
|
||||
|
||||
[System.Obsolete]
|
||||
public static RegionAttachment AttachUnitySprite (this Skeleton skeleton, string slotName, Sprite sprite, Shader shader, bool applyPMA, float rotation = 0f) {
|
||||
RegionAttachment att = applyPMA ? sprite.ToRegionAttachmentPMAClone(shader, rotation: rotation) : sprite.ToRegionAttachment(new Material(shader), rotation: rotation);
|
||||
skeleton.FindSlot(slotName).Attachment = att;
|
||||
return att;
|
||||
}
|
||||
|
||||
[System.Obsolete]
|
||||
public static RegionAttachment AddUnitySprite (this SkeletonData skeletonData, string slotName, Sprite sprite, string skinName, Shader shader, bool applyPMA, float rotation = 0f) {
|
||||
RegionAttachment att = applyPMA ? sprite.ToRegionAttachmentPMAClone(shader, rotation: rotation) : sprite.ToRegionAttachment(new Material(shader), rotation);
|
||||
|
||||
int slotIndex = skeletonData.FindSlot(slotName).Index;
|
||||
Skin skin = skeletonData.DefaultSkin;
|
||||
if (skinName != "")
|
||||
skin = skeletonData.FindSkin(skinName);
|
||||
|
||||
if (skin != null)
|
||||
skin.SetAttachment(slotIndex, att.Name, att);
|
||||
|
||||
return att;
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
// Original Contribution by: Mitch Thompson
|
||||
|
||||
using Spine.Unity.AttachmentTools;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class SpriteAttacher : MonoBehaviour {
|
||||
public const string DefaultPMAShader = "Spine/Skeleton";
|
||||
public const string DefaultStraightAlphaShader = "Sprites/Default";
|
||||
|
||||
#region Inspector
|
||||
public bool attachOnStart = true;
|
||||
public bool overrideAnimation = true;
|
||||
public Sprite sprite;
|
||||
[SpineSlot] public string slot;
|
||||
#endregion
|
||||
|
||||
#if UNITY_EDITOR
|
||||
void OnValidate () {
|
||||
ISkeletonComponent skeletonComponent = GetComponent<ISkeletonComponent>();
|
||||
SkeletonRenderer skeletonRenderer = skeletonComponent as SkeletonRenderer;
|
||||
bool applyPMA;
|
||||
|
||||
if (skeletonRenderer != null) {
|
||||
applyPMA = skeletonRenderer.pmaVertexColors;
|
||||
} else {
|
||||
SkeletonGraphic skeletonGraphic = skeletonComponent as SkeletonGraphic;
|
||||
applyPMA = skeletonGraphic != null && skeletonGraphic.MeshGenerator.settings.pmaVertexColors;
|
||||
}
|
||||
|
||||
if (applyPMA) {
|
||||
try {
|
||||
if (sprite == null)
|
||||
return;
|
||||
sprite.texture.GetPixel(0, 0);
|
||||
} catch (UnityException e) {
|
||||
Debug.LogFormat("Texture of {0} ({1}) is not read/write enabled. SpriteAttacher requires this in order to work with a SkeletonRenderer that renders premultiplied alpha. Please check the texture settings.", sprite.name, sprite.texture.name);
|
||||
UnityEditor.EditorGUIUtility.PingObject(sprite.texture);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
RegionAttachment attachment;
|
||||
Slot spineSlot;
|
||||
bool applyPMA;
|
||||
|
||||
static Dictionary<Texture, AtlasPage> atlasPageCache;
|
||||
static AtlasPage GetPageFor (Texture texture, Shader shader) {
|
||||
if (atlasPageCache == null) atlasPageCache = new Dictionary<Texture, AtlasPage>();
|
||||
AtlasPage atlasPage;
|
||||
atlasPageCache.TryGetValue(texture, out atlasPage);
|
||||
if (atlasPage == null) {
|
||||
Material newMaterial = new Material(shader);
|
||||
atlasPage = newMaterial.ToSpineAtlasPage();
|
||||
atlasPageCache[texture] = atlasPage;
|
||||
}
|
||||
return atlasPage;
|
||||
}
|
||||
|
||||
void Start () {
|
||||
// Initialize slot and attachment references.
|
||||
Initialize(false);
|
||||
|
||||
if (attachOnStart)
|
||||
Attach();
|
||||
}
|
||||
|
||||
void AnimationOverrideSpriteAttach (ISkeletonAnimation animated) {
|
||||
if (overrideAnimation && isActiveAndEnabled)
|
||||
Attach();
|
||||
}
|
||||
|
||||
public void Initialize (bool overwrite = true) {
|
||||
if (overwrite || attachment == null) {
|
||||
// Get the applyPMA value.
|
||||
ISkeletonComponent skeletonComponent = GetComponent<ISkeletonComponent>();
|
||||
SkeletonRenderer skeletonRenderer = skeletonComponent as SkeletonRenderer;
|
||||
if (skeletonRenderer != null)
|
||||
this.applyPMA = skeletonRenderer.pmaVertexColors;
|
||||
else {
|
||||
SkeletonGraphic skeletonGraphic = skeletonComponent as SkeletonGraphic;
|
||||
if (skeletonGraphic != null)
|
||||
this.applyPMA = skeletonGraphic.MeshGenerator.settings.pmaVertexColors;
|
||||
}
|
||||
|
||||
// Subscribe to UpdateComplete to override animation keys.
|
||||
if (overrideAnimation) {
|
||||
ISkeletonAnimation animatedSkeleton = skeletonComponent as ISkeletonAnimation;
|
||||
if (animatedSkeleton != null) {
|
||||
animatedSkeleton.UpdateComplete -= AnimationOverrideSpriteAttach;
|
||||
animatedSkeleton.UpdateComplete += AnimationOverrideSpriteAttach;
|
||||
}
|
||||
}
|
||||
|
||||
spineSlot = spineSlot ?? skeletonComponent.Skeleton.FindSlot(slot);
|
||||
Shader attachmentShader = applyPMA ? Shader.Find(DefaultPMAShader) : Shader.Find(DefaultStraightAlphaShader);
|
||||
if (sprite == null)
|
||||
attachment = null;
|
||||
else
|
||||
attachment = applyPMA ? sprite.ToRegionAttachmentPMAClone(attachmentShader) : sprite.ToRegionAttachment(SpriteAttacher.GetPageFor(sprite.texture, attachmentShader));
|
||||
}
|
||||
}
|
||||
|
||||
void OnDestroy () {
|
||||
ISkeletonAnimation animatedSkeleton = GetComponent<ISkeletonAnimation>();
|
||||
if (animatedSkeleton != null)
|
||||
animatedSkeleton.UpdateComplete -= AnimationOverrideSpriteAttach;
|
||||
}
|
||||
|
||||
/// <summary>Update the slot's attachment to the Attachment generated from the sprite.</summary>
|
||||
public void Attach () {
|
||||
if (spineSlot != null)
|
||||
spineSlot.Attachment = attachment;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static class SpriteAttachmentExtensions {
|
||||
[System.Obsolete]
|
||||
public static RegionAttachment AttachUnitySprite (this Skeleton skeleton, string slotName, Sprite sprite, string shaderName = SpriteAttacher.DefaultPMAShader, bool applyPMA = true, float rotation = 0f) {
|
||||
return skeleton.AttachUnitySprite(slotName, sprite, Shader.Find(shaderName), applyPMA, rotation: rotation);
|
||||
}
|
||||
|
||||
[System.Obsolete]
|
||||
public static RegionAttachment AddUnitySprite (this SkeletonData skeletonData, string slotName, Sprite sprite, string skinName = "", string shaderName = SpriteAttacher.DefaultPMAShader, bool applyPMA = true, float rotation = 0f) {
|
||||
return skeletonData.AddUnitySprite(slotName, sprite, skinName, Shader.Find(shaderName), applyPMA, rotation: rotation);
|
||||
}
|
||||
|
||||
[System.Obsolete]
|
||||
public static RegionAttachment AttachUnitySprite (this Skeleton skeleton, string slotName, Sprite sprite, Shader shader, bool applyPMA, float rotation = 0f) {
|
||||
RegionAttachment att = applyPMA ? sprite.ToRegionAttachmentPMAClone(shader, rotation: rotation) : sprite.ToRegionAttachment(new Material(shader), rotation: rotation);
|
||||
skeleton.FindSlot(slotName).Attachment = att;
|
||||
return att;
|
||||
}
|
||||
|
||||
[System.Obsolete]
|
||||
public static RegionAttachment AddUnitySprite (this SkeletonData skeletonData, string slotName, Sprite sprite, string skinName, Shader shader, bool applyPMA, float rotation = 0f) {
|
||||
RegionAttachment att = applyPMA ? sprite.ToRegionAttachmentPMAClone(shader, rotation: rotation) : sprite.ToRegionAttachment(new Material(shader), rotation);
|
||||
|
||||
int slotIndex = skeletonData.FindSlot(slotName).Index;
|
||||
Skin skin = skeletonData.DefaultSkin;
|
||||
if (skinName != "")
|
||||
skin = skeletonData.FindSkin(skinName);
|
||||
|
||||
if (skin != null)
|
||||
skin.SetAttachment(slotIndex, att.Name, att);
|
||||
|
||||
return att;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,69 +1,69 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
public class OutlineSkeletonGraphic : MonoBehaviour {
|
||||
|
||||
public SkeletonGraphic skeletonGraphic;
|
||||
public Material materialWithoutOutline;
|
||||
public Material materialWithOutline;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
void Reset () {
|
||||
skeletonGraphic = GetComponent<SkeletonGraphic>();
|
||||
|
||||
// Add normal material as default
|
||||
if (skeletonGraphic != null && skeletonGraphic.skeletonDataAsset != null) {
|
||||
AtlasAssetBase[] atlasAssets = skeletonGraphic.skeletonDataAsset.atlasAssets;
|
||||
|
||||
if (atlasAssets.Length > 0 && atlasAssets[0].PrimaryMaterial) {
|
||||
materialWithoutOutline = atlasAssets[0].PrimaryMaterial;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void OnEnable () {
|
||||
if (skeletonGraphic == null)
|
||||
skeletonGraphic = GetComponent<SkeletonGraphic>();
|
||||
}
|
||||
|
||||
public void EnableOutlineRendering () {
|
||||
skeletonGraphic.material = materialWithOutline;
|
||||
}
|
||||
|
||||
public void DisableOutlineRendering () {
|
||||
skeletonGraphic.material = materialWithoutOutline;
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
public class OutlineSkeletonGraphic : MonoBehaviour {
|
||||
|
||||
public SkeletonGraphic skeletonGraphic;
|
||||
public Material materialWithoutOutline;
|
||||
public Material materialWithOutline;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
void Reset () {
|
||||
skeletonGraphic = GetComponent<SkeletonGraphic>();
|
||||
|
||||
// Add normal material as default
|
||||
if (skeletonGraphic != null && skeletonGraphic.skeletonDataAsset != null) {
|
||||
AtlasAssetBase[] atlasAssets = skeletonGraphic.skeletonDataAsset.atlasAssets;
|
||||
|
||||
if (atlasAssets.Length > 0 && atlasAssets[0].PrimaryMaterial) {
|
||||
materialWithoutOutline = atlasAssets[0].PrimaryMaterial;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void OnEnable () {
|
||||
if (skeletonGraphic == null)
|
||||
skeletonGraphic = GetComponent<SkeletonGraphic>();
|
||||
}
|
||||
|
||||
public void EnableOutlineRendering () {
|
||||
skeletonGraphic.material = materialWithOutline;
|
||||
}
|
||||
|
||||
public void DisableOutlineRendering () {
|
||||
skeletonGraphic.material = materialWithoutOutline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
268
Assets/ThirdParty/Spine Examples/Scripts/Sample Components/RenderCombinedMesh.cs
vendored
Normal file
268
Assets/ThirdParty/Spine Examples/Scripts/Sample Components/RenderCombinedMesh.cs
vendored
Normal file
@ -0,0 +1,268 @@
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
|
||||
#define NEW_PREFAB_SYSTEM
|
||||
#endif
|
||||
|
||||
#if UNITY_2019_3_OR_NEWER
|
||||
#define SET_VERTICES_HAS_LENGTH_PARAMETER
|
||||
#endif
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
#if NEW_PREFAB_SYSTEM
|
||||
[ExecuteAlways]
|
||||
#else
|
||||
[ExecuteInEditMode]
|
||||
#endif
|
||||
public class RenderCombinedMesh : MonoBehaviour {
|
||||
public SkeletonRenderer skeletonRenderer;
|
||||
public SkeletonRenderSeparator renderSeparator;
|
||||
public MeshRenderer[] referenceRenderers;
|
||||
|
||||
bool updateViaSkeletonCallback = false;
|
||||
MeshFilter[] referenceMeshFilters;
|
||||
MeshRenderer ownRenderer;
|
||||
MeshFilter ownMeshFilter;
|
||||
|
||||
protected DoubleBuffered<Mesh> doubleBufferedMesh;
|
||||
protected ExposedList<Vector3> positionBuffer;
|
||||
protected ExposedList<Color32> colorBuffer;
|
||||
protected ExposedList<Vector2> uvBuffer;
|
||||
protected ExposedList<int> indexBuffer;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void Reset () {
|
||||
if (skeletonRenderer == null)
|
||||
skeletonRenderer = this.GetComponentInParent<SkeletonRenderer>();
|
||||
GatherRenderers();
|
||||
|
||||
Awake();
|
||||
if (referenceRenderers.Length > 0)
|
||||
ownRenderer.sharedMaterial = referenceRenderers[0].sharedMaterial;
|
||||
|
||||
LateUpdate();
|
||||
}
|
||||
#endif
|
||||
protected void GatherRenderers () {
|
||||
referenceRenderers = this.GetComponentsInChildren<MeshRenderer>();
|
||||
if (referenceRenderers.Length == 0 ||
|
||||
(referenceRenderers.Length == 1 && referenceRenderers[0].gameObject == this.gameObject)) {
|
||||
Transform parent = this.transform.parent;
|
||||
if (parent)
|
||||
referenceRenderers = parent.GetComponentsInChildren<MeshRenderer>();
|
||||
}
|
||||
referenceRenderers = referenceRenderers.Where(
|
||||
(val, idx) => val.gameObject != this.gameObject && val.enabled).ToArray();
|
||||
}
|
||||
|
||||
void Awake () {
|
||||
if (skeletonRenderer == null)
|
||||
skeletonRenderer = this.GetComponentInParent<SkeletonRenderer>();
|
||||
if (referenceRenderers == null || referenceRenderers.Length == 0) {
|
||||
GatherRenderers();
|
||||
}
|
||||
|
||||
if (renderSeparator == null) {
|
||||
if (skeletonRenderer)
|
||||
renderSeparator = skeletonRenderer.GetComponent<SkeletonRenderSeparator>();
|
||||
else
|
||||
renderSeparator = this.GetComponentInParent<SkeletonRenderSeparator>();
|
||||
}
|
||||
|
||||
int count = referenceRenderers.Length;
|
||||
referenceMeshFilters = new MeshFilter[count];
|
||||
for (int i = 0; i < count; ++i) {
|
||||
referenceMeshFilters[i] = referenceRenderers[i].GetComponent<MeshFilter>();
|
||||
}
|
||||
|
||||
ownRenderer = this.GetComponent<MeshRenderer>();
|
||||
if (ownRenderer == null)
|
||||
ownRenderer = this.gameObject.AddComponent<MeshRenderer>();
|
||||
ownMeshFilter = this.GetComponent<MeshFilter>();
|
||||
if (ownMeshFilter == null)
|
||||
ownMeshFilter = this.gameObject.AddComponent<MeshFilter>();
|
||||
}
|
||||
|
||||
void OnEnable () {
|
||||
#if UNITY_EDITOR
|
||||
if (Application.isPlaying)
|
||||
Awake();
|
||||
#endif
|
||||
if (skeletonRenderer) {
|
||||
skeletonRenderer.OnMeshAndMaterialsUpdated -= UpdateOnCallback;
|
||||
skeletonRenderer.OnMeshAndMaterialsUpdated += UpdateOnCallback;
|
||||
updateViaSkeletonCallback = true;
|
||||
}
|
||||
if (renderSeparator) {
|
||||
renderSeparator.OnMeshAndMaterialsUpdated -= UpdateOnCallback;
|
||||
renderSeparator.OnMeshAndMaterialsUpdated += UpdateOnCallback;
|
||||
updateViaSkeletonCallback = true;
|
||||
}
|
||||
}
|
||||
|
||||
void OnDisable () {
|
||||
if (skeletonRenderer)
|
||||
skeletonRenderer.OnMeshAndMaterialsUpdated -= UpdateOnCallback;
|
||||
if (renderSeparator)
|
||||
renderSeparator.OnMeshAndMaterialsUpdated -= UpdateOnCallback;
|
||||
}
|
||||
|
||||
void OnDestroy () {
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
Mesh mesh = doubleBufferedMesh.GetNext();
|
||||
#if UNITY_EDITOR
|
||||
if (Application.isEditor && !Application.isPlaying)
|
||||
UnityEngine.Object.DestroyImmediate(mesh);
|
||||
else
|
||||
UnityEngine.Object.Destroy(mesh);
|
||||
#else
|
||||
UnityEngine.Object.Destroy(mesh);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void LateUpdate () {
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying) {
|
||||
UpdateMesh();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (updateViaSkeletonCallback)
|
||||
return;
|
||||
UpdateMesh();
|
||||
}
|
||||
|
||||
void UpdateOnCallback (SkeletonRenderer r) {
|
||||
UpdateMesh();
|
||||
}
|
||||
|
||||
protected void EnsureBufferSizes (int combinedVertexCount, int combinedIndexCount) {
|
||||
if (positionBuffer == null) {
|
||||
positionBuffer = new ExposedList<Vector3>(combinedVertexCount);
|
||||
uvBuffer = new ExposedList<Vector2>(combinedVertexCount);
|
||||
colorBuffer = new ExposedList<Color32>(combinedVertexCount);
|
||||
indexBuffer = new ExposedList<int>(combinedIndexCount);
|
||||
}
|
||||
|
||||
if (positionBuffer.Count != combinedVertexCount) {
|
||||
positionBuffer.Resize(combinedVertexCount);
|
||||
uvBuffer.Resize(combinedVertexCount);
|
||||
colorBuffer.Resize(combinedVertexCount);
|
||||
}
|
||||
if (indexBuffer.Count != combinedIndexCount) {
|
||||
indexBuffer.Resize(combinedIndexCount);
|
||||
}
|
||||
}
|
||||
|
||||
void InitMesh () {
|
||||
if (doubleBufferedMesh == null) {
|
||||
doubleBufferedMesh = new DoubleBuffered<Mesh>();
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
Mesh combinedMesh = doubleBufferedMesh.GetNext();
|
||||
combinedMesh.MarkDynamic();
|
||||
combinedMesh.name = "RenderCombinedMesh" + i;
|
||||
combinedMesh.subMeshCount = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateMesh () {
|
||||
InitMesh();
|
||||
int combinedVertexCount = 0;
|
||||
int combinedIndexCount = 0;
|
||||
GetCombinedMeshInfo(ref combinedVertexCount, ref combinedIndexCount);
|
||||
|
||||
EnsureBufferSizes(combinedVertexCount, combinedIndexCount);
|
||||
|
||||
int combinedV = 0;
|
||||
int combinedI = 0;
|
||||
for (int r = 0, rendererCount = referenceMeshFilters.Length; r < rendererCount; ++r) {
|
||||
MeshFilter meshFilter = referenceMeshFilters[r];
|
||||
Mesh mesh = meshFilter.sharedMesh;
|
||||
if (mesh == null) continue;
|
||||
|
||||
int vertexCount = mesh.vertexCount;
|
||||
Vector3[] positions = mesh.vertices;
|
||||
Vector2[] uvs = mesh.uv;
|
||||
Color32[] colors = mesh.colors32;
|
||||
|
||||
System.Array.Copy(positions, 0, this.positionBuffer.Items, combinedV, vertexCount);
|
||||
System.Array.Copy(uvs, 0, this.uvBuffer.Items, combinedV, vertexCount);
|
||||
System.Array.Copy(colors, 0, this.colorBuffer.Items, combinedV, vertexCount);
|
||||
|
||||
for (int s = 0, submeshCount = mesh.subMeshCount; s < submeshCount; ++s) {
|
||||
int submeshIndexCount = (int)mesh.GetIndexCount(s);
|
||||
int[] submeshIndices = mesh.GetIndices(s);
|
||||
int[] dstIndices = this.indexBuffer.Items;
|
||||
for (int i = 0; i < submeshIndexCount; ++i)
|
||||
dstIndices[i + combinedI] = submeshIndices[i] + combinedV;
|
||||
combinedI += submeshIndexCount;
|
||||
}
|
||||
combinedV += vertexCount;
|
||||
}
|
||||
|
||||
Mesh combinedMesh = doubleBufferedMesh.GetNext();
|
||||
combinedMesh.Clear();
|
||||
#if SET_VERTICES_HAS_LENGTH_PARAMETER
|
||||
combinedMesh.SetVertices(this.positionBuffer.Items, 0, this.positionBuffer.Count);
|
||||
combinedMesh.SetUVs(0, this.uvBuffer.Items, 0, this.uvBuffer.Count);
|
||||
combinedMesh.SetColors(this.colorBuffer.Items, 0, this.colorBuffer.Count);
|
||||
combinedMesh.SetTriangles(this.indexBuffer.Items, 0, this.indexBuffer.Count, 0);
|
||||
#else
|
||||
// Note: excess already contains zero positions and indices after ExposedList.Resize().
|
||||
combinedMesh.vertices = this.positionBuffer.Items;
|
||||
combinedMesh.uv = this.uvBuffer.Items;
|
||||
combinedMesh.colors32 = this.colorBuffer.Items;
|
||||
combinedMesh.triangles = this.indexBuffer.Items;
|
||||
#endif
|
||||
ownMeshFilter.sharedMesh = combinedMesh;
|
||||
}
|
||||
|
||||
void GetCombinedMeshInfo (ref int vertexCount, ref int indexCount) {
|
||||
for (int r = 0, rendererCount = referenceMeshFilters.Length; r < rendererCount; ++r) {
|
||||
MeshFilter meshFilter = referenceMeshFilters[r];
|
||||
Mesh mesh = meshFilter.sharedMesh;
|
||||
if (mesh == null) continue;
|
||||
|
||||
vertexCount += mesh.vertexCount;
|
||||
for (int s = 0, submeshCount = mesh.subMeshCount; s < submeshCount; ++s) {
|
||||
indexCount += (int)mesh.GetIndexCount(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/ThirdParty/Spine Examples/Scripts/Sample Components/RenderCombinedMesh.cs.meta
vendored
Normal file
11
Assets/ThirdParty/Spine Examples/Scripts/Sample Components/RenderCombinedMesh.cs.meta
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 05709c69e8e14304b9781652ad05daef
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -1,151 +1,182 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
|
||||
#define NEW_PREFAB_SYSTEM
|
||||
#endif
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
#if NEW_PREFAB_SYSTEM
|
||||
[ExecuteAlways]
|
||||
#else
|
||||
[ExecuteInEditMode]
|
||||
#endif
|
||||
[RequireComponent(typeof(MeshRenderer)), RequireComponent(typeof(MeshFilter))]
|
||||
public class RenderExistingMesh : MonoBehaviour {
|
||||
public MeshRenderer referenceRenderer;
|
||||
|
||||
bool updateViaSkeletonCallback = false;
|
||||
MeshFilter referenceMeshFilter;
|
||||
MeshRenderer ownRenderer;
|
||||
MeshFilter ownMeshFilter;
|
||||
|
||||
[System.Serializable]
|
||||
public struct MaterialReplacement {
|
||||
public Material originalMaterial;
|
||||
public Material replacementMaterial;
|
||||
}
|
||||
public MaterialReplacement[] replacementMaterials = new MaterialReplacement[0];
|
||||
|
||||
private Dictionary<Material, Material> replacementMaterialDict = new Dictionary<Material, Material>();
|
||||
private Material[] sharedMaterials = new Material[0];
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void Reset () {
|
||||
if (referenceRenderer == null) {
|
||||
referenceRenderer = this.transform.parent.GetComponentInParent<MeshRenderer>();
|
||||
if (!referenceRenderer)
|
||||
return;
|
||||
}
|
||||
|
||||
Material[] parentMaterials = referenceRenderer.sharedMaterials;
|
||||
if (replacementMaterials.Length != parentMaterials.Length) {
|
||||
replacementMaterials = new MaterialReplacement[parentMaterials.Length];
|
||||
}
|
||||
for (int i = 0; i < parentMaterials.Length; ++i) {
|
||||
replacementMaterials[i].originalMaterial = parentMaterials[i];
|
||||
replacementMaterials[i].replacementMaterial = parentMaterials[i];
|
||||
}
|
||||
Awake();
|
||||
LateUpdate();
|
||||
}
|
||||
#endif
|
||||
|
||||
void Awake () {
|
||||
if (referenceRenderer == null) {
|
||||
referenceRenderer = this.transform.parent.GetComponentInParent<MeshRenderer>();
|
||||
}
|
||||
|
||||
// subscribe to OnMeshAndMaterialsUpdated
|
||||
SkeletonAnimation skeletonRenderer = referenceRenderer.GetComponent<SkeletonAnimation>();
|
||||
if (skeletonRenderer) {
|
||||
skeletonRenderer.OnMeshAndMaterialsUpdated -= UpdateOnCallback;
|
||||
skeletonRenderer.OnMeshAndMaterialsUpdated += UpdateOnCallback;
|
||||
updateViaSkeletonCallback = true;
|
||||
}
|
||||
referenceMeshFilter = referenceRenderer.GetComponent<MeshFilter>();
|
||||
ownRenderer = this.GetComponent<MeshRenderer>();
|
||||
ownMeshFilter = this.GetComponent<MeshFilter>();
|
||||
|
||||
InitializeDict();
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void Update () {
|
||||
if (!Application.isPlaying) {
|
||||
InitializeDict();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void LateUpdate () {
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying) {
|
||||
UpdateMaterials();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (updateViaSkeletonCallback)
|
||||
return;
|
||||
UpdateMaterials();
|
||||
}
|
||||
|
||||
void UpdateOnCallback (SkeletonRenderer r) {
|
||||
UpdateMaterials();
|
||||
}
|
||||
|
||||
void UpdateMaterials () {
|
||||
ownMeshFilter.sharedMesh = referenceMeshFilter.sharedMesh;
|
||||
|
||||
Material[] parentMaterials = referenceRenderer.sharedMaterials;
|
||||
if (sharedMaterials.Length != parentMaterials.Length) {
|
||||
sharedMaterials = new Material[parentMaterials.Length];
|
||||
}
|
||||
for (int i = 0; i < parentMaterials.Length; ++i) {
|
||||
Material parentMaterial = parentMaterials[i];
|
||||
if (replacementMaterialDict.ContainsKey(parentMaterial)) {
|
||||
sharedMaterials[i] = replacementMaterialDict[parentMaterial];
|
||||
}
|
||||
}
|
||||
ownRenderer.sharedMaterials = sharedMaterials;
|
||||
}
|
||||
|
||||
void InitializeDict () {
|
||||
for (int i = 0; i < replacementMaterials.Length; ++i) {
|
||||
MaterialReplacement entry = replacementMaterials[i];
|
||||
replacementMaterialDict[entry.originalMaterial] = entry.replacementMaterial;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
|
||||
#define NEW_PREFAB_SYSTEM
|
||||
#endif
|
||||
|
||||
#if UNITY_2018_2_OR_NEWER
|
||||
#define HAS_GET_SHARED_MATERIALS
|
||||
#endif
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
#if NEW_PREFAB_SYSTEM
|
||||
[ExecuteAlways]
|
||||
#else
|
||||
[ExecuteInEditMode]
|
||||
#endif
|
||||
[RequireComponent(typeof(MeshRenderer)), RequireComponent(typeof(MeshFilter))]
|
||||
public class RenderExistingMesh : MonoBehaviour {
|
||||
public MeshRenderer referenceRenderer;
|
||||
|
||||
bool updateViaSkeletonCallback = false;
|
||||
MeshFilter referenceMeshFilter;
|
||||
MeshRenderer ownRenderer;
|
||||
MeshFilter ownMeshFilter;
|
||||
|
||||
[System.Serializable]
|
||||
public struct MaterialReplacement {
|
||||
public Material originalMaterial;
|
||||
public Material replacementMaterial;
|
||||
}
|
||||
public MaterialReplacement[] replacementMaterials = new MaterialReplacement[0];
|
||||
|
||||
private Dictionary<Material, Material> replacementMaterialDict = new Dictionary<Material, Material>();
|
||||
private Material[] sharedMaterials = new Material[0];
|
||||
#if HAS_GET_SHARED_MATERIALS
|
||||
private List<Material> parentMaterials = new List<Material>();
|
||||
#endif
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void Reset () {
|
||||
if (referenceRenderer == null) {
|
||||
if (this.transform.parent)
|
||||
referenceRenderer = this.transform.parent.GetComponentInParent<MeshRenderer>();
|
||||
if (referenceRenderer == null) return;
|
||||
}
|
||||
#if HAS_GET_SHARED_MATERIALS
|
||||
referenceRenderer.GetSharedMaterials(parentMaterials);
|
||||
int parentMaterialsCount = parentMaterials.Count;
|
||||
#else
|
||||
Material[] parentMaterials = referenceRenderer.sharedMaterials;
|
||||
int parentMaterialsCount = parentMaterials.Length;
|
||||
#endif
|
||||
if (replacementMaterials.Length != parentMaterialsCount) {
|
||||
replacementMaterials = new MaterialReplacement[parentMaterialsCount];
|
||||
}
|
||||
for (int i = 0; i < parentMaterialsCount; ++i) {
|
||||
replacementMaterials[i].originalMaterial = parentMaterials[i];
|
||||
replacementMaterials[i].replacementMaterial = parentMaterials[i];
|
||||
}
|
||||
Awake();
|
||||
LateUpdate();
|
||||
}
|
||||
#endif
|
||||
|
||||
void Awake () {
|
||||
ownRenderer = this.GetComponent<MeshRenderer>();
|
||||
ownMeshFilter = this.GetComponent<MeshFilter>();
|
||||
|
||||
if (referenceRenderer == null) {
|
||||
if (this.transform.parent != null)
|
||||
referenceRenderer = this.transform.parent.GetComponentInParent<MeshRenderer>();
|
||||
if (referenceRenderer == null) return;
|
||||
}
|
||||
referenceMeshFilter = referenceRenderer.GetComponent<MeshFilter>();
|
||||
|
||||
// subscribe to OnMeshAndMaterialsUpdated
|
||||
SkeletonAnimation skeletonRenderer = referenceRenderer.GetComponent<SkeletonAnimation>();
|
||||
if (skeletonRenderer) {
|
||||
skeletonRenderer.OnMeshAndMaterialsUpdated -= UpdateOnCallback;
|
||||
skeletonRenderer.OnMeshAndMaterialsUpdated += UpdateOnCallback;
|
||||
updateViaSkeletonCallback = true;
|
||||
}
|
||||
|
||||
InitializeDict();
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
// handle disabled scene reload
|
||||
private void OnEnable () {
|
||||
if (Application.isPlaying)
|
||||
Awake();
|
||||
}
|
||||
|
||||
private void Update () {
|
||||
if (!Application.isPlaying)
|
||||
InitializeDict();
|
||||
}
|
||||
#endif
|
||||
|
||||
void LateUpdate () {
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying) {
|
||||
UpdateMaterials();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (updateViaSkeletonCallback)
|
||||
return;
|
||||
UpdateMaterials();
|
||||
}
|
||||
|
||||
void UpdateOnCallback (SkeletonRenderer r) {
|
||||
UpdateMaterials();
|
||||
}
|
||||
|
||||
void UpdateMaterials () {
|
||||
#if UNITY_EDITOR
|
||||
if (!referenceRenderer) return;
|
||||
if (!referenceMeshFilter) Reset();
|
||||
#endif
|
||||
ownMeshFilter.sharedMesh = referenceMeshFilter.sharedMesh;
|
||||
|
||||
#if HAS_GET_SHARED_MATERIALS
|
||||
referenceRenderer.GetSharedMaterials(parentMaterials);
|
||||
int parentMaterialsCount = parentMaterials.Count;
|
||||
#else
|
||||
Material[] parentMaterials = referenceRenderer.sharedMaterials;
|
||||
int parentMaterialsCount = parentMaterials.Length;
|
||||
#endif
|
||||
if (sharedMaterials.Length != parentMaterialsCount) {
|
||||
sharedMaterials = new Material[parentMaterialsCount];
|
||||
}
|
||||
for (int i = 0; i < parentMaterialsCount; ++i) {
|
||||
Material parentMaterial = parentMaterials[i];
|
||||
if (replacementMaterialDict.ContainsKey(parentMaterial)) {
|
||||
sharedMaterials[i] = replacementMaterialDict[parentMaterial];
|
||||
}
|
||||
}
|
||||
ownRenderer.sharedMaterials = sharedMaterials;
|
||||
}
|
||||
|
||||
void InitializeDict () {
|
||||
replacementMaterialDict.Clear();
|
||||
for (int i = 0; i < replacementMaterials.Length; ++i) {
|
||||
MaterialReplacement entry = replacementMaterials[i];
|
||||
replacementMaterialDict[entry.originalMaterial] = entry.replacementMaterial;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
224
Assets/ThirdParty/Spine Examples/Scripts/Sample Components/RenderExistingMeshGraphic.cs
vendored
Normal file
224
Assets/ThirdParty/Spine Examples/Scripts/Sample Components/RenderExistingMeshGraphic.cs
vendored
Normal file
@ -0,0 +1,224 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2025, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
|
||||
#define NEW_PREFAB_SYSTEM
|
||||
#endif
|
||||
|
||||
#if UNITY_2018_2_OR_NEWER
|
||||
#define HAS_CULL_TRANSPARENT_MESH
|
||||
#endif
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
using MaterialReplacement = RenderExistingMesh.MaterialReplacement;
|
||||
|
||||
#if NEW_PREFAB_SYSTEM
|
||||
[ExecuteAlways]
|
||||
#else
|
||||
[ExecuteInEditMode]
|
||||
#endif
|
||||
public class RenderExistingMeshGraphic : MonoBehaviour {
|
||||
public SkeletonGraphic referenceSkeletonGraphic;
|
||||
public Material replacementMaterial;
|
||||
|
||||
public MaterialReplacement[] replacementMaterials = new MaterialReplacement[0];
|
||||
|
||||
SkeletonSubmeshGraphic ownGraphic;
|
||||
public List<SkeletonSubmeshGraphic> ownSubmeshGraphics;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void Reset () {
|
||||
Awake();
|
||||
LateUpdate();
|
||||
}
|
||||
#endif
|
||||
|
||||
void Awake () {
|
||||
// subscribe to OnMeshAndMaterialsUpdated
|
||||
if (referenceSkeletonGraphic) {
|
||||
referenceSkeletonGraphic.OnMeshAndMaterialsUpdated -= UpdateOnCallback;
|
||||
referenceSkeletonGraphic.OnMeshAndMaterialsUpdated += UpdateOnCallback;
|
||||
}
|
||||
|
||||
ownGraphic = this.GetComponent<SkeletonSubmeshGraphic>();
|
||||
if (referenceSkeletonGraphic) {
|
||||
if (referenceSkeletonGraphic.allowMultipleCanvasRenderers)
|
||||
EnsureCanvasRendererCount(referenceSkeletonGraphic.canvasRenderers.Count);
|
||||
else
|
||||
SetupSubmeshGraphic();
|
||||
}
|
||||
}
|
||||
|
||||
protected void OnDisable () {
|
||||
if (referenceSkeletonGraphic) {
|
||||
referenceSkeletonGraphic.OnMeshAndMaterialsUpdated -= UpdateOnCallback;
|
||||
}
|
||||
}
|
||||
|
||||
protected void OnEnable () {
|
||||
#if UNITY_EDITOR
|
||||
// handle disabled scene reload
|
||||
if (Application.isPlaying) {
|
||||
Awake();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (referenceSkeletonGraphic) {
|
||||
referenceSkeletonGraphic.OnMeshAndMaterialsUpdated -= UpdateOnCallback;
|
||||
referenceSkeletonGraphic.OnMeshAndMaterialsUpdated += UpdateOnCallback;
|
||||
}
|
||||
}
|
||||
|
||||
void SetupSubmeshGraphic () {
|
||||
if (ownGraphic == null)
|
||||
ownGraphic = this.gameObject.AddComponent<SkeletonSubmeshGraphic>();
|
||||
|
||||
ownGraphic.maskable = referenceSkeletonGraphic.maskable;
|
||||
#if HAS_CULL_TRANSPARENT_MESH
|
||||
ownGraphic.canvasRenderer.cullTransparentMesh = referenceSkeletonGraphic.canvasRenderer.cullTransparentMesh;
|
||||
#endif
|
||||
ownGraphic.canvasRenderer.SetMaterial(replacementMaterial, referenceSkeletonGraphic.mainTexture);
|
||||
}
|
||||
|
||||
protected void EnsureCanvasRendererCount (int targetCount) {
|
||||
if (ownSubmeshGraphics == null)
|
||||
ownSubmeshGraphics = new List<SkeletonSubmeshGraphic>();
|
||||
|
||||
#if HAS_CULL_TRANSPARENT_MESH
|
||||
bool cullTransparentMesh = referenceSkeletonGraphic.canvasRenderer.cullTransparentMesh;
|
||||
#endif
|
||||
Vector2 pivot = referenceSkeletonGraphic.rectTransform.pivot;
|
||||
|
||||
int currentCount = ownSubmeshGraphics.Count;
|
||||
for (int i = currentCount; i < targetCount; ++i) {
|
||||
GameObject go = new GameObject(string.Format("Renderer{0}", i), typeof(RectTransform));
|
||||
go.transform.SetParent(this.transform, false);
|
||||
go.transform.localPosition = Vector3.zero;
|
||||
CanvasRenderer canvasRenderer = go.AddComponent<CanvasRenderer>();
|
||||
#if HAS_CULL_TRANSPARENT_MESH
|
||||
canvasRenderer.cullTransparentMesh = cullTransparentMesh;
|
||||
#endif
|
||||
SkeletonSubmeshGraphic submeshGraphic = go.AddComponent<SkeletonSubmeshGraphic>();
|
||||
ownSubmeshGraphics.Add(submeshGraphic);
|
||||
submeshGraphic.maskable = referenceSkeletonGraphic.maskable;
|
||||
submeshGraphic.raycastTarget = false;
|
||||
submeshGraphic.rectTransform.pivot = pivot;
|
||||
submeshGraphic.rectTransform.anchorMin = Vector2.zero;
|
||||
submeshGraphic.rectTransform.anchorMax = Vector2.one;
|
||||
submeshGraphic.rectTransform.sizeDelta = Vector2.zero;
|
||||
}
|
||||
}
|
||||
|
||||
protected void UpdateCanvasRenderers () {
|
||||
Mesh[] referenceMeshes = referenceSkeletonGraphic.MeshesMultipleCanvasRenderers.Items;
|
||||
Material[] referenceMaterials = referenceSkeletonGraphic.MaterialsMultipleCanvasRenderers.Items;
|
||||
Texture[] referenceTextures = referenceSkeletonGraphic.TexturesMultipleCanvasRenderers.Items;
|
||||
|
||||
int end = Math.Min(ownSubmeshGraphics.Count, referenceSkeletonGraphic.TexturesMultipleCanvasRenderers.Count);
|
||||
|
||||
for (int i = 0; i < end; i++) {
|
||||
SkeletonSubmeshGraphic submeshGraphic = ownSubmeshGraphics[i];
|
||||
CanvasRenderer reference = referenceSkeletonGraphic.canvasRenderers[i];
|
||||
|
||||
if (reference.gameObject.activeInHierarchy) {
|
||||
Material usedMaterial = replacementMaterial != null ?
|
||||
replacementMaterial : GetReplacementMaterialFor(referenceMaterials[i]);
|
||||
if (usedMaterial == null)
|
||||
usedMaterial = referenceMaterials[i];
|
||||
usedMaterial = referenceSkeletonGraphic.GetModifiedMaterial(usedMaterial);
|
||||
submeshGraphic.canvasRenderer.SetMaterial(usedMaterial, referenceTextures[i]);
|
||||
submeshGraphic.canvasRenderer.SetMesh(referenceMeshes[i]);
|
||||
submeshGraphic.gameObject.SetActive(true);
|
||||
} else {
|
||||
submeshGraphic.canvasRenderer.Clear();
|
||||
submeshGraphic.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void DisableCanvasRenderers () {
|
||||
for (int i = 0; i < ownSubmeshGraphics.Count; i++) {
|
||||
SkeletonSubmeshGraphic submeshGraphic = ownSubmeshGraphics[i];
|
||||
submeshGraphic.canvasRenderer.Clear();
|
||||
submeshGraphic.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
protected Material GetReplacementMaterialFor (Material originalMaterial) {
|
||||
for (int i = 0; i < replacementMaterials.Length; ++i) {
|
||||
MaterialReplacement entry = replacementMaterials[i];
|
||||
if (entry.originalMaterial != null && entry.originalMaterial.shader == originalMaterial.shader)
|
||||
return entry.replacementMaterial;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
void LateUpdate () {
|
||||
if (!Application.isPlaying) {
|
||||
UpdateMesh();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void UpdateOnCallback (SkeletonGraphic g) {
|
||||
UpdateMesh();
|
||||
}
|
||||
|
||||
void UpdateMesh () {
|
||||
if (!referenceSkeletonGraphic) return;
|
||||
|
||||
if (referenceSkeletonGraphic.allowMultipleCanvasRenderers) {
|
||||
EnsureCanvasRendererCount(referenceSkeletonGraphic.canvasRenderers.Count);
|
||||
UpdateCanvasRenderers();
|
||||
if (ownGraphic)
|
||||
ownGraphic.canvasRenderer.Clear();
|
||||
} else {
|
||||
if (ownGraphic == null)
|
||||
ownGraphic = this.gameObject.AddComponent<SkeletonSubmeshGraphic>();
|
||||
|
||||
DisableCanvasRenderers();
|
||||
|
||||
Material referenceMaterial = referenceSkeletonGraphic.materialForRendering;
|
||||
Material usedMaterial = replacementMaterial != null ? replacementMaterial : GetReplacementMaterialFor(referenceMaterial);
|
||||
if (usedMaterial == null)
|
||||
usedMaterial = referenceMaterial;
|
||||
usedMaterial = referenceSkeletonGraphic.GetModifiedMaterial(usedMaterial);
|
||||
ownGraphic.canvasRenderer.SetMaterial(usedMaterial, referenceSkeletonGraphic.mainTexture);
|
||||
Mesh mesh = referenceSkeletonGraphic.GetLastMesh();
|
||||
ownGraphic.canvasRenderer.SetMesh(mesh);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/ThirdParty/Spine Examples/Scripts/Sample Components/RenderExistingMeshGraphic.cs.meta
vendored
Normal file
11
Assets/ThirdParty/Spine Examples/Scripts/Sample Components/RenderExistingMeshGraphic.cs.meta
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ff6ce4ce6b9336a479c6bf5af81fa80a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -1,77 +1,77 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
public class RootMotionDeltaCompensation : MonoBehaviour {
|
||||
|
||||
[SerializeField] protected SkeletonRootMotionBase rootMotion;
|
||||
public Transform targetPosition;
|
||||
public int trackIndex = 0;
|
||||
public bool adjustX = true;
|
||||
public bool adjustY = true;
|
||||
public float minScaleX = -999;
|
||||
public float minScaleY = -999;
|
||||
public float maxScaleX = 999;
|
||||
public float maxScaleY = 999;
|
||||
|
||||
public bool allowXTranslation = false;
|
||||
public bool allowYTranslation = true;
|
||||
|
||||
void Start () {
|
||||
if (rootMotion == null)
|
||||
rootMotion = this.GetComponent<SkeletonRootMotionBase>();
|
||||
}
|
||||
|
||||
void Update () {
|
||||
AdjustDelta();
|
||||
}
|
||||
|
||||
void OnDisable () {
|
||||
if (adjustX)
|
||||
rootMotion.rootMotionScaleX = 1;
|
||||
if (adjustY)
|
||||
rootMotion.rootMotionScaleY = 1;
|
||||
if (allowXTranslation)
|
||||
rootMotion.rootMotionTranslateXPerY = 0;
|
||||
if (allowYTranslation)
|
||||
rootMotion.rootMotionTranslateYPerX = 0;
|
||||
}
|
||||
|
||||
void AdjustDelta () {
|
||||
Vector3 toTarget = targetPosition.position - this.transform.position;
|
||||
rootMotion.AdjustRootMotionToDistance(toTarget, trackIndex, adjustX, adjustY,
|
||||
minScaleX, maxScaleX, minScaleY, maxScaleY,
|
||||
allowXTranslation, allowYTranslation);
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
public class RootMotionDeltaCompensation : MonoBehaviour {
|
||||
|
||||
[SerializeField] protected SkeletonRootMotionBase rootMotion;
|
||||
public Transform targetPosition;
|
||||
public int trackIndex = 0;
|
||||
public bool adjustX = true;
|
||||
public bool adjustY = true;
|
||||
public float minScaleX = -999;
|
||||
public float minScaleY = -999;
|
||||
public float maxScaleX = 999;
|
||||
public float maxScaleY = 999;
|
||||
|
||||
public bool allowXTranslation = false;
|
||||
public bool allowYTranslation = true;
|
||||
|
||||
void Start () {
|
||||
if (rootMotion == null)
|
||||
rootMotion = this.GetComponent<SkeletonRootMotionBase>();
|
||||
}
|
||||
|
||||
void Update () {
|
||||
AdjustDelta();
|
||||
}
|
||||
|
||||
void OnDisable () {
|
||||
if (adjustX)
|
||||
rootMotion.rootMotionScaleX = 1;
|
||||
if (adjustY)
|
||||
rootMotion.rootMotionScaleY = 1;
|
||||
if (allowXTranslation)
|
||||
rootMotion.rootMotionTranslateXPerY = 0;
|
||||
if (allowYTranslation)
|
||||
rootMotion.rootMotionTranslateYPerX = 0;
|
||||
}
|
||||
|
||||
void AdjustDelta () {
|
||||
Vector3 toTarget = targetPosition.position - this.transform.position;
|
||||
rootMotion.AdjustRootMotionToDistance(toTarget, trackIndex, adjustX, adjustY,
|
||||
minScaleX, maxScaleX, minScaleY, maxScaleY,
|
||||
allowXTranslation, allowYTranslation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,84 +1,84 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
// This is a sample component for C# vertex effects for Spine rendering components.
|
||||
// Using shaders and materials to control vertex properties is still more performant
|
||||
// than using this API, but in cases where your vertex effect logic cannot be
|
||||
// expressed as shader code, these vertex effects can be useful.
|
||||
public class JitterEffectExample : MonoBehaviour {
|
||||
|
||||
[Range(0f, 0.8f)]
|
||||
public float jitterMagnitude = 0.2f;
|
||||
|
||||
SkeletonRenderer skeletonRenderer;
|
||||
|
||||
void OnEnable () {
|
||||
skeletonRenderer = GetComponent<SkeletonRenderer>();
|
||||
if (skeletonRenderer == null) return;
|
||||
|
||||
// Use the OnPostProcessVertices callback to modify the vertices at the correct time.
|
||||
skeletonRenderer.OnPostProcessVertices -= ProcessVertices;
|
||||
skeletonRenderer.OnPostProcessVertices += ProcessVertices;
|
||||
|
||||
Debug.Log("Jitter Effect Enabled.");
|
||||
}
|
||||
|
||||
void ProcessVertices (MeshGeneratorBuffers buffers) {
|
||||
if (!this.enabled) return;
|
||||
|
||||
// For efficiency, limit your effect to the actual mesh vertex count using vertexCount
|
||||
int vertexCount = buffers.vertexCount;
|
||||
|
||||
// Modify vertex positions by accessing Vector3[] vertexBuffer
|
||||
Vector3[] vertices = buffers.vertexBuffer;
|
||||
for (int i = 0; i < vertexCount; i++)
|
||||
vertices[i] += (Vector3)(Random.insideUnitCircle * jitterMagnitude);
|
||||
|
||||
// You can also modify uvs and colors.
|
||||
//Vector2[] uvs = buffers.uvBuffer;
|
||||
//Color32[] colors = buffers.colorBuffer;
|
||||
|
||||
//
|
||||
}
|
||||
|
||||
void OnDisable () {
|
||||
if (skeletonRenderer == null) return;
|
||||
skeletonRenderer.OnPostProcessVertices -= ProcessVertices;
|
||||
|
||||
Debug.Log("Jitter Effect Disabled.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
// This is a sample component for C# vertex effects for Spine rendering components.
|
||||
// Using shaders and materials to control vertex properties is still more performant
|
||||
// than using this API, but in cases where your vertex effect logic cannot be
|
||||
// expressed as shader code, these vertex effects can be useful.
|
||||
public class JitterEffectExample : MonoBehaviour {
|
||||
|
||||
[Range(0f, 0.8f)]
|
||||
public float jitterMagnitude = 0.2f;
|
||||
|
||||
SkeletonRenderer skeletonRenderer;
|
||||
|
||||
void OnEnable () {
|
||||
skeletonRenderer = GetComponent<SkeletonRenderer>();
|
||||
if (skeletonRenderer == null) return;
|
||||
|
||||
// Use the OnPostProcessVertices callback to modify the vertices at the correct time.
|
||||
skeletonRenderer.OnPostProcessVertices -= ProcessVertices;
|
||||
skeletonRenderer.OnPostProcessVertices += ProcessVertices;
|
||||
|
||||
Debug.Log("Jitter Effect Enabled.");
|
||||
}
|
||||
|
||||
void ProcessVertices (MeshGeneratorBuffers buffers) {
|
||||
if (!this.enabled) return;
|
||||
|
||||
// For efficiency, limit your effect to the actual mesh vertex count using vertexCount
|
||||
int vertexCount = buffers.vertexCount;
|
||||
|
||||
// Modify vertex positions by accessing Vector3[] vertexBuffer
|
||||
Vector3[] vertices = buffers.vertexBuffer;
|
||||
for (int i = 0; i < vertexCount; i++)
|
||||
vertices[i] += (Vector3)(Random.insideUnitCircle * jitterMagnitude);
|
||||
|
||||
// You can also modify uvs and colors.
|
||||
//Vector2[] uvs = buffers.uvBuffer;
|
||||
//Color32[] colors = buffers.colorBuffer;
|
||||
|
||||
//
|
||||
}
|
||||
|
||||
void OnDisable () {
|
||||
if (skeletonRenderer == null) return;
|
||||
skeletonRenderer.OnPostProcessVertices -= ProcessVertices;
|
||||
|
||||
Debug.Log("Jitter Effect Disabled.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,105 +1,109 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
// This is a sample component for C# vertex effects for Spine rendering components.
|
||||
// Using shaders and materials to control vertex properties is still more performant
|
||||
// than using this API, but in cases where your vertex effect logic cannot be
|
||||
// expressed as shader code, these vertex effects can be useful.
|
||||
public class TwoByTwoTransformEffectExample : MonoBehaviour {
|
||||
|
||||
public Vector2 xAxis = new Vector2(1, 0);
|
||||
public Vector2 yAxis = new Vector2(0, 1);
|
||||
|
||||
SkeletonRenderer skeletonRenderer;
|
||||
|
||||
void OnEnable () {
|
||||
skeletonRenderer = GetComponent<SkeletonRenderer>();
|
||||
if (skeletonRenderer == null) return;
|
||||
|
||||
// Use the OnPostProcessVertices callback to modify the vertices at the correct time.
|
||||
skeletonRenderer.OnPostProcessVertices -= ProcessVertices;
|
||||
skeletonRenderer.OnPostProcessVertices += ProcessVertices;
|
||||
|
||||
Debug.Log("2x2 Transform Effect Enabled.");
|
||||
}
|
||||
|
||||
void ProcessVertices (MeshGeneratorBuffers buffers) {
|
||||
if (!this.enabled)
|
||||
return;
|
||||
|
||||
int vertexCount = buffers.vertexCount; // For efficiency, limit your effect to the actual mesh vertex count using vertexCount
|
||||
|
||||
// Modify vertex positions by accessing Vector3[] vertexBuffer
|
||||
Vector3[] vertices = buffers.vertexBuffer;
|
||||
Vector3 transformedPos = default(Vector3);
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
Vector3 originalPos = vertices[i];
|
||||
transformedPos.x = (xAxis.x * originalPos.x) + (yAxis.x * originalPos.y);
|
||||
transformedPos.y = (xAxis.y * originalPos.x) + (yAxis.y * originalPos.y);
|
||||
vertices[i] = transformedPos;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void OnDisable () {
|
||||
if (skeletonRenderer == null) return;
|
||||
skeletonRenderer.OnPostProcessVertices -= ProcessVertices;
|
||||
Debug.Log("2x2 Transform Effect Disabled.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[UnityEditor.CustomEditor(typeof(Spine.Unity.Examples.TwoByTwoTransformEffectExample))]
|
||||
public class TwoByTwoTransformEffectExampleEditor : UnityEditor.Editor {
|
||||
|
||||
Spine.Unity.Examples.TwoByTwoTransformEffectExample Target { get { return target as Spine.Unity.Examples.TwoByTwoTransformEffectExample; } }
|
||||
|
||||
void OnSceneGUI () {
|
||||
Transform transform = Target.transform;
|
||||
LocalVectorHandle(ref Target.xAxis, transform, Color.red);
|
||||
LocalVectorHandle(ref Target.yAxis, transform, Color.green);
|
||||
}
|
||||
|
||||
static void LocalVectorHandle (ref Vector2 v, Transform transform, Color color) {
|
||||
Color originalColor = UnityEditor.Handles.color;
|
||||
UnityEditor.Handles.color = color;
|
||||
UnityEditor.Handles.DrawLine(transform.position, transform.TransformPoint(v));
|
||||
v = transform.InverseTransformPoint(UnityEditor.Handles.FreeMoveHandle(transform.TransformPoint(v), Quaternion.identity, 0.3f, Vector3.zero, UnityEditor.Handles.CubeHandleCap));
|
||||
UnityEditor.Handles.color = originalColor;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
// This is a sample component for C# vertex effects for Spine rendering components.
|
||||
// Using shaders and materials to control vertex properties is still more performant
|
||||
// than using this API, but in cases where your vertex effect logic cannot be
|
||||
// expressed as shader code, these vertex effects can be useful.
|
||||
public class TwoByTwoTransformEffectExample : MonoBehaviour {
|
||||
|
||||
public Vector2 xAxis = new Vector2(1, 0);
|
||||
public Vector2 yAxis = new Vector2(0, 1);
|
||||
|
||||
SkeletonRenderer skeletonRenderer;
|
||||
|
||||
void OnEnable () {
|
||||
skeletonRenderer = GetComponent<SkeletonRenderer>();
|
||||
if (skeletonRenderer == null) return;
|
||||
|
||||
// Use the OnPostProcessVertices callback to modify the vertices at the correct time.
|
||||
skeletonRenderer.OnPostProcessVertices -= ProcessVertices;
|
||||
skeletonRenderer.OnPostProcessVertices += ProcessVertices;
|
||||
|
||||
Debug.Log("2x2 Transform Effect Enabled.");
|
||||
}
|
||||
|
||||
void ProcessVertices (MeshGeneratorBuffers buffers) {
|
||||
if (!this.enabled)
|
||||
return;
|
||||
|
||||
int vertexCount = buffers.vertexCount; // For efficiency, limit your effect to the actual mesh vertex count using vertexCount
|
||||
|
||||
// Modify vertex positions by accessing Vector3[] vertexBuffer
|
||||
Vector3[] vertices = buffers.vertexBuffer;
|
||||
Vector3 transformedPos = default(Vector3);
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
Vector3 originalPos = vertices[i];
|
||||
transformedPos.x = (xAxis.x * originalPos.x) + (yAxis.x * originalPos.y);
|
||||
transformedPos.y = (xAxis.y * originalPos.x) + (yAxis.y * originalPos.y);
|
||||
vertices[i] = transformedPos;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void OnDisable () {
|
||||
if (skeletonRenderer == null) return;
|
||||
skeletonRenderer.OnPostProcessVertices -= ProcessVertices;
|
||||
Debug.Log("2x2 Transform Effect Disabled.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[UnityEditor.CustomEditor(typeof(Spine.Unity.Examples.TwoByTwoTransformEffectExample))]
|
||||
public class TwoByTwoTransformEffectExampleEditor : UnityEditor.Editor {
|
||||
|
||||
Spine.Unity.Examples.TwoByTwoTransformEffectExample Target { get { return target as Spine.Unity.Examples.TwoByTwoTransformEffectExample; } }
|
||||
|
||||
void OnSceneGUI () {
|
||||
Transform transform = Target.transform;
|
||||
LocalVectorHandle(ref Target.xAxis, transform, Color.red);
|
||||
LocalVectorHandle(ref Target.yAxis, transform, Color.green);
|
||||
}
|
||||
|
||||
static void LocalVectorHandle (ref Vector2 v, Transform transform, Color color) {
|
||||
Color originalColor = UnityEditor.Handles.color;
|
||||
UnityEditor.Handles.color = color;
|
||||
UnityEditor.Handles.DrawLine(transform.position, transform.TransformPoint(v));
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
v = transform.InverseTransformPoint(UnityEditor.Handles.FreeMoveHandle(transform.TransformPoint(v), 0.3f, Vector3.zero, UnityEditor.Handles.CubeHandleCap));
|
||||
#else
|
||||
v = transform.InverseTransformPoint(UnityEditor.Handles.FreeMoveHandle(transform.TransformPoint(v), Quaternion.identity, 0.3f, Vector3.zero, UnityEditor.Handles.CubeHandleCap));
|
||||
#endif
|
||||
UnityEditor.Handles.color = originalColor;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1,53 +1,53 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
/// <summary>
|
||||
/// This component is intended to increase the physics solver iteration count
|
||||
/// for Rigidbody Joint setups which would otherwise be too unstable.
|
||||
///
|
||||
/// To use this example component, add it to a GameObject which is parent of
|
||||
/// one or more Rigidbody instances. The physics setting "solver iteration count"
|
||||
/// will be overwritten by the provided value.
|
||||
/// </summary>
|
||||
[DisallowMultipleComponent]
|
||||
public class SetRigidbodySolverIterations : MonoBehaviour {
|
||||
public int solverIterations = 30;
|
||||
|
||||
void Awake () {
|
||||
Rigidbody[] rigidbodies = this.GetComponentsInChildren<Rigidbody>();
|
||||
foreach (Rigidbody rigidbody in rigidbodies) {
|
||||
rigidbody.solverIterations = solverIterations;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
/// <summary>
|
||||
/// This component is intended to increase the physics solver iteration count
|
||||
/// for Rigidbody Joint setups which would otherwise be too unstable.
|
||||
///
|
||||
/// To use this example component, add it to a GameObject which is parent of
|
||||
/// one or more Rigidbody instances. The physics setting "solver iteration count"
|
||||
/// will be overwritten by the provided value.
|
||||
/// </summary>
|
||||
[DisallowMultipleComponent]
|
||||
public class SetRigidbodySolverIterations : MonoBehaviour {
|
||||
public int solverIterations = 30;
|
||||
|
||||
void Awake () {
|
||||
Rigidbody[] rigidbodies = this.GetComponentsInChildren<Rigidbody>();
|
||||
foreach (Rigidbody rigidbody in rigidbodies) {
|
||||
rigidbody.solverIterations = solverIterations;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,96 +1,96 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity {
|
||||
|
||||
// To use this example component, add it to your SkeletonAnimation Spine GameObject.
|
||||
// This component will disable that SkeletonAnimation component to prevent it from calling its own Update and LateUpdate methods.
|
||||
|
||||
[DisallowMultipleComponent]
|
||||
public sealed class SkeletonAnimationFixedTimestep : MonoBehaviour {
|
||||
#region Inspector
|
||||
public SkeletonAnimation skeletonAnimation;
|
||||
|
||||
[Tooltip("The duration of each frame in seconds. For 12 fps: enter '1/12' in the Unity inspector.")]
|
||||
public float frameDeltaTime = 1 / 15f;
|
||||
|
||||
[Header("Advanced")]
|
||||
[Tooltip("The maximum number of fixed timesteps. If the game framerate drops below the If the framerate is consistently faster than the limited frames, this does nothing.")]
|
||||
public int maxFrameSkip = 4;
|
||||
|
||||
[Tooltip("If enabled, the Skeleton mesh will be updated only on the same frame when the animation and skeleton are updated. Disable this or call SkeletonAnimation.LateUpdate yourself if you are modifying the Skeleton using other components that don't run in the same fixed timestep.")]
|
||||
public bool frameskipMeshUpdate = true;
|
||||
|
||||
[Tooltip("This is the amount the internal accumulator starts with. Set it to some fraction of your frame delta time if you want to stagger updates between multiple skeletons.")]
|
||||
public float timeOffset;
|
||||
#endregion
|
||||
|
||||
float accumulatedTime = 0;
|
||||
bool requiresNewMesh;
|
||||
|
||||
void OnValidate () {
|
||||
skeletonAnimation = GetComponent<SkeletonAnimation>();
|
||||
if (frameDeltaTime <= 0) frameDeltaTime = 1 / 60f;
|
||||
if (maxFrameSkip < 1) maxFrameSkip = 1;
|
||||
}
|
||||
|
||||
void Awake () {
|
||||
requiresNewMesh = true;
|
||||
accumulatedTime = timeOffset;
|
||||
}
|
||||
|
||||
void Update () {
|
||||
if (skeletonAnimation.enabled)
|
||||
skeletonAnimation.enabled = false;
|
||||
|
||||
accumulatedTime += Time.deltaTime;
|
||||
|
||||
float frames = 0;
|
||||
while (accumulatedTime >= frameDeltaTime) {
|
||||
frames++;
|
||||
if (frames > maxFrameSkip) break;
|
||||
accumulatedTime -= frameDeltaTime;
|
||||
}
|
||||
|
||||
if (frames > 0) {
|
||||
skeletonAnimation.Update(frames * frameDeltaTime);
|
||||
requiresNewMesh = true;
|
||||
}
|
||||
}
|
||||
|
||||
void LateUpdate () {
|
||||
if (frameskipMeshUpdate && !requiresNewMesh) return;
|
||||
|
||||
skeletonAnimation.LateUpdate();
|
||||
requiresNewMesh = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity {
|
||||
|
||||
// To use this example component, add it to your SkeletonAnimation Spine GameObject.
|
||||
// This component will disable that SkeletonAnimation component to prevent it from calling its own Update and LateUpdate methods.
|
||||
|
||||
[DisallowMultipleComponent]
|
||||
public sealed class SkeletonAnimationFixedTimestep : MonoBehaviour {
|
||||
#region Inspector
|
||||
public SkeletonAnimation skeletonAnimation;
|
||||
|
||||
[Tooltip("The duration of each frame in seconds. For 12 fps: enter '1/12' in the Unity inspector.")]
|
||||
public float frameDeltaTime = 1 / 15f;
|
||||
|
||||
[Header("Advanced")]
|
||||
[Tooltip("The maximum number of fixed timesteps. If the game framerate drops below the If the framerate is consistently faster than the limited frames, this does nothing.")]
|
||||
public int maxFrameSkip = 4;
|
||||
|
||||
[Tooltip("If enabled, the Skeleton mesh will be updated only on the same frame when the animation and skeleton are updated. Disable this or call SkeletonAnimation.LateUpdate yourself if you are modifying the Skeleton using other components that don't run in the same fixed timestep.")]
|
||||
public bool frameskipMeshUpdate = true;
|
||||
|
||||
[Tooltip("This is the amount the internal accumulator starts with. Set it to some fraction of your frame delta time if you want to stagger updates between multiple skeletons.")]
|
||||
public float timeOffset;
|
||||
#endregion
|
||||
|
||||
float accumulatedTime = 0;
|
||||
bool requiresNewMesh;
|
||||
|
||||
void OnValidate () {
|
||||
skeletonAnimation = GetComponent<SkeletonAnimation>();
|
||||
if (frameDeltaTime <= 0) frameDeltaTime = 1 / 60f;
|
||||
if (maxFrameSkip < 1) maxFrameSkip = 1;
|
||||
}
|
||||
|
||||
void Awake () {
|
||||
requiresNewMesh = true;
|
||||
accumulatedTime = timeOffset;
|
||||
}
|
||||
|
||||
void Update () {
|
||||
if (skeletonAnimation.enabled)
|
||||
skeletonAnimation.enabled = false;
|
||||
|
||||
accumulatedTime += Time.deltaTime;
|
||||
|
||||
float frames = 0;
|
||||
while (accumulatedTime >= frameDeltaTime) {
|
||||
frames++;
|
||||
if (frames > maxFrameSkip) break;
|
||||
accumulatedTime -= frameDeltaTime;
|
||||
}
|
||||
|
||||
if (frames > 0) {
|
||||
skeletonAnimation.Update(frames * frameDeltaTime);
|
||||
requiresNewMesh = true;
|
||||
}
|
||||
}
|
||||
|
||||
void LateUpdate () {
|
||||
if (frameskipMeshUpdate && !requiresNewMesh) return;
|
||||
|
||||
skeletonAnimation.LateUpdate();
|
||||
requiresNewMesh = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,168 +1,168 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine;
|
||||
using Spine.Unity;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity {
|
||||
|
||||
using Animation = Spine.Animation;
|
||||
using AnimationState = Spine.AnimationState;
|
||||
|
||||
public class SkeletonAnimationMulti : MonoBehaviour {
|
||||
const int MainTrackIndex = 0;
|
||||
|
||||
public bool initialFlipX, initialFlipY;
|
||||
public string initialAnimation;
|
||||
public bool initialLoop;
|
||||
[Space]
|
||||
public List<SkeletonDataAsset> skeletonDataAssets = new List<SkeletonDataAsset>();
|
||||
[Header("Settings")]
|
||||
public MeshGenerator.Settings meshGeneratorSettings = MeshGenerator.Settings.Default;
|
||||
|
||||
readonly List<SkeletonAnimation> skeletonAnimations = new List<SkeletonAnimation>();
|
||||
readonly Dictionary<string, Animation> animationNameTable = new Dictionary<string, Animation>();
|
||||
readonly Dictionary<Animation, SkeletonAnimation> animationSkeletonTable = new Dictionary<Animation, SkeletonAnimation>();
|
||||
//Stateful
|
||||
SkeletonAnimation currentSkeletonAnimation;
|
||||
|
||||
void Clear () {
|
||||
foreach (SkeletonAnimation skeletonAnimation in skeletonAnimations)
|
||||
Destroy(skeletonAnimation.gameObject);
|
||||
|
||||
skeletonAnimations.Clear();
|
||||
animationNameTable.Clear();
|
||||
animationSkeletonTable.Clear();
|
||||
}
|
||||
|
||||
void SetActiveSkeleton (int index) {
|
||||
if (index < 0 || index >= skeletonAnimations.Count)
|
||||
SetActiveSkeleton(null);
|
||||
else
|
||||
SetActiveSkeleton(skeletonAnimations[index]);
|
||||
}
|
||||
|
||||
void SetActiveSkeleton (SkeletonAnimation skeletonAnimation) {
|
||||
foreach (SkeletonAnimation iter in skeletonAnimations)
|
||||
iter.gameObject.SetActive(iter == skeletonAnimation);
|
||||
|
||||
currentSkeletonAnimation = skeletonAnimation;
|
||||
}
|
||||
|
||||
#region Lifecycle
|
||||
void Awake () {
|
||||
Initialize(false);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region API
|
||||
public Dictionary<Animation, SkeletonAnimation> AnimationSkeletonTable { get { return this.animationSkeletonTable; } }
|
||||
public Dictionary<string, Animation> AnimationNameTable { get { return this.animationNameTable; } }
|
||||
public SkeletonAnimation CurrentSkeletonAnimation { get { return this.currentSkeletonAnimation; } }
|
||||
public List<SkeletonAnimation> SkeletonAnimations { get { return skeletonAnimations; } }
|
||||
|
||||
public void Initialize (bool overwrite) {
|
||||
if (skeletonAnimations.Count != 0 && !overwrite) return;
|
||||
|
||||
Clear();
|
||||
|
||||
MeshGenerator.Settings settings = this.meshGeneratorSettings;
|
||||
Transform thisTransform = this.transform;
|
||||
foreach (SkeletonDataAsset dataAsset in skeletonDataAssets) {
|
||||
SkeletonAnimation newSkeletonAnimation = SkeletonAnimation.NewSkeletonAnimationGameObject(dataAsset);
|
||||
newSkeletonAnimation.transform.SetParent(thisTransform, false);
|
||||
|
||||
newSkeletonAnimation.SetMeshSettings(settings);
|
||||
newSkeletonAnimation.initialFlipX = this.initialFlipX;
|
||||
newSkeletonAnimation.initialFlipY = this.initialFlipY;
|
||||
Skeleton skeleton = newSkeletonAnimation.skeleton;
|
||||
skeleton.ScaleX = this.initialFlipX ? -1 : 1;
|
||||
skeleton.ScaleY = this.initialFlipY ? -1 : 1;
|
||||
|
||||
newSkeletonAnimation.Initialize(false);
|
||||
skeletonAnimations.Add(newSkeletonAnimation);
|
||||
}
|
||||
|
||||
// Build cache
|
||||
Dictionary<string, Animation> animationNameTable = this.animationNameTable;
|
||||
Dictionary<Animation, SkeletonAnimation> animationSkeletonTable = this.animationSkeletonTable;
|
||||
foreach (SkeletonAnimation skeletonAnimation in skeletonAnimations) {
|
||||
foreach (Animation animationObject in skeletonAnimation.Skeleton.Data.Animations) {
|
||||
animationNameTable[animationObject.Name] = animationObject;
|
||||
animationSkeletonTable[animationObject] = skeletonAnimation;
|
||||
}
|
||||
}
|
||||
|
||||
SetActiveSkeleton(skeletonAnimations[0]);
|
||||
SetAnimation(initialAnimation, initialLoop);
|
||||
}
|
||||
|
||||
public Animation FindAnimation (string animationName) {
|
||||
Animation animation;
|
||||
animationNameTable.TryGetValue(animationName, out animation);
|
||||
return animation;
|
||||
}
|
||||
|
||||
public TrackEntry SetAnimation (string animationName, bool loop) {
|
||||
return SetAnimation(FindAnimation(animationName), loop);
|
||||
}
|
||||
|
||||
public TrackEntry SetAnimation (Animation animation, bool loop) {
|
||||
if (animation == null) return null;
|
||||
|
||||
SkeletonAnimation skeletonAnimation;
|
||||
animationSkeletonTable.TryGetValue(animation, out skeletonAnimation);
|
||||
|
||||
if (skeletonAnimation != null) {
|
||||
SetActiveSkeleton(skeletonAnimation);
|
||||
skeletonAnimation.skeleton.SetToSetupPose();
|
||||
TrackEntry trackEntry = skeletonAnimation.state.SetAnimation(MainTrackIndex, animation, loop);
|
||||
skeletonAnimation.Update(0);
|
||||
return trackEntry;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void SetEmptyAnimation (float mixDuration) {
|
||||
currentSkeletonAnimation.state.SetEmptyAnimation(MainTrackIndex, mixDuration);
|
||||
}
|
||||
|
||||
public void ClearAnimation () {
|
||||
currentSkeletonAnimation.state.ClearTrack(MainTrackIndex);
|
||||
}
|
||||
|
||||
public TrackEntry GetCurrent () {
|
||||
return currentSkeletonAnimation.state.GetCurrent(MainTrackIndex);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine;
|
||||
using Spine.Unity;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity {
|
||||
|
||||
using Animation = Spine.Animation;
|
||||
using AnimationState = Spine.AnimationState;
|
||||
|
||||
public class SkeletonAnimationMulti : MonoBehaviour {
|
||||
const int MainTrackIndex = 0;
|
||||
|
||||
public bool initialFlipX, initialFlipY;
|
||||
public string initialAnimation;
|
||||
public bool initialLoop;
|
||||
[Space]
|
||||
public List<SkeletonDataAsset> skeletonDataAssets = new List<SkeletonDataAsset>();
|
||||
[Header("Settings")]
|
||||
public MeshGenerator.Settings meshGeneratorSettings = MeshGenerator.Settings.Default;
|
||||
|
||||
readonly List<SkeletonAnimation> skeletonAnimations = new List<SkeletonAnimation>();
|
||||
readonly Dictionary<string, Animation> animationNameTable = new Dictionary<string, Animation>();
|
||||
readonly Dictionary<Animation, SkeletonAnimation> animationSkeletonTable = new Dictionary<Animation, SkeletonAnimation>();
|
||||
//Stateful
|
||||
SkeletonAnimation currentSkeletonAnimation;
|
||||
|
||||
void Clear () {
|
||||
foreach (SkeletonAnimation skeletonAnimation in skeletonAnimations)
|
||||
Destroy(skeletonAnimation.gameObject);
|
||||
|
||||
skeletonAnimations.Clear();
|
||||
animationNameTable.Clear();
|
||||
animationSkeletonTable.Clear();
|
||||
}
|
||||
|
||||
void SetActiveSkeleton (int index) {
|
||||
if (index < 0 || index >= skeletonAnimations.Count)
|
||||
SetActiveSkeleton(null);
|
||||
else
|
||||
SetActiveSkeleton(skeletonAnimations[index]);
|
||||
}
|
||||
|
||||
void SetActiveSkeleton (SkeletonAnimation skeletonAnimation) {
|
||||
foreach (SkeletonAnimation iter in skeletonAnimations)
|
||||
iter.gameObject.SetActive(iter == skeletonAnimation);
|
||||
|
||||
currentSkeletonAnimation = skeletonAnimation;
|
||||
}
|
||||
|
||||
#region Lifecycle
|
||||
void Awake () {
|
||||
Initialize(false);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region API
|
||||
public Dictionary<Animation, SkeletonAnimation> AnimationSkeletonTable { get { return this.animationSkeletonTable; } }
|
||||
public Dictionary<string, Animation> AnimationNameTable { get { return this.animationNameTable; } }
|
||||
public SkeletonAnimation CurrentSkeletonAnimation { get { return this.currentSkeletonAnimation; } }
|
||||
public List<SkeletonAnimation> SkeletonAnimations { get { return skeletonAnimations; } }
|
||||
|
||||
public void Initialize (bool overwrite) {
|
||||
if (skeletonAnimations.Count != 0 && !overwrite) return;
|
||||
|
||||
Clear();
|
||||
|
||||
MeshGenerator.Settings settings = this.meshGeneratorSettings;
|
||||
Transform thisTransform = this.transform;
|
||||
foreach (SkeletonDataAsset dataAsset in skeletonDataAssets) {
|
||||
SkeletonAnimation newSkeletonAnimation = SkeletonAnimation.NewSkeletonAnimationGameObject(dataAsset);
|
||||
newSkeletonAnimation.transform.SetParent(thisTransform, false);
|
||||
|
||||
newSkeletonAnimation.SetMeshSettings(settings);
|
||||
newSkeletonAnimation.initialFlipX = this.initialFlipX;
|
||||
newSkeletonAnimation.initialFlipY = this.initialFlipY;
|
||||
Skeleton skeleton = newSkeletonAnimation.skeleton;
|
||||
skeleton.ScaleX = this.initialFlipX ? -1 : 1;
|
||||
skeleton.ScaleY = this.initialFlipY ? -1 : 1;
|
||||
|
||||
newSkeletonAnimation.Initialize(false);
|
||||
skeletonAnimations.Add(newSkeletonAnimation);
|
||||
}
|
||||
|
||||
// Build cache
|
||||
Dictionary<string, Animation> animationNameTable = this.animationNameTable;
|
||||
Dictionary<Animation, SkeletonAnimation> animationSkeletonTable = this.animationSkeletonTable;
|
||||
foreach (SkeletonAnimation skeletonAnimation in skeletonAnimations) {
|
||||
foreach (Animation animationObject in skeletonAnimation.Skeleton.Data.Animations) {
|
||||
animationNameTable[animationObject.Name] = animationObject;
|
||||
animationSkeletonTable[animationObject] = skeletonAnimation;
|
||||
}
|
||||
}
|
||||
|
||||
SetActiveSkeleton(skeletonAnimations[0]);
|
||||
SetAnimation(initialAnimation, initialLoop);
|
||||
}
|
||||
|
||||
public Animation FindAnimation (string animationName) {
|
||||
Animation animation;
|
||||
animationNameTable.TryGetValue(animationName, out animation);
|
||||
return animation;
|
||||
}
|
||||
|
||||
public TrackEntry SetAnimation (string animationName, bool loop) {
|
||||
return SetAnimation(FindAnimation(animationName), loop);
|
||||
}
|
||||
|
||||
public TrackEntry SetAnimation (Animation animation, bool loop) {
|
||||
if (animation == null) return null;
|
||||
|
||||
SkeletonAnimation skeletonAnimation;
|
||||
animationSkeletonTable.TryGetValue(animation, out skeletonAnimation);
|
||||
|
||||
if (skeletonAnimation != null) {
|
||||
SetActiveSkeleton(skeletonAnimation);
|
||||
skeletonAnimation.skeleton.SetToSetupPose();
|
||||
TrackEntry trackEntry = skeletonAnimation.state.SetAnimation(MainTrackIndex, animation, loop);
|
||||
skeletonAnimation.Update(0);
|
||||
return trackEntry;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void SetEmptyAnimation (float mixDuration) {
|
||||
currentSkeletonAnimation.state.SetEmptyAnimation(MainTrackIndex, mixDuration);
|
||||
}
|
||||
|
||||
public void ClearAnimation () {
|
||||
currentSkeletonAnimation.state.ClearTrack(MainTrackIndex);
|
||||
}
|
||||
|
||||
public TrackEntry GetCurrent () {
|
||||
return currentSkeletonAnimation.state.GetCurrent(MainTrackIndex);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,83 +1,83 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine;
|
||||
using Spine.Unity;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Prototyping {
|
||||
/// <summary>
|
||||
/// Stores and serializes initial settings for a Spine Skeleton component. The settings only get applied on Start at runtime.</summary>
|
||||
public class SkeletonColorInitialize : MonoBehaviour {
|
||||
public Color skeletonColor = Color.white;
|
||||
public List<SlotSettings> slotSettings = new List<SlotSettings>();
|
||||
|
||||
[System.Serializable]
|
||||
public class SlotSettings {
|
||||
[SpineSlot]
|
||||
public string slot = string.Empty;
|
||||
public Color color = Color.white;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
void OnValidate () {
|
||||
ISkeletonComponent skeletonComponent = GetComponent<ISkeletonComponent>();
|
||||
if (skeletonComponent != null) {
|
||||
skeletonComponent.Skeleton.SetSlotsToSetupPose();
|
||||
IAnimationStateComponent animationStateComponent = GetComponent<IAnimationStateComponent>();
|
||||
if (animationStateComponent != null && animationStateComponent.AnimationState != null) {
|
||||
animationStateComponent.AnimationState.Apply(skeletonComponent.Skeleton);
|
||||
}
|
||||
}
|
||||
ApplySettings();
|
||||
}
|
||||
#endif
|
||||
|
||||
void Start () {
|
||||
ApplySettings();
|
||||
}
|
||||
|
||||
void ApplySettings () {
|
||||
ISkeletonComponent skeletonComponent = GetComponent<ISkeletonComponent>();
|
||||
if (skeletonComponent != null) {
|
||||
Skeleton skeleton = skeletonComponent.Skeleton;
|
||||
skeleton.SetColor(skeletonColor);
|
||||
|
||||
foreach (SlotSettings s in slotSettings) {
|
||||
Slot slot = skeleton.FindSlot(s.slot);
|
||||
if (slot != null) slot.SetColor(s.color);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine;
|
||||
using Spine.Unity;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Prototyping {
|
||||
/// <summary>
|
||||
/// Stores and serializes initial settings for a Spine Skeleton component. The settings only get applied on Start at runtime.</summary>
|
||||
public class SkeletonColorInitialize : MonoBehaviour {
|
||||
public Color skeletonColor = Color.white;
|
||||
public List<SlotSettings> slotSettings = new List<SlotSettings>();
|
||||
|
||||
[System.Serializable]
|
||||
public class SlotSettings {
|
||||
[SpineSlot]
|
||||
public string slot = string.Empty;
|
||||
public Color color = Color.white;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
void OnValidate () {
|
||||
ISkeletonComponent skeletonComponent = GetComponent<ISkeletonComponent>();
|
||||
if (skeletonComponent != null) {
|
||||
skeletonComponent.Skeleton.SetSlotsToSetupPose();
|
||||
IAnimationStateComponent animationStateComponent = GetComponent<IAnimationStateComponent>();
|
||||
if (animationStateComponent != null && animationStateComponent.AnimationState != null) {
|
||||
animationStateComponent.AnimationState.Apply(skeletonComponent.Skeleton);
|
||||
}
|
||||
}
|
||||
ApplySettings();
|
||||
}
|
||||
#endif
|
||||
|
||||
void Start () {
|
||||
ApplySettings();
|
||||
}
|
||||
|
||||
void ApplySettings () {
|
||||
ISkeletonComponent skeletonComponent = GetComponent<ISkeletonComponent>();
|
||||
if (skeletonComponent != null) {
|
||||
Skeleton skeleton = skeletonComponent.Skeleton;
|
||||
skeleton.SetColor(skeletonColor);
|
||||
|
||||
foreach (SlotSettings s in slotSettings) {
|
||||
Slot slot = skeleton.FindSlot(s.slot);
|
||||
if (slot != null) slot.SetColor(s.color);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,104 +1,104 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class SkeletonGraphicMirror : MonoBehaviour {
|
||||
|
||||
public SkeletonRenderer source;
|
||||
public bool mirrorOnStart = true;
|
||||
public bool restoreOnDisable = true;
|
||||
SkeletonGraphic skeletonGraphic;
|
||||
|
||||
Skeleton originalSkeleton;
|
||||
bool originalFreeze;
|
||||
Texture2D overrideTexture;
|
||||
|
||||
private void Awake () {
|
||||
skeletonGraphic = GetComponent<SkeletonGraphic>();
|
||||
}
|
||||
|
||||
void Start () {
|
||||
if (mirrorOnStart)
|
||||
StartMirroring();
|
||||
}
|
||||
|
||||
void LateUpdate () {
|
||||
skeletonGraphic.UpdateMesh();
|
||||
}
|
||||
|
||||
void OnDisable () {
|
||||
if (restoreOnDisable)
|
||||
RestoreIndependentSkeleton();
|
||||
}
|
||||
|
||||
/// <summary>Freeze the SkeletonGraphic on this GameObject, and use the source as the Skeleton to be rendered by the SkeletonGraphic.</summary>
|
||||
public void StartMirroring () {
|
||||
if (source == null)
|
||||
return;
|
||||
if (skeletonGraphic == null)
|
||||
return;
|
||||
|
||||
skeletonGraphic.startingAnimation = string.Empty;
|
||||
|
||||
if (originalSkeleton == null) {
|
||||
originalSkeleton = skeletonGraphic.Skeleton;
|
||||
originalFreeze = skeletonGraphic.freeze;
|
||||
}
|
||||
|
||||
skeletonGraphic.Skeleton = source.skeleton;
|
||||
skeletonGraphic.freeze = true;
|
||||
if (overrideTexture != null)
|
||||
skeletonGraphic.OverrideTexture = overrideTexture;
|
||||
}
|
||||
|
||||
/// <summary>Use a new texture for the SkeletonGraphic. Use this if your source skeleton uses a repacked atlas. </summary>
|
||||
public void UpdateTexture (Texture2D newOverrideTexture) {
|
||||
overrideTexture = newOverrideTexture;
|
||||
if (newOverrideTexture != null)
|
||||
skeletonGraphic.OverrideTexture = overrideTexture;
|
||||
}
|
||||
|
||||
/// <summary>Stops mirroring the source SkeletonRenderer and allows the SkeletonGraphic to become an independent Skeleton component again.</summary>
|
||||
public void RestoreIndependentSkeleton () {
|
||||
if (originalSkeleton == null)
|
||||
return;
|
||||
|
||||
skeletonGraphic.Skeleton = originalSkeleton;
|
||||
skeletonGraphic.freeze = originalFreeze;
|
||||
skeletonGraphic.OverrideTexture = null;
|
||||
|
||||
originalSkeleton = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class SkeletonGraphicMirror : MonoBehaviour {
|
||||
|
||||
public SkeletonRenderer source;
|
||||
public bool mirrorOnStart = true;
|
||||
public bool restoreOnDisable = true;
|
||||
SkeletonGraphic skeletonGraphic;
|
||||
|
||||
Skeleton originalSkeleton;
|
||||
bool originalFreeze;
|
||||
Texture2D overrideTexture;
|
||||
|
||||
private void Awake () {
|
||||
skeletonGraphic = GetComponent<SkeletonGraphic>();
|
||||
}
|
||||
|
||||
void Start () {
|
||||
if (mirrorOnStart)
|
||||
StartMirroring();
|
||||
}
|
||||
|
||||
void LateUpdate () {
|
||||
skeletonGraphic.UpdateMesh();
|
||||
}
|
||||
|
||||
void OnDisable () {
|
||||
if (restoreOnDisable)
|
||||
RestoreIndependentSkeleton();
|
||||
}
|
||||
|
||||
/// <summary>Freeze the SkeletonGraphic on this GameObject, and use the source as the Skeleton to be rendered by the SkeletonGraphic.</summary>
|
||||
public void StartMirroring () {
|
||||
if (source == null)
|
||||
return;
|
||||
if (skeletonGraphic == null)
|
||||
return;
|
||||
|
||||
skeletonGraphic.startingAnimation = string.Empty;
|
||||
|
||||
if (originalSkeleton == null) {
|
||||
originalSkeleton = skeletonGraphic.Skeleton;
|
||||
originalFreeze = skeletonGraphic.freeze;
|
||||
}
|
||||
|
||||
skeletonGraphic.Skeleton = source.skeleton;
|
||||
skeletonGraphic.freeze = true;
|
||||
if (overrideTexture != null)
|
||||
skeletonGraphic.OverrideTexture = overrideTexture;
|
||||
}
|
||||
|
||||
/// <summary>Use a new texture for the SkeletonGraphic. Use this if your source skeleton uses a repacked atlas. </summary>
|
||||
public void UpdateTexture (Texture2D newOverrideTexture) {
|
||||
overrideTexture = newOverrideTexture;
|
||||
if (newOverrideTexture != null)
|
||||
skeletonGraphic.OverrideTexture = overrideTexture;
|
||||
}
|
||||
|
||||
/// <summary>Stops mirroring the source SkeletonRenderer and allows the SkeletonGraphic to become an independent Skeleton component again.</summary>
|
||||
public void RestoreIndependentSkeleton () {
|
||||
if (originalSkeleton == null)
|
||||
return;
|
||||
|
||||
skeletonGraphic.Skeleton = originalSkeleton;
|
||||
skeletonGraphic.freeze = originalFreeze;
|
||||
skeletonGraphic.OverrideTexture = null;
|
||||
|
||||
originalSkeleton = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,52 +1,52 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity;
|
||||
using UnityEngine;
|
||||
|
||||
public class SkeletonGraphicPlayAnimationAtEvent : MonoBehaviour {
|
||||
|
||||
public SkeletonGraphic skeletonGraphic;
|
||||
public int trackIndex = 0;
|
||||
public float playbackSpeed = 1.0f;
|
||||
|
||||
public void PlayAnimationLooping (string animation) {
|
||||
Spine.TrackEntry entry = skeletonGraphic.AnimationState.SetAnimation(trackIndex, animation, true);
|
||||
entry.TimeScale = playbackSpeed;
|
||||
}
|
||||
|
||||
public void PlayAnimationOnce (string animation) {
|
||||
Spine.TrackEntry entry = skeletonGraphic.AnimationState.SetAnimation(trackIndex, animation, false);
|
||||
entry.TimeScale = playbackSpeed;
|
||||
}
|
||||
|
||||
public void ClearTrack () {
|
||||
skeletonGraphic.AnimationState.ClearTrack(trackIndex);
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity;
|
||||
using UnityEngine;
|
||||
|
||||
public class SkeletonGraphicPlayAnimationAtEvent : MonoBehaviour {
|
||||
|
||||
public SkeletonGraphic skeletonGraphic;
|
||||
public int trackIndex = 0;
|
||||
public float playbackSpeed = 1.0f;
|
||||
|
||||
public void PlayAnimationLooping (string animation) {
|
||||
Spine.TrackEntry entry = skeletonGraphic.AnimationState.SetAnimation(trackIndex, animation, true);
|
||||
entry.TimeScale = playbackSpeed;
|
||||
}
|
||||
|
||||
public void PlayAnimationOnce (string animation) {
|
||||
Spine.TrackEntry entry = skeletonGraphic.AnimationState.SetAnimation(trackIndex, animation, false);
|
||||
entry.TimeScale = playbackSpeed;
|
||||
}
|
||||
|
||||
public void ClearTrack () {
|
||||
skeletonGraphic.AnimationState.ClearTrack(trackIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,106 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: RenderQuadGraphicMaterial
|
||||
m_Shader: {fileID: 4800000, guid: fa95b0fb6983c0f40a152e6f9aa82bfb, type: 3}
|
||||
m_Parent: {fileID: 0}
|
||||
m_ModifiedSerializedProperties: 0
|
||||
m_ValidKeywords:
|
||||
- _CANVAS_GROUP_COMPATIBLE
|
||||
m_InvalidKeywords:
|
||||
- _ALPHAPREMULTIPLY_ON
|
||||
- _USE8NEIGHBOURHOOD_ON
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_LockedProperties:
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _BumpScale: 1
|
||||
- _CanvasGroupCompatible: 1
|
||||
- _ColorMask: 15
|
||||
- _Cutoff: 0.5
|
||||
- _DarkColorAlphaAdditive: 0
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 10
|
||||
- _GlossMapScale: 1
|
||||
- _Glossiness: 0.5
|
||||
- _GlossyReflections: 1
|
||||
- _Metallic: 0
|
||||
- _Mode: 3
|
||||
- _OcclusionStrength: 1
|
||||
- _OutlineMipLevel: 0
|
||||
- _OutlineOpaqueAlpha: 1
|
||||
- _OutlineReferenceTexWidth: 1024
|
||||
- _OutlineSmoothness: 1
|
||||
- _OutlineWidth: 3
|
||||
- _Parallax: 0.02
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _Stencil: 0
|
||||
- _StencilComp: 8
|
||||
- _StencilOp: 0
|
||||
- _StencilReadMask: 255
|
||||
- _StencilRef: 1
|
||||
- _StencilWriteMask: 255
|
||||
- _StraightAlphaInput: 0
|
||||
- _ThresholdEnd: 0.25
|
||||
- _UVSec: 0
|
||||
- _Use8Neighbourhood: 1
|
||||
- _UseUIAlphaClip: 0
|
||||
- _ZWrite: 0
|
||||
m_Colors:
|
||||
- _Black: {r: 0, g: 0, b: 0, a: 0}
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
- _OutlineColor: {r: 1, g: 1, b: 0, a: 1}
|
||||
m_BuildTextureStacks: []
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: afeb0ae2ea2cda94796515bf8d1b3cb1
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -1,260 +1,295 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2022, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
#define HAS_VECTOR2INT
|
||||
#endif
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
/// <summary>
|
||||
/// When enabled, this component renders a skeleton to a RenderTexture and
|
||||
/// then draws this RenderTexture at a UI RawImage quad of the same size.
|
||||
/// This allows changing transparency at a single quad, which produces a more
|
||||
/// natural fadeout effect.
|
||||
/// Note: It is recommended to keep this component disabled as much as possible
|
||||
/// because of the additional rendering overhead. Only enable it when alpha blending is required.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(SkeletonGraphic))]
|
||||
public class SkeletonGraphicRenderTexture : SkeletonRenderTextureBase {
|
||||
#if HAS_VECTOR2INT
|
||||
[System.Serializable]
|
||||
public struct TextureMaterialPair {
|
||||
public Texture texture;
|
||||
public Material material;
|
||||
|
||||
public TextureMaterialPair (Texture texture, Material material) {
|
||||
this.texture = texture;
|
||||
this.material = material;
|
||||
}
|
||||
}
|
||||
|
||||
public RectTransform customRenderRect;
|
||||
protected SkeletonGraphic skeletonGraphic;
|
||||
public List<TextureMaterialPair> meshRendererMaterialForTexture = new List<TextureMaterialPair>();
|
||||
protected CanvasRenderer quadCanvasRenderer;
|
||||
protected RawImage quadRawImage;
|
||||
protected readonly Vector3[] worldCorners = new Vector3[4];
|
||||
|
||||
protected override void Awake () {
|
||||
base.Awake();
|
||||
skeletonGraphic = this.GetComponent<SkeletonGraphic>();
|
||||
if (targetCamera == null) {
|
||||
targetCamera = skeletonGraphic.canvas.worldCamera;
|
||||
if (targetCamera == null)
|
||||
targetCamera = Camera.main;
|
||||
}
|
||||
CreateQuadChild();
|
||||
}
|
||||
|
||||
void CreateQuadChild () {
|
||||
quad = new GameObject(this.name + " RenderTexture", typeof(CanvasRenderer), typeof(RawImage));
|
||||
quad.transform.SetParent(this.transform.parent, false);
|
||||
quadCanvasRenderer = quad.GetComponent<CanvasRenderer>();
|
||||
quadRawImage = quad.GetComponent<RawImage>();
|
||||
|
||||
quadMesh = new Mesh();
|
||||
quadMesh.MarkDynamic();
|
||||
quadMesh.name = "RenderTexture Quad";
|
||||
quadMesh.hideFlags = HideFlags.DontSaveInBuild | HideFlags.DontSaveInEditor;
|
||||
}
|
||||
|
||||
void Reset () {
|
||||
skeletonGraphic = this.GetComponent<SkeletonGraphic>();
|
||||
AtlasAssetBase[] atlasAssets = skeletonGraphic.SkeletonDataAsset.atlasAssets;
|
||||
for (int i = 0; i < atlasAssets.Length; ++i) {
|
||||
foreach (Material material in atlasAssets[i].Materials) {
|
||||
if (material.mainTexture != null) {
|
||||
meshRendererMaterialForTexture.Add(
|
||||
new TextureMaterialPair(material.mainTexture, material));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnEnable () {
|
||||
skeletonGraphic.OnInstructionsPrepared += PrepareQuad;
|
||||
skeletonGraphic.AssignMeshOverrideSingleRenderer += RenderSingleMeshToRenderTexture;
|
||||
skeletonGraphic.AssignMeshOverrideMultipleRenderers += RenderMultipleMeshesToRenderTexture;
|
||||
skeletonGraphic.disableMeshAssignmentOnOverride = true;
|
||||
skeletonGraphic.OnMeshAndMaterialsUpdated += RenderOntoQuad;
|
||||
List<CanvasRenderer> canvasRenderers = skeletonGraphic.canvasRenderers;
|
||||
for (int i = 0; i < canvasRenderers.Count; ++i)
|
||||
canvasRenderers[i].cull = true;
|
||||
|
||||
if (quadCanvasRenderer)
|
||||
quadCanvasRenderer.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
void OnDisable () {
|
||||
skeletonGraphic.OnInstructionsPrepared -= PrepareQuad;
|
||||
skeletonGraphic.AssignMeshOverrideSingleRenderer -= RenderSingleMeshToRenderTexture;
|
||||
skeletonGraphic.AssignMeshOverrideMultipleRenderers -= RenderMultipleMeshesToRenderTexture;
|
||||
skeletonGraphic.disableMeshAssignmentOnOverride = false;
|
||||
skeletonGraphic.OnMeshAndMaterialsUpdated -= RenderOntoQuad;
|
||||
List<CanvasRenderer> canvasRenderers = skeletonGraphic.canvasRenderers;
|
||||
for (int i = 0; i < canvasRenderers.Count; ++i)
|
||||
canvasRenderers[i].cull = false;
|
||||
|
||||
if (quadCanvasRenderer)
|
||||
quadCanvasRenderer.gameObject.SetActive(false);
|
||||
if (renderTexture)
|
||||
RenderTexture.ReleaseTemporary(renderTexture);
|
||||
allocatedRenderTextureSize = Vector2Int.zero;
|
||||
}
|
||||
|
||||
void PrepareQuad (SkeletonRendererInstruction instruction) {
|
||||
PrepareForMesh();
|
||||
SetupQuad();
|
||||
}
|
||||
|
||||
void RenderOntoQuad (SkeletonGraphic skeletonRenderer) {
|
||||
AssignAtQuad();
|
||||
}
|
||||
|
||||
protected void PrepareForMesh () {
|
||||
// We need to get the min/max of all four corners, rotation of the skeleton
|
||||
// in combination with perspective projection otherwise might lead to incorrect
|
||||
// screen space min/max.
|
||||
RectTransform rectTransform = customRenderRect ? customRenderRect : skeletonGraphic.rectTransform;
|
||||
rectTransform.GetWorldCorners(worldCorners);
|
||||
|
||||
RenderMode canvasRenderMode = skeletonGraphic.canvas.renderMode;
|
||||
Vector3 screenCorner0, screenCorner1, screenCorner2, screenCorner3;
|
||||
// note: world corners are ordered bottom left, top left, top right, bottom right.
|
||||
// This corresponds to 0, 3, 1, 2 in our desired order.
|
||||
if (canvasRenderMode == RenderMode.ScreenSpaceOverlay) {
|
||||
screenCorner0 = worldCorners[0];
|
||||
screenCorner1 = worldCorners[3];
|
||||
screenCorner2 = worldCorners[1];
|
||||
screenCorner3 = worldCorners[2];
|
||||
} else {
|
||||
screenCorner0 = targetCamera.WorldToScreenPoint(worldCorners[0]);
|
||||
screenCorner1 = targetCamera.WorldToScreenPoint(worldCorners[3]);
|
||||
screenCorner2 = targetCamera.WorldToScreenPoint(worldCorners[1]);
|
||||
screenCorner3 = targetCamera.WorldToScreenPoint(worldCorners[2]);
|
||||
}
|
||||
|
||||
// To avoid perspective distortion when rotated, we project all vertices
|
||||
// onto a plane parallel to the view frustum near plane.
|
||||
// Avoids the requirement of 'noperspective' vertex attribute interpolation modifier in shaders.
|
||||
float averageScreenDepth = (screenCorner0.z + screenCorner1.z + screenCorner2.z + screenCorner3.z) / 4.0f;
|
||||
screenCorner0.z = screenCorner1.z = screenCorner2.z = screenCorner3.z = averageScreenDepth;
|
||||
|
||||
if (canvasRenderMode == RenderMode.ScreenSpaceOverlay) {
|
||||
worldCornerNoDistortion0 = screenCorner0;
|
||||
worldCornerNoDistortion1 = screenCorner1;
|
||||
worldCornerNoDistortion2 = screenCorner2;
|
||||
worldCornerNoDistortion3 = screenCorner3;
|
||||
} else {
|
||||
worldCornerNoDistortion0 = targetCamera.ScreenToWorldPoint(screenCorner0);
|
||||
worldCornerNoDistortion1 = targetCamera.ScreenToWorldPoint(screenCorner1);
|
||||
worldCornerNoDistortion2 = targetCamera.ScreenToWorldPoint(screenCorner2);
|
||||
worldCornerNoDistortion3 = targetCamera.ScreenToWorldPoint(screenCorner3);
|
||||
}
|
||||
Vector3 screenSpaceMin, screenSpaceMax;
|
||||
PrepareTextureMapping(out screenSpaceMin, out screenSpaceMax,
|
||||
screenCorner0, screenCorner1, screenCorner2, screenCorner3);
|
||||
PrepareCommandBuffer(targetCamera, screenSpaceMin, screenSpaceMax);
|
||||
}
|
||||
|
||||
protected Material MeshRendererMaterialForTexture (Texture texture) {
|
||||
return meshRendererMaterialForTexture.Find(x => x.texture == texture).material;
|
||||
}
|
||||
|
||||
protected void RenderSingleMeshToRenderTexture (Mesh mesh, Material graphicMaterial, Texture texture) {
|
||||
Material meshRendererMaterial = MeshRendererMaterialForTexture(texture);
|
||||
commandBuffer.DrawMesh(mesh, transform.localToWorldMatrix, meshRendererMaterial, 0, -1);
|
||||
Graphics.ExecuteCommandBuffer(commandBuffer);
|
||||
}
|
||||
|
||||
protected void RenderMultipleMeshesToRenderTexture (int meshCount,
|
||||
Mesh[] meshes, Material[] graphicMaterials, Texture[] textures) {
|
||||
|
||||
for (int i = 0; i < meshCount; ++i) {
|
||||
Material meshRendererMaterial = MeshRendererMaterialForTexture(textures[i]);
|
||||
commandBuffer.DrawMesh(meshes[i], transform.localToWorldMatrix, meshRendererMaterial, 0, -1);
|
||||
}
|
||||
Graphics.ExecuteCommandBuffer(commandBuffer);
|
||||
}
|
||||
|
||||
protected void SetupQuad () {
|
||||
quadRawImage.texture = this.renderTexture;
|
||||
quadRawImage.color = color;
|
||||
quadCanvasRenderer.SetColor(color);
|
||||
|
||||
RectTransform srcRectTransform = skeletonGraphic.rectTransform;
|
||||
RectTransform dstRectTransform = quadRawImage.rectTransform;
|
||||
|
||||
dstRectTransform.anchorMin = srcRectTransform.anchorMin;
|
||||
dstRectTransform.anchorMax = srcRectTransform.anchorMax;
|
||||
dstRectTransform.anchoredPosition = srcRectTransform.anchoredPosition;
|
||||
dstRectTransform.pivot = srcRectTransform.pivot;
|
||||
dstRectTransform.localScale = srcRectTransform.localScale;
|
||||
dstRectTransform.sizeDelta = srcRectTransform.sizeDelta;
|
||||
dstRectTransform.rotation = srcRectTransform.rotation;
|
||||
}
|
||||
|
||||
protected void PrepareCommandBuffer (Camera targetCamera, Vector3 screenSpaceMin, Vector3 screenSpaceMax) {
|
||||
commandBuffer.Clear();
|
||||
commandBuffer.SetRenderTarget(renderTexture);
|
||||
commandBuffer.ClearRenderTarget(true, true, Color.clear);
|
||||
|
||||
Rect canvasRect = skeletonGraphic.canvas.pixelRect;
|
||||
|
||||
Matrix4x4 projectionMatrix = Matrix4x4.Ortho(
|
||||
canvasRect.x, canvasRect.x + canvasRect.width,
|
||||
canvasRect.y, canvasRect.y + canvasRect.height,
|
||||
float.MinValue, float.MaxValue);
|
||||
|
||||
RenderMode canvasRenderMode = skeletonGraphic.canvas.renderMode;
|
||||
if (canvasRenderMode == RenderMode.ScreenSpaceOverlay) {
|
||||
commandBuffer.SetViewMatrix(Matrix4x4.identity);
|
||||
commandBuffer.SetProjectionMatrix(projectionMatrix);
|
||||
} else {
|
||||
commandBuffer.SetViewMatrix(targetCamera.worldToCameraMatrix);
|
||||
commandBuffer.SetProjectionMatrix(targetCamera.projectionMatrix);
|
||||
}
|
||||
|
||||
Vector2 targetCameraViewportSize = targetCamera.pixelRect.size;
|
||||
Rect viewportRect = new Rect(-screenSpaceMin * downScaleFactor, targetCameraViewportSize * downScaleFactor);
|
||||
commandBuffer.SetViewport(viewportRect);
|
||||
}
|
||||
|
||||
protected override void AssignMeshAtRenderer () {
|
||||
quadCanvasRenderer.SetMesh(quadMesh);
|
||||
}
|
||||
#endif // HAS_VECTOR2INT
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
#define HAS_VECTOR2INT
|
||||
#endif
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
/// <summary>
|
||||
/// When enabled, this component renders a skeleton to a RenderTexture and
|
||||
/// then draws this RenderTexture at a UI SkeletonSubmeshGraphic quad of the same size.
|
||||
/// This allows changing transparency at a single quad, which produces a more
|
||||
/// natural fadeout effect.
|
||||
/// Note: It is recommended to keep this component disabled as much as possible
|
||||
/// because of the additional rendering overhead. Only enable it when alpha blending is required.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(SkeletonGraphic))]
|
||||
public class SkeletonGraphicRenderTexture : SkeletonRenderTextureBase {
|
||||
#if HAS_VECTOR2INT
|
||||
[System.Serializable]
|
||||
public struct TextureMaterialPair {
|
||||
public Texture texture;
|
||||
public Material material;
|
||||
|
||||
public TextureMaterialPair (Texture texture, Material material) {
|
||||
this.texture = texture;
|
||||
this.material = material;
|
||||
}
|
||||
}
|
||||
|
||||
public RectTransform customRenderRect;
|
||||
protected SkeletonGraphic skeletonGraphic;
|
||||
public List<TextureMaterialPair> meshRendererMaterialForTexture = new List<TextureMaterialPair>();
|
||||
protected CanvasRenderer quadCanvasRenderer;
|
||||
protected SkeletonSubmeshGraphic quadMaskableGraphic;
|
||||
protected readonly Vector3[] worldCorners = new Vector3[4];
|
||||
|
||||
public void ResetMeshRendererMaterials () {
|
||||
meshRendererMaterialForTexture.Clear();
|
||||
AtlasAssetBase[] atlasAssets = skeletonGraphic.SkeletonDataAsset.atlasAssets;
|
||||
for (int i = 0; i < atlasAssets.Length; ++i) {
|
||||
foreach (Material material in atlasAssets[i].Materials) {
|
||||
if (material.mainTexture != null) {
|
||||
meshRendererMaterialForTexture.Add(
|
||||
new TextureMaterialPair(material.mainTexture, material));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Awake () {
|
||||
base.Awake();
|
||||
skeletonGraphic = this.GetComponent<SkeletonGraphic>();
|
||||
if (targetCamera == null) {
|
||||
targetCamera = skeletonGraphic.canvas.worldCamera;
|
||||
if (targetCamera == null)
|
||||
targetCamera = Camera.main;
|
||||
}
|
||||
CreateQuadChild();
|
||||
}
|
||||
|
||||
void CreateQuadChild () {
|
||||
quad = new GameObject(this.name + " RenderTexture", typeof(CanvasRenderer), typeof(SkeletonSubmeshGraphic));
|
||||
quad.transform.SetParent(this.transform.parent, false);
|
||||
quadCanvasRenderer = quad.GetComponent<CanvasRenderer>();
|
||||
quadMaskableGraphic = quad.GetComponent<SkeletonSubmeshGraphic>();
|
||||
|
||||
quadMesh = new Mesh();
|
||||
quadMesh.MarkDynamic();
|
||||
quadMesh.name = "RenderTexture Quad";
|
||||
quadMesh.hideFlags = HideFlags.DontSaveInBuild | HideFlags.DontSaveInEditor;
|
||||
|
||||
if (quadMaterial == null) {
|
||||
quadMaterial = new Material(Shader.Find("Spine/SkeletonGraphic"));
|
||||
quadMaterial.EnableKeyword("_CANVAS_GROUP_COMPATIBLE");
|
||||
}
|
||||
}
|
||||
|
||||
void Reset () {
|
||||
skeletonGraphic = this.GetComponent<SkeletonGraphic>();
|
||||
ResetMeshRendererMaterials();
|
||||
#if UNITY_EDITOR
|
||||
string[] assets = UnityEditor.AssetDatabase.FindAssets("t:material RenderQuadGraphicMaterial");
|
||||
if (assets.Length > 0) {
|
||||
string materialPath = UnityEditor.AssetDatabase.GUIDToAssetPath(assets[0]);
|
||||
quadMaterial = UnityEditor.AssetDatabase.LoadAssetAtPath<Material>(materialPath);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void OnEnable () {
|
||||
skeletonGraphic.OnInstructionsPrepared += PrepareQuad;
|
||||
skeletonGraphic.AssignMeshOverrideSingleRenderer += RenderSingleMeshToRenderTexture;
|
||||
skeletonGraphic.AssignMeshOverrideMultipleRenderers += RenderMultipleMeshesToRenderTexture;
|
||||
skeletonGraphic.disableMeshAssignmentOnOverride = true;
|
||||
skeletonGraphic.OnMeshAndMaterialsUpdated += RenderOntoQuad;
|
||||
skeletonGraphic.OnAnimationRebuild += OnRebuild;
|
||||
List<CanvasRenderer> canvasRenderers = skeletonGraphic.canvasRenderers;
|
||||
for (int i = 0; i < canvasRenderers.Count; ++i)
|
||||
canvasRenderers[i].cull = true;
|
||||
|
||||
if (quadCanvasRenderer)
|
||||
quadCanvasRenderer.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
void OnDisable () {
|
||||
skeletonGraphic.OnInstructionsPrepared -= PrepareQuad;
|
||||
skeletonGraphic.AssignMeshOverrideSingleRenderer -= RenderSingleMeshToRenderTexture;
|
||||
skeletonGraphic.AssignMeshOverrideMultipleRenderers -= RenderMultipleMeshesToRenderTexture;
|
||||
skeletonGraphic.disableMeshAssignmentOnOverride = false;
|
||||
skeletonGraphic.OnMeshAndMaterialsUpdated -= RenderOntoQuad;
|
||||
skeletonGraphic.OnAnimationRebuild -= OnRebuild;
|
||||
List<CanvasRenderer> canvasRenderers = skeletonGraphic.canvasRenderers;
|
||||
for (int i = 0; i < canvasRenderers.Count; ++i)
|
||||
canvasRenderers[i].cull = false;
|
||||
|
||||
if (quadCanvasRenderer)
|
||||
quadCanvasRenderer.gameObject.SetActive(false);
|
||||
if (renderTexture)
|
||||
RenderTexture.ReleaseTemporary(renderTexture);
|
||||
allocatedRenderTextureSize = Vector2Int.zero;
|
||||
}
|
||||
|
||||
void PrepareQuad (SkeletonRendererInstruction instruction) {
|
||||
PrepareForMesh();
|
||||
SetupQuad();
|
||||
}
|
||||
|
||||
void RenderOntoQuad (SkeletonGraphic skeletonRenderer) {
|
||||
AssignAtQuad();
|
||||
}
|
||||
|
||||
void OnRebuild (ISkeletonAnimation skeletonGraphic) {
|
||||
ResetMeshRendererMaterials();
|
||||
}
|
||||
|
||||
protected void PrepareForMesh () {
|
||||
// We need to get the min/max of all four corners, rotation of the skeleton
|
||||
// in combination with perspective projection otherwise might lead to incorrect
|
||||
// screen space min/max.
|
||||
RectTransform rectTransform = customRenderRect ? customRenderRect : skeletonGraphic.rectTransform;
|
||||
rectTransform.GetWorldCorners(worldCorners);
|
||||
|
||||
RenderMode canvasRenderMode = skeletonGraphic.canvas.renderMode;
|
||||
Vector3 screenCorner0, screenCorner1, screenCorner2, screenCorner3;
|
||||
// note: world corners are ordered bottom left, top left, top right, bottom right.
|
||||
// This corresponds to 0, 3, 1, 2 in our desired order.
|
||||
if (canvasRenderMode == RenderMode.ScreenSpaceOverlay) {
|
||||
screenCorner0 = worldCorners[0];
|
||||
screenCorner1 = worldCorners[3];
|
||||
screenCorner2 = worldCorners[1];
|
||||
screenCorner3 = worldCorners[2];
|
||||
} else {
|
||||
screenCorner0 = targetCamera.WorldToScreenPoint(worldCorners[0]);
|
||||
screenCorner1 = targetCamera.WorldToScreenPoint(worldCorners[3]);
|
||||
screenCorner2 = targetCamera.WorldToScreenPoint(worldCorners[1]);
|
||||
screenCorner3 = targetCamera.WorldToScreenPoint(worldCorners[2]);
|
||||
}
|
||||
|
||||
// To avoid perspective distortion when rotated, we project all vertices
|
||||
// onto a plane parallel to the view frustum near plane.
|
||||
// Avoids the requirement of 'noperspective' vertex attribute interpolation modifier in shaders.
|
||||
float averageScreenDepth = (screenCorner0.z + screenCorner1.z + screenCorner2.z + screenCorner3.z) / 4.0f;
|
||||
screenCorner0.z = screenCorner1.z = screenCorner2.z = screenCorner3.z = averageScreenDepth;
|
||||
|
||||
if (canvasRenderMode == RenderMode.ScreenSpaceOverlay) {
|
||||
worldCornerNoDistortion0 = screenCorner0;
|
||||
worldCornerNoDistortion1 = screenCorner1;
|
||||
worldCornerNoDistortion2 = screenCorner2;
|
||||
worldCornerNoDistortion3 = screenCorner3;
|
||||
} else {
|
||||
worldCornerNoDistortion0 = targetCamera.ScreenToWorldPoint(screenCorner0);
|
||||
worldCornerNoDistortion1 = targetCamera.ScreenToWorldPoint(screenCorner1);
|
||||
worldCornerNoDistortion2 = targetCamera.ScreenToWorldPoint(screenCorner2);
|
||||
worldCornerNoDistortion3 = targetCamera.ScreenToWorldPoint(screenCorner3);
|
||||
}
|
||||
Vector3 screenSpaceMin, screenSpaceMax;
|
||||
PrepareTextureMapping(out screenSpaceMin, out screenSpaceMax,
|
||||
screenCorner0, screenCorner1, screenCorner2, screenCorner3);
|
||||
PrepareCommandBuffer(targetCamera, screenSpaceMin, screenSpaceMax);
|
||||
}
|
||||
|
||||
protected Material MeshRendererMaterialForTexture (Texture texture) {
|
||||
return meshRendererMaterialForTexture.Find(x => x.texture == texture).material;
|
||||
}
|
||||
|
||||
protected void RenderSingleMeshToRenderTexture (Mesh mesh, Material graphicMaterial, Texture texture) {
|
||||
if (mesh.subMeshCount == 0) return;
|
||||
Material meshRendererMaterial = MeshRendererMaterialForTexture(texture);
|
||||
foreach (int shaderPass in shaderPasses)
|
||||
commandBuffer.DrawMesh(mesh, transform.localToWorldMatrix, meshRendererMaterial, 0, shaderPass);
|
||||
Graphics.ExecuteCommandBuffer(commandBuffer);
|
||||
}
|
||||
|
||||
protected void RenderMultipleMeshesToRenderTexture (int meshCount,
|
||||
Mesh[] meshes, Material[] graphicMaterials, Texture[] textures) {
|
||||
|
||||
for (int i = 0; i < meshCount; ++i) {
|
||||
Mesh mesh = meshes[i];
|
||||
if (mesh.subMeshCount == 0) continue;
|
||||
|
||||
Material meshRendererMaterial = MeshRendererMaterialForTexture(textures[i]);
|
||||
foreach (int shaderPass in shaderPasses)
|
||||
commandBuffer.DrawMesh(mesh, transform.localToWorldMatrix, meshRendererMaterial, 0, shaderPass);
|
||||
}
|
||||
Graphics.ExecuteCommandBuffer(commandBuffer);
|
||||
}
|
||||
|
||||
protected void SetupQuad () {
|
||||
quadCanvasRenderer.SetMaterial(quadMaterial, this.renderTexture);
|
||||
quadMaskableGraphic.color = color;
|
||||
quadCanvasRenderer.SetColor(color);
|
||||
|
||||
RectTransform srcRectTransform = skeletonGraphic.rectTransform;
|
||||
RectTransform dstRectTransform = quadMaskableGraphic.rectTransform;
|
||||
|
||||
dstRectTransform.anchorMin = srcRectTransform.anchorMin;
|
||||
dstRectTransform.anchorMax = srcRectTransform.anchorMax;
|
||||
dstRectTransform.anchoredPosition = srcRectTransform.anchoredPosition;
|
||||
dstRectTransform.pivot = srcRectTransform.pivot;
|
||||
dstRectTransform.localScale = srcRectTransform.localScale;
|
||||
dstRectTransform.sizeDelta = srcRectTransform.sizeDelta;
|
||||
dstRectTransform.rotation = srcRectTransform.rotation;
|
||||
}
|
||||
|
||||
protected void PrepareCommandBuffer (Camera targetCamera, Vector3 screenSpaceMin, Vector3 screenSpaceMax) {
|
||||
commandBuffer.Clear();
|
||||
commandBuffer.SetRenderTarget(renderTexture);
|
||||
commandBuffer.ClearRenderTarget(true, true, Color.clear);
|
||||
|
||||
Vector2 targetViewportSize = new Vector2(
|
||||
screenSpaceMax.x - screenSpaceMin.x,
|
||||
screenSpaceMax.y - screenSpaceMin.y);
|
||||
|
||||
RenderMode canvasRenderMode = skeletonGraphic.canvas.renderMode;
|
||||
if (canvasRenderMode == RenderMode.ScreenSpaceOverlay) {
|
||||
Rect canvasRect = skeletonGraphic.canvas.pixelRect;
|
||||
canvasRect.x += screenSpaceMin.x;
|
||||
canvasRect.y += screenSpaceMin.y;
|
||||
canvasRect.width = targetViewportSize.x;
|
||||
canvasRect.height = targetViewportSize.y;
|
||||
Matrix4x4 projectionMatrix = Matrix4x4.Ortho(
|
||||
canvasRect.x, canvasRect.x + canvasRect.width,
|
||||
canvasRect.y, canvasRect.y + canvasRect.height,
|
||||
float.MinValue, float.MaxValue);
|
||||
commandBuffer.SetViewMatrix(Matrix4x4.identity);
|
||||
commandBuffer.SetProjectionMatrix(projectionMatrix);
|
||||
} else {
|
||||
commandBuffer.SetViewMatrix(targetCamera.worldToCameraMatrix);
|
||||
Matrix4x4 projectionMatrix = CalculateProjectionMatrix(targetCamera,
|
||||
screenSpaceMin, screenSpaceMax, skeletonGraphic.canvas.pixelRect.size);
|
||||
commandBuffer.SetProjectionMatrix(projectionMatrix);
|
||||
}
|
||||
Rect viewportRect = new Rect(Vector2.zero, targetViewportSize * downScaleFactor);
|
||||
commandBuffer.SetViewport(viewportRect);
|
||||
}
|
||||
|
||||
protected override void AssignMeshAtRenderer () {
|
||||
quadCanvasRenderer.SetMesh(quadMesh);
|
||||
}
|
||||
#endif // HAS_VECTOR2INT
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,191 +1,221 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2022, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2019_3_OR_NEWER
|
||||
#define HAS_FORCE_RENDER_OFF
|
||||
#endif
|
||||
|
||||
#if UNITY_2018_2_OR_NEWER
|
||||
#define HAS_GET_SHARED_MATERIALS
|
||||
#endif
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
/// <summary>
|
||||
/// When enabled, this component renders a skeleton to a RenderTexture and
|
||||
/// then draws this RenderTexture at a quad of the same size.
|
||||
/// This allows changing transparency at a single quad, which produces a more
|
||||
/// natural fadeout effect.
|
||||
/// Note: It is recommended to keep this component disabled as much as possible
|
||||
/// because of the additional rendering overhead. Only enable it when alpha blending is required.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(SkeletonRenderer))]
|
||||
public class SkeletonRenderTexture : SkeletonRenderTextureBase {
|
||||
#if HAS_GET_SHARED_MATERIALS
|
||||
public Material quadMaterial;
|
||||
protected SkeletonRenderer skeletonRenderer;
|
||||
protected MeshRenderer meshRenderer;
|
||||
protected MeshFilter meshFilter;
|
||||
protected MeshRenderer quadMeshRenderer;
|
||||
protected MeshFilter quadMeshFilter;
|
||||
|
||||
private MaterialPropertyBlock propertyBlock;
|
||||
private readonly List<Material> materials = new List<Material>();
|
||||
protected override void Awake () {
|
||||
base.Awake();
|
||||
meshRenderer = this.GetComponent<MeshRenderer>();
|
||||
meshFilter = this.GetComponent<MeshFilter>();
|
||||
skeletonRenderer = this.GetComponent<SkeletonRenderer>();
|
||||
if (targetCamera == null)
|
||||
targetCamera = Camera.main;
|
||||
|
||||
propertyBlock = new MaterialPropertyBlock();
|
||||
CreateQuadChild();
|
||||
}
|
||||
|
||||
void CreateQuadChild () {
|
||||
quad = new GameObject(this.name + " RenderTexture", typeof(MeshRenderer), typeof(MeshFilter));
|
||||
quad.transform.SetParent(this.transform.parent, false);
|
||||
quadMeshRenderer = quad.GetComponent<MeshRenderer>();
|
||||
quadMeshFilter = quad.GetComponent<MeshFilter>();
|
||||
|
||||
quadMeshRenderer.sortingOrder = meshRenderer.sortingOrder;
|
||||
quadMeshRenderer.sortingLayerID = meshRenderer.sortingLayerID;
|
||||
|
||||
quadMesh = new Mesh();
|
||||
quadMesh.MarkDynamic();
|
||||
quadMesh.name = "RenderTexture Quad";
|
||||
quadMesh.hideFlags = HideFlags.DontSaveInBuild | HideFlags.DontSaveInEditor;
|
||||
|
||||
if (quadMaterial != null)
|
||||
quadMeshRenderer.material = new Material(quadMaterial);
|
||||
else
|
||||
quadMeshRenderer.material = new Material(Shader.Find("Spine/RenderQuad"));
|
||||
}
|
||||
|
||||
void OnEnable () {
|
||||
skeletonRenderer.OnMeshAndMaterialsUpdated += RenderOntoQuad;
|
||||
#if HAS_FORCE_RENDER_OFF
|
||||
meshRenderer.forceRenderingOff = true;
|
||||
#else
|
||||
Debug.LogError("This component requires Unity 2019.3 or newer for meshRenderer.forceRenderingOff. " +
|
||||
"Otherwise you will see the mesh rendered twice.");
|
||||
#endif
|
||||
if (quadMeshRenderer)
|
||||
quadMeshRenderer.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
void OnDisable () {
|
||||
skeletonRenderer.OnMeshAndMaterialsUpdated -= RenderOntoQuad;
|
||||
#if HAS_FORCE_RENDER_OFF
|
||||
meshRenderer.forceRenderingOff = false;
|
||||
#endif
|
||||
if (quadMeshRenderer)
|
||||
quadMeshRenderer.gameObject.SetActive(false);
|
||||
if (renderTexture)
|
||||
RenderTexture.ReleaseTemporary(renderTexture);
|
||||
allocatedRenderTextureSize = Vector2Int.zero;
|
||||
}
|
||||
|
||||
void RenderOntoQuad (SkeletonRenderer skeletonRenderer) {
|
||||
PrepareForMesh();
|
||||
RenderToRenderTexture();
|
||||
AssignAtQuad();
|
||||
}
|
||||
|
||||
protected void PrepareForMesh () {
|
||||
// We need to get the min/max of all four corners, rotation of the skeleton
|
||||
// in combination with perspective projection otherwise might lead to incorrect
|
||||
// screen space min/max.
|
||||
Bounds boundsLocalSpace = meshFilter.sharedMesh.bounds;
|
||||
Vector3 localCorner0 = boundsLocalSpace.min;
|
||||
Vector3 localCorner3 = boundsLocalSpace.max;
|
||||
Vector3 localCorner1 = new Vector3(localCorner0.x, localCorner3.y, localCorner0.z);
|
||||
Vector3 localCorner2 = new Vector3(localCorner3.x, localCorner0.y, localCorner3.z);
|
||||
|
||||
Vector3 worldCorner0 = transform.TransformPoint(localCorner0);
|
||||
Vector3 worldCorner1 = transform.TransformPoint(localCorner1);
|
||||
Vector3 worldCorner2 = transform.TransformPoint(localCorner2);
|
||||
Vector3 worldCorner3 = transform.TransformPoint(localCorner3);
|
||||
|
||||
Vector3 screenCorner0 = targetCamera.WorldToScreenPoint(worldCorner0);
|
||||
Vector3 screenCorner1 = targetCamera.WorldToScreenPoint(worldCorner1);
|
||||
Vector3 screenCorner2 = targetCamera.WorldToScreenPoint(worldCorner2);
|
||||
Vector3 screenCorner3 = targetCamera.WorldToScreenPoint(worldCorner3);
|
||||
|
||||
// To avoid perspective distortion when rotated, we project all vertices
|
||||
// onto a plane parallel to the view frustum near plane.
|
||||
// Avoids the requirement of 'noperspective' vertex attribute interpolation modifier in shaders.
|
||||
float averageScreenDepth = (screenCorner0.z + screenCorner1.z + screenCorner2.z + screenCorner3.z) / 4.0f;
|
||||
screenCorner0.z = screenCorner1.z = screenCorner2.z = screenCorner3.z = averageScreenDepth;
|
||||
worldCornerNoDistortion0 = targetCamera.ScreenToWorldPoint(screenCorner0);
|
||||
worldCornerNoDistortion1 = targetCamera.ScreenToWorldPoint(screenCorner1);
|
||||
worldCornerNoDistortion2 = targetCamera.ScreenToWorldPoint(screenCorner2);
|
||||
worldCornerNoDistortion3 = targetCamera.ScreenToWorldPoint(screenCorner3);
|
||||
|
||||
Vector3 screenSpaceMin, screenSpaceMax;
|
||||
PrepareTextureMapping(out screenSpaceMin, out screenSpaceMax,
|
||||
screenCorner0, screenCorner1, screenCorner2, screenCorner3);
|
||||
PrepareCommandBuffer(targetCamera, screenSpaceMin, screenSpaceMax);
|
||||
}
|
||||
|
||||
protected void PrepareCommandBuffer (Camera targetCamera, Vector3 screenSpaceMin, Vector3 screenSpaceMax) {
|
||||
commandBuffer.Clear();
|
||||
commandBuffer.SetRenderTarget(renderTexture);
|
||||
commandBuffer.ClearRenderTarget(true, true, Color.clear);
|
||||
|
||||
commandBuffer.SetProjectionMatrix(targetCamera.projectionMatrix);
|
||||
commandBuffer.SetViewMatrix(targetCamera.worldToCameraMatrix);
|
||||
Vector2 targetCameraViewportSize = targetCamera.pixelRect.size;
|
||||
Rect viewportRect = new Rect(-screenSpaceMin * downScaleFactor, targetCameraViewportSize * downScaleFactor);
|
||||
commandBuffer.SetViewport(viewportRect);
|
||||
}
|
||||
|
||||
protected void RenderToRenderTexture () {
|
||||
meshRenderer.GetPropertyBlock(propertyBlock);
|
||||
meshRenderer.GetSharedMaterials(materials);
|
||||
|
||||
for (int i = 0; i < materials.Count; i++)
|
||||
commandBuffer.DrawMesh(meshFilter.sharedMesh, transform.localToWorldMatrix,
|
||||
materials[i], meshRenderer.subMeshStartIndex + i, -1, propertyBlock);
|
||||
Graphics.ExecuteCommandBuffer(commandBuffer);
|
||||
}
|
||||
|
||||
protected override void AssignMeshAtRenderer () {
|
||||
quadMeshFilter.mesh = quadMesh;
|
||||
quadMeshRenderer.sharedMaterial.mainTexture = this.renderTexture;
|
||||
quadMeshRenderer.sharedMaterial.color = color;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2019_3_OR_NEWER
|
||||
#define HAS_FORCE_RENDER_OFF
|
||||
#endif
|
||||
|
||||
#if UNITY_2018_2_OR_NEWER
|
||||
#define HAS_GET_SHARED_MATERIALS
|
||||
#endif
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
/// <summary>
|
||||
/// When enabled, this component renders a skeleton to a RenderTexture and
|
||||
/// then draws this RenderTexture at a quad of the same size.
|
||||
/// This allows changing transparency at a single quad, which produces a more
|
||||
/// natural fadeout effect.
|
||||
/// Note: It is recommended to keep this component disabled as much as possible
|
||||
/// because of the additional rendering overhead. Only enable it when alpha blending is required.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(SkeletonRenderer))]
|
||||
public class SkeletonRenderTexture : SkeletonRenderTextureBase {
|
||||
#if HAS_GET_SHARED_MATERIALS
|
||||
protected SkeletonRenderer skeletonRenderer;
|
||||
protected MeshRenderer meshRenderer;
|
||||
protected MeshFilter meshFilter;
|
||||
protected MeshRenderer quadMeshRenderer;
|
||||
protected MeshFilter quadMeshFilter;
|
||||
|
||||
private MaterialPropertyBlock propertyBlock;
|
||||
private readonly List<Material> materials = new List<Material>();
|
||||
protected override void Awake () {
|
||||
base.Awake();
|
||||
meshRenderer = this.GetComponent<MeshRenderer>();
|
||||
meshFilter = this.GetComponent<MeshFilter>();
|
||||
skeletonRenderer = this.GetComponent<SkeletonRenderer>();
|
||||
if (targetCamera == null)
|
||||
targetCamera = Camera.main;
|
||||
|
||||
propertyBlock = new MaterialPropertyBlock();
|
||||
CreateQuadChild();
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
protected void Reset () {
|
||||
string[] folders = { "Assets", "Packages" };
|
||||
string[] assets = UnityEditor.AssetDatabase.FindAssets("t:material RenderQuadMaterial", folders);
|
||||
if (assets.Length > 0) {
|
||||
string materialPath = UnityEditor.AssetDatabase.GUIDToAssetPath(assets[0]);
|
||||
quadMaterial = UnityEditor.AssetDatabase.LoadAssetAtPath<Material>(materialPath);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void CreateQuadChild () {
|
||||
quad = new GameObject(this.name + " RenderTexture", typeof(MeshRenderer), typeof(MeshFilter));
|
||||
quad.transform.SetParent(this.transform.parent, false);
|
||||
quad.layer = meshRenderer.gameObject.layer;
|
||||
quadMeshRenderer = quad.GetComponent<MeshRenderer>();
|
||||
quadMeshFilter = quad.GetComponent<MeshFilter>();
|
||||
|
||||
quadMeshRenderer.sortingOrder = meshRenderer.sortingOrder;
|
||||
quadMeshRenderer.sortingLayerID = meshRenderer.sortingLayerID;
|
||||
|
||||
quadMesh = new Mesh();
|
||||
quadMesh.MarkDynamic();
|
||||
quadMesh.name = "RenderTexture Quad";
|
||||
quadMesh.hideFlags = HideFlags.DontSaveInBuild | HideFlags.DontSaveInEditor;
|
||||
|
||||
if (quadMaterial != null)
|
||||
quadMeshRenderer.material = new Material(quadMaterial);
|
||||
else
|
||||
quadMeshRenderer.material = new Material(Shader.Find("Spine/RenderQuad"));
|
||||
}
|
||||
|
||||
void OnEnable () {
|
||||
skeletonRenderer.OnMeshAndMaterialsUpdated += RenderOntoQuad;
|
||||
#if HAS_FORCE_RENDER_OFF
|
||||
meshRenderer.forceRenderingOff = true;
|
||||
#else
|
||||
Debug.LogError("This component requires Unity 2019.3 or newer for meshRenderer.forceRenderingOff. " +
|
||||
"Otherwise you will see the mesh rendered twice.");
|
||||
#endif
|
||||
if (quadMeshRenderer)
|
||||
quadMeshRenderer.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
void OnDisable () {
|
||||
skeletonRenderer.OnMeshAndMaterialsUpdated -= RenderOntoQuad;
|
||||
#if HAS_FORCE_RENDER_OFF
|
||||
meshRenderer.forceRenderingOff = false;
|
||||
#endif
|
||||
if (quadMeshRenderer)
|
||||
quadMeshRenderer.gameObject.SetActive(false);
|
||||
if (renderTexture)
|
||||
RenderTexture.ReleaseTemporary(renderTexture);
|
||||
allocatedRenderTextureSize = Vector2Int.zero;
|
||||
}
|
||||
|
||||
void RenderOntoQuad (SkeletonRenderer skeletonRenderer) {
|
||||
if (meshFilter == null)
|
||||
meshFilter = this.GetComponent<MeshFilter>();
|
||||
Vector3 size = meshFilter.sharedMesh.bounds.size;
|
||||
if (size.x == 0f || size.y == 0f) {
|
||||
AssignNullMeshAtQuad();
|
||||
return;
|
||||
}
|
||||
PrepareForMesh();
|
||||
RenderToRenderTexture();
|
||||
AssignAtQuad();
|
||||
}
|
||||
|
||||
protected void PrepareForMesh () {
|
||||
// We need to get the min/max of all four corners, rotation of the skeleton
|
||||
// in combination with perspective projection otherwise might lead to incorrect
|
||||
// screen space min/max.
|
||||
Bounds boundsLocalSpace = meshFilter.sharedMesh.bounds;
|
||||
Vector3 localCorner0 = boundsLocalSpace.min;
|
||||
Vector3 localCorner3 = boundsLocalSpace.max;
|
||||
Vector3 localCorner1 = new Vector3(localCorner0.x, localCorner3.y, localCorner0.z);
|
||||
Vector3 localCorner2 = new Vector3(localCorner3.x, localCorner0.y, localCorner3.z);
|
||||
|
||||
Vector3 worldCorner0 = transform.TransformPoint(localCorner0);
|
||||
Vector3 worldCorner1 = transform.TransformPoint(localCorner1);
|
||||
Vector3 worldCorner2 = transform.TransformPoint(localCorner2);
|
||||
Vector3 worldCorner3 = transform.TransformPoint(localCorner3);
|
||||
|
||||
Vector3 screenCorner0 = targetCamera.WorldToScreenPoint(worldCorner0);
|
||||
Vector3 screenCorner1 = targetCamera.WorldToScreenPoint(worldCorner1);
|
||||
Vector3 screenCorner2 = targetCamera.WorldToScreenPoint(worldCorner2);
|
||||
Vector3 screenCorner3 = targetCamera.WorldToScreenPoint(worldCorner3);
|
||||
|
||||
// To avoid perspective distortion when rotated, we project all vertices
|
||||
// onto a plane parallel to the view frustum near plane.
|
||||
// Avoids the requirement of 'noperspective' vertex attribute interpolation modifier in shaders.
|
||||
float averageScreenDepth = (screenCorner0.z + screenCorner1.z + screenCorner2.z + screenCorner3.z) / 4.0f;
|
||||
screenCorner0.z = screenCorner1.z = screenCorner2.z = screenCorner3.z = averageScreenDepth;
|
||||
worldCornerNoDistortion0 = targetCamera.ScreenToWorldPoint(screenCorner0);
|
||||
worldCornerNoDistortion1 = targetCamera.ScreenToWorldPoint(screenCorner1);
|
||||
worldCornerNoDistortion2 = targetCamera.ScreenToWorldPoint(screenCorner2);
|
||||
worldCornerNoDistortion3 = targetCamera.ScreenToWorldPoint(screenCorner3);
|
||||
|
||||
Vector3 screenSpaceMin, screenSpaceMax;
|
||||
PrepareTextureMapping(out screenSpaceMin, out screenSpaceMax,
|
||||
screenCorner0, screenCorner1, screenCorner2, screenCorner3);
|
||||
PrepareCommandBuffer(targetCamera, screenSpaceMin, screenSpaceMax);
|
||||
}
|
||||
|
||||
protected void PrepareCommandBuffer (Camera targetCamera, Vector3 screenSpaceMin, Vector3 screenSpaceMax) {
|
||||
commandBuffer.Clear();
|
||||
commandBuffer.SetRenderTarget(renderTexture);
|
||||
commandBuffer.ClearRenderTarget(true, true, Color.clear);
|
||||
|
||||
commandBuffer.SetViewMatrix(targetCamera.worldToCameraMatrix);
|
||||
|
||||
Matrix4x4 projectionMatrix = CalculateProjectionMatrix(targetCamera,
|
||||
screenSpaceMin, screenSpaceMax, targetCamera.pixelRect.size);
|
||||
commandBuffer.SetProjectionMatrix(projectionMatrix);
|
||||
|
||||
Vector2 targetViewportSize = new Vector2(
|
||||
screenSpaceMax.x - screenSpaceMin.x,
|
||||
screenSpaceMax.y - screenSpaceMin.y);
|
||||
Rect viewportRect = new Rect(Vector2.zero, targetViewportSize * downScaleFactor);
|
||||
commandBuffer.SetViewport(viewportRect);
|
||||
}
|
||||
|
||||
protected void RenderToRenderTexture () {
|
||||
meshRenderer.GetPropertyBlock(propertyBlock);
|
||||
meshRenderer.GetSharedMaterials(materials);
|
||||
|
||||
for (int i = 0; i < materials.Count; i++) {
|
||||
foreach (int shaderPass in shaderPasses)
|
||||
commandBuffer.DrawMesh(meshFilter.sharedMesh, transform.localToWorldMatrix,
|
||||
materials[i], meshRenderer.subMeshStartIndex + i, shaderPass, propertyBlock);
|
||||
}
|
||||
Graphics.ExecuteCommandBuffer(commandBuffer);
|
||||
}
|
||||
|
||||
protected override void AssignMeshAtRenderer () {
|
||||
quadMeshFilter.mesh = quadMesh;
|
||||
quadMeshRenderer.sharedMaterial.mainTexture = this.renderTexture;
|
||||
quadMeshRenderer.sharedMaterial.color = color;
|
||||
}
|
||||
|
||||
protected void AssignNullMeshAtQuad () {
|
||||
quadMeshFilter.mesh = null;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,164 +1,208 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2022, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
#define HAS_VECTOR2INT
|
||||
#endif
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
public abstract class SkeletonRenderTextureBase : MonoBehaviour {
|
||||
#if HAS_VECTOR2INT
|
||||
public Color color = Color.white;
|
||||
public int maxRenderTextureSize = 1024;
|
||||
public GameObject quad;
|
||||
protected Mesh quadMesh;
|
||||
public RenderTexture renderTexture;
|
||||
public Camera targetCamera;
|
||||
|
||||
protected CommandBuffer commandBuffer;
|
||||
protected Vector2Int screenSize;
|
||||
protected Vector2Int usedRenderTextureSize;
|
||||
protected Vector2Int allocatedRenderTextureSize;
|
||||
protected Vector2 downScaleFactor = Vector2.one;
|
||||
|
||||
protected Vector3 worldCornerNoDistortion0;
|
||||
protected Vector3 worldCornerNoDistortion1;
|
||||
protected Vector3 worldCornerNoDistortion2;
|
||||
protected Vector3 worldCornerNoDistortion3;
|
||||
protected Vector2 uvCorner0;
|
||||
protected Vector2 uvCorner1;
|
||||
protected Vector2 uvCorner2;
|
||||
protected Vector2 uvCorner3;
|
||||
|
||||
protected virtual void Awake () {
|
||||
commandBuffer = new CommandBuffer();
|
||||
}
|
||||
|
||||
void OnDestroy () {
|
||||
if (renderTexture)
|
||||
RenderTexture.ReleaseTemporary(renderTexture);
|
||||
}
|
||||
|
||||
protected void PrepareTextureMapping (out Vector3 screenSpaceMin, out Vector3 screenSpaceMax,
|
||||
Vector3 screenCorner0, Vector3 screenCorner1, Vector3 screenCorner2, Vector3 screenCorner3) {
|
||||
|
||||
screenSpaceMin =
|
||||
Vector3.Min(screenCorner0, Vector3.Min(screenCorner1,
|
||||
Vector3.Min(screenCorner2, screenCorner3)));
|
||||
screenSpaceMax =
|
||||
Vector3.Max(screenCorner0, Vector3.Max(screenCorner1,
|
||||
Vector3.Max(screenCorner2, screenCorner3)));
|
||||
// ensure we are on whole pixel borders
|
||||
screenSpaceMin.x = Mathf.Floor(screenSpaceMin.x);
|
||||
screenSpaceMin.y = Mathf.Floor(screenSpaceMin.y);
|
||||
screenSpaceMax.x = Mathf.Ceil(screenSpaceMax.x);
|
||||
screenSpaceMax.y = Mathf.Ceil(screenSpaceMax.y);
|
||||
|
||||
// inverse-map screenCornerN to screenSpaceMin/screenSpaceMax area to get UV coordinates
|
||||
uvCorner0 = MathUtilities.InverseLerp(screenSpaceMin, screenSpaceMax, screenCorner0);
|
||||
uvCorner1 = MathUtilities.InverseLerp(screenSpaceMin, screenSpaceMax, screenCorner1);
|
||||
uvCorner2 = MathUtilities.InverseLerp(screenSpaceMin, screenSpaceMax, screenCorner2);
|
||||
uvCorner3 = MathUtilities.InverseLerp(screenSpaceMin, screenSpaceMax, screenCorner3);
|
||||
|
||||
screenSize = new Vector2Int(Math.Abs((int)screenSpaceMax.x - (int)screenSpaceMin.x),
|
||||
Math.Abs((int)screenSpaceMax.y - (int)screenSpaceMin.y));
|
||||
usedRenderTextureSize = new Vector2Int(
|
||||
Math.Min(maxRenderTextureSize, screenSize.x),
|
||||
Math.Min(maxRenderTextureSize, screenSize.y));
|
||||
downScaleFactor = new Vector2(
|
||||
(float)usedRenderTextureSize.x / (float)screenSize.x,
|
||||
(float)usedRenderTextureSize.y / (float)screenSize.y);
|
||||
|
||||
PrepareRenderTexture();
|
||||
}
|
||||
|
||||
protected void PrepareRenderTexture () {
|
||||
Vector2Int textureSize = new Vector2Int(
|
||||
Mathf.NextPowerOfTwo(usedRenderTextureSize.x),
|
||||
Mathf.NextPowerOfTwo(usedRenderTextureSize.y));
|
||||
|
||||
if (textureSize != allocatedRenderTextureSize) {
|
||||
if (renderTexture)
|
||||
RenderTexture.ReleaseTemporary(renderTexture);
|
||||
renderTexture = RenderTexture.GetTemporary(textureSize.x, textureSize.y);
|
||||
renderTexture.filterMode = FilterMode.Point;
|
||||
allocatedRenderTextureSize = textureSize;
|
||||
}
|
||||
}
|
||||
|
||||
protected void AssignAtQuad () {
|
||||
Transform quadTransform = quad.transform;
|
||||
quadTransform.position = this.transform.position;
|
||||
quadTransform.rotation = this.transform.rotation;
|
||||
quadTransform.localScale = this.transform.localScale;
|
||||
|
||||
Vector3 v0 = quadTransform.InverseTransformPoint(worldCornerNoDistortion0);
|
||||
Vector3 v1 = quadTransform.InverseTransformPoint(worldCornerNoDistortion1);
|
||||
Vector3 v2 = quadTransform.InverseTransformPoint(worldCornerNoDistortion2);
|
||||
Vector3 v3 = quadTransform.InverseTransformPoint(worldCornerNoDistortion3);
|
||||
Vector3[] vertices = new Vector3[4] { v0, v1, v2, v3 };
|
||||
|
||||
quadMesh.vertices = vertices;
|
||||
|
||||
int[] indices = new int[6] { 0, 1, 2, 2, 1, 3 };
|
||||
quadMesh.triangles = indices;
|
||||
|
||||
Vector3[] normals = new Vector3[4] {
|
||||
-Vector3.forward,
|
||||
-Vector3.forward,
|
||||
-Vector3.forward,
|
||||
-Vector3.forward
|
||||
};
|
||||
quadMesh.normals = normals;
|
||||
|
||||
float maxU = (float)usedRenderTextureSize.x / (float)allocatedRenderTextureSize.x;
|
||||
float maxV = (float)usedRenderTextureSize.y / (float)allocatedRenderTextureSize.y;
|
||||
if (downScaleFactor.x < 1 || downScaleFactor.y < 1) {
|
||||
maxU = downScaleFactor.x * (float)screenSize.x / (float)allocatedRenderTextureSize.x;
|
||||
maxV = downScaleFactor.y * (float)screenSize.y / (float)allocatedRenderTextureSize.y;
|
||||
}
|
||||
Vector2[] uv = new Vector2[4] {
|
||||
new Vector2(uvCorner0.x * maxU, uvCorner0.y * maxV),
|
||||
new Vector2(uvCorner1.x * maxU, uvCorner1.y * maxV),
|
||||
new Vector2(uvCorner2.x * maxU, uvCorner2.y * maxV),
|
||||
new Vector2(uvCorner3.x * maxU, uvCorner3.y * maxV),
|
||||
};
|
||||
quadMesh.uv = uv;
|
||||
AssignMeshAtRenderer();
|
||||
}
|
||||
|
||||
protected abstract void AssignMeshAtRenderer ();
|
||||
#endif // HAS_VECTOR2INT
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
#define HAS_VECTOR2INT
|
||||
#endif
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
public abstract class SkeletonRenderTextureBase : MonoBehaviour {
|
||||
#if HAS_VECTOR2INT
|
||||
public Color color = Color.white;
|
||||
public int maxRenderTextureSize = 1024;
|
||||
public GameObject quad;
|
||||
public Material quadMaterial;
|
||||
protected Mesh quadMesh;
|
||||
public RenderTexture renderTexture;
|
||||
public Camera targetCamera;
|
||||
[Tooltip("Shader passes to render to the RenderTexture. E.g. set the first element " +
|
||||
"to -1 to render all shader passes, or set it to 0 to only render the first " +
|
||||
"shader pass, which may be required when using URP or shadow-casting shaders.")]
|
||||
public int[] shaderPasses = new int[1] { 0 };
|
||||
|
||||
protected CommandBuffer commandBuffer;
|
||||
protected Vector2Int screenSize;
|
||||
protected Vector2Int usedRenderTextureSize;
|
||||
protected Vector2Int allocatedRenderTextureSize;
|
||||
protected Vector2 downScaleFactor = Vector2.one;
|
||||
|
||||
protected Vector3 worldCornerNoDistortion0;
|
||||
protected Vector3 worldCornerNoDistortion1;
|
||||
protected Vector3 worldCornerNoDistortion2;
|
||||
protected Vector3 worldCornerNoDistortion3;
|
||||
protected Vector2 uvCorner0;
|
||||
protected Vector2 uvCorner1;
|
||||
protected Vector2 uvCorner2;
|
||||
protected Vector2 uvCorner3;
|
||||
|
||||
protected virtual void Awake () {
|
||||
commandBuffer = new CommandBuffer();
|
||||
}
|
||||
|
||||
void OnDestroy () {
|
||||
if (renderTexture)
|
||||
RenderTexture.ReleaseTemporary(renderTexture);
|
||||
}
|
||||
|
||||
protected void PrepareTextureMapping (out Vector3 screenSpaceMin, out Vector3 screenSpaceMax,
|
||||
Vector3 screenCorner0, Vector3 screenCorner1, Vector3 screenCorner2, Vector3 screenCorner3) {
|
||||
|
||||
screenSpaceMin =
|
||||
Vector3.Min(screenCorner0, Vector3.Min(screenCorner1,
|
||||
Vector3.Min(screenCorner2, screenCorner3)));
|
||||
screenSpaceMax =
|
||||
Vector3.Max(screenCorner0, Vector3.Max(screenCorner1,
|
||||
Vector3.Max(screenCorner2, screenCorner3)));
|
||||
// ensure we are on whole pixel borders
|
||||
screenSpaceMin.x = Mathf.Floor(screenSpaceMin.x);
|
||||
screenSpaceMin.y = Mathf.Floor(screenSpaceMin.y);
|
||||
screenSpaceMax.x = Mathf.Ceil(screenSpaceMax.x);
|
||||
screenSpaceMax.y = Mathf.Ceil(screenSpaceMax.y);
|
||||
|
||||
// inverse-map screenCornerN to screenSpaceMin/screenSpaceMax area to get UV coordinates
|
||||
uvCorner0 = MathUtilities.InverseLerp(screenSpaceMin, screenSpaceMax, screenCorner0);
|
||||
uvCorner1 = MathUtilities.InverseLerp(screenSpaceMin, screenSpaceMax, screenCorner1);
|
||||
uvCorner2 = MathUtilities.InverseLerp(screenSpaceMin, screenSpaceMax, screenCorner2);
|
||||
uvCorner3 = MathUtilities.InverseLerp(screenSpaceMin, screenSpaceMax, screenCorner3);
|
||||
|
||||
screenSize = new Vector2Int(Math.Abs((int)screenSpaceMax.x - (int)screenSpaceMin.x),
|
||||
Math.Abs((int)screenSpaceMax.y - (int)screenSpaceMin.y));
|
||||
usedRenderTextureSize = new Vector2Int(
|
||||
Math.Min(maxRenderTextureSize, screenSize.x),
|
||||
Math.Min(maxRenderTextureSize, screenSize.y));
|
||||
downScaleFactor = new Vector2(
|
||||
(float)usedRenderTextureSize.x / (float)screenSize.x,
|
||||
(float)usedRenderTextureSize.y / (float)screenSize.y);
|
||||
|
||||
PrepareRenderTexture();
|
||||
}
|
||||
|
||||
protected void PrepareRenderTexture () {
|
||||
Vector2Int textureSize = new Vector2Int(
|
||||
Mathf.NextPowerOfTwo(usedRenderTextureSize.x),
|
||||
Mathf.NextPowerOfTwo(usedRenderTextureSize.y));
|
||||
|
||||
if (textureSize != allocatedRenderTextureSize) {
|
||||
if (renderTexture)
|
||||
RenderTexture.ReleaseTemporary(renderTexture);
|
||||
renderTexture = RenderTexture.GetTemporary(textureSize.x, textureSize.y);
|
||||
renderTexture.filterMode = FilterMode.Point;
|
||||
allocatedRenderTextureSize = textureSize;
|
||||
}
|
||||
}
|
||||
|
||||
protected Matrix4x4 CalculateProjectionMatrix (Camera targetCamera,
|
||||
Vector3 screenSpaceMin, Vector3 screenSpaceMax, Vector2 fullSizePixels) {
|
||||
if (targetCamera.orthographic)
|
||||
return CalculateOrthoMatrix(targetCamera, screenSpaceMin, screenSpaceMax, fullSizePixels);
|
||||
else
|
||||
return CalculatePerspectiveMatrix(targetCamera, screenSpaceMin, screenSpaceMax, fullSizePixels);
|
||||
}
|
||||
|
||||
protected Matrix4x4 CalculateOrthoMatrix (Camera targetCamera,
|
||||
Vector3 screenSpaceMin, Vector3 screenSpaceMax, Vector2 fullSizePixels) {
|
||||
|
||||
Vector2 cameraSize = new Vector2(
|
||||
targetCamera.orthographicSize * 2.0f * targetCamera.aspect,
|
||||
targetCamera.orthographicSize * 2.0f);
|
||||
Vector2 min = new Vector2(screenSpaceMin.x, screenSpaceMin.y) / fullSizePixels;
|
||||
Vector2 max = new Vector2(screenSpaceMax.x, screenSpaceMax.y) / fullSizePixels;
|
||||
Vector2 centerOffset = new Vector2(-0.5f, -0.5f);
|
||||
min = (min + centerOffset) * cameraSize;
|
||||
max = (max + centerOffset) * cameraSize;
|
||||
|
||||
return Matrix4x4.Ortho(min.x, max.x, min.y, max.y, float.MinValue, float.MaxValue);
|
||||
}
|
||||
|
||||
protected Matrix4x4 CalculatePerspectiveMatrix (Camera targetCamera,
|
||||
Vector3 screenSpaceMin, Vector3 screenSpaceMax, Vector2 fullSizePixels) {
|
||||
|
||||
FrustumPlanes frustumPlanes = targetCamera.projectionMatrix.decomposeProjection;
|
||||
Vector2 planesSize = new Vector2(
|
||||
frustumPlanes.right - frustumPlanes.left,
|
||||
frustumPlanes.top - frustumPlanes.bottom);
|
||||
Vector2 min = new Vector2(screenSpaceMin.x, screenSpaceMin.y) / fullSizePixels * planesSize;
|
||||
Vector2 max = new Vector2(screenSpaceMax.x, screenSpaceMax.y) / fullSizePixels * planesSize;
|
||||
frustumPlanes.right = frustumPlanes.left + max.x;
|
||||
frustumPlanes.top = frustumPlanes.bottom + max.y;
|
||||
frustumPlanes.left += min.x;
|
||||
frustumPlanes.bottom += min.y;
|
||||
return Matrix4x4.Frustum(frustumPlanes);
|
||||
}
|
||||
|
||||
protected void AssignAtQuad () {
|
||||
Transform quadTransform = quad.transform;
|
||||
quadTransform.position = this.transform.position;
|
||||
quadTransform.rotation = this.transform.rotation;
|
||||
quadTransform.localScale = this.transform.localScale;
|
||||
|
||||
Vector3 v0 = quadTransform.InverseTransformPoint(worldCornerNoDistortion0);
|
||||
Vector3 v1 = quadTransform.InverseTransformPoint(worldCornerNoDistortion1);
|
||||
Vector3 v2 = quadTransform.InverseTransformPoint(worldCornerNoDistortion2);
|
||||
Vector3 v3 = quadTransform.InverseTransformPoint(worldCornerNoDistortion3);
|
||||
Vector3[] vertices = new Vector3[4] { v0, v1, v2, v3 };
|
||||
|
||||
quadMesh.vertices = vertices;
|
||||
|
||||
int[] indices = new int[6] { 0, 1, 2, 2, 1, 3 };
|
||||
quadMesh.triangles = indices;
|
||||
|
||||
Vector3[] normals = new Vector3[4] {
|
||||
-Vector3.forward,
|
||||
-Vector3.forward,
|
||||
-Vector3.forward,
|
||||
-Vector3.forward
|
||||
};
|
||||
quadMesh.normals = normals;
|
||||
|
||||
float maxU = (float)usedRenderTextureSize.x / (float)allocatedRenderTextureSize.x;
|
||||
float maxV = (float)usedRenderTextureSize.y / (float)allocatedRenderTextureSize.y;
|
||||
if (downScaleFactor.x < 1 || downScaleFactor.y < 1) {
|
||||
maxU = downScaleFactor.x * (float)screenSize.x / (float)allocatedRenderTextureSize.x;
|
||||
maxV = downScaleFactor.y * (float)screenSize.y / (float)allocatedRenderTextureSize.y;
|
||||
}
|
||||
Vector2[] uv = new Vector2[4] {
|
||||
new Vector2(uvCorner0.x * maxU, uvCorner0.y * maxV),
|
||||
new Vector2(uvCorner1.x * maxU, uvCorner1.y * maxV),
|
||||
new Vector2(uvCorner2.x * maxU, uvCorner2.y * maxV),
|
||||
new Vector2(uvCorner3.x * maxU, uvCorner3.y * maxV),
|
||||
};
|
||||
quadMesh.uv = uv;
|
||||
AssignMeshAtRenderer();
|
||||
}
|
||||
|
||||
protected abstract void AssignMeshAtRenderer ();
|
||||
#endif // HAS_VECTOR2INT
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,88 +1,88 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2022, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2019_3_OR_NEWER
|
||||
#define HAS_FORCE_RENDER_OFF
|
||||
#endif
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
#define HAS_VECTOR_INT
|
||||
#endif
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
/// <summary>
|
||||
/// A simple fadeout component that uses a <see cref="SkeletonRenderTexture"/> for transparency fadeout.
|
||||
/// Attach a <see cref="SkeletonRenderTexture"/> and this component to a skeleton GameObject and disable both
|
||||
/// components initially and keep them disabled during normal gameplay. When you need to start fadeout,
|
||||
/// enable this component.
|
||||
/// At the end of the fadeout, the event delegate <c>OnFadeoutComplete</c> is called, to which you can bind e.g.
|
||||
/// a method that disables or destroys the entire GameObject.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(SkeletonRenderTextureBase))]
|
||||
public class SkeletonRenderTextureFadeout : MonoBehaviour {
|
||||
SkeletonRenderTextureBase skeletonRenderTexture;
|
||||
|
||||
public float fadeoutSeconds = 2.0f;
|
||||
protected float fadeoutSecondsRemaining;
|
||||
|
||||
public delegate void FadeoutCallback (SkeletonRenderTextureFadeout skeleton);
|
||||
public event FadeoutCallback OnFadeoutComplete;
|
||||
|
||||
protected void Awake () {
|
||||
skeletonRenderTexture = this.GetComponent<SkeletonRenderTextureBase>();
|
||||
}
|
||||
|
||||
protected void OnEnable () {
|
||||
fadeoutSecondsRemaining = fadeoutSeconds;
|
||||
skeletonRenderTexture.enabled = true;
|
||||
}
|
||||
|
||||
protected void Update () {
|
||||
if (fadeoutSecondsRemaining == 0)
|
||||
return;
|
||||
|
||||
fadeoutSecondsRemaining -= Time.deltaTime;
|
||||
if (fadeoutSecondsRemaining <= 0) {
|
||||
fadeoutSecondsRemaining = 0;
|
||||
if (OnFadeoutComplete != null)
|
||||
OnFadeoutComplete(this);
|
||||
return;
|
||||
}
|
||||
float fadeoutAlpha = fadeoutSecondsRemaining / fadeoutSeconds;
|
||||
#if HAS_VECTOR_INT
|
||||
skeletonRenderTexture.color.a = fadeoutAlpha;
|
||||
#else
|
||||
Debug.LogError("The SkeletonRenderTexture component requires Unity 2017.2 or newer.");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2019_3_OR_NEWER
|
||||
#define HAS_FORCE_RENDER_OFF
|
||||
#endif
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
#define HAS_VECTOR_INT
|
||||
#endif
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
/// <summary>
|
||||
/// A simple fadeout component that uses a <see cref="SkeletonRenderTexture"/> for transparency fadeout.
|
||||
/// Attach a <see cref="SkeletonRenderTexture"/> and this component to a skeleton GameObject and disable both
|
||||
/// components initially and keep them disabled during normal gameplay. When you need to start fadeout,
|
||||
/// enable this component.
|
||||
/// At the end of the fadeout, the event delegate <c>OnFadeoutComplete</c> is called, to which you can bind e.g.
|
||||
/// a method that disables or destroys the entire GameObject.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(SkeletonRenderTextureBase))]
|
||||
public class SkeletonRenderTextureFadeout : MonoBehaviour {
|
||||
SkeletonRenderTextureBase skeletonRenderTexture;
|
||||
|
||||
public float fadeoutSeconds = 2.0f;
|
||||
protected float fadeoutSecondsRemaining;
|
||||
|
||||
public delegate void FadeoutCallback (SkeletonRenderTextureFadeout skeleton);
|
||||
public event FadeoutCallback OnFadeoutComplete;
|
||||
|
||||
protected void Awake () {
|
||||
skeletonRenderTexture = this.GetComponent<SkeletonRenderTextureBase>();
|
||||
}
|
||||
|
||||
protected void OnEnable () {
|
||||
fadeoutSecondsRemaining = fadeoutSeconds;
|
||||
skeletonRenderTexture.enabled = true;
|
||||
}
|
||||
|
||||
protected void Update () {
|
||||
if (fadeoutSecondsRemaining == 0)
|
||||
return;
|
||||
|
||||
fadeoutSecondsRemaining -= Time.deltaTime;
|
||||
if (fadeoutSecondsRemaining <= 0) {
|
||||
fadeoutSecondsRemaining = 0;
|
||||
if (OnFadeoutComplete != null)
|
||||
OnFadeoutComplete(this);
|
||||
return;
|
||||
}
|
||||
float fadeoutAlpha = fadeoutSecondsRemaining / fadeoutSeconds;
|
||||
#if HAS_VECTOR_INT
|
||||
skeletonRenderTexture.color.a = fadeoutAlpha;
|
||||
#else
|
||||
Debug.LogError("The SkeletonRenderTexture component requires Unity 2017.2 or newer.");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,37 +1,37 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
// Contributed by: Mitch Thompson
|
||||
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class SkeletonRagdoll2DInspector { }
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
// Contributed by: Mitch Thompson
|
||||
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class SkeletonRagdoll2DInspector { }
|
||||
}
|
||||
|
||||
@ -1,46 +1,46 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
// Contributed by: Mitch Thompson
|
||||
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
public class SkeletonRagdollInspector : UnityEditor.Editor {
|
||||
[CustomPropertyDrawer(typeof(SkeletonRagdoll.LayerFieldAttribute))]
|
||||
public class LayerFieldPropertyDrawer : PropertyDrawer {
|
||||
public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) {
|
||||
property.intValue = EditorGUI.LayerField(position, label, property.intValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
// Contributed by: Mitch Thompson
|
||||
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
public class SkeletonRagdollInspector : UnityEditor.Editor {
|
||||
[CustomPropertyDrawer(typeof(SkeletonRagdoll.LayerFieldAttribute))]
|
||||
public class LayerFieldPropertyDrawer : PropertyDrawer {
|
||||
public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) {
|
||||
property.intValue = EditorGUI.LayerField(position, label, property.intValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,443 +1,443 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
// Contributed by: Mitch Thompson
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
[RequireComponent(typeof(SkeletonRenderer))]
|
||||
public class SkeletonRagdoll : MonoBehaviour {
|
||||
static Transform parentSpaceHelper;
|
||||
|
||||
#region Inspector
|
||||
[Header("Hierarchy")]
|
||||
[SpineBone]
|
||||
public string startingBoneName = "";
|
||||
[SpineBone]
|
||||
public List<string> stopBoneNames = new List<string>();
|
||||
|
||||
[Header("Parameters")]
|
||||
public bool applyOnStart;
|
||||
[Tooltip("Warning! You will have to re-enable and tune mix values manually if attempting to remove the ragdoll system.")]
|
||||
public bool disableIK = true;
|
||||
public bool disableOtherConstraints = false;
|
||||
[Space(18)]
|
||||
[Tooltip("Set RootRigidbody IsKinematic to true when Apply is called.")]
|
||||
public bool pinStartBone;
|
||||
[Tooltip("Enable Collision between adjacent ragdoll elements (IE: Neck and Head)")]
|
||||
public bool enableJointCollision;
|
||||
public bool useGravity = true;
|
||||
[Tooltip("If no BoundingBox Attachment is attached to a bone, this becomes the default Width or Radius of a Bone's ragdoll Rigidbody")]
|
||||
public float thickness = 0.125f;
|
||||
[Tooltip("Default rotational limit value. Min is negative this value, Max is this value.")]
|
||||
public float rotationLimit = 20;
|
||||
public float rootMass = 20;
|
||||
[Tooltip("If your ragdoll seems unstable or uneffected by limits, try lowering this value.")]
|
||||
[Range(0.01f, 1f)]
|
||||
public float massFalloffFactor = 0.4f;
|
||||
[Tooltip("The layer assigned to all of the rigidbody parts.")]
|
||||
public int colliderLayer = 0;
|
||||
[Range(0, 1)]
|
||||
public float mix = 1;
|
||||
public bool oldRagdollBehaviour = false;
|
||||
#endregion
|
||||
|
||||
ISkeletonAnimation targetSkeletonComponent;
|
||||
Skeleton skeleton;
|
||||
struct BoneFlipEntry {
|
||||
public BoneFlipEntry (bool flipX, bool flipY) {
|
||||
this.flipX = flipX;
|
||||
this.flipY = flipY;
|
||||
}
|
||||
|
||||
public bool flipX;
|
||||
public bool flipY;
|
||||
}
|
||||
Dictionary<Bone, Transform> boneTable = new Dictionary<Bone, Transform>();
|
||||
Dictionary<Bone, BoneFlipEntry> boneFlipTable = new Dictionary<Bone, BoneFlipEntry>();
|
||||
Transform ragdollRoot;
|
||||
public Rigidbody RootRigidbody { get; private set; }
|
||||
public Bone StartingBone { get; private set; }
|
||||
Vector3 rootOffset;
|
||||
public Vector3 RootOffset { get { return this.rootOffset; } }
|
||||
bool isActive;
|
||||
public bool IsActive { get { return this.isActive; } }
|
||||
|
||||
IEnumerator Start () {
|
||||
if (parentSpaceHelper == null) {
|
||||
parentSpaceHelper = (new GameObject("Parent Space Helper")).transform;
|
||||
parentSpaceHelper.hideFlags = HideFlags.HideInHierarchy;
|
||||
}
|
||||
|
||||
targetSkeletonComponent = GetComponent<SkeletonRenderer>() as ISkeletonAnimation;
|
||||
if (targetSkeletonComponent == null) Debug.LogError("Attached Spine component does not implement ISkeletonAnimation. This script is not compatible.");
|
||||
skeleton = targetSkeletonComponent.Skeleton;
|
||||
|
||||
if (applyOnStart) {
|
||||
yield return null;
|
||||
Apply();
|
||||
}
|
||||
}
|
||||
|
||||
#region API
|
||||
public Rigidbody[] RigidbodyArray {
|
||||
get {
|
||||
if (!isActive)
|
||||
return new Rigidbody[0];
|
||||
|
||||
Rigidbody[] rigidBodies = new Rigidbody[boneTable.Count];
|
||||
int i = 0;
|
||||
foreach (Transform t in boneTable.Values) {
|
||||
rigidBodies[i] = t.GetComponent<Rigidbody>();
|
||||
i++;
|
||||
}
|
||||
|
||||
return rigidBodies;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 EstimatedSkeletonPosition {
|
||||
get { return RootRigidbody.position - rootOffset; }
|
||||
}
|
||||
|
||||
/// <summary>Instantiates the ragdoll simulation and applies its transforms to the skeleton.</summary>
|
||||
public void Apply () {
|
||||
isActive = true;
|
||||
mix = 1;
|
||||
|
||||
StartingBone = skeleton.FindBone(startingBoneName);
|
||||
RecursivelyCreateBoneProxies(StartingBone);
|
||||
|
||||
RootRigidbody = boneTable[StartingBone].GetComponent<Rigidbody>();
|
||||
RootRigidbody.isKinematic = pinStartBone;
|
||||
RootRigidbody.mass = rootMass;
|
||||
List<Collider> boneColliders = new List<Collider>();
|
||||
foreach (KeyValuePair<Bone, Transform> pair in boneTable) {
|
||||
Bone b = pair.Key;
|
||||
Transform t = pair.Value;
|
||||
Transform parentTransform;
|
||||
boneColliders.Add(t.GetComponent<Collider>());
|
||||
if (b == StartingBone) {
|
||||
ragdollRoot = new GameObject("RagdollRoot").transform;
|
||||
ragdollRoot.SetParent(transform, false);
|
||||
if (b == skeleton.RootBone) { // RagdollRoot is skeleton root's parent, thus the skeleton's scale and position.
|
||||
ragdollRoot.localPosition = new Vector3(skeleton.X, skeleton.Y, 0);
|
||||
ragdollRoot.localRotation = (skeleton.ScaleX < 0) ? Quaternion.Euler(0, 0, 180.0f) : Quaternion.identity;
|
||||
} else {
|
||||
ragdollRoot.localPosition = new Vector3(b.Parent.WorldX, b.Parent.WorldY, 0);
|
||||
ragdollRoot.localRotation = Quaternion.Euler(0, 0, b.Parent.WorldRotationX - b.Parent.ShearX);
|
||||
}
|
||||
parentTransform = ragdollRoot;
|
||||
rootOffset = t.position - transform.position;
|
||||
} else {
|
||||
parentTransform = boneTable[b.Parent];
|
||||
}
|
||||
|
||||
// Add joint and attach to parent.
|
||||
Rigidbody rbParent = parentTransform.GetComponent<Rigidbody>();
|
||||
if (rbParent != null) {
|
||||
HingeJoint joint = t.gameObject.AddComponent<HingeJoint>();
|
||||
joint.connectedBody = rbParent;
|
||||
Vector3 localPos = parentTransform.InverseTransformPoint(t.position);
|
||||
localPos.x *= 1;
|
||||
joint.connectedAnchor = localPos;
|
||||
joint.axis = Vector3.forward;
|
||||
|
||||
joint.GetComponent<Rigidbody>().mass = joint.connectedBody.mass * massFalloffFactor;
|
||||
joint.limits = new JointLimits {
|
||||
min = -rotationLimit,
|
||||
max = rotationLimit,
|
||||
};
|
||||
joint.useLimits = true;
|
||||
joint.enableCollision = enableJointCollision;
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore collisions among bones.
|
||||
for (int x = 0; x < boneColliders.Count; x++) {
|
||||
for (int y = 0; y < boneColliders.Count; y++) {
|
||||
if (x == y) continue;
|
||||
Physics.IgnoreCollision(boneColliders[x], boneColliders[y]);
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy existing override-mode SkeletonUtilityBones.
|
||||
SkeletonUtilityBone[] utilityBones = GetComponentsInChildren<SkeletonUtilityBone>();
|
||||
if (utilityBones.Length > 0) {
|
||||
List<string> destroyedUtilityBoneNames = new List<string>();
|
||||
foreach (SkeletonUtilityBone ub in utilityBones) {
|
||||
if (ub.mode == SkeletonUtilityBone.Mode.Override) {
|
||||
destroyedUtilityBoneNames.Add(ub.gameObject.name);
|
||||
Destroy(ub.gameObject);
|
||||
}
|
||||
}
|
||||
if (destroyedUtilityBoneNames.Count > 0) {
|
||||
string msg = "Destroyed Utility Bones: ";
|
||||
for (int i = 0; i < destroyedUtilityBoneNames.Count; i++) {
|
||||
msg += destroyedUtilityBoneNames[i];
|
||||
if (i != destroyedUtilityBoneNames.Count - 1) {
|
||||
msg += ",";
|
||||
}
|
||||
}
|
||||
Debug.LogWarning(msg);
|
||||
}
|
||||
}
|
||||
|
||||
// Disable skeleton constraints.
|
||||
if (disableIK) {
|
||||
ExposedList<IkConstraint> ikConstraints = skeleton.IkConstraints;
|
||||
for (int i = 0, n = ikConstraints.Count; i < n; i++)
|
||||
ikConstraints.Items[i].Mix = 0;
|
||||
}
|
||||
|
||||
if (disableOtherConstraints) {
|
||||
ExposedList<TransformConstraint> transformConstraints = skeleton.TransformConstraints;
|
||||
for (int i = 0, n = transformConstraints.Count; i < n; i++) {
|
||||
transformConstraints.Items[i].MixRotate = 0;
|
||||
transformConstraints.Items[i].MixScaleX = 0;
|
||||
transformConstraints.Items[i].MixScaleY = 0;
|
||||
transformConstraints.Items[i].MixShearY = 0;
|
||||
transformConstraints.Items[i].MixX = 0;
|
||||
transformConstraints.Items[i].MixY = 0;
|
||||
}
|
||||
|
||||
ExposedList<PathConstraint> pathConstraints = skeleton.PathConstraints;
|
||||
for (int i = 0, n = pathConstraints.Count; i < n; i++) {
|
||||
pathConstraints.Items[i].MixRotate = 0;
|
||||
pathConstraints.Items[i].MixX = 0;
|
||||
pathConstraints.Items[i].MixY = 0;
|
||||
}
|
||||
}
|
||||
|
||||
targetSkeletonComponent.UpdateWorld += UpdateSpineSkeleton;
|
||||
}
|
||||
|
||||
/// <summary>Transitions the mix value from the current value to a target value.</summary>
|
||||
public Coroutine SmoothMix (float target, float duration) {
|
||||
return StartCoroutine(SmoothMixCoroutine(target, duration));
|
||||
}
|
||||
|
||||
IEnumerator SmoothMixCoroutine (float target, float duration) {
|
||||
float startTime = Time.time;
|
||||
float startMix = mix;
|
||||
while (mix > 0) {
|
||||
skeleton.SetBonesToSetupPose();
|
||||
mix = Mathf.SmoothStep(startMix, target, (Time.time - startTime) / duration);
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Set the transform world position while preserving the ragdoll parts world position.</summary>
|
||||
public void SetSkeletonPosition (Vector3 worldPosition) {
|
||||
if (!isActive) {
|
||||
Debug.LogWarning("Can't call SetSkeletonPosition while Ragdoll is not active!");
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 offset = worldPosition - transform.position;
|
||||
transform.position = worldPosition;
|
||||
foreach (Transform t in boneTable.Values)
|
||||
t.position -= offset;
|
||||
|
||||
UpdateSpineSkeleton(null);
|
||||
skeleton.UpdateWorldTransform();
|
||||
}
|
||||
|
||||
/// <summary>Removes the ragdoll instance and effect from the animated skeleton.</summary>
|
||||
public void Remove () {
|
||||
isActive = false;
|
||||
foreach (Transform t in boneTable.Values)
|
||||
Destroy(t.gameObject);
|
||||
|
||||
Destroy(ragdollRoot.gameObject);
|
||||
|
||||
boneTable.Clear();
|
||||
targetSkeletonComponent.UpdateWorld -= UpdateSpineSkeleton;
|
||||
}
|
||||
|
||||
public Rigidbody GetRigidbody (string boneName) {
|
||||
Bone bone = skeleton.FindBone(boneName);
|
||||
return (bone != null && boneTable.ContainsKey(bone)) ? boneTable[bone].GetComponent<Rigidbody>() : null;
|
||||
}
|
||||
#endregion
|
||||
|
||||
void RecursivelyCreateBoneProxies (Bone b) {
|
||||
string boneName = b.Data.Name;
|
||||
if (stopBoneNames.Contains(boneName))
|
||||
return;
|
||||
|
||||
GameObject boneGameObject = new GameObject(boneName);
|
||||
boneGameObject.layer = colliderLayer;
|
||||
Transform t = boneGameObject.transform;
|
||||
boneTable.Add(b, t);
|
||||
|
||||
t.parent = transform;
|
||||
t.localPosition = new Vector3(b.WorldX, b.WorldY, 0);
|
||||
t.localRotation = Quaternion.Euler(0, 0, b.WorldRotationX - b.ShearX);
|
||||
t.localScale = new Vector3(b.WorldScaleX, b.WorldScaleY, 1);
|
||||
|
||||
List<Collider> colliders = AttachBoundingBoxRagdollColliders(b);
|
||||
if (colliders.Count == 0) {
|
||||
float length = b.Data.Length;
|
||||
if (length == 0) {
|
||||
SphereCollider ball = boneGameObject.AddComponent<SphereCollider>();
|
||||
ball.radius = thickness * 0.5f;
|
||||
} else {
|
||||
BoxCollider box = boneGameObject.AddComponent<BoxCollider>();
|
||||
box.size = new Vector3(length, thickness, thickness);
|
||||
box.center = new Vector3(length * 0.5f, 0);
|
||||
}
|
||||
}
|
||||
Rigidbody rb = boneGameObject.AddComponent<Rigidbody>();
|
||||
rb.constraints = RigidbodyConstraints.FreezePositionZ;
|
||||
|
||||
foreach (Bone child in b.Children)
|
||||
RecursivelyCreateBoneProxies(child);
|
||||
}
|
||||
|
||||
void UpdateSpineSkeleton (ISkeletonAnimation skeletonRenderer) {
|
||||
bool parentFlipX;
|
||||
bool parentFlipY;
|
||||
GetStartBoneParentFlipState(out parentFlipX, out parentFlipY);
|
||||
|
||||
foreach (KeyValuePair<Bone, Transform> pair in boneTable) {
|
||||
Bone b = pair.Key;
|
||||
Transform t = pair.Value;
|
||||
bool isStartingBone = b == StartingBone;
|
||||
Bone parentBone = b.Parent;
|
||||
Transform parentTransform = isStartingBone ? ragdollRoot : boneTable[parentBone];
|
||||
if (!isStartingBone) {
|
||||
BoneFlipEntry parentBoneFlip = boneFlipTable[parentBone];
|
||||
parentFlipX = parentBoneFlip.flipX;
|
||||
parentFlipY = parentBoneFlip.flipY;
|
||||
}
|
||||
bool flipX = parentFlipX ^ (b.ScaleX < 0);
|
||||
bool flipY = parentFlipY ^ (b.ScaleY < 0);
|
||||
|
||||
BoneFlipEntry boneFlip;
|
||||
boneFlipTable.TryGetValue(b, out boneFlip);
|
||||
boneFlip.flipX = flipX;
|
||||
boneFlip.flipY = flipY;
|
||||
boneFlipTable[b] = boneFlip;
|
||||
|
||||
bool flipXOR = flipX ^ flipY;
|
||||
bool parentFlipXOR = parentFlipX ^ parentFlipY;
|
||||
|
||||
if (!oldRagdollBehaviour && isStartingBone) {
|
||||
if (b != skeleton.RootBone) { // RagdollRoot is not skeleton root.
|
||||
ragdollRoot.localPosition = new Vector3(parentBone.WorldX, parentBone.WorldY, 0);
|
||||
ragdollRoot.localRotation = Quaternion.Euler(0, 0, parentBone.WorldRotationX - parentBone.ShearX);
|
||||
ragdollRoot.localScale = new Vector3(parentBone.WorldScaleX, parentBone.WorldScaleY, 1);
|
||||
}
|
||||
}
|
||||
Vector3 parentTransformWorldPosition = parentTransform.position;
|
||||
Quaternion parentTransformWorldRotation = parentTransform.rotation;
|
||||
|
||||
parentSpaceHelper.position = parentTransformWorldPosition;
|
||||
parentSpaceHelper.rotation = parentTransformWorldRotation;
|
||||
parentSpaceHelper.localScale = parentTransform.lossyScale;
|
||||
|
||||
if (oldRagdollBehaviour) {
|
||||
if (isStartingBone && b != skeleton.RootBone) {
|
||||
Vector3 localPosition = new Vector3(b.Parent.WorldX, b.Parent.WorldY, 0);
|
||||
parentSpaceHelper.position = ragdollRoot.TransformPoint(localPosition);
|
||||
parentSpaceHelper.localRotation = Quaternion.Euler(0, 0, parentBone.WorldRotationX - parentBone.ShearX);
|
||||
parentSpaceHelper.localScale = new Vector3(parentBone.WorldScaleX, parentBone.WorldScaleY, 1);
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 boneWorldPosition = t.position;
|
||||
Vector3 right = parentSpaceHelper.InverseTransformDirection(t.right);
|
||||
|
||||
Vector3 boneLocalPosition = parentSpaceHelper.InverseTransformPoint(boneWorldPosition);
|
||||
float boneLocalRotation = Mathf.Atan2(right.y, right.x) * Mathf.Rad2Deg;
|
||||
|
||||
if (flipXOR) boneLocalPosition.y *= -1f;
|
||||
if (parentFlipXOR != flipXOR) boneLocalPosition.y *= -1f;
|
||||
|
||||
if (parentFlipXOR) boneLocalRotation *= -1f;
|
||||
if (parentFlipX != flipX) boneLocalRotation += 180;
|
||||
|
||||
b.X = Mathf.Lerp(b.X, boneLocalPosition.x, mix);
|
||||
b.Y = Mathf.Lerp(b.Y, boneLocalPosition.y, mix);
|
||||
b.Rotation = Mathf.Lerp(b.Rotation, boneLocalRotation, mix);
|
||||
//b.AppliedRotation = Mathf.Lerp(b.AppliedRotation, boneLocalRotation, mix);
|
||||
}
|
||||
}
|
||||
|
||||
void GetStartBoneParentFlipState (out bool parentFlipX, out bool parentFlipY) {
|
||||
parentFlipX = skeleton.ScaleX < 0;
|
||||
parentFlipY = skeleton.ScaleY < 0;
|
||||
Bone parent = this.StartingBone == null ? null : this.StartingBone.Parent;
|
||||
while (parent != null) {
|
||||
parentFlipX ^= parent.ScaleX < 0;
|
||||
parentFlipY ^= parent.ScaleY < 0;
|
||||
parent = parent.Parent;
|
||||
}
|
||||
}
|
||||
|
||||
List<Collider> AttachBoundingBoxRagdollColliders (Bone b) {
|
||||
const string AttachmentNameMarker = "ragdoll";
|
||||
List<Collider> colliders = new List<Collider>();
|
||||
|
||||
Transform t = boneTable[b];
|
||||
GameObject go = t.gameObject;
|
||||
Skin skin = skeleton.Skin ?? skeleton.Data.DefaultSkin;
|
||||
|
||||
List<Skin.SkinEntry> skinEntries = new List<Skin.SkinEntry>();
|
||||
foreach (Slot s in skeleton.Slots) {
|
||||
if (s.Bone == b) {
|
||||
skin.GetAttachments(skeleton.Slots.IndexOf(s), skinEntries);
|
||||
|
||||
foreach (Skin.SkinEntry entry in skinEntries) {
|
||||
BoundingBoxAttachment bbAttachment = entry.Attachment as BoundingBoxAttachment;
|
||||
if (bbAttachment != null) {
|
||||
if (!entry.Name.ToLower().Contains(AttachmentNameMarker))
|
||||
continue;
|
||||
|
||||
BoxCollider bbCollider = go.AddComponent<BoxCollider>();
|
||||
Bounds bounds = SkeletonUtility.GetBoundingBoxBounds(bbAttachment, thickness);
|
||||
bbCollider.center = bounds.center;
|
||||
bbCollider.size = bounds.size;
|
||||
colliders.Add(bbCollider);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return colliders;
|
||||
}
|
||||
|
||||
public class LayerFieldAttribute : PropertyAttribute { }
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
// Contributed by: Mitch Thompson
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
[RequireComponent(typeof(SkeletonRenderer))]
|
||||
public class SkeletonRagdoll : MonoBehaviour {
|
||||
static Transform parentSpaceHelper;
|
||||
|
||||
#region Inspector
|
||||
[Header("Hierarchy")]
|
||||
[SpineBone]
|
||||
public string startingBoneName = "";
|
||||
[SpineBone]
|
||||
public List<string> stopBoneNames = new List<string>();
|
||||
|
||||
[Header("Parameters")]
|
||||
public bool applyOnStart;
|
||||
[Tooltip("Warning! You will have to re-enable and tune mix values manually if attempting to remove the ragdoll system.")]
|
||||
public bool disableIK = true;
|
||||
public bool disableOtherConstraints = false;
|
||||
[Space(18)]
|
||||
[Tooltip("Set RootRigidbody IsKinematic to true when Apply is called.")]
|
||||
public bool pinStartBone;
|
||||
[Tooltip("Enable Collision between adjacent ragdoll elements (IE: Neck and Head)")]
|
||||
public bool enableJointCollision;
|
||||
public bool useGravity = true;
|
||||
[Tooltip("If no BoundingBox Attachment is attached to a bone, this becomes the default Width or Radius of a Bone's ragdoll Rigidbody")]
|
||||
public float thickness = 0.125f;
|
||||
[Tooltip("Default rotational limit value. Min is negative this value, Max is this value.")]
|
||||
public float rotationLimit = 20;
|
||||
public float rootMass = 20;
|
||||
[Tooltip("If your ragdoll seems unstable or uneffected by limits, try lowering this value.")]
|
||||
[Range(0.01f, 1f)]
|
||||
public float massFalloffFactor = 0.4f;
|
||||
[Tooltip("The layer assigned to all of the rigidbody parts.")]
|
||||
public int colliderLayer = 0;
|
||||
[Range(0, 1)]
|
||||
public float mix = 1;
|
||||
public bool oldRagdollBehaviour = false;
|
||||
#endregion
|
||||
|
||||
ISkeletonAnimation targetSkeletonComponent;
|
||||
Skeleton skeleton;
|
||||
struct BoneFlipEntry {
|
||||
public BoneFlipEntry (bool flipX, bool flipY) {
|
||||
this.flipX = flipX;
|
||||
this.flipY = flipY;
|
||||
}
|
||||
|
||||
public bool flipX;
|
||||
public bool flipY;
|
||||
}
|
||||
Dictionary<Bone, Transform> boneTable = new Dictionary<Bone, Transform>();
|
||||
Dictionary<Bone, BoneFlipEntry> boneFlipTable = new Dictionary<Bone, BoneFlipEntry>();
|
||||
Transform ragdollRoot;
|
||||
public Rigidbody RootRigidbody { get; private set; }
|
||||
public Bone StartingBone { get; private set; }
|
||||
Vector3 rootOffset;
|
||||
public Vector3 RootOffset { get { return this.rootOffset; } }
|
||||
bool isActive;
|
||||
public bool IsActive { get { return this.isActive; } }
|
||||
|
||||
IEnumerator Start () {
|
||||
if (parentSpaceHelper == null) {
|
||||
parentSpaceHelper = (new GameObject("Parent Space Helper")).transform;
|
||||
parentSpaceHelper.hideFlags = HideFlags.HideInHierarchy;
|
||||
}
|
||||
|
||||
targetSkeletonComponent = GetComponent<SkeletonRenderer>() as ISkeletonAnimation;
|
||||
if (targetSkeletonComponent == null) Debug.LogError("Attached Spine component does not implement ISkeletonAnimation. This script is not compatible.");
|
||||
skeleton = targetSkeletonComponent.Skeleton;
|
||||
|
||||
if (applyOnStart) {
|
||||
yield return null;
|
||||
Apply();
|
||||
}
|
||||
}
|
||||
|
||||
#region API
|
||||
public Rigidbody[] RigidbodyArray {
|
||||
get {
|
||||
if (!isActive)
|
||||
return new Rigidbody[0];
|
||||
|
||||
Rigidbody[] rigidBodies = new Rigidbody[boneTable.Count];
|
||||
int i = 0;
|
||||
foreach (Transform t in boneTable.Values) {
|
||||
rigidBodies[i] = t.GetComponent<Rigidbody>();
|
||||
i++;
|
||||
}
|
||||
|
||||
return rigidBodies;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 EstimatedSkeletonPosition {
|
||||
get { return RootRigidbody.position - rootOffset; }
|
||||
}
|
||||
|
||||
/// <summary>Instantiates the ragdoll simulation and applies its transforms to the skeleton.</summary>
|
||||
public void Apply () {
|
||||
isActive = true;
|
||||
mix = 1;
|
||||
|
||||
StartingBone = skeleton.FindBone(startingBoneName);
|
||||
RecursivelyCreateBoneProxies(StartingBone);
|
||||
|
||||
RootRigidbody = boneTable[StartingBone].GetComponent<Rigidbody>();
|
||||
RootRigidbody.isKinematic = pinStartBone;
|
||||
RootRigidbody.mass = rootMass;
|
||||
List<Collider> boneColliders = new List<Collider>();
|
||||
foreach (KeyValuePair<Bone, Transform> pair in boneTable) {
|
||||
Bone b = pair.Key;
|
||||
Transform t = pair.Value;
|
||||
Transform parentTransform;
|
||||
boneColliders.Add(t.GetComponent<Collider>());
|
||||
if (b == StartingBone) {
|
||||
ragdollRoot = new GameObject("RagdollRoot").transform;
|
||||
ragdollRoot.SetParent(transform, false);
|
||||
if (b == skeleton.RootBone) { // RagdollRoot is skeleton root's parent, thus the skeleton's scale and position.
|
||||
ragdollRoot.localPosition = new Vector3(skeleton.X, skeleton.Y, 0);
|
||||
ragdollRoot.localRotation = (skeleton.ScaleX < 0) ? Quaternion.Euler(0, 0, 180.0f) : Quaternion.identity;
|
||||
} else {
|
||||
ragdollRoot.localPosition = new Vector3(b.Parent.WorldX, b.Parent.WorldY, 0);
|
||||
ragdollRoot.localRotation = Quaternion.Euler(0, 0, b.Parent.WorldRotationX - b.Parent.ShearX);
|
||||
}
|
||||
parentTransform = ragdollRoot;
|
||||
rootOffset = t.position - transform.position;
|
||||
} else {
|
||||
parentTransform = boneTable[b.Parent];
|
||||
}
|
||||
|
||||
// Add joint and attach to parent.
|
||||
Rigidbody rbParent = parentTransform.GetComponent<Rigidbody>();
|
||||
if (rbParent != null) {
|
||||
HingeJoint joint = t.gameObject.AddComponent<HingeJoint>();
|
||||
joint.connectedBody = rbParent;
|
||||
Vector3 localPos = parentTransform.InverseTransformPoint(t.position);
|
||||
localPos.x *= 1;
|
||||
joint.connectedAnchor = localPos;
|
||||
joint.axis = Vector3.forward;
|
||||
|
||||
joint.GetComponent<Rigidbody>().mass = joint.connectedBody.mass * massFalloffFactor;
|
||||
joint.limits = new JointLimits {
|
||||
min = -rotationLimit,
|
||||
max = rotationLimit,
|
||||
};
|
||||
joint.useLimits = true;
|
||||
joint.enableCollision = enableJointCollision;
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore collisions among bones.
|
||||
for (int x = 0; x < boneColliders.Count; x++) {
|
||||
for (int y = 0; y < boneColliders.Count; y++) {
|
||||
if (x == y) continue;
|
||||
Physics.IgnoreCollision(boneColliders[x], boneColliders[y]);
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy existing override-mode SkeletonUtilityBones.
|
||||
SkeletonUtilityBone[] utilityBones = GetComponentsInChildren<SkeletonUtilityBone>();
|
||||
if (utilityBones.Length > 0) {
|
||||
List<string> destroyedUtilityBoneNames = new List<string>();
|
||||
foreach (SkeletonUtilityBone ub in utilityBones) {
|
||||
if (ub.mode == SkeletonUtilityBone.Mode.Override) {
|
||||
destroyedUtilityBoneNames.Add(ub.gameObject.name);
|
||||
Destroy(ub.gameObject);
|
||||
}
|
||||
}
|
||||
if (destroyedUtilityBoneNames.Count > 0) {
|
||||
string msg = "Destroyed Utility Bones: ";
|
||||
for (int i = 0; i < destroyedUtilityBoneNames.Count; i++) {
|
||||
msg += destroyedUtilityBoneNames[i];
|
||||
if (i != destroyedUtilityBoneNames.Count - 1) {
|
||||
msg += ",";
|
||||
}
|
||||
}
|
||||
Debug.LogWarning(msg);
|
||||
}
|
||||
}
|
||||
|
||||
// Disable skeleton constraints.
|
||||
if (disableIK) {
|
||||
ExposedList<IkConstraint> ikConstraints = skeleton.IkConstraints;
|
||||
for (int i = 0, n = ikConstraints.Count; i < n; i++)
|
||||
ikConstraints.Items[i].Mix = 0;
|
||||
}
|
||||
|
||||
if (disableOtherConstraints) {
|
||||
ExposedList<TransformConstraint> transformConstraints = skeleton.TransformConstraints;
|
||||
for (int i = 0, n = transformConstraints.Count; i < n; i++) {
|
||||
transformConstraints.Items[i].MixRotate = 0;
|
||||
transformConstraints.Items[i].MixScaleX = 0;
|
||||
transformConstraints.Items[i].MixScaleY = 0;
|
||||
transformConstraints.Items[i].MixShearY = 0;
|
||||
transformConstraints.Items[i].MixX = 0;
|
||||
transformConstraints.Items[i].MixY = 0;
|
||||
}
|
||||
|
||||
ExposedList<PathConstraint> pathConstraints = skeleton.PathConstraints;
|
||||
for (int i = 0, n = pathConstraints.Count; i < n; i++) {
|
||||
pathConstraints.Items[i].MixRotate = 0;
|
||||
pathConstraints.Items[i].MixX = 0;
|
||||
pathConstraints.Items[i].MixY = 0;
|
||||
}
|
||||
}
|
||||
|
||||
targetSkeletonComponent.UpdateWorld += UpdateSpineSkeleton;
|
||||
}
|
||||
|
||||
/// <summary>Transitions the mix value from the current value to a target value.</summary>
|
||||
public Coroutine SmoothMix (float target, float duration) {
|
||||
return StartCoroutine(SmoothMixCoroutine(target, duration));
|
||||
}
|
||||
|
||||
IEnumerator SmoothMixCoroutine (float target, float duration) {
|
||||
float startTime = Time.time;
|
||||
float startMix = mix;
|
||||
while (mix > 0) {
|
||||
skeleton.SetBonesToSetupPose();
|
||||
mix = Mathf.SmoothStep(startMix, target, (Time.time - startTime) / duration);
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Set the transform world position while preserving the ragdoll parts world position.</summary>
|
||||
public void SetSkeletonPosition (Vector3 worldPosition) {
|
||||
if (!isActive) {
|
||||
Debug.LogWarning("Can't call SetSkeletonPosition while Ragdoll is not active!");
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 offset = worldPosition - transform.position;
|
||||
transform.position = worldPosition;
|
||||
foreach (Transform t in boneTable.Values)
|
||||
t.position -= offset;
|
||||
|
||||
UpdateSpineSkeleton(null);
|
||||
skeleton.UpdateWorldTransform(Skeleton.Physics.Update);
|
||||
}
|
||||
|
||||
/// <summary>Removes the ragdoll instance and effect from the animated skeleton.</summary>
|
||||
public void Remove () {
|
||||
isActive = false;
|
||||
foreach (Transform t in boneTable.Values)
|
||||
Destroy(t.gameObject);
|
||||
|
||||
Destroy(ragdollRoot.gameObject);
|
||||
|
||||
boneTable.Clear();
|
||||
targetSkeletonComponent.UpdateWorld -= UpdateSpineSkeleton;
|
||||
}
|
||||
|
||||
public Rigidbody GetRigidbody (string boneName) {
|
||||
Bone bone = skeleton.FindBone(boneName);
|
||||
return (bone != null && boneTable.ContainsKey(bone)) ? boneTable[bone].GetComponent<Rigidbody>() : null;
|
||||
}
|
||||
#endregion
|
||||
|
||||
void RecursivelyCreateBoneProxies (Bone b) {
|
||||
string boneName = b.Data.Name;
|
||||
if (stopBoneNames.Contains(boneName))
|
||||
return;
|
||||
|
||||
GameObject boneGameObject = new GameObject(boneName);
|
||||
boneGameObject.layer = colliderLayer;
|
||||
Transform t = boneGameObject.transform;
|
||||
boneTable.Add(b, t);
|
||||
|
||||
t.parent = transform;
|
||||
t.localPosition = new Vector3(b.WorldX, b.WorldY, 0);
|
||||
t.localRotation = Quaternion.Euler(0, 0, b.WorldRotationX - b.ShearX);
|
||||
t.localScale = new Vector3(b.WorldScaleX, b.WorldScaleY, 1);
|
||||
|
||||
List<Collider> colliders = AttachBoundingBoxRagdollColliders(b);
|
||||
if (colliders.Count == 0) {
|
||||
float length = b.Data.Length;
|
||||
if (length == 0) {
|
||||
SphereCollider ball = boneGameObject.AddComponent<SphereCollider>();
|
||||
ball.radius = thickness * 0.5f;
|
||||
} else {
|
||||
BoxCollider box = boneGameObject.AddComponent<BoxCollider>();
|
||||
box.size = new Vector3(length, thickness, thickness);
|
||||
box.center = new Vector3(length * 0.5f, 0);
|
||||
}
|
||||
}
|
||||
Rigidbody rb = boneGameObject.AddComponent<Rigidbody>();
|
||||
rb.constraints = RigidbodyConstraints.FreezePositionZ;
|
||||
|
||||
foreach (Bone child in b.Children)
|
||||
RecursivelyCreateBoneProxies(child);
|
||||
}
|
||||
|
||||
void UpdateSpineSkeleton (ISkeletonAnimation skeletonRenderer) {
|
||||
bool parentFlipX;
|
||||
bool parentFlipY;
|
||||
GetStartBoneParentFlipState(out parentFlipX, out parentFlipY);
|
||||
|
||||
foreach (KeyValuePair<Bone, Transform> pair in boneTable) {
|
||||
Bone b = pair.Key;
|
||||
Transform t = pair.Value;
|
||||
bool isStartingBone = b == StartingBone;
|
||||
Bone parentBone = b.Parent;
|
||||
Transform parentTransform = isStartingBone ? ragdollRoot : boneTable[parentBone];
|
||||
if (!isStartingBone) {
|
||||
BoneFlipEntry parentBoneFlip = boneFlipTable[parentBone];
|
||||
parentFlipX = parentBoneFlip.flipX;
|
||||
parentFlipY = parentBoneFlip.flipY;
|
||||
}
|
||||
bool flipX = parentFlipX ^ (b.ScaleX < 0);
|
||||
bool flipY = parentFlipY ^ (b.ScaleY < 0);
|
||||
|
||||
BoneFlipEntry boneFlip;
|
||||
boneFlipTable.TryGetValue(b, out boneFlip);
|
||||
boneFlip.flipX = flipX;
|
||||
boneFlip.flipY = flipY;
|
||||
boneFlipTable[b] = boneFlip;
|
||||
|
||||
bool flipXOR = flipX ^ flipY;
|
||||
bool parentFlipXOR = parentFlipX ^ parentFlipY;
|
||||
|
||||
if (!oldRagdollBehaviour && isStartingBone) {
|
||||
if (b != skeleton.RootBone) { // RagdollRoot is not skeleton root.
|
||||
ragdollRoot.localPosition = new Vector3(parentBone.WorldX, parentBone.WorldY, 0);
|
||||
ragdollRoot.localRotation = Quaternion.Euler(0, 0, parentBone.WorldRotationX - parentBone.ShearX);
|
||||
ragdollRoot.localScale = new Vector3(parentBone.WorldScaleX, parentBone.WorldScaleY, 1);
|
||||
}
|
||||
}
|
||||
Vector3 parentTransformWorldPosition = parentTransform.position;
|
||||
Quaternion parentTransformWorldRotation = parentTransform.rotation;
|
||||
|
||||
parentSpaceHelper.position = parentTransformWorldPosition;
|
||||
parentSpaceHelper.rotation = parentTransformWorldRotation;
|
||||
parentSpaceHelper.localScale = parentTransform.lossyScale;
|
||||
|
||||
if (oldRagdollBehaviour) {
|
||||
if (isStartingBone && b != skeleton.RootBone) {
|
||||
Vector3 localPosition = new Vector3(b.Parent.WorldX, b.Parent.WorldY, 0);
|
||||
parentSpaceHelper.position = ragdollRoot.TransformPoint(localPosition);
|
||||
parentSpaceHelper.localRotation = Quaternion.Euler(0, 0, parentBone.WorldRotationX - parentBone.ShearX);
|
||||
parentSpaceHelper.localScale = new Vector3(parentBone.WorldScaleX, parentBone.WorldScaleY, 1);
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 boneWorldPosition = t.position;
|
||||
Vector3 right = parentSpaceHelper.InverseTransformDirection(t.right);
|
||||
|
||||
Vector3 boneLocalPosition = parentSpaceHelper.InverseTransformPoint(boneWorldPosition);
|
||||
float boneLocalRotation = Mathf.Atan2(right.y, right.x) * Mathf.Rad2Deg;
|
||||
|
||||
if (flipXOR) boneLocalPosition.y *= -1f;
|
||||
if (parentFlipXOR != flipXOR) boneLocalPosition.y *= -1f;
|
||||
|
||||
if (parentFlipXOR) boneLocalRotation *= -1f;
|
||||
if (parentFlipX != flipX) boneLocalRotation += 180;
|
||||
|
||||
b.X = Mathf.Lerp(b.X, boneLocalPosition.x, mix);
|
||||
b.Y = Mathf.Lerp(b.Y, boneLocalPosition.y, mix);
|
||||
b.Rotation = Mathf.Lerp(b.Rotation, boneLocalRotation, mix);
|
||||
//b.AppliedRotation = Mathf.Lerp(b.AppliedRotation, boneLocalRotation, mix);
|
||||
}
|
||||
}
|
||||
|
||||
void GetStartBoneParentFlipState (out bool parentFlipX, out bool parentFlipY) {
|
||||
parentFlipX = skeleton.ScaleX < 0;
|
||||
parentFlipY = skeleton.ScaleY < 0;
|
||||
Bone parent = this.StartingBone == null ? null : this.StartingBone.Parent;
|
||||
while (parent != null) {
|
||||
parentFlipX ^= parent.ScaleX < 0;
|
||||
parentFlipY ^= parent.ScaleY < 0;
|
||||
parent = parent.Parent;
|
||||
}
|
||||
}
|
||||
|
||||
List<Collider> AttachBoundingBoxRagdollColliders (Bone b) {
|
||||
const string AttachmentNameMarker = "ragdoll";
|
||||
List<Collider> colliders = new List<Collider>();
|
||||
|
||||
Transform t = boneTable[b];
|
||||
GameObject go = t.gameObject;
|
||||
Skin skin = skeleton.Skin ?? skeleton.Data.DefaultSkin;
|
||||
|
||||
List<Skin.SkinEntry> skinEntries = new List<Skin.SkinEntry>();
|
||||
foreach (Slot s in skeleton.Slots) {
|
||||
if (s.Bone == b) {
|
||||
skin.GetAttachments(skeleton.Slots.IndexOf(s), skinEntries);
|
||||
|
||||
foreach (Skin.SkinEntry entry in skinEntries) {
|
||||
BoundingBoxAttachment bbAttachment = entry.Attachment as BoundingBoxAttachment;
|
||||
if (bbAttachment != null) {
|
||||
if (!entry.Name.ToLower().Contains(AttachmentNameMarker))
|
||||
continue;
|
||||
|
||||
BoxCollider bbCollider = go.AddComponent<BoxCollider>();
|
||||
Bounds bounds = SkeletonUtility.GetBoundingBoxBounds(bbAttachment, thickness);
|
||||
bbCollider.center = bounds.center;
|
||||
bbCollider.size = bounds.size;
|
||||
colliders.Add(bbCollider);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return colliders;
|
||||
}
|
||||
|
||||
public class LayerFieldAttribute : PropertyAttribute { }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,472 +1,472 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
// Contributed by: Mitch Thompson
|
||||
|
||||
#if UNITY_2019_2 || UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 // note: 2020.3+ uses old bahavior again
|
||||
#define HINGE_JOINT_2019_BEHAVIOUR
|
||||
#endif
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
[RequireComponent(typeof(SkeletonRenderer))]
|
||||
public class SkeletonRagdoll2D : MonoBehaviour {
|
||||
static Transform parentSpaceHelper;
|
||||
|
||||
#region Inspector
|
||||
[Header("Hierarchy")]
|
||||
[SpineBone]
|
||||
public string startingBoneName = "";
|
||||
[SpineBone]
|
||||
public List<string> stopBoneNames = new List<string>();
|
||||
|
||||
[Header("Parameters")]
|
||||
public bool applyOnStart;
|
||||
[Tooltip("Warning! You will have to re-enable and tune mix values manually if attempting to remove the ragdoll system.")]
|
||||
public bool disableIK = true;
|
||||
public bool disableOtherConstraints = false;
|
||||
[Space]
|
||||
[Tooltip("Set RootRigidbody IsKinematic to true when Apply is called.")]
|
||||
public bool pinStartBone;
|
||||
public float gravityScale = 1;
|
||||
[Tooltip("If no BoundingBox Attachment is attached to a bone, this becomes the default Width or Radius of a Bone's ragdoll Rigidbody")]
|
||||
public float thickness = 0.125f;
|
||||
[Tooltip("Default rotational limit value. Min is negative this value, Max is this value.")]
|
||||
public float rotationLimit = 20;
|
||||
public float rootMass = 20;
|
||||
[Tooltip("If your ragdoll seems unstable or uneffected by limits, try lowering this value.")]
|
||||
[Range(0.01f, 1f)]
|
||||
public float massFalloffFactor = 0.4f;
|
||||
[Tooltip("The layer assigned to all of the rigidbody parts.")]
|
||||
[SkeletonRagdoll.LayerField]
|
||||
public int colliderLayer = 0;
|
||||
[Range(0, 1)]
|
||||
public float mix = 1;
|
||||
public bool oldRagdollBehaviour = false;
|
||||
#endregion
|
||||
|
||||
ISkeletonAnimation targetSkeletonComponent;
|
||||
Skeleton skeleton;
|
||||
struct BoneFlipEntry {
|
||||
public BoneFlipEntry (bool flipX, bool flipY) {
|
||||
this.flipX = flipX;
|
||||
this.flipY = flipY;
|
||||
}
|
||||
|
||||
public bool flipX;
|
||||
public bool flipY;
|
||||
}
|
||||
Dictionary<Bone, Transform> boneTable = new Dictionary<Bone, Transform>();
|
||||
Dictionary<Bone, BoneFlipEntry> boneFlipTable = new Dictionary<Bone, BoneFlipEntry>();
|
||||
Transform ragdollRoot;
|
||||
public Rigidbody2D RootRigidbody { get; private set; }
|
||||
public Bone StartingBone { get; private set; }
|
||||
Vector2 rootOffset;
|
||||
public Vector3 RootOffset { get { return this.rootOffset; } }
|
||||
bool isActive;
|
||||
public bool IsActive { get { return this.isActive; } }
|
||||
|
||||
IEnumerator Start () {
|
||||
if (parentSpaceHelper == null) {
|
||||
parentSpaceHelper = (new GameObject("Parent Space Helper")).transform;
|
||||
}
|
||||
|
||||
targetSkeletonComponent = GetComponent<SkeletonRenderer>() as ISkeletonAnimation;
|
||||
if (targetSkeletonComponent == null) Debug.LogError("Attached Spine component does not implement ISkeletonAnimation. This script is not compatible.");
|
||||
skeleton = targetSkeletonComponent.Skeleton;
|
||||
|
||||
if (applyOnStart) {
|
||||
yield return null;
|
||||
Apply();
|
||||
}
|
||||
}
|
||||
|
||||
#region API
|
||||
public Rigidbody2D[] RigidbodyArray {
|
||||
get {
|
||||
if (!isActive)
|
||||
return new Rigidbody2D[0];
|
||||
|
||||
Rigidbody2D[] rigidBodies = new Rigidbody2D[boneTable.Count];
|
||||
int i = 0;
|
||||
foreach (Transform t in boneTable.Values) {
|
||||
rigidBodies[i] = t.GetComponent<Rigidbody2D>();
|
||||
i++;
|
||||
}
|
||||
|
||||
return rigidBodies;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 EstimatedSkeletonPosition {
|
||||
get { return this.RootRigidbody.position - rootOffset; }
|
||||
}
|
||||
|
||||
/// <summary>Instantiates the ragdoll simulation and applies its transforms to the skeleton.</summary>
|
||||
public void Apply () {
|
||||
isActive = true;
|
||||
mix = 1;
|
||||
|
||||
Bone startingBone = this.StartingBone = skeleton.FindBone(startingBoneName);
|
||||
RecursivelyCreateBoneProxies(startingBone);
|
||||
|
||||
RootRigidbody = boneTable[startingBone].GetComponent<Rigidbody2D>();
|
||||
RootRigidbody.isKinematic = pinStartBone;
|
||||
RootRigidbody.mass = rootMass;
|
||||
List<Collider2D> boneColliders = new List<Collider2D>();
|
||||
foreach (KeyValuePair<Bone, Transform> pair in boneTable) {
|
||||
Bone b = pair.Key;
|
||||
Transform t = pair.Value;
|
||||
Transform parentTransform;
|
||||
boneColliders.Add(t.GetComponent<Collider2D>());
|
||||
if (b == startingBone) {
|
||||
ragdollRoot = new GameObject("RagdollRoot").transform;
|
||||
ragdollRoot.SetParent(transform, false);
|
||||
if (b == skeleton.RootBone) { // RagdollRoot is skeleton root's parent, thus the skeleton's scale and position.
|
||||
ragdollRoot.localPosition = new Vector3(skeleton.X, skeleton.Y, 0);
|
||||
ragdollRoot.localRotation = (skeleton.ScaleX < 0) ? Quaternion.Euler(0, 0, 180.0f) : Quaternion.identity;
|
||||
} else {
|
||||
ragdollRoot.localPosition = new Vector3(b.Parent.WorldX, b.Parent.WorldY, 0);
|
||||
ragdollRoot.localRotation = Quaternion.Euler(0, 0, b.Parent.WorldRotationX - b.Parent.ShearX);
|
||||
}
|
||||
parentTransform = ragdollRoot;
|
||||
rootOffset = t.position - transform.position;
|
||||
} else {
|
||||
parentTransform = boneTable[b.Parent];
|
||||
}
|
||||
|
||||
// Add joint and attach to parent.
|
||||
Rigidbody2D rbParent = parentTransform.GetComponent<Rigidbody2D>();
|
||||
if (rbParent != null) {
|
||||
HingeJoint2D joint = t.gameObject.AddComponent<HingeJoint2D>();
|
||||
joint.connectedBody = rbParent;
|
||||
Vector3 localPos = parentTransform.InverseTransformPoint(t.position);
|
||||
joint.connectedAnchor = localPos;
|
||||
|
||||
joint.GetComponent<Rigidbody2D>().mass = joint.connectedBody.mass * massFalloffFactor;
|
||||
|
||||
#if HINGE_JOINT_2019_BEHAVIOUR
|
||||
float referenceAngle = (rbParent.transform.eulerAngles.z - t.eulerAngles.z + 360f) % 360f;
|
||||
float minAngle = referenceAngle - rotationLimit;
|
||||
float maxAngle = referenceAngle + rotationLimit;
|
||||
if (maxAngle > 180f) {
|
||||
minAngle -= 360f;
|
||||
maxAngle -= 360f;
|
||||
}
|
||||
#else
|
||||
float minAngle = -rotationLimit;
|
||||
float maxAngle = rotationLimit;
|
||||
#endif
|
||||
joint.limits = new JointAngleLimits2D {
|
||||
min = minAngle,
|
||||
max = maxAngle
|
||||
};
|
||||
joint.useLimits = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore collisions among bones.
|
||||
for (int x = 0; x < boneColliders.Count; x++) {
|
||||
for (int y = 0; y < boneColliders.Count; y++) {
|
||||
if (x == y) continue;
|
||||
Physics2D.IgnoreCollision(boneColliders[x], boneColliders[y]);
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy existing override-mode SkeletonUtility bones.
|
||||
SkeletonUtilityBone[] utilityBones = GetComponentsInChildren<SkeletonUtilityBone>();
|
||||
if (utilityBones.Length > 0) {
|
||||
List<string> destroyedUtilityBoneNames = new List<string>();
|
||||
foreach (SkeletonUtilityBone ub in utilityBones) {
|
||||
if (ub.mode == SkeletonUtilityBone.Mode.Override) {
|
||||
destroyedUtilityBoneNames.Add(ub.gameObject.name);
|
||||
Destroy(ub.gameObject);
|
||||
}
|
||||
}
|
||||
if (destroyedUtilityBoneNames.Count > 0) {
|
||||
string msg = "Destroyed Utility Bones: ";
|
||||
for (int i = 0; i < destroyedUtilityBoneNames.Count; i++) {
|
||||
msg += destroyedUtilityBoneNames[i];
|
||||
if (i != destroyedUtilityBoneNames.Count - 1) {
|
||||
msg += ",";
|
||||
}
|
||||
}
|
||||
Debug.LogWarning(msg);
|
||||
}
|
||||
}
|
||||
|
||||
// Disable skeleton constraints.
|
||||
if (disableIK) {
|
||||
ExposedList<IkConstraint> ikConstraints = skeleton.IkConstraints;
|
||||
for (int i = 0, n = ikConstraints.Count; i < n; i++)
|
||||
ikConstraints.Items[i].Mix = 0;
|
||||
}
|
||||
|
||||
if (disableOtherConstraints) {
|
||||
ExposedList<TransformConstraint> transformConstraints = skeleton.TransformConstraints;
|
||||
for (int i = 0, n = transformConstraints.Count; i < n; i++) {
|
||||
transformConstraints.Items[i].MixRotate = 0;
|
||||
transformConstraints.Items[i].MixScaleX = 0;
|
||||
transformConstraints.Items[i].MixScaleY = 0;
|
||||
transformConstraints.Items[i].MixShearY = 0;
|
||||
transformConstraints.Items[i].MixX = 0;
|
||||
transformConstraints.Items[i].MixY = 0;
|
||||
}
|
||||
|
||||
ExposedList<PathConstraint> pathConstraints = skeleton.PathConstraints;
|
||||
for (int i = 0, n = pathConstraints.Count; i < n; i++) {
|
||||
pathConstraints.Items[i].MixRotate = 0;
|
||||
pathConstraints.Items[i].MixX = 0;
|
||||
pathConstraints.Items[i].MixY = 0;
|
||||
}
|
||||
}
|
||||
|
||||
targetSkeletonComponent.UpdateWorld += UpdateSpineSkeleton;
|
||||
}
|
||||
|
||||
/// <summary>Transitions the mix value from the current value to a target value.</summary>
|
||||
public Coroutine SmoothMix (float target, float duration) {
|
||||
return StartCoroutine(SmoothMixCoroutine(target, duration));
|
||||
}
|
||||
|
||||
IEnumerator SmoothMixCoroutine (float target, float duration) {
|
||||
float startTime = Time.time;
|
||||
float startMix = mix;
|
||||
while (mix > 0) {
|
||||
skeleton.SetBonesToSetupPose();
|
||||
mix = Mathf.SmoothStep(startMix, target, (Time.time - startTime) / duration);
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Set the transform world position while preserving the ragdoll parts world position.</summary>
|
||||
public void SetSkeletonPosition (Vector3 worldPosition) {
|
||||
if (!isActive) {
|
||||
Debug.LogWarning("Can't call SetSkeletonPosition while Ragdoll is not active!");
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 offset = worldPosition - transform.position;
|
||||
transform.position = worldPosition;
|
||||
foreach (Transform t in boneTable.Values)
|
||||
t.position -= offset;
|
||||
|
||||
UpdateSpineSkeleton(null);
|
||||
skeleton.UpdateWorldTransform();
|
||||
}
|
||||
|
||||
/// <summary>Removes the ragdoll instance and effect from the animated skeleton.</summary>
|
||||
public void Remove () {
|
||||
isActive = false;
|
||||
foreach (Transform t in boneTable.Values)
|
||||
Destroy(t.gameObject);
|
||||
|
||||
Destroy(ragdollRoot.gameObject);
|
||||
boneTable.Clear();
|
||||
targetSkeletonComponent.UpdateWorld -= UpdateSpineSkeleton;
|
||||
}
|
||||
|
||||
public Rigidbody2D GetRigidbody (string boneName) {
|
||||
Bone bone = skeleton.FindBone(boneName);
|
||||
return (bone != null && boneTable.ContainsKey(bone)) ? boneTable[bone].GetComponent<Rigidbody2D>() : null;
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>Generates the ragdoll simulation's Transform and joint setup.</summary>
|
||||
void RecursivelyCreateBoneProxies (Bone b) {
|
||||
string boneName = b.Data.Name;
|
||||
if (stopBoneNames.Contains(boneName))
|
||||
return;
|
||||
|
||||
GameObject boneGameObject = new GameObject(boneName);
|
||||
boneGameObject.layer = this.colliderLayer;
|
||||
Transform t = boneGameObject.transform;
|
||||
boneTable.Add(b, t);
|
||||
|
||||
t.parent = transform;
|
||||
t.localPosition = new Vector3(b.WorldX, b.WorldY, 0);
|
||||
t.localRotation = Quaternion.Euler(0, 0, b.WorldRotationX - b.ShearX);
|
||||
t.localScale = new Vector3(b.WorldScaleX, b.WorldScaleY, 1);
|
||||
|
||||
List<Collider2D> colliders = AttachBoundingBoxRagdollColliders(b, boneGameObject, skeleton, this.gravityScale);
|
||||
if (colliders.Count == 0) {
|
||||
float length = b.Data.Length;
|
||||
if (length == 0) {
|
||||
CircleCollider2D circle = boneGameObject.AddComponent<CircleCollider2D>();
|
||||
circle.radius = thickness * 0.5f;
|
||||
} else {
|
||||
BoxCollider2D box = boneGameObject.AddComponent<BoxCollider2D>();
|
||||
box.size = new Vector2(length, thickness);
|
||||
box.offset = new Vector2(length * 0.5f, 0); // box.center in UNITY_4
|
||||
}
|
||||
}
|
||||
|
||||
Rigidbody2D rb = boneGameObject.GetComponent<Rigidbody2D>();
|
||||
if (rb == null) rb = boneGameObject.AddComponent<Rigidbody2D>();
|
||||
rb.gravityScale = this.gravityScale;
|
||||
|
||||
foreach (Bone child in b.Children)
|
||||
RecursivelyCreateBoneProxies(child);
|
||||
}
|
||||
|
||||
/// <summary>Performed every skeleton animation update to translate Unity Transforms positions into Spine bone transforms.</summary>
|
||||
void UpdateSpineSkeleton (ISkeletonAnimation animatedSkeleton) {
|
||||
bool parentFlipX;
|
||||
bool parentFlipY;
|
||||
Bone startingBone = this.StartingBone;
|
||||
GetStartBoneParentFlipState(out parentFlipX, out parentFlipY);
|
||||
|
||||
foreach (KeyValuePair<Bone, Transform> pair in boneTable) {
|
||||
Bone b = pair.Key;
|
||||
Transform t = pair.Value;
|
||||
bool isStartingBone = (b == startingBone);
|
||||
Bone parentBone = b.Parent;
|
||||
Transform parentTransform = isStartingBone ? ragdollRoot : boneTable[parentBone];
|
||||
if (!isStartingBone) {
|
||||
BoneFlipEntry parentBoneFlip = boneFlipTable[parentBone];
|
||||
parentFlipX = parentBoneFlip.flipX;
|
||||
parentFlipY = parentBoneFlip.flipY;
|
||||
}
|
||||
bool flipX = parentFlipX ^ (b.ScaleX < 0);
|
||||
bool flipY = parentFlipY ^ (b.ScaleY < 0);
|
||||
|
||||
BoneFlipEntry boneFlip;
|
||||
boneFlipTable.TryGetValue(b, out boneFlip);
|
||||
boneFlip.flipX = flipX;
|
||||
boneFlip.flipY = flipY;
|
||||
boneFlipTable[b] = boneFlip;
|
||||
|
||||
bool flipXOR = flipX ^ flipY;
|
||||
bool parentFlipXOR = parentFlipX ^ parentFlipY;
|
||||
|
||||
if (!oldRagdollBehaviour && isStartingBone) {
|
||||
if (b != skeleton.RootBone) { // RagdollRoot is not skeleton root.
|
||||
ragdollRoot.localPosition = new Vector3(parentBone.WorldX, parentBone.WorldY, 0);
|
||||
ragdollRoot.localRotation = Quaternion.Euler(0, 0, parentBone.WorldRotationX - parentBone.ShearX);
|
||||
ragdollRoot.localScale = new Vector3(parentBone.WorldScaleX, parentBone.WorldScaleY, 1);
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 parentTransformWorldPosition = parentTransform.position;
|
||||
Quaternion parentTransformWorldRotation = parentTransform.rotation;
|
||||
|
||||
parentSpaceHelper.position = parentTransformWorldPosition;
|
||||
parentSpaceHelper.rotation = parentTransformWorldRotation;
|
||||
parentSpaceHelper.localScale = parentTransform.lossyScale;
|
||||
|
||||
if (oldRagdollBehaviour) {
|
||||
if (isStartingBone && b != skeleton.RootBone) {
|
||||
Vector3 localPosition = new Vector3(b.Parent.WorldX, b.Parent.WorldY, 0);
|
||||
parentSpaceHelper.position = ragdollRoot.TransformPoint(localPosition);
|
||||
parentSpaceHelper.localRotation = Quaternion.Euler(0, 0, parentBone.WorldRotationX - parentBone.ShearX);
|
||||
parentSpaceHelper.localScale = new Vector3(parentBone.WorldScaleX, parentBone.WorldScaleY, 1);
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 boneWorldPosition = t.position;
|
||||
Vector3 right = parentSpaceHelper.InverseTransformDirection(t.right);
|
||||
|
||||
Vector3 boneLocalPosition = parentSpaceHelper.InverseTransformPoint(boneWorldPosition);
|
||||
float boneLocalRotation = Mathf.Atan2(right.y, right.x) * Mathf.Rad2Deg;
|
||||
|
||||
if (flipXOR) boneLocalPosition.y *= -1f;
|
||||
if (parentFlipXOR != flipXOR) boneLocalPosition.y *= -1f;
|
||||
|
||||
if (parentFlipXOR) boneLocalRotation *= -1f;
|
||||
if (parentFlipX != flipX) boneLocalRotation += 180;
|
||||
|
||||
b.X = Mathf.Lerp(b.X, boneLocalPosition.x, mix);
|
||||
b.Y = Mathf.Lerp(b.Y, boneLocalPosition.y, mix);
|
||||
b.Rotation = Mathf.Lerp(b.Rotation, boneLocalRotation, mix);
|
||||
//b.AppliedRotation = Mathf.Lerp(b.AppliedRotation, boneLocalRotation, mix);
|
||||
}
|
||||
}
|
||||
|
||||
void GetStartBoneParentFlipState (out bool parentFlipX, out bool parentFlipY) {
|
||||
parentFlipX = skeleton.ScaleX < 0;
|
||||
parentFlipY = skeleton.ScaleY < 0;
|
||||
Bone parent = this.StartingBone == null ? null : this.StartingBone.Parent;
|
||||
while (parent != null) {
|
||||
parentFlipX ^= parent.ScaleX < 0;
|
||||
parentFlipY ^= parent.ScaleY < 0;
|
||||
parent = parent.Parent;
|
||||
}
|
||||
}
|
||||
|
||||
static List<Collider2D> AttachBoundingBoxRagdollColliders (Bone b, GameObject go, Skeleton skeleton, float gravityScale) {
|
||||
const string AttachmentNameMarker = "ragdoll";
|
||||
List<Collider2D> colliders = new List<Collider2D>();
|
||||
Skin skin = skeleton.Skin ?? skeleton.Data.DefaultSkin;
|
||||
|
||||
List<Skin.SkinEntry> skinEntries = new List<Skin.SkinEntry>();
|
||||
foreach (Slot slot in skeleton.Slots) {
|
||||
if (slot.Bone == b) {
|
||||
skin.GetAttachments(skeleton.Slots.IndexOf(slot), skinEntries);
|
||||
|
||||
bool bbAttachmentAdded = false;
|
||||
foreach (Skin.SkinEntry entry in skinEntries) {
|
||||
BoundingBoxAttachment bbAttachment = entry.Attachment as BoundingBoxAttachment;
|
||||
if (bbAttachment != null) {
|
||||
if (!entry.Name.ToLower().Contains(AttachmentNameMarker))
|
||||
continue;
|
||||
|
||||
bbAttachmentAdded = true;
|
||||
PolygonCollider2D bbCollider = SkeletonUtility.AddBoundingBoxAsComponent(bbAttachment, slot, go, isTrigger: false);
|
||||
colliders.Add(bbCollider);
|
||||
}
|
||||
}
|
||||
|
||||
if (bbAttachmentAdded)
|
||||
SkeletonUtility.AddBoneRigidbody2D(go, isKinematic: false, gravityScale: gravityScale);
|
||||
}
|
||||
}
|
||||
|
||||
return colliders;
|
||||
}
|
||||
|
||||
static Vector3 FlipScale (bool flipX, bool flipY) {
|
||||
return new Vector3(flipX ? -1f : 1f, flipY ? -1f : 1f, 1f);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
void OnDrawGizmosSelected () {
|
||||
if (isActive) {
|
||||
Gizmos.DrawWireSphere(transform.position, thickness * 1.2f);
|
||||
Vector3 newTransformPos = RootRigidbody.position - rootOffset;
|
||||
Gizmos.DrawLine(transform.position, newTransformPos);
|
||||
Gizmos.DrawWireSphere(newTransformPos, thickness * 1.2f);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
// Contributed by: Mitch Thompson
|
||||
|
||||
#if UNITY_2019_2 || UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 // note: 2020.3+ uses old bahavior again
|
||||
#define HINGE_JOINT_2019_BEHAVIOUR
|
||||
#endif
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
[RequireComponent(typeof(SkeletonRenderer))]
|
||||
public class SkeletonRagdoll2D : MonoBehaviour {
|
||||
static Transform parentSpaceHelper;
|
||||
|
||||
#region Inspector
|
||||
[Header("Hierarchy")]
|
||||
[SpineBone]
|
||||
public string startingBoneName = "";
|
||||
[SpineBone]
|
||||
public List<string> stopBoneNames = new List<string>();
|
||||
|
||||
[Header("Parameters")]
|
||||
public bool applyOnStart;
|
||||
[Tooltip("Warning! You will have to re-enable and tune mix values manually if attempting to remove the ragdoll system.")]
|
||||
public bool disableIK = true;
|
||||
public bool disableOtherConstraints = false;
|
||||
[Space]
|
||||
[Tooltip("Set RootRigidbody IsKinematic to true when Apply is called.")]
|
||||
public bool pinStartBone;
|
||||
public float gravityScale = 1;
|
||||
[Tooltip("If no BoundingBox Attachment is attached to a bone, this becomes the default Width or Radius of a Bone's ragdoll Rigidbody")]
|
||||
public float thickness = 0.125f;
|
||||
[Tooltip("Default rotational limit value. Min is negative this value, Max is this value.")]
|
||||
public float rotationLimit = 20;
|
||||
public float rootMass = 20;
|
||||
[Tooltip("If your ragdoll seems unstable or uneffected by limits, try lowering this value.")]
|
||||
[Range(0.01f, 1f)]
|
||||
public float massFalloffFactor = 0.4f;
|
||||
[Tooltip("The layer assigned to all of the rigidbody parts.")]
|
||||
[SkeletonRagdoll.LayerField]
|
||||
public int colliderLayer = 0;
|
||||
[Range(0, 1)]
|
||||
public float mix = 1;
|
||||
public bool oldRagdollBehaviour = false;
|
||||
#endregion
|
||||
|
||||
ISkeletonAnimation targetSkeletonComponent;
|
||||
Skeleton skeleton;
|
||||
struct BoneFlipEntry {
|
||||
public BoneFlipEntry (bool flipX, bool flipY) {
|
||||
this.flipX = flipX;
|
||||
this.flipY = flipY;
|
||||
}
|
||||
|
||||
public bool flipX;
|
||||
public bool flipY;
|
||||
}
|
||||
Dictionary<Bone, Transform> boneTable = new Dictionary<Bone, Transform>();
|
||||
Dictionary<Bone, BoneFlipEntry> boneFlipTable = new Dictionary<Bone, BoneFlipEntry>();
|
||||
Transform ragdollRoot;
|
||||
public Rigidbody2D RootRigidbody { get; private set; }
|
||||
public Bone StartingBone { get; private set; }
|
||||
Vector2 rootOffset;
|
||||
public Vector3 RootOffset { get { return this.rootOffset; } }
|
||||
bool isActive;
|
||||
public bool IsActive { get { return this.isActive; } }
|
||||
|
||||
IEnumerator Start () {
|
||||
if (parentSpaceHelper == null) {
|
||||
parentSpaceHelper = (new GameObject("Parent Space Helper")).transform;
|
||||
}
|
||||
|
||||
targetSkeletonComponent = GetComponent<SkeletonRenderer>() as ISkeletonAnimation;
|
||||
if (targetSkeletonComponent == null) Debug.LogError("Attached Spine component does not implement ISkeletonAnimation. This script is not compatible.");
|
||||
skeleton = targetSkeletonComponent.Skeleton;
|
||||
|
||||
if (applyOnStart) {
|
||||
yield return null;
|
||||
Apply();
|
||||
}
|
||||
}
|
||||
|
||||
#region API
|
||||
public Rigidbody2D[] RigidbodyArray {
|
||||
get {
|
||||
if (!isActive)
|
||||
return new Rigidbody2D[0];
|
||||
|
||||
Rigidbody2D[] rigidBodies = new Rigidbody2D[boneTable.Count];
|
||||
int i = 0;
|
||||
foreach (Transform t in boneTable.Values) {
|
||||
rigidBodies[i] = t.GetComponent<Rigidbody2D>();
|
||||
i++;
|
||||
}
|
||||
|
||||
return rigidBodies;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 EstimatedSkeletonPosition {
|
||||
get { return this.RootRigidbody.position - rootOffset; }
|
||||
}
|
||||
|
||||
/// <summary>Instantiates the ragdoll simulation and applies its transforms to the skeleton.</summary>
|
||||
public void Apply () {
|
||||
isActive = true;
|
||||
mix = 1;
|
||||
|
||||
Bone startingBone = this.StartingBone = skeleton.FindBone(startingBoneName);
|
||||
RecursivelyCreateBoneProxies(startingBone);
|
||||
|
||||
RootRigidbody = boneTable[startingBone].GetComponent<Rigidbody2D>();
|
||||
RootRigidbody.isKinematic = pinStartBone;
|
||||
RootRigidbody.mass = rootMass;
|
||||
List<Collider2D> boneColliders = new List<Collider2D>();
|
||||
foreach (KeyValuePair<Bone, Transform> pair in boneTable) {
|
||||
Bone b = pair.Key;
|
||||
Transform t = pair.Value;
|
||||
Transform parentTransform;
|
||||
boneColliders.Add(t.GetComponent<Collider2D>());
|
||||
if (b == startingBone) {
|
||||
ragdollRoot = new GameObject("RagdollRoot").transform;
|
||||
ragdollRoot.SetParent(transform, false);
|
||||
if (b == skeleton.RootBone) { // RagdollRoot is skeleton root's parent, thus the skeleton's scale and position.
|
||||
ragdollRoot.localPosition = new Vector3(skeleton.X, skeleton.Y, 0);
|
||||
ragdollRoot.localRotation = (skeleton.ScaleX < 0) ? Quaternion.Euler(0, 0, 180.0f) : Quaternion.identity;
|
||||
} else {
|
||||
ragdollRoot.localPosition = new Vector3(b.Parent.WorldX, b.Parent.WorldY, 0);
|
||||
ragdollRoot.localRotation = Quaternion.Euler(0, 0, b.Parent.WorldRotationX - b.Parent.ShearX);
|
||||
}
|
||||
parentTransform = ragdollRoot;
|
||||
rootOffset = t.position - transform.position;
|
||||
} else {
|
||||
parentTransform = boneTable[b.Parent];
|
||||
}
|
||||
|
||||
// Add joint and attach to parent.
|
||||
Rigidbody2D rbParent = parentTransform.GetComponent<Rigidbody2D>();
|
||||
if (rbParent != null) {
|
||||
HingeJoint2D joint = t.gameObject.AddComponent<HingeJoint2D>();
|
||||
joint.connectedBody = rbParent;
|
||||
Vector3 localPos = parentTransform.InverseTransformPoint(t.position);
|
||||
joint.connectedAnchor = localPos;
|
||||
|
||||
joint.GetComponent<Rigidbody2D>().mass = joint.connectedBody.mass * massFalloffFactor;
|
||||
|
||||
#if HINGE_JOINT_2019_BEHAVIOUR
|
||||
float referenceAngle = (rbParent.transform.eulerAngles.z - t.eulerAngles.z + 360f) % 360f;
|
||||
float minAngle = referenceAngle - rotationLimit;
|
||||
float maxAngle = referenceAngle + rotationLimit;
|
||||
if (maxAngle > 180f) {
|
||||
minAngle -= 360f;
|
||||
maxAngle -= 360f;
|
||||
}
|
||||
#else
|
||||
float minAngle = -rotationLimit;
|
||||
float maxAngle = rotationLimit;
|
||||
#endif
|
||||
joint.limits = new JointAngleLimits2D {
|
||||
min = minAngle,
|
||||
max = maxAngle
|
||||
};
|
||||
joint.useLimits = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore collisions among bones.
|
||||
for (int x = 0; x < boneColliders.Count; x++) {
|
||||
for (int y = 0; y < boneColliders.Count; y++) {
|
||||
if (x == y) continue;
|
||||
Physics2D.IgnoreCollision(boneColliders[x], boneColliders[y]);
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy existing override-mode SkeletonUtility bones.
|
||||
SkeletonUtilityBone[] utilityBones = GetComponentsInChildren<SkeletonUtilityBone>();
|
||||
if (utilityBones.Length > 0) {
|
||||
List<string> destroyedUtilityBoneNames = new List<string>();
|
||||
foreach (SkeletonUtilityBone ub in utilityBones) {
|
||||
if (ub.mode == SkeletonUtilityBone.Mode.Override) {
|
||||
destroyedUtilityBoneNames.Add(ub.gameObject.name);
|
||||
Destroy(ub.gameObject);
|
||||
}
|
||||
}
|
||||
if (destroyedUtilityBoneNames.Count > 0) {
|
||||
string msg = "Destroyed Utility Bones: ";
|
||||
for (int i = 0; i < destroyedUtilityBoneNames.Count; i++) {
|
||||
msg += destroyedUtilityBoneNames[i];
|
||||
if (i != destroyedUtilityBoneNames.Count - 1) {
|
||||
msg += ",";
|
||||
}
|
||||
}
|
||||
Debug.LogWarning(msg);
|
||||
}
|
||||
}
|
||||
|
||||
// Disable skeleton constraints.
|
||||
if (disableIK) {
|
||||
ExposedList<IkConstraint> ikConstraints = skeleton.IkConstraints;
|
||||
for (int i = 0, n = ikConstraints.Count; i < n; i++)
|
||||
ikConstraints.Items[i].Mix = 0;
|
||||
}
|
||||
|
||||
if (disableOtherConstraints) {
|
||||
ExposedList<TransformConstraint> transformConstraints = skeleton.TransformConstraints;
|
||||
for (int i = 0, n = transformConstraints.Count; i < n; i++) {
|
||||
transformConstraints.Items[i].MixRotate = 0;
|
||||
transformConstraints.Items[i].MixScaleX = 0;
|
||||
transformConstraints.Items[i].MixScaleY = 0;
|
||||
transformConstraints.Items[i].MixShearY = 0;
|
||||
transformConstraints.Items[i].MixX = 0;
|
||||
transformConstraints.Items[i].MixY = 0;
|
||||
}
|
||||
|
||||
ExposedList<PathConstraint> pathConstraints = skeleton.PathConstraints;
|
||||
for (int i = 0, n = pathConstraints.Count; i < n; i++) {
|
||||
pathConstraints.Items[i].MixRotate = 0;
|
||||
pathConstraints.Items[i].MixX = 0;
|
||||
pathConstraints.Items[i].MixY = 0;
|
||||
}
|
||||
}
|
||||
|
||||
targetSkeletonComponent.UpdateWorld += UpdateSpineSkeleton;
|
||||
}
|
||||
|
||||
/// <summary>Transitions the mix value from the current value to a target value.</summary>
|
||||
public Coroutine SmoothMix (float target, float duration) {
|
||||
return StartCoroutine(SmoothMixCoroutine(target, duration));
|
||||
}
|
||||
|
||||
IEnumerator SmoothMixCoroutine (float target, float duration) {
|
||||
float startTime = Time.time;
|
||||
float startMix = mix;
|
||||
while (mix > 0) {
|
||||
skeleton.SetBonesToSetupPose();
|
||||
mix = Mathf.SmoothStep(startMix, target, (Time.time - startTime) / duration);
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Set the transform world position while preserving the ragdoll parts world position.</summary>
|
||||
public void SetSkeletonPosition (Vector3 worldPosition) {
|
||||
if (!isActive) {
|
||||
Debug.LogWarning("Can't call SetSkeletonPosition while Ragdoll is not active!");
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 offset = worldPosition - transform.position;
|
||||
transform.position = worldPosition;
|
||||
foreach (Transform t in boneTable.Values)
|
||||
t.position -= offset;
|
||||
|
||||
UpdateSpineSkeleton(null);
|
||||
skeleton.UpdateWorldTransform(Skeleton.Physics.Update);
|
||||
}
|
||||
|
||||
/// <summary>Removes the ragdoll instance and effect from the animated skeleton.</summary>
|
||||
public void Remove () {
|
||||
isActive = false;
|
||||
foreach (Transform t in boneTable.Values)
|
||||
Destroy(t.gameObject);
|
||||
|
||||
Destroy(ragdollRoot.gameObject);
|
||||
boneTable.Clear();
|
||||
targetSkeletonComponent.UpdateWorld -= UpdateSpineSkeleton;
|
||||
}
|
||||
|
||||
public Rigidbody2D GetRigidbody (string boneName) {
|
||||
Bone bone = skeleton.FindBone(boneName);
|
||||
return (bone != null && boneTable.ContainsKey(bone)) ? boneTable[bone].GetComponent<Rigidbody2D>() : null;
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>Generates the ragdoll simulation's Transform and joint setup.</summary>
|
||||
void RecursivelyCreateBoneProxies (Bone b) {
|
||||
string boneName = b.Data.Name;
|
||||
if (stopBoneNames.Contains(boneName))
|
||||
return;
|
||||
|
||||
GameObject boneGameObject = new GameObject(boneName);
|
||||
boneGameObject.layer = this.colliderLayer;
|
||||
Transform t = boneGameObject.transform;
|
||||
boneTable.Add(b, t);
|
||||
|
||||
t.parent = transform;
|
||||
t.localPosition = new Vector3(b.WorldX, b.WorldY, 0);
|
||||
t.localRotation = Quaternion.Euler(0, 0, b.WorldRotationX - b.ShearX);
|
||||
t.localScale = new Vector3(b.WorldScaleX, b.WorldScaleY, 1);
|
||||
|
||||
List<Collider2D> colliders = AttachBoundingBoxRagdollColliders(b, boneGameObject, skeleton, this.gravityScale);
|
||||
if (colliders.Count == 0) {
|
||||
float length = b.Data.Length;
|
||||
if (length == 0) {
|
||||
CircleCollider2D circle = boneGameObject.AddComponent<CircleCollider2D>();
|
||||
circle.radius = thickness * 0.5f;
|
||||
} else {
|
||||
BoxCollider2D box = boneGameObject.AddComponent<BoxCollider2D>();
|
||||
box.size = new Vector2(length, thickness);
|
||||
box.offset = new Vector2(length * 0.5f, 0); // box.center in UNITY_4
|
||||
}
|
||||
}
|
||||
|
||||
Rigidbody2D rb = boneGameObject.GetComponent<Rigidbody2D>();
|
||||
if (rb == null) rb = boneGameObject.AddComponent<Rigidbody2D>();
|
||||
rb.gravityScale = this.gravityScale;
|
||||
|
||||
foreach (Bone child in b.Children)
|
||||
RecursivelyCreateBoneProxies(child);
|
||||
}
|
||||
|
||||
/// <summary>Performed every skeleton animation update to translate Unity Transforms positions into Spine bone transforms.</summary>
|
||||
void UpdateSpineSkeleton (ISkeletonAnimation animatedSkeleton) {
|
||||
bool parentFlipX;
|
||||
bool parentFlipY;
|
||||
Bone startingBone = this.StartingBone;
|
||||
GetStartBoneParentFlipState(out parentFlipX, out parentFlipY);
|
||||
|
||||
foreach (KeyValuePair<Bone, Transform> pair in boneTable) {
|
||||
Bone b = pair.Key;
|
||||
Transform t = pair.Value;
|
||||
bool isStartingBone = (b == startingBone);
|
||||
Bone parentBone = b.Parent;
|
||||
Transform parentTransform = isStartingBone ? ragdollRoot : boneTable[parentBone];
|
||||
if (!isStartingBone) {
|
||||
BoneFlipEntry parentBoneFlip = boneFlipTable[parentBone];
|
||||
parentFlipX = parentBoneFlip.flipX;
|
||||
parentFlipY = parentBoneFlip.flipY;
|
||||
}
|
||||
bool flipX = parentFlipX ^ (b.ScaleX < 0);
|
||||
bool flipY = parentFlipY ^ (b.ScaleY < 0);
|
||||
|
||||
BoneFlipEntry boneFlip;
|
||||
boneFlipTable.TryGetValue(b, out boneFlip);
|
||||
boneFlip.flipX = flipX;
|
||||
boneFlip.flipY = flipY;
|
||||
boneFlipTable[b] = boneFlip;
|
||||
|
||||
bool flipXOR = flipX ^ flipY;
|
||||
bool parentFlipXOR = parentFlipX ^ parentFlipY;
|
||||
|
||||
if (!oldRagdollBehaviour && isStartingBone) {
|
||||
if (b != skeleton.RootBone) { // RagdollRoot is not skeleton root.
|
||||
ragdollRoot.localPosition = new Vector3(parentBone.WorldX, parentBone.WorldY, 0);
|
||||
ragdollRoot.localRotation = Quaternion.Euler(0, 0, parentBone.WorldRotationX - parentBone.ShearX);
|
||||
ragdollRoot.localScale = new Vector3(parentBone.WorldScaleX, parentBone.WorldScaleY, 1);
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 parentTransformWorldPosition = parentTransform.position;
|
||||
Quaternion parentTransformWorldRotation = parentTransform.rotation;
|
||||
|
||||
parentSpaceHelper.position = parentTransformWorldPosition;
|
||||
parentSpaceHelper.rotation = parentTransformWorldRotation;
|
||||
parentSpaceHelper.localScale = parentTransform.lossyScale;
|
||||
|
||||
if (oldRagdollBehaviour) {
|
||||
if (isStartingBone && b != skeleton.RootBone) {
|
||||
Vector3 localPosition = new Vector3(b.Parent.WorldX, b.Parent.WorldY, 0);
|
||||
parentSpaceHelper.position = ragdollRoot.TransformPoint(localPosition);
|
||||
parentSpaceHelper.localRotation = Quaternion.Euler(0, 0, parentBone.WorldRotationX - parentBone.ShearX);
|
||||
parentSpaceHelper.localScale = new Vector3(parentBone.WorldScaleX, parentBone.WorldScaleY, 1);
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 boneWorldPosition = t.position;
|
||||
Vector3 right = parentSpaceHelper.InverseTransformDirection(t.right);
|
||||
|
||||
Vector3 boneLocalPosition = parentSpaceHelper.InverseTransformPoint(boneWorldPosition);
|
||||
float boneLocalRotation = Mathf.Atan2(right.y, right.x) * Mathf.Rad2Deg;
|
||||
|
||||
if (flipXOR) boneLocalPosition.y *= -1f;
|
||||
if (parentFlipXOR != flipXOR) boneLocalPosition.y *= -1f;
|
||||
|
||||
if (parentFlipXOR) boneLocalRotation *= -1f;
|
||||
if (parentFlipX != flipX) boneLocalRotation += 180;
|
||||
|
||||
b.X = Mathf.Lerp(b.X, boneLocalPosition.x, mix);
|
||||
b.Y = Mathf.Lerp(b.Y, boneLocalPosition.y, mix);
|
||||
b.Rotation = Mathf.Lerp(b.Rotation, boneLocalRotation, mix);
|
||||
//b.AppliedRotation = Mathf.Lerp(b.AppliedRotation, boneLocalRotation, mix);
|
||||
}
|
||||
}
|
||||
|
||||
void GetStartBoneParentFlipState (out bool parentFlipX, out bool parentFlipY) {
|
||||
parentFlipX = skeleton.ScaleX < 0;
|
||||
parentFlipY = skeleton.ScaleY < 0;
|
||||
Bone parent = this.StartingBone == null ? null : this.StartingBone.Parent;
|
||||
while (parent != null) {
|
||||
parentFlipX ^= parent.ScaleX < 0;
|
||||
parentFlipY ^= parent.ScaleY < 0;
|
||||
parent = parent.Parent;
|
||||
}
|
||||
}
|
||||
|
||||
static List<Collider2D> AttachBoundingBoxRagdollColliders (Bone b, GameObject go, Skeleton skeleton, float gravityScale) {
|
||||
const string AttachmentNameMarker = "ragdoll";
|
||||
List<Collider2D> colliders = new List<Collider2D>();
|
||||
Skin skin = skeleton.Skin ?? skeleton.Data.DefaultSkin;
|
||||
|
||||
List<Skin.SkinEntry> skinEntries = new List<Skin.SkinEntry>();
|
||||
foreach (Slot slot in skeleton.Slots) {
|
||||
if (slot.Bone == b) {
|
||||
skin.GetAttachments(skeleton.Slots.IndexOf(slot), skinEntries);
|
||||
|
||||
bool bbAttachmentAdded = false;
|
||||
foreach (Skin.SkinEntry entry in skinEntries) {
|
||||
BoundingBoxAttachment bbAttachment = entry.Attachment as BoundingBoxAttachment;
|
||||
if (bbAttachment != null) {
|
||||
if (!entry.Name.ToLower().Contains(AttachmentNameMarker))
|
||||
continue;
|
||||
|
||||
bbAttachmentAdded = true;
|
||||
PolygonCollider2D bbCollider = SkeletonUtility.AddBoundingBoxAsComponent(bbAttachment, slot, go, isTrigger: false);
|
||||
colliders.Add(bbCollider);
|
||||
}
|
||||
}
|
||||
|
||||
if (bbAttachmentAdded)
|
||||
SkeletonUtility.AddBoneRigidbody2D(go, isKinematic: false, gravityScale: gravityScale);
|
||||
}
|
||||
}
|
||||
|
||||
return colliders;
|
||||
}
|
||||
|
||||
static Vector3 FlipScale (bool flipX, bool flipY) {
|
||||
return new Vector3(flipX ? -1f : 1f, flipY ? -1f : 1f, 1f);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
void OnDrawGizmosSelected () {
|
||||
if (isActive) {
|
||||
Gizmos.DrawWireSphere(transform.position, thickness * 1.2f);
|
||||
Vector3 newTransformPos = RootRigidbody.position - rootOffset;
|
||||
Gizmos.DrawLine(transform.position, newTransformPos);
|
||||
Gizmos.DrawWireSphere(newTransformPos, thickness * 1.2f);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,84 +1,84 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class SkeletonUtilityEyeConstraint : SkeletonUtilityConstraint {
|
||||
public Transform[] eyes;
|
||||
public float radius = 0.5f;
|
||||
public Transform target;
|
||||
public Vector3 targetPosition;
|
||||
public float speed = 10;
|
||||
Vector3[] origins;
|
||||
Vector3 centerPoint;
|
||||
|
||||
protected override void OnEnable () {
|
||||
if (!Application.isPlaying) return;
|
||||
base.OnEnable();
|
||||
|
||||
Bounds centerBounds = new Bounds(eyes[0].localPosition, Vector3.zero);
|
||||
origins = new Vector3[eyes.Length];
|
||||
for (int i = 0; i < eyes.Length; i++) {
|
||||
origins[i] = eyes[i].localPosition;
|
||||
centerBounds.Encapsulate(origins[i]);
|
||||
}
|
||||
|
||||
centerPoint = centerBounds.center;
|
||||
}
|
||||
|
||||
protected override void OnDisable () {
|
||||
if (!Application.isPlaying) return;
|
||||
|
||||
for (int i = 0; i < eyes.Length; i++) {
|
||||
eyes[i].localPosition = origins[i];
|
||||
}
|
||||
base.OnDisable();
|
||||
}
|
||||
|
||||
public override void DoUpdate () {
|
||||
if (target != null) targetPosition = target.position;
|
||||
|
||||
Vector3 goal = targetPosition;
|
||||
Vector3 center = transform.TransformPoint(centerPoint);
|
||||
Vector3 dir = goal - center;
|
||||
|
||||
if (dir.magnitude > 1)
|
||||
dir.Normalize();
|
||||
|
||||
for (int i = 0; i < eyes.Length; i++) {
|
||||
center = transform.TransformPoint(origins[i]);
|
||||
eyes[i].position = Vector3.MoveTowards(eyes[i].position, center + (dir * radius * hierarchy.PositionScale),
|
||||
speed * hierarchy.PositionScale * Time.deltaTime);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class SkeletonUtilityEyeConstraint : SkeletonUtilityConstraint {
|
||||
public Transform[] eyes;
|
||||
public float radius = 0.5f;
|
||||
public Transform target;
|
||||
public Vector3 targetPosition;
|
||||
public float speed = 10;
|
||||
Vector3[] origins;
|
||||
Vector3 centerPoint;
|
||||
|
||||
protected override void OnEnable () {
|
||||
if (!Application.isPlaying) return;
|
||||
base.OnEnable();
|
||||
|
||||
Bounds centerBounds = new Bounds(eyes[0].localPosition, Vector3.zero);
|
||||
origins = new Vector3[eyes.Length];
|
||||
for (int i = 0; i < eyes.Length; i++) {
|
||||
origins[i] = eyes[i].localPosition;
|
||||
centerBounds.Encapsulate(origins[i]);
|
||||
}
|
||||
|
||||
centerPoint = centerBounds.center;
|
||||
}
|
||||
|
||||
protected override void OnDisable () {
|
||||
if (!Application.isPlaying) return;
|
||||
|
||||
for (int i = 0; i < eyes.Length; i++) {
|
||||
eyes[i].localPosition = origins[i];
|
||||
}
|
||||
base.OnDisable();
|
||||
}
|
||||
|
||||
public override void DoUpdate () {
|
||||
if (target != null) targetPosition = target.position;
|
||||
|
||||
Vector3 goal = targetPosition;
|
||||
Vector3 center = transform.TransformPoint(centerPoint);
|
||||
Vector3 dir = goal - center;
|
||||
|
||||
if (dir.magnitude > 1)
|
||||
dir.Normalize();
|
||||
|
||||
for (int i = 0; i < eyes.Length; i++) {
|
||||
center = transform.TransformPoint(origins[i]);
|
||||
eyes[i].position = Vector3.MoveTowards(eyes[i].position, center + (dir * radius * hierarchy.PositionScale),
|
||||
speed * hierarchy.PositionScale * Time.deltaTime);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,140 +1,140 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
|
||||
#define NEW_PREFAB_SYSTEM
|
||||
#endif
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
#if NEW_PREFAB_SYSTEM
|
||||
[ExecuteAlways]
|
||||
#else
|
||||
[ExecuteInEditMode]
|
||||
#endif
|
||||
[RequireComponent(typeof(SkeletonUtilityBone))]
|
||||
public class SkeletonUtilityGroundConstraint : SkeletonUtilityConstraint {
|
||||
|
||||
[Tooltip("LayerMask for what objects to raycast against")]
|
||||
public LayerMask groundMask;
|
||||
[Tooltip("Use 2D")]
|
||||
public bool use2D = false;
|
||||
[Tooltip("Uses SphereCast for 3D mode and CircleCast for 2D mode")]
|
||||
public bool useRadius = false;
|
||||
[Tooltip("The Radius")]
|
||||
public float castRadius = 0.1f;
|
||||
[Tooltip("How high above the target bone to begin casting from")]
|
||||
public float castDistance = 5f;
|
||||
[Tooltip("X-Axis adjustment")]
|
||||
public float castOffset = 0;
|
||||
[Tooltip("Y-Axis adjustment")]
|
||||
public float groundOffset = 0;
|
||||
[Tooltip("How fast the target IK position adjusts to the ground. Use smaller values to prevent snapping")]
|
||||
public float adjustSpeed = 5;
|
||||
|
||||
Vector3 rayOrigin;
|
||||
Vector3 rayDir = new Vector3(0, -1, 0);
|
||||
float hitY;
|
||||
float lastHitY;
|
||||
|
||||
protected override void OnEnable () {
|
||||
base.OnEnable();
|
||||
lastHitY = transform.position.y;
|
||||
}
|
||||
|
||||
public override void DoUpdate () {
|
||||
rayOrigin = transform.position + new Vector3(castOffset, castDistance, 0);
|
||||
|
||||
float positionScale = hierarchy.PositionScale;
|
||||
float adjustDistanceThisFrame = adjustSpeed * positionScale * Time.deltaTime;
|
||||
hitY = float.MinValue;
|
||||
if (use2D) {
|
||||
RaycastHit2D hit;
|
||||
|
||||
if (useRadius)
|
||||
hit = Physics2D.CircleCast(rayOrigin, castRadius, rayDir, castDistance + groundOffset, groundMask);
|
||||
else
|
||||
hit = Physics2D.Raycast(rayOrigin, rayDir, castDistance + groundOffset, groundMask);
|
||||
|
||||
if (hit.collider != null) {
|
||||
hitY = hit.point.y + groundOffset;
|
||||
if (Application.isPlaying)
|
||||
hitY = Mathf.MoveTowards(lastHitY, hitY, adjustDistanceThisFrame);
|
||||
} else {
|
||||
if (Application.isPlaying)
|
||||
hitY = Mathf.MoveTowards(lastHitY, transform.position.y, adjustDistanceThisFrame);
|
||||
}
|
||||
} else {
|
||||
RaycastHit hit;
|
||||
bool validHit = false;
|
||||
|
||||
if (useRadius)
|
||||
validHit = Physics.SphereCast(rayOrigin, castRadius, rayDir, out hit, castDistance + groundOffset, groundMask);
|
||||
else
|
||||
validHit = Physics.Raycast(rayOrigin, rayDir, out hit, castDistance + groundOffset, groundMask);
|
||||
|
||||
if (validHit) {
|
||||
hitY = hit.point.y + groundOffset;
|
||||
if (Application.isPlaying)
|
||||
hitY = Mathf.MoveTowards(lastHitY, hitY, adjustDistanceThisFrame);
|
||||
|
||||
} else {
|
||||
if (Application.isPlaying)
|
||||
hitY = Mathf.MoveTowards(lastHitY, transform.position.y, adjustDistanceThisFrame);
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 v = transform.position;
|
||||
v.y = Mathf.Clamp(v.y, Mathf.Min(lastHitY, hitY), float.MaxValue);
|
||||
transform.position = v;
|
||||
|
||||
bone.bone.X = transform.localPosition.x / hierarchy.PositionScale;
|
||||
bone.bone.Y = transform.localPosition.y / hierarchy.PositionScale;
|
||||
|
||||
lastHitY = hitY;
|
||||
}
|
||||
|
||||
void OnDrawGizmos () {
|
||||
Vector3 hitEnd = rayOrigin + (rayDir * Mathf.Min(castDistance, rayOrigin.y - hitY));
|
||||
Vector3 clearEnd = rayOrigin + (rayDir * castDistance);
|
||||
Gizmos.DrawLine(rayOrigin, hitEnd);
|
||||
|
||||
if (useRadius) {
|
||||
Gizmos.DrawLine(new Vector3(hitEnd.x - castRadius, hitEnd.y - groundOffset, hitEnd.z), new Vector3(hitEnd.x + castRadius, hitEnd.y - groundOffset, hitEnd.z));
|
||||
Gizmos.DrawLine(new Vector3(clearEnd.x - castRadius, clearEnd.y, clearEnd.z), new Vector3(clearEnd.x + castRadius, clearEnd.y, clearEnd.z));
|
||||
}
|
||||
|
||||
Gizmos.color = Color.red;
|
||||
Gizmos.DrawLine(hitEnd, clearEnd);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
|
||||
#define NEW_PREFAB_SYSTEM
|
||||
#endif
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
#if NEW_PREFAB_SYSTEM
|
||||
[ExecuteAlways]
|
||||
#else
|
||||
[ExecuteInEditMode]
|
||||
#endif
|
||||
[RequireComponent(typeof(SkeletonUtilityBone))]
|
||||
public class SkeletonUtilityGroundConstraint : SkeletonUtilityConstraint {
|
||||
|
||||
[Tooltip("LayerMask for what objects to raycast against")]
|
||||
public LayerMask groundMask;
|
||||
[Tooltip("Use 2D")]
|
||||
public bool use2D = false;
|
||||
[Tooltip("Uses SphereCast for 3D mode and CircleCast for 2D mode")]
|
||||
public bool useRadius = false;
|
||||
[Tooltip("The Radius")]
|
||||
public float castRadius = 0.1f;
|
||||
[Tooltip("How high above the target bone to begin casting from")]
|
||||
public float castDistance = 5f;
|
||||
[Tooltip("X-Axis adjustment")]
|
||||
public float castOffset = 0;
|
||||
[Tooltip("Y-Axis adjustment")]
|
||||
public float groundOffset = 0;
|
||||
[Tooltip("How fast the target IK position adjusts to the ground. Use smaller values to prevent snapping")]
|
||||
public float adjustSpeed = 5;
|
||||
|
||||
Vector3 rayOrigin;
|
||||
Vector3 rayDir = new Vector3(0, -1, 0);
|
||||
float hitY;
|
||||
float lastHitY;
|
||||
|
||||
protected override void OnEnable () {
|
||||
base.OnEnable();
|
||||
lastHitY = transform.position.y;
|
||||
}
|
||||
|
||||
public override void DoUpdate () {
|
||||
rayOrigin = transform.position + new Vector3(castOffset, castDistance, 0);
|
||||
|
||||
float positionScale = hierarchy.PositionScale;
|
||||
float adjustDistanceThisFrame = adjustSpeed * positionScale * Time.deltaTime;
|
||||
hitY = float.MinValue;
|
||||
if (use2D) {
|
||||
RaycastHit2D hit;
|
||||
|
||||
if (useRadius)
|
||||
hit = Physics2D.CircleCast(rayOrigin, castRadius, rayDir, castDistance + groundOffset, groundMask);
|
||||
else
|
||||
hit = Physics2D.Raycast(rayOrigin, rayDir, castDistance + groundOffset, groundMask);
|
||||
|
||||
if (hit.collider != null) {
|
||||
hitY = hit.point.y + groundOffset;
|
||||
if (Application.isPlaying)
|
||||
hitY = Mathf.MoveTowards(lastHitY, hitY, adjustDistanceThisFrame);
|
||||
} else {
|
||||
if (Application.isPlaying)
|
||||
hitY = Mathf.MoveTowards(lastHitY, transform.position.y, adjustDistanceThisFrame);
|
||||
}
|
||||
} else {
|
||||
RaycastHit hit;
|
||||
bool validHit = false;
|
||||
|
||||
if (useRadius)
|
||||
validHit = Physics.SphereCast(rayOrigin, castRadius, rayDir, out hit, castDistance + groundOffset, groundMask);
|
||||
else
|
||||
validHit = Physics.Raycast(rayOrigin, rayDir, out hit, castDistance + groundOffset, groundMask);
|
||||
|
||||
if (validHit) {
|
||||
hitY = hit.point.y + groundOffset;
|
||||
if (Application.isPlaying)
|
||||
hitY = Mathf.MoveTowards(lastHitY, hitY, adjustDistanceThisFrame);
|
||||
|
||||
} else {
|
||||
if (Application.isPlaying)
|
||||
hitY = Mathf.MoveTowards(lastHitY, transform.position.y, adjustDistanceThisFrame);
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 v = transform.position;
|
||||
v.y = Mathf.Clamp(v.y, Mathf.Min(lastHitY, hitY), float.MaxValue);
|
||||
transform.position = v;
|
||||
|
||||
bone.bone.X = transform.localPosition.x / hierarchy.PositionScale;
|
||||
bone.bone.Y = transform.localPosition.y / hierarchy.PositionScale;
|
||||
|
||||
lastHitY = hitY;
|
||||
}
|
||||
|
||||
void OnDrawGizmos () {
|
||||
Vector3 hitEnd = rayOrigin + (rayDir * Mathf.Min(castDistance, rayOrigin.y - hitY));
|
||||
Vector3 clearEnd = rayOrigin + (rayDir * castDistance);
|
||||
Gizmos.DrawLine(rayOrigin, hitEnd);
|
||||
|
||||
if (useRadius) {
|
||||
Gizmos.DrawLine(new Vector3(hitEnd.x - castRadius, hitEnd.y - groundOffset, hitEnd.z), new Vector3(hitEnd.x + castRadius, hitEnd.y - groundOffset, hitEnd.z));
|
||||
Gizmos.DrawLine(new Vector3(clearEnd.x - castRadius, clearEnd.y, clearEnd.z), new Vector3(clearEnd.x + castRadius, clearEnd.y, clearEnd.z));
|
||||
}
|
||||
|
||||
Gizmos.color = Color.red;
|
||||
Gizmos.DrawLine(hitEnd, clearEnd);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user