mirror of
https://github.com/tuyoogame/YooAsset.git
synced 2026-05-14 19:40:47 +00:00
Compare commits
1664 Commits
1.0.1
...
6b23927f71
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6b23927f71 | ||
|
|
dfa9ff6954 | ||
|
|
4c717b69db | ||
|
|
d64997a0df | ||
|
|
a265b85d37 | ||
|
|
5b81269090 | ||
|
|
d228e41df7 | ||
|
|
23032cc269 | ||
|
|
72f02bd73f | ||
|
|
a37663a8c2 | ||
|
|
f375d45bd6 | ||
|
|
3dd3d4ef76 | ||
|
|
f0563cce0b | ||
|
|
9b83dcf723 | ||
|
|
ee67a55c0f | ||
|
|
454afc9ba6 | ||
|
|
539ca3523e | ||
|
|
c87efdb509 | ||
|
|
1884fab0c2 | ||
|
|
e5d0a856a5 | ||
|
|
5da8c6baf8 | ||
|
|
33356cb270 | ||
|
|
4b6a8ca406 | ||
|
|
c8e45a6cae | ||
|
|
1fbc9d26a6 | ||
|
|
abb087b02e | ||
|
|
aeaf03011f | ||
|
|
78d24ad3a6 | ||
|
|
aab2c4625e | ||
|
|
079ef75605 | ||
|
|
75881b55f6 | ||
|
|
2020c7d508 | ||
|
|
088d939346 | ||
|
|
fa50e91c9f | ||
|
|
2e7b992a4b | ||
|
|
29fbbd97ff | ||
|
|
abb150e33f | ||
|
|
78e20f434e | ||
|
|
304222b788 | ||
|
|
101236db8a | ||
|
|
37de007b3f | ||
|
|
d570ba8d74 | ||
|
|
2a956099ae | ||
|
|
74037a5a29 | ||
|
|
861f850a32 | ||
|
|
8b1b5f988a | ||
|
|
efafd1173f | ||
|
|
03e49ff1fb | ||
|
|
ea34be1f00 | ||
|
|
831a9981e3 | ||
|
|
9de4aaa658 | ||
|
|
3579a23bd5 | ||
|
|
c865ddc7f2 | ||
|
|
0bde506aec | ||
|
|
15005b3d30 | ||
|
|
4caf733ac6 | ||
|
|
014b17f5cb | ||
|
|
f3ebda0c04 | ||
|
|
5602addaca | ||
|
|
c4ae67aa8e | ||
|
|
bbcc3bf971 | ||
|
|
8b0e75b9b3 | ||
|
|
b1f02049cc | ||
|
|
512886cdf6 | ||
|
|
0c3ccc5c2f | ||
|
|
b0ea03170f | ||
|
|
2c3b890329 | ||
|
|
0f39cb9444 | ||
|
|
8acc16d3f6 | ||
|
|
fd1715a89b | ||
|
|
0934c813d1 | ||
|
|
be71d38cd8 | ||
|
|
4cdfde31da | ||
|
|
0133549ef8 | ||
|
|
81d9eb47c8 | ||
|
|
5fde689f1f | ||
|
|
5d51bfe751 | ||
|
|
ed86edd2b0 | ||
|
|
f627b5b59a | ||
|
|
549ec74519 | ||
|
|
247ee31348 | ||
|
|
90d3a53bc3 | ||
|
|
19f1d67a61 | ||
|
|
a71c46d1c4 | ||
|
|
82d7bc8fef | ||
|
|
cc85099253 | ||
|
|
d392b02bd4 | ||
|
|
a5138b9846 | ||
|
|
e1b6458c26 | ||
|
|
0f73dc3047 | ||
|
|
a85e49c22a | ||
|
|
6b291de922 | ||
|
|
a4b1300195 | ||
|
|
6f34951a74 | ||
|
|
c798250258 | ||
|
|
6fc82bb55a | ||
|
|
c22cf5ffeb | ||
|
|
36bc24f9fd | ||
|
|
addb0ecdfe | ||
|
|
89e23e0df8 | ||
|
|
e2f582834e | ||
|
|
d2c2844f61 | ||
|
|
1de64278ad | ||
|
|
227f2332a9 | ||
|
|
131614687c | ||
|
|
b8ec902f60 | ||
|
|
eb3e29b6ad | ||
|
|
11ed9d391a | ||
|
|
9cd50bc7f3 | ||
|
|
e92505ba88 | ||
|
|
06a670730c | ||
|
|
ccd21e56cb | ||
|
|
522bcc529a | ||
|
|
2254ac9f5e | ||
|
|
956b3db71d | ||
|
|
fb56959c61 | ||
|
|
b9b9f4e37d | ||
|
|
c050d6d172 | ||
|
|
baf76a454b | ||
|
|
385d343262 | ||
|
|
1f5ad24d44 | ||
|
|
fefc0043cf | ||
|
|
f49143d4f7 | ||
|
|
fd760b12a3 | ||
|
|
14cf8e9ca3 | ||
|
|
3595219a71 | ||
|
|
a4c7d4b8f5 | ||
|
|
43c5c7fb53 | ||
|
|
48d2b36d4e | ||
|
|
2fd87f4d4b | ||
|
|
0fd75b835a | ||
|
|
4489ca570b | ||
|
|
268792b576 | ||
|
|
33907ea967 | ||
|
|
5d7afff3e4 | ||
|
|
fa15f83d85 | ||
|
|
1801974c8a | ||
|
|
bfd476d59c | ||
|
|
7dd08e9634 | ||
|
|
b2776b933a | ||
|
|
9f09b6c526 | ||
|
|
01f6103b48 | ||
|
|
053b4a00d7 | ||
|
|
db159428c6 | ||
|
|
ac7ee16017 | ||
|
|
c2fb7c3cbb | ||
|
|
e70b0d37cd | ||
|
|
53db012fc8 | ||
|
|
b3622167da | ||
|
|
dd6fab46f9 | ||
|
|
f0796dccc9 | ||
|
|
f383c59327 | ||
|
|
e34b9270d2 | ||
|
|
b90ab01fe9 | ||
|
|
236468b4a8 | ||
|
|
6f5fcd55b1 | ||
|
|
4b8f2e3acc | ||
|
|
090e4f4b15 | ||
|
|
53163a75ae | ||
|
|
273401cb20 | ||
|
|
97fe3b0681 | ||
|
|
d401086fd1 | ||
|
|
e3a12ef361 | ||
|
|
1b0288fcd0 | ||
|
|
3ee94fb3b9 | ||
|
|
a0ea80c158 | ||
|
|
264415b362 | ||
|
|
6a76d44c38 | ||
|
|
cebfd57851 | ||
|
|
60eb1c3522 | ||
|
|
40c82835bf | ||
|
|
a13913f572 | ||
|
|
150b46a0a7 | ||
|
|
ebde5a52d3 | ||
|
|
e57466e9e2 | ||
|
|
6f7fca7b34 | ||
|
|
756331fe0b | ||
|
|
5139e2f3a7 | ||
|
|
1c4aba6db5 | ||
|
|
44faa0c5e6 | ||
|
|
72c97341b1 | ||
|
|
9acc240b5a | ||
|
|
ed89e73d26 | ||
|
|
9e33df0375 | ||
|
|
6c98f9a09d | ||
|
|
9ed85afb29 | ||
|
|
560a395173 | ||
|
|
8bce963588 | ||
|
|
f8a3fe47e5 | ||
|
|
48356a4f9e | ||
|
|
d2a28bd801 | ||
|
|
3949abb53f | ||
|
|
06a50a049e | ||
|
|
6f049e2427 | ||
|
|
01c08a46ab | ||
|
|
31dc5b494d | ||
|
|
18e74e906e | ||
|
|
4f62b249b4 | ||
|
|
fe7f9bff08 | ||
|
|
e71077f294 | ||
|
|
eabebf3d8f | ||
|
|
4ef789520a | ||
|
|
4322f3c58c | ||
|
|
c40a796170 | ||
|
|
32841d4773 | ||
|
|
e469b32d94 | ||
|
|
c0e5315953 | ||
|
|
7b5f366533 | ||
|
|
e674d5bf97 | ||
|
|
9b0bebd981 | ||
|
|
dc46462bfa | ||
|
|
51c9943cf2 | ||
|
|
3db9b750e3 | ||
|
|
1b57a0b7df | ||
|
|
bd5ce1e6bd | ||
|
|
7eb74d4dd1 | ||
|
|
a384ca1f18 | ||
|
|
c7253a3f23 | ||
|
|
b296abb27e | ||
|
|
999ede6bab | ||
|
|
bd1569c34d | ||
|
|
3c265c1ab4 | ||
|
|
570a3a817c | ||
|
|
7a8f344927 | ||
|
|
b2c9cb3a7e | ||
|
|
06a5c90b23 | ||
|
|
dcd8ced42a | ||
|
|
76b31bd3cf | ||
|
|
009e8ece79 | ||
|
|
4e257ab27d | ||
|
|
927400b669 | ||
|
|
c0d42e79d8 | ||
|
|
b843c6b0ed | ||
|
|
9fb7f8bbfe | ||
|
|
b0382afad0 | ||
|
|
1ab7689174 | ||
|
|
29d456c065 | ||
|
|
b0dc829b04 | ||
|
|
b3ead90832 | ||
|
|
7bf00d4ff6 | ||
|
|
030e94d8ff | ||
|
|
cf05254121 | ||
|
|
3f786bca3b | ||
|
|
98719d212f | ||
|
|
3409f7ce4d | ||
|
|
f57b354e9b | ||
|
|
974493f88d | ||
|
|
69a69988a1 | ||
|
|
4e9c1955eb | ||
|
|
b6c68a533e | ||
|
|
38aa1c3509 | ||
|
|
eb2f783417 | ||
|
|
8556e071fa | ||
|
|
6155256fb6 | ||
|
|
0d4f2bc893 | ||
|
|
600e928ab4 | ||
|
|
4599ff098c | ||
|
|
4d2df5b705 | ||
|
|
79a7732cfd | ||
|
|
79467bbf13 | ||
|
|
c7d678282b | ||
|
|
d376afc217 | ||
|
|
a62f808591 | ||
|
|
b334a4986b | ||
|
|
a4111349a0 | ||
|
|
bdcf95384f | ||
|
|
d910af589d | ||
|
|
0531864534 | ||
|
|
72b1278f5c | ||
|
|
875cd24cba | ||
|
|
fcc729a0bf | ||
|
|
d10e54248b | ||
|
|
b84800a905 | ||
|
|
8ccd7e552c | ||
|
|
772ba484eb | ||
|
|
cdbedee705 | ||
|
|
10cce48e71 | ||
|
|
13e8410d80 | ||
|
|
6f07faf4da | ||
|
|
e3228d406e | ||
|
|
daf2133535 | ||
|
|
9bcbc10862 | ||
|
|
e6958d205e | ||
|
|
b03d9db2b0 | ||
|
|
30853b6d62 | ||
|
|
a7cafcb328 | ||
|
|
d03bca5512 | ||
|
|
af3fc50188 | ||
|
|
b71eeeb855 | ||
|
|
317c42521a | ||
|
|
064d69269e | ||
|
|
9e6401d3c0 | ||
|
|
2aaba328ee | ||
|
|
62fdc93a82 | ||
|
|
408f0942ee | ||
|
|
ddda9e29db | ||
|
|
c2b33f5ec4 | ||
|
|
e58999e484 | ||
|
|
ed9692574c | ||
|
|
f7e078e064 | ||
|
|
b74a44dc36 | ||
|
|
6b36cdb5ee | ||
|
|
56ae1a8f95 | ||
|
|
3069b1d1f1 | ||
|
|
e7d346e4e1 | ||
|
|
7d9e00a574 | ||
|
|
7382afe535 | ||
|
|
af7d4774d6 | ||
|
|
520a8a0623 | ||
|
|
fbd0d8ec40 | ||
|
|
3fea98ce4c | ||
|
|
7c561ce254 | ||
|
|
522ddb5115 | ||
|
|
47f5790507 | ||
|
|
0cdcfe7f52 | ||
|
|
e4d69d869b | ||
|
|
61afb70cb9 | ||
|
|
79580697a1 | ||
|
|
6cb74760b0 | ||
|
|
c758aa81ff | ||
|
|
400c2ccefe | ||
|
|
64e9734bbe | ||
|
|
f6244885be | ||
|
|
82c57c382f | ||
|
|
7eacb46555 | ||
|
|
d9c911d89b | ||
|
|
a3ceb3dcb6 | ||
|
|
a5b68b28b2 | ||
|
|
bd285faf37 | ||
|
|
8a4960b560 | ||
|
|
83c6ae2057 | ||
|
|
b71563e889 | ||
|
|
79e0cf85f9 | ||
|
|
e996eaa008 | ||
|
|
5088c9e985 | ||
|
|
610b3c6d32 | ||
|
|
cc7290f10e | ||
|
|
576b842368 | ||
|
|
d23c0ba715 | ||
|
|
98e19baebd | ||
|
|
f5947db44a | ||
|
|
e978164329 | ||
|
|
966c8f2efa | ||
|
|
a57fec3d71 | ||
|
|
84844eda20 | ||
|
|
698cdcba61 | ||
|
|
1d6c9393d4 | ||
|
|
b654ac156d | ||
|
|
d133a9a692 | ||
|
|
d55db19f0e | ||
|
|
e3fc3df32c | ||
|
|
f2334da72d | ||
|
|
2902b6c2cf | ||
|
|
dfa95b57b9 | ||
|
|
33a2cf66d0 | ||
|
|
5f52cf5b51 | ||
|
|
9d07905f2d | ||
|
|
26dbe9dfdd | ||
|
|
98c5851071 | ||
|
|
a6ee571d65 | ||
|
|
a138701afe | ||
|
|
e52bdea255 | ||
|
|
068a712a30 | ||
|
|
80a5300648 | ||
|
|
0c36e458f7 | ||
|
|
b2fa52e4c4 | ||
|
|
151e978e5b | ||
|
|
9e806861ec | ||
|
|
a9a9368b9b | ||
|
|
7936ba31ea | ||
|
|
afc456de9a | ||
|
|
a98db0ba83 | ||
|
|
fb8720edd3 | ||
|
|
2aa2a0ac3a | ||
|
|
0531b6ef3a | ||
|
|
24142de11f | ||
|
|
7fad6eb70b | ||
|
|
f60227abdf | ||
|
|
18d6a74c53 | ||
|
|
03d06ba657 | ||
|
|
07086b68c8 | ||
|
|
0a85f3126f | ||
|
|
efa4180340 | ||
|
|
fb06f2aa11 | ||
|
|
ce023cedb8 | ||
|
|
3d1a28a50e | ||
|
|
5d2d0b4168 | ||
|
|
fa985a5a93 | ||
|
|
40f9937b60 | ||
|
|
c543c629c3 | ||
|
|
f861279c49 | ||
|
|
ee89f81d46 | ||
|
|
6d216561f8 | ||
|
|
0a96e583d3 | ||
|
|
c9d263c60d | ||
|
|
2d6488abf4 | ||
|
|
7dfbac4a24 | ||
|
|
7cfe4cb2c9 | ||
|
|
30cba8ca5f | ||
|
|
e9261a0ec0 | ||
|
|
89ee22837d | ||
|
|
939f3747cd | ||
|
|
f72814a51b | ||
|
|
94ee2ba5c1 | ||
|
|
fd9533d63f | ||
|
|
6571faae4e | ||
|
|
e031498d5b | ||
|
|
31a0017351 | ||
|
|
6e8cb0366d | ||
|
|
a02b3fbf6e | ||
|
|
37a663e0e1 | ||
|
|
e925d9892f | ||
|
|
e7907eeaa7 | ||
|
|
644e6655ff | ||
|
|
20c07af504 | ||
|
|
38471cdd6c | ||
|
|
0b5d16bd0e | ||
|
|
203b9994df | ||
|
|
e76bbb6a85 | ||
|
|
4e6c146bde | ||
|
|
7e1dc7ef24 | ||
|
|
698d81a433 | ||
|
|
012f9b9f03 | ||
|
|
12bd282ace | ||
|
|
31a89fa1a3 | ||
|
|
57d1e92e59 | ||
|
|
377fca20d9 | ||
|
|
415f844982 | ||
|
|
cbb8472153 | ||
|
|
c85ced89ef | ||
|
|
d5b8c90c94 | ||
|
|
9bcfb04f91 | ||
|
|
ae0fbd4b10 | ||
|
|
ef4f011cf6 | ||
|
|
7cc985205a | ||
|
|
a38b76eb8f | ||
|
|
9f844912cf | ||
|
|
d72b0b10d4 | ||
|
|
655f756d56 | ||
|
|
912e2c28a3 | ||
|
|
9add447566 | ||
|
|
7c435f6dc0 | ||
|
|
5e2fc84ebf | ||
|
|
793a57647d | ||
|
|
c32e7bc525 | ||
|
|
20fac33efc | ||
|
|
8cf356cadb | ||
|
|
17d2c8bf0a | ||
|
|
3dec5ac004 | ||
|
|
cf2ada8f2b | ||
|
|
c801f601d3 | ||
|
|
6a97704dab | ||
|
|
ee6c8301c4 | ||
|
|
de35f4308d | ||
|
|
3d4ed38f17 | ||
|
|
a84f981147 | ||
|
|
b70d821384 | ||
|
|
bc7c6c1f33 | ||
|
|
2a8761c29e | ||
|
|
0c732755ec | ||
|
|
5c638d713e | ||
|
|
8ff16f7205 | ||
|
|
6bf8e3643b | ||
|
|
6ab704bb77 | ||
|
|
41329f3bbc | ||
|
|
a59ebd69b4 | ||
|
|
278b6e3cc8 | ||
|
|
1d0c0ee7cb | ||
|
|
a8bf0a62fa | ||
|
|
fc58fb27e2 | ||
|
|
b1abeb4ec2 | ||
|
|
d9b7f33bde | ||
|
|
c0a1061204 | ||
|
|
7cbdfeec51 | ||
|
|
381c16d574 | ||
|
|
3e6be2f293 | ||
|
|
1bd62c4673 | ||
|
|
04aa4067cd | ||
|
|
499fb8239e | ||
|
|
fe75491024 | ||
|
|
8803003cf7 | ||
|
|
5a850aef07 | ||
|
|
d1d6e023c4 | ||
|
|
4370ed544f | ||
|
|
42c87519e1 | ||
|
|
769134eaf9 | ||
|
|
51b688bbdd | ||
|
|
748e74e515 | ||
|
|
d1d3ad9869 | ||
|
|
f9b72a22ae | ||
|
|
766cf90a19 | ||
|
|
8a2dc86cf7 | ||
|
|
5ca54b88fa | ||
|
|
7257c8778d | ||
|
|
dc21696ae1 | ||
|
|
7f566e5388 | ||
|
|
fe352ceb84 | ||
|
|
10750a0123 | ||
|
|
f2e6da649b | ||
|
|
9737cd06dd | ||
|
|
df8cf4d9ca | ||
|
|
36b4cbb8c2 | ||
|
|
bae84f65da | ||
|
|
313ec2d100 | ||
|
|
bfda5ec952 | ||
|
|
248bdba839 | ||
|
|
75dd3d0e5e | ||
|
|
8944ec0e02 | ||
|
|
25c5683a09 | ||
|
|
069e29ac07 | ||
|
|
942e4bf672 | ||
|
|
dca37a3794 | ||
|
|
f84419b7a6 | ||
|
|
aa3a049985 | ||
|
|
3f8c7bd91f | ||
|
|
11984d6972 | ||
|
|
31b0a3fb54 | ||
|
|
666d0b53a6 | ||
|
|
df77df4854 | ||
|
|
4f75248f5b | ||
|
|
2b56f4469d | ||
|
|
8d1f0d2010 | ||
|
|
16117b67f1 | ||
|
|
4fc0d06908 | ||
|
|
6254d00bb5 | ||
|
|
6d6fd3af2c | ||
|
|
16344393a1 | ||
|
|
36f561a595 | ||
|
|
f5f024b1d6 | ||
|
|
429f68ff64 | ||
|
|
f9074518dd | ||
|
|
bda803761b | ||
|
|
d3c1c5acb0 | ||
|
|
dcaafedabb | ||
|
|
985c76d8ce | ||
|
|
8c532798cb | ||
|
|
17aed56270 | ||
|
|
1f07411dde | ||
|
|
906e0e3554 | ||
|
|
22958923ad | ||
|
|
a5f94198c0 | ||
|
|
8a2bac8770 | ||
|
|
3fd24f6f19 | ||
|
|
c30292013b | ||
|
|
edd6db731f | ||
|
|
19e0c7b01a | ||
|
|
58fc76b8d2 | ||
|
|
1638bb301d | ||
|
|
f0ed677d86 | ||
|
|
4b0c52d2dd | ||
|
|
5f4e1d0b2f | ||
|
|
a98a48a58d | ||
|
|
763054884b | ||
|
|
376088e63c | ||
|
|
c614ba4705 | ||
|
|
14ea408fec | ||
|
|
038a52f7fc | ||
|
|
341bd5947f | ||
|
|
b5d857d2f1 | ||
|
|
97f9a3d4b1 | ||
|
|
9607d7135b | ||
|
|
b1338a9ffd | ||
|
|
bf1e3da298 | ||
|
|
a91cbee50c | ||
|
|
15fbbf3873 | ||
|
|
f73abba79f | ||
|
|
5fa9ebee80 | ||
|
|
d890ccd5e6 | ||
|
|
e76a782a80 | ||
|
|
0f7c5b2564 | ||
|
|
fcf0f34d5a | ||
|
|
acf2301028 | ||
|
|
9bc0577423 | ||
|
|
d037ce5b86 | ||
|
|
02250c3352 | ||
|
|
cdaa45e163 | ||
|
|
2b9014f4d8 | ||
|
|
75a013d961 | ||
|
|
27563fa58e | ||
|
|
55f958266c | ||
|
|
d980b55997 | ||
|
|
7232caa5c0 | ||
|
|
c0df366676 | ||
|
|
8e7a43275f | ||
|
|
d3567d8dd5 | ||
|
|
e9539636ac | ||
|
|
093dd25e0f | ||
|
|
e0427d3062 | ||
|
|
9e2030c83d | ||
|
|
0627641845 | ||
|
|
4bbcc3c73d | ||
|
|
945842c0e7 | ||
|
|
02ba98f120 | ||
|
|
688f8ec26c | ||
|
|
7652de0129 | ||
|
|
3f027e5456 | ||
|
|
6a17335231 | ||
|
|
ebf0dd9e46 | ||
|
|
04bd352a05 | ||
|
|
fa4ebfe3be | ||
|
|
87421bb391 | ||
|
|
c35e22fbd7 | ||
|
|
94623d8dc0 | ||
|
|
50eed2be10 | ||
|
|
e9b7336146 | ||
|
|
fbec06fa81 | ||
|
|
9fe8dad72d | ||
|
|
3046bbe697 | ||
|
|
7089952895 | ||
|
|
737d2a796b | ||
|
|
e25fd14675 | ||
|
|
c55dc713f4 | ||
|
|
40ef17edcd | ||
|
|
418536ded1 | ||
|
|
c156b5c0a7 | ||
|
|
ae454b72dc | ||
|
|
d34d1117a0 | ||
|
|
a5f3767cbc | ||
|
|
3bdb339f54 | ||
|
|
22cb3c3942 | ||
|
|
e5f5241879 | ||
|
|
79ac231df2 | ||
|
|
b7b375092f | ||
|
|
f86ea04521 | ||
|
|
738c02f58f | ||
|
|
d017688416 | ||
|
|
6b56275f87 | ||
|
|
b89f00130e | ||
|
|
4f58c54eff | ||
|
|
9001be21ac | ||
|
|
be3fa0b688 | ||
|
|
b421e7d2f8 | ||
|
|
0e7c14abde | ||
|
|
caf072ed9b | ||
|
|
51f2709956 | ||
|
|
0d5558f29f | ||
|
|
c6377ce544 | ||
|
|
07d34891ef | ||
|
|
ddce031ee5 | ||
|
|
6680a6450b | ||
|
|
dc119b26c7 | ||
|
|
2cbfca4f3b | ||
|
|
7d8fce6f46 | ||
|
|
13ad50aef5 | ||
|
|
30245b3668 | ||
|
|
589eea7cf3 | ||
|
|
24c5108ce1 | ||
|
|
21fbb01ce4 | ||
|
|
e664f20d34 | ||
|
|
b0ce14dc0e | ||
|
|
d2b38cbc1b | ||
|
|
a6d978090c | ||
|
|
f9d40987eb | ||
|
|
cab710493e | ||
|
|
9970cf704b | ||
|
|
260867b588 | ||
|
|
25231ecd32 | ||
|
|
b282515c39 | ||
|
|
bafd15571a | ||
|
|
481711fd75 | ||
|
|
d09b52301a | ||
|
|
0c77ef628f | ||
|
|
54f585c67a | ||
|
|
a9e5e7fdd3 | ||
|
|
b151f968d7 | ||
|
|
86ef93caa3 | ||
|
|
75511397d6 | ||
|
|
db8d09d0d6 | ||
|
|
02d70a476d | ||
|
|
9420f8561f | ||
|
|
d43eb821b9 | ||
|
|
b82ede8bde | ||
|
|
ff02da5c54 | ||
|
|
2987d356b6 | ||
|
|
dc5f0b151b | ||
|
|
dd5bcc3d9d | ||
|
|
80188ae6e6 | ||
|
|
05e77dc166 | ||
|
|
b9b8f8e170 | ||
|
|
c9cc09cbed | ||
|
|
bef90bf3b8 | ||
|
|
a369efa429 | ||
|
|
370329b07d | ||
|
|
e743a15fbc | ||
|
|
10c8b52092 | ||
|
|
1461b91a94 | ||
|
|
b5ffd5005a | ||
|
|
f06bd83dc3 | ||
|
|
a1450ee78a | ||
|
|
4c619778c3 | ||
|
|
4e8840cd93 | ||
|
|
0a709f741a | ||
|
|
ef8229981e | ||
|
|
2a5a2626a4 | ||
|
|
f4ddaedbf4 | ||
|
|
42104eb944 | ||
|
|
fadc8e6fd6 | ||
|
|
81747462b1 | ||
|
|
c01adad2a0 | ||
|
|
e598d60439 | ||
|
|
929cd23f35 | ||
|
|
d1aca5b675 | ||
|
|
b67868868d | ||
|
|
af3bf8448c | ||
|
|
4170c60f0c | ||
|
|
0a7a883aae | ||
|
|
88a1184877 | ||
|
|
c7329fcab5 | ||
|
|
6eb9a90a03 | ||
|
|
7586882a97 | ||
|
|
6f13c021b9 | ||
|
|
5f30c92d44 | ||
|
|
3e6c55d981 | ||
|
|
de36f984d7 | ||
|
|
95328fe1a6 | ||
|
|
1fb78185ff | ||
|
|
58f9aea979 | ||
|
|
4d4bb1e34f | ||
|
|
6e1978ec10 | ||
|
|
d8a8afba5e | ||
|
|
6e6f425bdd | ||
|
|
9ebe92f832 | ||
|
|
cbdb84a69f | ||
|
|
67b2b886a8 | ||
|
|
2838289650 | ||
|
|
4b68362fb8 | ||
|
|
e8e7696a4d | ||
|
|
82b2a5cc20 | ||
|
|
2332765932 | ||
|
|
552d689317 | ||
|
|
5e2d82d071 | ||
|
|
727f356eea | ||
|
|
544832c46a | ||
|
|
5c1d316d67 | ||
|
|
267ec77c37 | ||
|
|
c2a7106221 | ||
|
|
0e29e9823d | ||
|
|
47962424eb | ||
|
|
505d23ca07 | ||
|
|
d4fcb868d8 | ||
|
|
6dd1f43445 | ||
|
|
2626cb6750 | ||
|
|
81a98ded8a | ||
|
|
930f02765d | ||
|
|
a4ffa580b7 | ||
|
|
506612527d | ||
|
|
74f9f2b0e6 | ||
|
|
4119f02c60 | ||
|
|
bc9a4e07e2 | ||
|
|
9418544264 | ||
|
|
460ea091bd | ||
|
|
64681db027 | ||
|
|
992957e1e9 | ||
|
|
ce62dbc27f | ||
|
|
e2df967aa9 | ||
|
|
5b4a188c0b | ||
|
|
e8b5a58a90 | ||
|
|
c3d5c13a80 | ||
|
|
d30a8aefa4 | ||
|
|
194afe435a | ||
|
|
82ef993d83 | ||
|
|
6d7177a3b5 | ||
|
|
205dd58afd | ||
|
|
d5d5063453 | ||
|
|
f63fcf1227 | ||
|
|
0c70f27560 | ||
|
|
db889366ac | ||
|
|
9476bbe562 | ||
|
|
1313e05d5d | ||
|
|
8817b35517 | ||
|
|
cfe8a77dd5 | ||
|
|
a874d17798 | ||
|
|
5d9ef12577 | ||
|
|
b3a135e1a2 | ||
|
|
a25d03f073 | ||
|
|
589c0d3ce5 | ||
|
|
8457705807 | ||
|
|
ce7aefb744 | ||
|
|
499d7766db | ||
|
|
988327c9bd | ||
|
|
d0d0bf2b63 | ||
|
|
feb34761ce | ||
|
|
0ceeeb8c5b | ||
|
|
0c7289bbc8 | ||
|
|
e02fe2331d | ||
|
|
6877900ac2 | ||
|
|
45dbe2a0e6 | ||
|
|
4234885f94 | ||
|
|
bae55ca511 | ||
|
|
f804e8405e | ||
|
|
3c9c61c346 | ||
|
|
d560d8a2e8 | ||
|
|
054ee93360 | ||
|
|
eb98eaeb3b | ||
|
|
8fe2fa7bc6 | ||
|
|
95894f92db | ||
|
|
61e06dee4c | ||
|
|
e207d834bd | ||
|
|
e358bbf46c | ||
|
|
9c0f9557e8 | ||
|
|
006d4c6f09 | ||
|
|
6fb5a4b946 | ||
|
|
6687d75090 | ||
|
|
01cf9ccd54 | ||
|
|
880b6d429d | ||
|
|
070db961fc | ||
|
|
96ef379668 | ||
|
|
697a87721f | ||
|
|
09cf93d852 | ||
|
|
8725821a27 | ||
|
|
7ad8651ca0 | ||
|
|
a2e57c6e90 | ||
|
|
6d37bca2a9 | ||
|
|
8471bb0f9a | ||
|
|
05cb57db09 | ||
|
|
064e9a1aa3 | ||
|
|
a618b6cf9e | ||
|
|
e3e810e702 | ||
|
|
b4f0d6bab8 | ||
|
|
44cb4168cf | ||
|
|
559ed95999 | ||
|
|
b766df1d31 | ||
|
|
057ff6b22b | ||
|
|
995b0c8050 | ||
|
|
a2d4691f04 | ||
|
|
ab2d7d4724 | ||
|
|
9b4abf86b6 | ||
|
|
0331b7b6e3 | ||
|
|
e31799e78b | ||
|
|
a8405eea6d | ||
|
|
c11f072c50 | ||
|
|
bd080eb19b | ||
|
|
ef231e213e | ||
|
|
a5900b5f99 | ||
|
|
b22bbd4e27 | ||
|
|
664866b627 | ||
|
|
ad9bdc6574 | ||
|
|
b93b993951 | ||
|
|
cb2cb4e556 | ||
|
|
ab32bd390d | ||
|
|
b34374adfa | ||
|
|
b53b6a4246 | ||
|
|
191fbff768 | ||
|
|
e8a4ddf331 | ||
|
|
aee6e2d2f8 | ||
|
|
b737b20602 | ||
|
|
b5df539392 | ||
|
|
36c53e5d94 | ||
|
|
15ce6b8c8c | ||
|
|
19aa82c131 | ||
|
|
92ed6e7d1c | ||
|
|
b9a45a58a8 | ||
|
|
0c1efe7420 | ||
|
|
9dd7680457 | ||
|
|
087216b9da | ||
|
|
ecb6f71f81 | ||
|
|
ffffff16e9 | ||
|
|
0311d976bb | ||
|
|
120c07cc2e | ||
|
|
ed5ae40cb3 | ||
|
|
5931d91b5f | ||
|
|
472a5ae97a | ||
|
|
829ea66d0e | ||
|
|
ba39291ee7 | ||
|
|
d3d15fc59f | ||
|
|
8a3358c990 | ||
|
|
8eadba3aa6 | ||
|
|
b0917623b6 | ||
|
|
a7d9a4ecbc | ||
|
|
2643ab81ed | ||
|
|
c5314c72f0 | ||
|
|
fbb48ba330 | ||
|
|
4e6879e34f | ||
|
|
09c3d4e479 | ||
|
|
1e88bad73e | ||
|
|
9a2ed64b4e | ||
|
|
60e93f9809 | ||
|
|
f5c72e913f | ||
|
|
3ca300d956 | ||
|
|
d1087aa74c | ||
|
|
43c40e4bbe | ||
|
|
d9c4e5336b | ||
|
|
772198255a | ||
|
|
19c46a2f60 | ||
|
|
f54c8d6da4 | ||
|
|
84f9d1985e | ||
|
|
0b2a2bf97d | ||
|
|
561cf411ef | ||
|
|
f24ae6eb2a | ||
|
|
3bb3d4382c | ||
|
|
43db19c257 | ||
|
|
1d5663d93a | ||
|
|
b98d4cb091 | ||
|
|
14ee95615f | ||
|
|
8ccddce0f8 | ||
|
|
9dde15ac41 | ||
|
|
95111ef1e1 | ||
|
|
dc33abde46 | ||
|
|
aae7b08dd1 | ||
|
|
f70582af1a | ||
|
|
f04d84bb93 | ||
|
|
78693deed6 | ||
|
|
f1a5965b4c | ||
|
|
cd43d0775d | ||
|
|
cf532a84ef | ||
|
|
651b65d148 | ||
|
|
895dde1cc8 | ||
|
|
f6e94c9514 | ||
|
|
da4ba4453c | ||
|
|
53ea8c8002 | ||
|
|
d4549b1228 | ||
|
|
fcf9eff2f6 | ||
|
|
93b58149d2 | ||
|
|
c91c49465b | ||
|
|
e9fa3ead04 | ||
|
|
eff2f1d968 | ||
|
|
cd0a6579b8 | ||
|
|
18c2e232cf | ||
|
|
ad680638ac | ||
|
|
0764061d8f | ||
|
|
d448026250 | ||
|
|
34f553b9e3 | ||
|
|
25d1e32ce9 | ||
|
|
8686c32ada | ||
|
|
f043c6710a | ||
|
|
acd27e36fa | ||
|
|
37f0d1e5a1 | ||
|
|
e6397559ff | ||
|
|
812c46adeb | ||
|
|
4d7fb6301a | ||
|
|
f0951f2a25 | ||
|
|
7d2defedb7 | ||
|
|
17ab618bed | ||
|
|
0f9e932616 | ||
|
|
20b0bd26ae | ||
|
|
3b395861d9 | ||
|
|
d5d1f851ab | ||
|
|
c2e2a33af1 | ||
|
|
9a729f921e | ||
|
|
1b75f4b6e9 | ||
|
|
aaab6692c3 | ||
|
|
70fc85e456 | ||
|
|
29358a7b4b | ||
|
|
b1b0563d84 | ||
|
|
21b1e5bee7 | ||
|
|
c02eeef846 | ||
|
|
e84e50708b | ||
|
|
1471ca06f3 | ||
|
|
60b04c19dc | ||
|
|
4490c99eee | ||
|
|
9a84cdef9f | ||
|
|
62bbf110fb | ||
|
|
fd282d96d1 | ||
|
|
4e4da4440b | ||
|
|
5651d6dd9d | ||
|
|
e0499993a4 | ||
|
|
5c59cfe983 | ||
|
|
396ec7121c | ||
|
|
e403c80d51 | ||
|
|
aac315826e | ||
|
|
567c34d4d1 | ||
|
|
896681df87 | ||
|
|
e278883958 | ||
|
|
0d57565cae | ||
|
|
513c71398d | ||
|
|
a22c80a199 | ||
|
|
16e3001e51 | ||
|
|
3943850bc1 | ||
|
|
4fc41a449e | ||
|
|
f945508625 | ||
|
|
beaa77832c | ||
|
|
d0480edda6 | ||
|
|
de43495af5 | ||
|
|
c60cc1e84f | ||
|
|
82c83fcdf7 | ||
|
|
19221480a0 | ||
|
|
290e139346 | ||
|
|
923b0751e5 | ||
|
|
334b96f90e | ||
|
|
7ae8a6c247 | ||
|
|
18830544a6 | ||
|
|
37cab30ed7 | ||
|
|
91fe51d10a | ||
|
|
027ae02aa0 | ||
|
|
49e0d9729d | ||
|
|
15c667b043 | ||
|
|
4820d2a54a | ||
|
|
58a40ad1d1 | ||
|
|
1877a373d6 | ||
|
|
192b60f037 | ||
|
|
c40224b454 | ||
|
|
6508bf6851 | ||
|
|
96b8ced64f | ||
|
|
254da59b7a | ||
|
|
c9b775d8ff | ||
|
|
d60b0ea0ea | ||
|
|
20061983d6 | ||
|
|
ff8f8623d9 | ||
|
|
1ce1a6f0ff | ||
|
|
67d09d95fa | ||
|
|
10e04c7645 | ||
|
|
9c05ac8cc2 | ||
|
|
55d1eb145e | ||
|
|
c8cdeb2ae1 | ||
|
|
9891ab23a2 | ||
|
|
9739fe2b79 | ||
|
|
c976221cbb | ||
|
|
8267904155 | ||
|
|
ef8a8ff497 | ||
|
|
2384921477 | ||
|
|
985b05f29d | ||
|
|
5254fb65ef | ||
|
|
8ff666d5e2 | ||
|
|
ed77d6dc1f | ||
|
|
7b41fd82a4 | ||
|
|
ac0112199d | ||
|
|
ef5e1e65f9 | ||
|
|
b330d26b4f | ||
|
|
93d7c34454 | ||
|
|
0bd5677e26 | ||
|
|
22e2e978ef | ||
|
|
65c2651105 | ||
|
|
ef13e19c48 | ||
|
|
39ffad6da6 | ||
|
|
13924fca13 | ||
|
|
438f006d1d | ||
|
|
6fb5626230 | ||
|
|
ab29069af5 | ||
|
|
fc3ed28eda | ||
|
|
46c9110b85 | ||
|
|
06b033ed36 | ||
|
|
ab96f3f28c | ||
|
|
295238cbb6 | ||
|
|
69125e967f | ||
|
|
4f0f0e54ac | ||
|
|
a9a01b08dc | ||
|
|
c27a3e105c | ||
|
|
3cfc084e62 | ||
|
|
7c1873e861 | ||
|
|
c57c313dbe | ||
|
|
19cf9c0129 | ||
|
|
ebcb05cc55 | ||
|
|
7c4dbb1f38 | ||
|
|
091b46ccaf | ||
|
|
4da2bf441f | ||
|
|
365ed560f6 | ||
|
|
bcf6372602 | ||
|
|
a5e24be5d4 | ||
|
|
cdaf6f0dca | ||
|
|
e38d0bc6d0 | ||
|
|
eb16ba8365 | ||
|
|
3beb4f53d6 | ||
|
|
f8ba0c9753 | ||
|
|
0232e5adec | ||
|
|
a0bc521903 | ||
|
|
071a84d9ef | ||
|
|
aa40b5336e | ||
|
|
157402bb39 | ||
|
|
5a98a68c27 | ||
|
|
f6bc52fd59 | ||
|
|
d1f2712e5f | ||
|
|
8958317f61 | ||
|
|
fdf27cbc1a | ||
|
|
26ffb829d0 | ||
|
|
521e3e2587 | ||
|
|
17c6158478 | ||
|
|
fa0dc48993 | ||
|
|
826bdaab5c | ||
|
|
7d21da76fb | ||
|
|
70465a49d7 | ||
|
|
acca74dce7 | ||
|
|
d8e7892ab7 | ||
|
|
e887bf1fd7 | ||
|
|
145ca936e7 | ||
|
|
69c7a51215 | ||
|
|
c4875d4f80 | ||
|
|
eed3c9768b | ||
|
|
2c650f2bdf | ||
|
|
71e8392359 | ||
|
|
cfbf6e23ec | ||
|
|
9be5ec0f31 | ||
|
|
a8a0c3831b | ||
|
|
ef31d5a938 | ||
|
|
812db6dafe | ||
|
|
66fe2f0995 | ||
|
|
3b40cc7833 | ||
|
|
5a01ca061a | ||
|
|
ef0cc05f5c | ||
|
|
c5c6e4ae23 | ||
|
|
1c2bbfea93 | ||
|
|
8893317f59 | ||
|
|
ca8b5c85dd | ||
|
|
a64d485278 | ||
|
|
2612764922 | ||
|
|
8ce8e81792 | ||
|
|
fbba2ddec9 | ||
|
|
33a1b9d4bf | ||
|
|
03abac082c | ||
|
|
3672a7e1fa | ||
|
|
df27e7ba75 | ||
|
|
423655e1ca | ||
|
|
f620223613 | ||
|
|
365a94d7b7 | ||
|
|
a98efd83b6 | ||
|
|
6488e96127 | ||
|
|
cc75594747 | ||
|
|
e5de104933 | ||
|
|
954e76ab33 | ||
|
|
82bda518c9 | ||
|
|
cdc5bcd31f | ||
|
|
61f6d480ae | ||
|
|
df6df3548c | ||
|
|
ac839450e2 | ||
|
|
4fa01e1a29 | ||
|
|
db2a45ec35 | ||
|
|
76c6f5cc1c | ||
|
|
339b519881 | ||
|
|
de2fab1370 | ||
|
|
fd4b6794cc | ||
|
|
f3e3f7cf85 | ||
|
|
dd824254a9 | ||
|
|
16943d4590 | ||
|
|
a95697088b | ||
|
|
f771a98f25 | ||
|
|
3b1a8beadf | ||
|
|
209e9d7705 | ||
|
|
de09a042e6 | ||
|
|
66cd491493 | ||
|
|
4a158319e5 | ||
|
|
b322a848ba | ||
|
|
4e759134bd | ||
|
|
5c16171781 | ||
|
|
08ad68d4a2 | ||
|
|
2ace30acd8 | ||
|
|
fc55b1be82 | ||
|
|
b287dfedcf | ||
|
|
d6984f0ad4 | ||
|
|
85cb1ed3f6 | ||
|
|
32b5240fcc | ||
|
|
7b9fda2298 | ||
|
|
15a605b677 | ||
|
|
f4a3fcece8 | ||
|
|
d67fc31c26 | ||
|
|
889000d8a8 | ||
|
|
e827e74cc7 | ||
|
|
45ca1ebf02 | ||
|
|
3a81d7babd | ||
|
|
a1d5949177 | ||
|
|
d7ae52160b | ||
|
|
e3fa33b9b5 | ||
|
|
ac251114ff | ||
|
|
824d1c1501 | ||
|
|
ac88fd5cf6 | ||
|
|
5197d42807 | ||
|
|
7a0f4caa9b | ||
|
|
5bf1d29edc | ||
|
|
2687466ed4 | ||
|
|
14512d6470 | ||
|
|
32268f5a4a | ||
|
|
81401ca0b8 | ||
|
|
688cc271d5 | ||
|
|
a290353cfa | ||
|
|
6038e7acd6 | ||
|
|
4abec5a389 | ||
|
|
a2b51a8044 | ||
|
|
19cb239746 | ||
|
|
7aab610be5 | ||
|
|
4ec5a126ac | ||
|
|
32643caf51 | ||
|
|
114ebab6ae | ||
|
|
d1463e1fc6 | ||
|
|
aa49980231 | ||
|
|
2696da092d | ||
|
|
5415d95f36 | ||
|
|
efa71c8bb7 | ||
|
|
d59df4c561 | ||
|
|
140bcb037f | ||
|
|
2a4384e093 | ||
|
|
5aafed85ed | ||
|
|
6ad4b91c60 | ||
|
|
cd62686316 | ||
|
|
dcd606e573 | ||
|
|
f6f326119c | ||
|
|
f31e5e0d22 | ||
|
|
abc12d2a1d | ||
|
|
b7e2f084b1 | ||
|
|
adf1776b1e | ||
|
|
fd1edcdedf | ||
|
|
ebc25c401d | ||
|
|
67574bf759 | ||
|
|
e94923c3c6 | ||
|
|
5718d57b88 | ||
|
|
82cff36194 | ||
|
|
3e4e2d5eb6 | ||
|
|
015f09d27b | ||
|
|
3fedc5b1b3 | ||
|
|
4776ab9bd8 | ||
|
|
3bb01ef9a8 | ||
|
|
0204f5f68f | ||
|
|
217d88beaa | ||
|
|
77080b3934 | ||
|
|
83f6dc2f76 | ||
|
|
29b3ca4e69 | ||
|
|
9394ff49fd | ||
|
|
49949ecda5 | ||
|
|
1dab0f2b19 | ||
|
|
1cf03bf049 | ||
|
|
c00594738f | ||
|
|
d5f601b0eb | ||
|
|
304bff1f19 | ||
|
|
ce9e0cd88c | ||
|
|
40903d9ad5 | ||
|
|
0fc97ad2f1 | ||
|
|
2bb66ea583 | ||
|
|
03aa9780eb | ||
|
|
d3a9005964 | ||
|
|
48bcf4a848 | ||
|
|
72f0426531 | ||
|
|
44ec5b3de3 | ||
|
|
292fdb1288 | ||
|
|
76e65286fd | ||
|
|
9397a0ebae | ||
|
|
c37b5e52ac | ||
|
|
ecfced7195 | ||
|
|
1c7a79f7d7 | ||
|
|
1149906786 | ||
|
|
9db111c08a | ||
|
|
0844447b46 | ||
|
|
c7116ad165 | ||
|
|
a805e0639e | ||
|
|
e8e69a2e86 | ||
|
|
3e4761a60f | ||
|
|
3413157c67 | ||
|
|
b5f2174ed0 | ||
|
|
bdc8285255 | ||
|
|
cd79f0e434 | ||
|
|
171f40551e | ||
|
|
ba4efebbce | ||
|
|
2486287a0e | ||
|
|
2599639aeb | ||
|
|
c1192b37c6 | ||
|
|
1f647163f2 | ||
|
|
cc04efe76b | ||
|
|
18426d0481 | ||
|
|
500b469bce | ||
|
|
49c242e7bc | ||
|
|
2d72d6dbc9 | ||
|
|
1f3e55ebea | ||
|
|
0ecb37419b | ||
|
|
c758bf6530 | ||
|
|
46d985a720 | ||
|
|
9404882fc7 | ||
|
|
ec1c3d6070 | ||
|
|
8eb7816e30 | ||
|
|
c196e44bc6 | ||
|
|
989d88f7d3 | ||
|
|
cb4ebb6306 | ||
|
|
92e7ec9682 | ||
|
|
32b7ff1b36 | ||
|
|
5a68ef558f | ||
|
|
18d48ae963 | ||
|
|
d61c723933 | ||
|
|
bb64ff7278 | ||
|
|
d7760cd34d | ||
|
|
f9ecad1cf0 | ||
|
|
a6de89ab74 | ||
|
|
e663dcf83b | ||
|
|
88e8e5cd54 | ||
|
|
9b43d36793 | ||
|
|
794314a8e1 | ||
|
|
0a1c40cee5 | ||
|
|
958cdd25a5 | ||
|
|
2fb77c1bf8 | ||
|
|
3aa46664f7 | ||
|
|
8389ce5793 | ||
|
|
5199430766 | ||
|
|
0afe5ada2c | ||
|
|
1774eb63b7 | ||
|
|
609cd21603 | ||
|
|
97fc65e66d | ||
|
|
ccac691701 | ||
|
|
a283c8bbad | ||
|
|
9bc5580229 | ||
|
|
eca5d73b94 | ||
|
|
fdacd5f3f8 | ||
|
|
c449a070b4 | ||
|
|
9e2efe3717 | ||
|
|
90ad292b84 | ||
|
|
f2422ed16c | ||
|
|
52ac982481 | ||
|
|
661c3a6d61 | ||
|
|
c14db5fd0d | ||
|
|
6116e49a05 | ||
|
|
8b6cd759ef | ||
|
|
e3f1ad79a8 | ||
|
|
b4c190efb7 | ||
|
|
bd11f2e7b8 | ||
|
|
1f26f001e9 | ||
|
|
ecd2bb4590 | ||
|
|
330eabcfc5 | ||
|
|
bd8ecab31b | ||
|
|
e9af0c7042 | ||
|
|
72a49d0ed8 | ||
|
|
66304c91ec | ||
|
|
c2192dd657 | ||
|
|
1de9e0b79d | ||
|
|
608f401a80 | ||
|
|
ef1acdc3d1 | ||
|
|
82631fb336 | ||
|
|
a348d9131d | ||
|
|
fc575f5bc0 | ||
|
|
e277649878 | ||
|
|
f07cbcbb81 | ||
|
|
9df32816a1 | ||
|
|
f7fd589b13 | ||
|
|
852d031254 | ||
|
|
38c0ca0ce1 | ||
|
|
4eca73303b | ||
|
|
d5292f3fc3 | ||
|
|
6549fbb552 | ||
|
|
a71921cdd1 | ||
|
|
46c219505f | ||
|
|
0a129f9250 | ||
|
|
4ece14e921 | ||
|
|
a4c8fb6e1b | ||
|
|
c8d3f6efed | ||
|
|
fe47de01d3 | ||
|
|
84045b13c6 | ||
|
|
af37bb6e54 | ||
|
|
e1801a5fba | ||
|
|
50bfde6e8e | ||
|
|
f0ac319a73 | ||
|
|
39c277b090 | ||
|
|
81e6aab53d | ||
|
|
7c1e1ab593 | ||
|
|
2381b67312 | ||
|
|
ca83a4450d | ||
|
|
8cec0abf0e | ||
|
|
a89127df1d | ||
|
|
95924868f7 | ||
|
|
778b097f7a | ||
|
|
3a7f3bb68d | ||
|
|
02b9b689b7 | ||
|
|
3882fe9f3f | ||
|
|
af29cb738d | ||
|
|
4975d3b1ba | ||
|
|
fb4910e265 | ||
|
|
9ccaba480a | ||
|
|
97a7624b94 | ||
|
|
d697ebe521 | ||
|
|
6df57cd3cd | ||
|
|
3f518ec321 | ||
|
|
f112f18723 | ||
|
|
ee9389db2c | ||
|
|
769e0199d5 | ||
|
|
e77dfb5ca3 | ||
|
|
53b53eb0a0 | ||
|
|
ec25af8517 | ||
|
|
8d2779b446 | ||
|
|
7e20c39fb3 | ||
|
|
a9e858bc9a | ||
|
|
d47c0bf4b6 | ||
|
|
ea99232d3b | ||
|
|
5bd444f9b3 | ||
|
|
4498fed8be | ||
|
|
b5c82438a0 | ||
|
|
16f8592497 | ||
|
|
fbbf762e70 | ||
|
|
aba68f859f | ||
|
|
b5be5b60da | ||
|
|
631547f8c7 | ||
|
|
a422bcc858 | ||
|
|
4b11238b6c | ||
|
|
c5ca825b25 | ||
|
|
314c5cd86a | ||
|
|
a1ad7acb3d | ||
|
|
dcd4475617 | ||
|
|
a6fdb5691a | ||
|
|
2ff01d10b0 | ||
|
|
d6e3da322b | ||
|
|
188957ee91 | ||
|
|
706e8601a3 | ||
|
|
216949d7a5 | ||
|
|
7e6c678e91 | ||
|
|
195d1805e9 | ||
|
|
4ea52a9287 | ||
|
|
1253ce71af | ||
|
|
3401c69729 | ||
|
|
68e14a48f1 | ||
|
|
5b8a004720 | ||
|
|
3e716887c9 | ||
|
|
fe95b8ec5d | ||
|
|
e3dcaec9b5 | ||
|
|
b4dfba9a44 | ||
|
|
e80c715e44 | ||
|
|
8b8f44d2a8 | ||
|
|
b8b85e30a6 | ||
|
|
81b28a0407 | ||
|
|
cecbb35f1a | ||
|
|
083c7af361 | ||
|
|
a7993efeda | ||
|
|
141086929f | ||
|
|
4f417e123b | ||
|
|
2204f4d129 | ||
|
|
f80a3229cc | ||
|
|
d94d196c83 | ||
|
|
9c67461dbc | ||
|
|
75910b7558 | ||
|
|
88b9afe189 | ||
|
|
6fa17e617a | ||
|
|
2c9360721a | ||
|
|
6851495da5 | ||
|
|
1b25835d1a | ||
|
|
e36918b6ec | ||
|
|
65468d5b15 | ||
|
|
78f81ea335 | ||
|
|
21f350a84e | ||
|
|
17fab5ad61 | ||
|
|
7f41ba9a3c | ||
|
|
1dc434832a | ||
|
|
045e74c82f | ||
|
|
c96fa23d61 | ||
|
|
7881f39b97 | ||
|
|
cf1a32ed1f | ||
|
|
d0b7ae020c | ||
|
|
e5c7bbdf52 | ||
|
|
42d52720f3 | ||
|
|
6d392139df | ||
|
|
852c741310 | ||
|
|
41761f0a97 | ||
|
|
2d5854ed58 | ||
|
|
1370ffb3bb | ||
|
|
6efc88423e | ||
|
|
6e2314eab5 | ||
|
|
d64b31f6ce | ||
|
|
d5a4b3365f | ||
|
|
86142ed4db | ||
|
|
2cb9278db0 | ||
|
|
92fad7f29b | ||
|
|
c782e8154b | ||
|
|
77c387bfe9 | ||
|
|
aea9099e34 | ||
|
|
6446b3ed40 | ||
|
|
8967e6f8c4 | ||
|
|
d6010a81e1 | ||
|
|
95e6921a4e | ||
|
|
df5f0b9c13 | ||
|
|
665a6afd74 | ||
|
|
f53c4300e8 | ||
|
|
1fdeeb781f | ||
|
|
e340af90ed | ||
|
|
7fa7cc4af1 | ||
|
|
ca3c011f34 | ||
|
|
669339d5b4 | ||
|
|
c6567650fe | ||
|
|
3ae70412fa | ||
|
|
d575850f9f | ||
|
|
d1439da54e | ||
|
|
89022d3df4 | ||
|
|
3c38fe6155 | ||
|
|
e68ece6925 | ||
|
|
ea9b8874cc | ||
|
|
475efd90fc | ||
|
|
682605d5c2 | ||
|
|
256844ddf5 | ||
|
|
96f95bbd99 | ||
|
|
4f7bb945e0 | ||
|
|
0d69d779f6 | ||
|
|
5df26908fb | ||
|
|
fb5e289de0 | ||
|
|
b238759f61 | ||
|
|
2bb0d18891 | ||
|
|
7d5b6504f4 | ||
|
|
63f90e1537 | ||
|
|
65b43feb38 | ||
|
|
4f00a19344 | ||
|
|
3bfca7d340 | ||
|
|
8538d0de28 | ||
|
|
5425e17d6f | ||
|
|
bb3065d08d | ||
|
|
1adc3d7ed6 | ||
|
|
556b23b488 | ||
|
|
5b0c189d75 | ||
|
|
161fdff09a | ||
|
|
81b3dd57b1 | ||
|
|
1ab0f447d2 | ||
|
|
9ac07e94d1 | ||
|
|
fee6e8f4dd | ||
|
|
1e39b1af6d | ||
|
|
727d841d47 | ||
|
|
5e0d4d6ee1 | ||
|
|
32ce99949b | ||
|
|
fbb9bff3c7 | ||
|
|
6471b237ce | ||
|
|
d452c610c1 | ||
|
|
009fa88402 | ||
|
|
6d26276352 | ||
|
|
bdca693413 | ||
|
|
a2d30ca99a | ||
|
|
5c02bc2bee | ||
|
|
00ffd55fef | ||
|
|
32148821a1 | ||
|
|
60f6483a86 | ||
|
|
9b80300f19 | ||
|
|
8f02bfa3a6 | ||
|
|
93607ad62a | ||
|
|
3cbf891674 | ||
|
|
00688a65af | ||
|
|
c0099cb90c | ||
|
|
43248408fc | ||
|
|
d535500b9e | ||
|
|
9cea3e1ba9 | ||
|
|
746fa44ab8 | ||
|
|
b23d56f49c | ||
|
|
3693f1ea98 | ||
|
|
14127e8097 | ||
|
|
ad0d47bd68 | ||
|
|
b59fb0d811 | ||
|
|
0b1990f040 | ||
|
|
8deb239450 | ||
|
|
33387e8d26 | ||
|
|
9d4656a1f2 | ||
|
|
9c49d8d54a | ||
|
|
4ee6b3cdc2 | ||
|
|
d5636a71b1 | ||
|
|
b1ca47fc14 | ||
|
|
ddb35620cb | ||
|
|
a906a84721 | ||
|
|
d43d30f72f | ||
|
|
e9841a65c6 | ||
|
|
2dd3ba847e | ||
|
|
0dcbe0574c | ||
|
|
d01dce438c | ||
|
|
76929cc015 | ||
|
|
cde0f4bcd8 | ||
|
|
8dc0560537 | ||
|
|
a054740de6 | ||
|
|
029b850d6b | ||
|
|
8260653eae | ||
|
|
bd7b9b5c44 | ||
|
|
8f33a391f8 | ||
|
|
2f9d3a9f11 | ||
|
|
316294f449 | ||
|
|
09fac3bd64 | ||
|
|
2da81212b4 | ||
|
|
4cad587609 | ||
|
|
67eeae31c7 | ||
|
|
ae465a47a9 | ||
|
|
23b59f6ad6 | ||
|
|
09e3483e0a | ||
|
|
b3f4e9ae6e | ||
|
|
79efe6237d | ||
|
|
bf0f479234 | ||
|
|
ece1dab28b | ||
|
|
b913b5c20c | ||
|
|
366cf3c792 | ||
|
|
21ccd4d29f | ||
|
|
b8ba4219cd | ||
|
|
43da6847ba | ||
|
|
c22c87e16b | ||
|
|
4551dabb39 | ||
|
|
774ad0e5ef | ||
|
|
bd87e982ef | ||
|
|
ecd4973948 | ||
|
|
6dd1eee6c3 | ||
|
|
42703def02 | ||
|
|
afc08d4e46 | ||
|
|
65875b66c2 | ||
|
|
091758022f | ||
|
|
c395a7a750 | ||
|
|
2ab045658b | ||
|
|
c196cd84d3 | ||
|
|
c3c18cd555 | ||
|
|
cb48c672bd | ||
|
|
713073203c | ||
|
|
eafdb8cd31 | ||
|
|
d592fb96a6 | ||
|
|
0c116b7701 | ||
|
|
664bb1f71c | ||
|
|
5f809cc26a | ||
|
|
1bb70edd4b | ||
|
|
2922b44747 | ||
|
|
f34078a604 | ||
|
|
1c1bb078b1 | ||
|
|
9ec841ff67 | ||
|
|
665a16fe60 | ||
|
|
8d02406211 | ||
|
|
873d873194 | ||
|
|
2c9819762a | ||
|
|
ce70eebda6 | ||
|
|
47af58bb5b | ||
|
|
b0397981ce | ||
|
|
650d8689ee | ||
|
|
b443a1c308 | ||
|
|
b1bb79bd95 | ||
|
|
7ca1ebac79 | ||
|
|
f8036782e4 | ||
|
|
ca7b42981b | ||
|
|
c6440c9312 | ||
|
|
3de44a416c | ||
|
|
62f1c050ca | ||
|
|
6070e619da | ||
|
|
636fbed7f2 | ||
|
|
d354db382c | ||
|
|
501765eaa7 | ||
|
|
9f1eaf4a62 | ||
|
|
a4b098084d | ||
|
|
2cb006f3d9 | ||
|
|
775c724840 | ||
|
|
15dc047488 | ||
|
|
91b25400dc | ||
|
|
9b3839ac0b | ||
|
|
ff74dcdd8b | ||
|
|
d316c5000a | ||
|
|
d8692c836f | ||
|
|
0a4a3d8f2e | ||
|
|
5484b604a7 | ||
|
|
66c3c4862a | ||
|
|
e9d31bbf94 | ||
|
|
55bcd502e2 | ||
|
|
9bf22f2c79 | ||
|
|
cbf142dbf8 | ||
|
|
a6e94acefb | ||
|
|
469d73d641 | ||
|
|
0d521c68bd | ||
|
|
cd62c1dd9a | ||
|
|
e6422445a6 | ||
|
|
7683746032 | ||
|
|
a25fd19bcc | ||
|
|
6675e8f171 | ||
|
|
c836dce54d | ||
|
|
f3ab8f63e7 | ||
|
|
20d2c517b2 | ||
|
|
d6a2b31d5c | ||
|
|
533f96361a | ||
|
|
09807901c0 | ||
|
|
57ae9aa18c | ||
|
|
08efcaf4c1 | ||
|
|
b221b8121a | ||
|
|
abb75fe858 | ||
|
|
4591d0b5f6 | ||
|
|
b25f656372 | ||
|
|
cc1c8d6414 | ||
|
|
99a3abf697 | ||
|
|
023dc82f8e | ||
|
|
09a985fadb | ||
|
|
eb6b6e3aba | ||
|
|
89bde69417 | ||
|
|
6bb3c17f82 | ||
|
|
8be6d54f22 | ||
|
|
ea28d3e6e1 | ||
|
|
9fbce6a726 | ||
|
|
46467171ba | ||
|
|
d2d6d2ad14 | ||
|
|
f38d663e9d | ||
|
|
11e03c7a13 | ||
|
|
f466a02fd7 | ||
|
|
3bb4d5082b | ||
|
|
fb743ada63 | ||
|
|
a17e742218 | ||
|
|
d6b54dd49c | ||
|
|
b7a20d4bdb | ||
|
|
28c22694ba | ||
|
|
efd0789e09 |
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.cs text eol=lf
|
||||
21
.gitignore
vendored
21
.gitignore
vendored
@@ -10,8 +10,26 @@
|
||||
/[Ll]ogs/
|
||||
/[Mm]emoryCaptures/
|
||||
|
||||
|
||||
|
||||
/Bundles/
|
||||
/ProjectSettings/
|
||||
/App/
|
||||
/yoo/
|
||||
/Assets/Docs
|
||||
/Assets/Docs.meta
|
||||
/Assets/StreamingAssets
|
||||
/Assets/StreamingAssets.meta
|
||||
/Assets/Samples
|
||||
/Assets/Samples.meta
|
||||
/Assets/csc.rsp
|
||||
/Assets/csc.rsp.meta
|
||||
/UserSettings
|
||||
|
||||
|
||||
|
||||
# Asset meta data should only be ignored when the corresponding asset is also ignored
|
||||
!/[Aa]ssets/**/*.meta
|
||||
|
||||
|
||||
# Uncomment this line if you wish to ignore the asset store tools plugin
|
||||
# /[Aa]ssets/AssetStoreTools*
|
||||
@@ -54,6 +72,7 @@ sysinfo.txt
|
||||
# Builds
|
||||
*.apk
|
||||
*.unitypackage
|
||||
*.zip
|
||||
|
||||
# Crashlytics generated file
|
||||
crashlytics-build.properties
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
# CHANGELOG
|
||||
|
||||
All notable changes to this package will be documented in this file.
|
||||
All notable changes to this package will be documented in this file.
|
||||
|
||||
## [1.0.1] - 2022-04-07
|
||||
|
||||
### Fixed
|
||||
|
||||
- 修复Assets目录下存在多个YooAsset同名文件夹时,工具窗口无法显示的问题。
|
||||
- 修复通过Packages导入YooAsset,工具窗口无法显示的问题。
|
||||
|
||||
## [1.0.0] - 2022-04-05
|
||||
*Compatible with Unity 2019.4*
|
||||
## [3.0.0-beta] - 2026-05-09
|
||||
|
||||
beta released.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 58462a7dcef164e43878a037395d4417
|
||||
guid: fab3cd742c11be2479b07f5d447a78c9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
5
Assets/YooAsset/Editor/Assembly/AssemblyInfo.cs
Normal file
5
Assets/YooAsset/Editor/Assembly/AssemblyInfo.cs
Normal file
@@ -0,0 +1,5 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// 外部友元
|
||||
[assembly: InternalsVisibleTo("YooAsset.Extension.Editor")]
|
||||
[assembly: InternalsVisibleTo("Assembly-CSharp-Editor")]
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e9274735f1f14af4b893c21a4240b816
|
||||
guid: ef774f01e50ab0a4d88122041938a6b9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -1,126 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class AssetBundleBuilder
|
||||
{
|
||||
public class BuildParametersContext : IContextObject
|
||||
{
|
||||
private readonly System.Diagnostics.Stopwatch _buildWatch = new System.Diagnostics.Stopwatch();
|
||||
|
||||
/// <summary>
|
||||
/// 构建参数
|
||||
/// </summary>
|
||||
public BuildParameters Parameters { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 构建管线的输出目录
|
||||
/// </summary>
|
||||
public string PipelineOutputDirectory { private set; get; }
|
||||
|
||||
|
||||
public BuildParametersContext(BuildParameters parameters)
|
||||
{
|
||||
Parameters = parameters;
|
||||
PipelineOutputDirectory = AssetBundleBuilderHelper.MakePipelineOutputDirectory(parameters.OutputRoot, parameters.BuildTarget);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取本次构建的补丁目录
|
||||
/// </summary>
|
||||
public string GetPackageDirectory()
|
||||
{
|
||||
return $"{Parameters.OutputRoot}/{Parameters.BuildTarget}/{Parameters.BuildVersion}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取构建选项
|
||||
/// </summary>
|
||||
public BuildAssetBundleOptions GetPipelineBuildOptions()
|
||||
{
|
||||
// For the new build system, unity always need BuildAssetBundleOptions.CollectDependencies and BuildAssetBundleOptions.DeterministicAssetBundle
|
||||
// 除非设置ForceRebuildAssetBundle标记,否则会进行增量打包
|
||||
|
||||
BuildAssetBundleOptions opt = BuildAssetBundleOptions.None;
|
||||
opt |= BuildAssetBundleOptions.StrictMode; //Do not allow the build to succeed if any errors are reporting during it.
|
||||
|
||||
if (Parameters.CompressOption == ECompressOption.Uncompressed)
|
||||
opt |= BuildAssetBundleOptions.UncompressedAssetBundle;
|
||||
else if (Parameters.CompressOption == ECompressOption.LZ4)
|
||||
opt |= BuildAssetBundleOptions.ChunkBasedCompression;
|
||||
|
||||
if (Parameters.ForceRebuild)
|
||||
opt |= BuildAssetBundleOptions.ForceRebuildAssetBundle; //Force rebuild the asset bundles
|
||||
if (Parameters.AppendHash)
|
||||
opt |= BuildAssetBundleOptions.AppendHashToAssetBundleName; //Append the hash to the assetBundle name
|
||||
if (Parameters.DisableWriteTypeTree)
|
||||
opt |= BuildAssetBundleOptions.DisableWriteTypeTree; //Do not include type information within the asset bundle (don't write type tree).
|
||||
if (Parameters.IgnoreTypeTreeChanges)
|
||||
opt |= BuildAssetBundleOptions.IgnoreTypeTreeChanges; //Ignore the type tree changes when doing the incremental build check.
|
||||
if (Parameters.DisableLoadAssetByFileName)
|
||||
{
|
||||
opt |= BuildAssetBundleOptions.DisableLoadAssetByFileName; //Disables Asset Bundle LoadAsset by file name.
|
||||
opt |= BuildAssetBundleOptions.DisableLoadAssetByFileNameWithExtension; //Disables Asset Bundle LoadAsset by file name with extension.
|
||||
}
|
||||
|
||||
return opt;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取构建的耗时(单位:秒)
|
||||
/// </summary>
|
||||
public int GetBuildingSeconds()
|
||||
{
|
||||
int seconds = (int)(_buildWatch.ElapsedMilliseconds / 1000);
|
||||
return seconds;
|
||||
}
|
||||
public void BeginWatch()
|
||||
{
|
||||
_buildWatch.Start();
|
||||
}
|
||||
public void StopWatch()
|
||||
{
|
||||
_buildWatch.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
private readonly BuildContext _buildContext = new BuildContext();
|
||||
|
||||
/// <summary>
|
||||
/// 开始构建
|
||||
/// </summary>
|
||||
public bool Run(BuildParameters buildParameters)
|
||||
{
|
||||
// 清空旧数据
|
||||
_buildContext.ClearAllContext();
|
||||
|
||||
// 构建参数
|
||||
var buildParametersContext = new BuildParametersContext(buildParameters);
|
||||
_buildContext.SetContextObject(buildParametersContext);
|
||||
|
||||
// 执行构建流程
|
||||
List<IBuildTask> pipeline = new List<IBuildTask>
|
||||
{
|
||||
new TaskPrepare(), //前期准备工作
|
||||
new TaskGetBuildMap(), //获取构建列表
|
||||
new TaskBuilding(), //开始执行构建
|
||||
new TaskEncryption(), //加密资源文件
|
||||
new TaskCreatePatchManifest(), //创建清单文件
|
||||
new TaskCreateReport(), //创建报告文件
|
||||
new TaskCreatePatchPackage(), //制作补丁包
|
||||
new TaskCopyBuildinFiles(), //拷贝内置文件
|
||||
};
|
||||
|
||||
bool succeed = BuildRunner.Run(pipeline, _buildContext);
|
||||
if (succeed)
|
||||
Debug.Log($"构建成功!");
|
||||
else
|
||||
Debug.LogWarning($"构建失败!");
|
||||
return succeed;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public static class AssetBundleBuilderHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取默认的输出根路录
|
||||
/// </summary>
|
||||
public static string GetDefaultOutputRoot()
|
||||
{
|
||||
string projectPath = EditorTools.GetProjectPath();
|
||||
return $"{projectPath}/Bundles";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取构建管线的输出目录
|
||||
/// </summary>
|
||||
public static string MakePipelineOutputDirectory(string outputRoot, BuildTarget buildTarget)
|
||||
{
|
||||
return $"{outputRoot}/{buildTarget}/{YooAssetSettingsData.Setting.UnityManifestFileName}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清空流文件夹
|
||||
/// </summary>
|
||||
public static void ClearStreamingAssetsFolder()
|
||||
{
|
||||
string streamingPath = Application.dataPath + "/StreamingAssets";
|
||||
EditorTools.ClearFolder(streamingPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除流文件夹内无关的文件
|
||||
/// 删除.manifest文件和.meta文件
|
||||
/// </summary>
|
||||
public static void DeleteStreamingAssetsIgnoreFiles()
|
||||
{
|
||||
string streamingPath = Application.dataPath + "/StreamingAssets";
|
||||
if (Directory.Exists(streamingPath))
|
||||
{
|
||||
string[] files = Directory.GetFiles(streamingPath, "*.manifest", SearchOption.AllDirectories);
|
||||
foreach (var file in files)
|
||||
{
|
||||
FileInfo info = new FileInfo(file);
|
||||
info.Delete();
|
||||
}
|
||||
|
||||
files = Directory.GetFiles(streamingPath, "*.meta", SearchOption.AllDirectories);
|
||||
foreach (var item in files)
|
||||
{
|
||||
FileInfo info = new FileInfo(item);
|
||||
info.Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有补丁包版本列表
|
||||
/// 注意:列表会按照版本号从小到大排序
|
||||
/// </summary>
|
||||
private static List<int> GetPackageVersionList(BuildTarget buildTarget, string outputRoot)
|
||||
{
|
||||
List<int> versionList = new List<int>();
|
||||
|
||||
string parentPath = $"{outputRoot}/{buildTarget}";
|
||||
if (Directory.Exists(parentPath) == false)
|
||||
return versionList;
|
||||
|
||||
// 获取所有补丁包文件夹
|
||||
string[] allFolders = Directory.GetDirectories(parentPath);
|
||||
for (int i = 0; i < allFolders.Length; i++)
|
||||
{
|
||||
string folderName = Path.GetFileNameWithoutExtension(allFolders[i]);
|
||||
if (int.TryParse(folderName, out int version))
|
||||
versionList.Add(version);
|
||||
}
|
||||
|
||||
// 从小到大排序
|
||||
versionList.Sort();
|
||||
return versionList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前最大的补丁包版本号
|
||||
/// </summary>
|
||||
/// <returns>如果没有任何补丁版本,那么返回-1</returns>
|
||||
public static int GetMaxPackageVersion(BuildTarget buildTarget, string outputRoot)
|
||||
{
|
||||
List<int> versionList = GetPackageVersionList(buildTarget, outputRoot);
|
||||
if (versionList.Count == 0)
|
||||
return -1;
|
||||
return versionList[versionList.Count - 1];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否存在任何补丁包版本
|
||||
/// </summary>
|
||||
public static bool HasAnyPackageVersion(BuildTarget buildTarget, string outputRoot)
|
||||
{
|
||||
List<int> versionList = GetPackageVersionList(buildTarget, outputRoot);
|
||||
return versionList.Count > 0;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 从输出目录加载补丁清单文件
|
||||
/// </summary>
|
||||
internal static PatchManifest LoadPatchManifestFile(string fileDirectory)
|
||||
{
|
||||
string filePath = $"{fileDirectory}/{YooAssetSettingsData.Setting.PatchManifestFileName}";
|
||||
if (File.Exists(filePath) == false)
|
||||
{
|
||||
throw new System.Exception($"Not found patch manifest file : {filePath}");
|
||||
}
|
||||
|
||||
string jsonData = FileUtility.ReadFile(filePath);
|
||||
return PatchManifest.Deserialize(jsonData);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,215 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Animations;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public static class AssetBundleBuilderTools
|
||||
{
|
||||
/// <summary>
|
||||
/// 检测所有损坏的预制体文件
|
||||
/// </summary>
|
||||
public static void CheckCorruptionPrefab(List<string> searchDirectorys)
|
||||
{
|
||||
if (searchDirectorys.Count == 0)
|
||||
throw new Exception("路径列表不能为空!");
|
||||
|
||||
// 获取所有资源列表
|
||||
int checkCount = 0;
|
||||
int invalidCount = 0;
|
||||
string[] findAssets = EditorTools.FindAssets(EAssetSearchType.Prefab, searchDirectorys.ToArray());
|
||||
foreach (string assetPath in findAssets)
|
||||
{
|
||||
UnityEngine.Object prefab = AssetDatabase.LoadAssetAtPath(assetPath, typeof(UnityEngine.Object));
|
||||
if (prefab == null)
|
||||
{
|
||||
invalidCount++;
|
||||
Debug.LogError($"发现损坏预制件:{assetPath}");
|
||||
}
|
||||
EditorTools.DisplayProgressBar("检测预制件文件是否损坏", ++checkCount, findAssets.Length);
|
||||
}
|
||||
EditorTools.ClearProgressBar();
|
||||
|
||||
if (invalidCount == 0)
|
||||
Debug.Log($"没有发现损坏预制件");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测所有动画控制器的冗余状态
|
||||
/// </summary>
|
||||
public static void FindRedundantAnimationState(List<string> searchDirectorys)
|
||||
{
|
||||
if (searchDirectorys.Count == 0)
|
||||
throw new Exception("路径列表不能为空!");
|
||||
|
||||
// 获取所有资源列表
|
||||
int checkCount = 0;
|
||||
int findCount = 0;
|
||||
string[] findAssets = EditorTools.FindAssets(EAssetSearchType.RuntimeAnimatorController, searchDirectorys.ToArray());
|
||||
foreach (string assetPath in findAssets)
|
||||
{
|
||||
AnimatorController animator= AssetDatabase.LoadAssetAtPath<AnimatorController>(assetPath);
|
||||
if (FindRedundantAnimationState(animator))
|
||||
{
|
||||
findCount++;
|
||||
Debug.LogWarning($"发现冗余的动画控制器:{assetPath}");
|
||||
}
|
||||
EditorTools.DisplayProgressBar("检测冗余的动画控制器", ++checkCount, findAssets.Length);
|
||||
}
|
||||
EditorTools.ClearProgressBar();
|
||||
|
||||
if (findCount == 0)
|
||||
Debug.Log($"没有发现冗余的动画控制器");
|
||||
else
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理所有材质球的冗余属性
|
||||
/// </summary>
|
||||
public static void ClearMaterialUnusedProperty(List<string> searchDirectorys)
|
||||
{
|
||||
if (searchDirectorys.Count == 0)
|
||||
throw new Exception("路径列表不能为空!");
|
||||
|
||||
// 获取所有资源列表
|
||||
int checkCount = 0;
|
||||
int removedCount = 0;
|
||||
string[] findAssets = EditorTools.FindAssets(EAssetSearchType.Material, searchDirectorys.ToArray());
|
||||
foreach (string assetPath in findAssets)
|
||||
{
|
||||
Material mat = AssetDatabase.LoadAssetAtPath<Material>(assetPath);
|
||||
if (ClearMaterialUnusedProperty(mat))
|
||||
{
|
||||
removedCount++;
|
||||
Debug.LogWarning($"材质球已被处理:{assetPath}");
|
||||
}
|
||||
EditorTools.DisplayProgressBar("清理冗余的材质球", ++checkCount, findAssets.Length);
|
||||
}
|
||||
EditorTools.ClearProgressBar();
|
||||
|
||||
if (removedCount == 0)
|
||||
Debug.Log($"没有发现冗余的材质球");
|
||||
else
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 清理无用的材质球属性
|
||||
/// </summary>
|
||||
private static bool ClearMaterialUnusedProperty(Material mat)
|
||||
{
|
||||
bool removeUnused = false;
|
||||
SerializedObject so = new SerializedObject(mat);
|
||||
SerializedProperty sp = so.FindProperty("m_SavedProperties");
|
||||
|
||||
sp.Next(true);
|
||||
do
|
||||
{
|
||||
if (sp.isArray == false)
|
||||
continue;
|
||||
|
||||
for (int i = sp.arraySize - 1; i >= 0; --i)
|
||||
{
|
||||
var p1 = sp.GetArrayElementAtIndex(i);
|
||||
if (p1.isArray)
|
||||
{
|
||||
for (int ii = p1.arraySize - 1; ii >= 0; --ii)
|
||||
{
|
||||
var p2 = p1.GetArrayElementAtIndex(ii);
|
||||
var val = p2.FindPropertyRelative("first");
|
||||
if (mat.HasProperty(val.stringValue) == false)
|
||||
{
|
||||
Debug.Log($"Material {mat.name} remove unused property : {val.stringValue}");
|
||||
p1.DeleteArrayElementAtIndex(ii);
|
||||
removeUnused = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var val = p1.FindPropertyRelative("first");
|
||||
if (mat.HasProperty(val.stringValue) == false)
|
||||
{
|
||||
Debug.Log($"Material {mat.name} remove unused property : {val.stringValue}");
|
||||
sp.DeleteArrayElementAtIndex(i);
|
||||
removeUnused = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while (sp.Next(false));
|
||||
so.ApplyModifiedProperties();
|
||||
return removeUnused;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找动画控制器里冗余的动画状态机
|
||||
/// </summary>
|
||||
private static bool FindRedundantAnimationState(AnimatorController animatorController)
|
||||
{
|
||||
if (animatorController == null)
|
||||
return false;
|
||||
|
||||
string assetPath = AssetDatabase.GetAssetPath(animatorController);
|
||||
|
||||
// 查找使用的状态机名称
|
||||
List<string> usedStateNames = new List<string>();
|
||||
foreach (var layer in animatorController.layers)
|
||||
{
|
||||
foreach (var state in layer.stateMachine.states)
|
||||
{
|
||||
usedStateNames.Add(state.state.name);
|
||||
}
|
||||
}
|
||||
|
||||
List<string> allLines = new List<string>();
|
||||
List<int> stateIndexList = new List<int>();
|
||||
using (StreamReader reader = File.OpenText(assetPath))
|
||||
{
|
||||
string content;
|
||||
while (null != (content = reader.ReadLine()))
|
||||
{
|
||||
allLines.Add(content);
|
||||
if (content.StartsWith("AnimatorState:"))
|
||||
{
|
||||
stateIndexList.Add(allLines.Count - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<string> allStateNames = new List<string>();
|
||||
foreach (var index in stateIndexList)
|
||||
{
|
||||
for (int i = index; i < allLines.Count; i++)
|
||||
{
|
||||
string content = allLines[i];
|
||||
content = content.Trim();
|
||||
if (content.StartsWith("m_Name"))
|
||||
{
|
||||
string[] splits = content.Split(':');
|
||||
string name = splits[1].TrimStart(' '); //移除前面的空格
|
||||
allStateNames.Add(name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool foundRedundantState = false;
|
||||
foreach (var stateName in allStateNames)
|
||||
{
|
||||
if (usedStateNames.Contains(stateName) == false)
|
||||
{
|
||||
Debug.LogWarning($"发现冗余的动画文件:{assetPath}={stateName}");
|
||||
foundRedundantState = true;
|
||||
}
|
||||
}
|
||||
return foundRedundantState;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
#if UNITY_2019_4_OR_NEWER
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class AssetBundleBuilderWindow : EditorWindow
|
||||
{
|
||||
[MenuItem("YooAsset/AssetBundle Builder", false, 102)]
|
||||
public static void ShowExample()
|
||||
{
|
||||
AssetBundleBuilderWindow window = GetWindow<AssetBundleBuilderWindow>();
|
||||
window.titleContent = new GUIContent("资源包构建工具");
|
||||
window.minSize = new Vector2(800, 600);
|
||||
}
|
||||
|
||||
private BuildTarget _buildTarget;
|
||||
private List<Type> _encryptionServicesClassTypes;
|
||||
private List<string> _encryptionServicesClassNames;
|
||||
|
||||
private TextField _buildOutputTxt;
|
||||
private IntegerField _buildVersionField;
|
||||
private EnumField _compressionField;
|
||||
private PopupField<string> _encryptionField;
|
||||
private Toggle _appendExtensionToggle;
|
||||
private Toggle _forceRebuildToggle;
|
||||
private TextField _buildTagsTxt;
|
||||
|
||||
|
||||
public void CreateGUI()
|
||||
{
|
||||
VisualElement root = this.rootVisualElement;
|
||||
|
||||
// 加载布局文件
|
||||
string rootPath = EditorTools.GetYooAssetPath();
|
||||
string uxml = $"{rootPath}/Editor/AssetBundleBuilder/{nameof(AssetBundleBuilderWindow)}.uxml";
|
||||
var visualAsset = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(uxml);
|
||||
if (visualAsset == null)
|
||||
{
|
||||
Debug.LogError($"Not found {nameof(AssetBundleBuilderWindow)}.uxml : {uxml}");
|
||||
return;
|
||||
}
|
||||
visualAsset.CloneTree(root);
|
||||
|
||||
try
|
||||
{
|
||||
_buildTarget = EditorUserBuildSettings.activeBuildTarget;
|
||||
_encryptionServicesClassTypes = GetEncryptionServicesClassTypes();
|
||||
_encryptionServicesClassNames = _encryptionServicesClassTypes.Select(t => t.FullName).ToList();
|
||||
|
||||
// 输出目录
|
||||
string defaultOutputRoot = AssetBundleBuilderHelper.GetDefaultOutputRoot();
|
||||
string pipelineOutputDirectory = AssetBundleBuilderHelper.MakePipelineOutputDirectory(defaultOutputRoot, _buildTarget);
|
||||
_buildOutputTxt = root.Q<TextField>("BuildOutput");
|
||||
_buildOutputTxt.SetValueWithoutNotify(pipelineOutputDirectory);
|
||||
_buildOutputTxt.SetEnabled(false);
|
||||
|
||||
// 构建版本
|
||||
var appVersion = new Version(Application.version);
|
||||
_buildVersionField = root.Q<IntegerField>("BuildVersion");
|
||||
_buildVersionField.SetValueWithoutNotify(appVersion.Revision);
|
||||
|
||||
// 压缩方式
|
||||
_compressionField = root.Q<EnumField>("Compression");
|
||||
_compressionField.Init(ECompressOption.LZ4);
|
||||
_compressionField.SetValueWithoutNotify(ECompressOption.LZ4);
|
||||
_compressionField.style.width = 300;
|
||||
|
||||
// 加密方法
|
||||
var encryptionContainer = root.Q("EncryptionContainer");
|
||||
if (_encryptionServicesClassNames.Count > 0)
|
||||
{
|
||||
_encryptionField = new PopupField<string>(_encryptionServicesClassNames, 0);
|
||||
_encryptionField.label = "Encryption";
|
||||
_encryptionField.style.width = 300;
|
||||
encryptionContainer.Add(_encryptionField);
|
||||
}
|
||||
else
|
||||
{
|
||||
_encryptionField = new PopupField<string>();
|
||||
_encryptionField.label = "Encryption";
|
||||
_encryptionField.style.width = 300;
|
||||
encryptionContainer.Add(_encryptionField);
|
||||
}
|
||||
|
||||
// 附加后缀格式
|
||||
_appendExtensionToggle = root.Q<Toggle>("AppendExtension");
|
||||
|
||||
// 强制构建
|
||||
_forceRebuildToggle = root.Q<Toggle>("ForceRebuild");
|
||||
_forceRebuildToggle.SetValueWithoutNotify(true);
|
||||
_forceRebuildToggle.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
_buildTagsTxt.SetEnabled(_forceRebuildToggle.value);
|
||||
});
|
||||
|
||||
// 内置标签
|
||||
_buildTagsTxt = root.Q<TextField>("BuildinTags");
|
||||
_buildTagsTxt.SetEnabled(_forceRebuildToggle.value);
|
||||
|
||||
// 构建按钮
|
||||
var buildButton = root.Q<Button>("Build");
|
||||
buildButton.clicked += BuildButton_clicked; ;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError(e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private void BuildButton_clicked()
|
||||
{
|
||||
string title;
|
||||
string content;
|
||||
if (_forceRebuildToggle.value)
|
||||
{
|
||||
title = "警告";
|
||||
content = "确定开始强制构建吗,这样会删除所有已有构建的文件";
|
||||
}
|
||||
else
|
||||
{
|
||||
title = "提示";
|
||||
content = "确定开始增量构建吗";
|
||||
}
|
||||
if (EditorUtility.DisplayDialog(title, content, "Yes", "No"))
|
||||
{
|
||||
EditorTools.ClearUnityConsole();
|
||||
EditorApplication.delayCall += ExecuteBuild;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("[Build] 打包已经取消");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行构建
|
||||
/// </summary>
|
||||
private void ExecuteBuild()
|
||||
{
|
||||
string defaultOutputRoot = AssetBundleBuilderHelper.GetDefaultOutputRoot();
|
||||
BuildParameters buildParameters = new BuildParameters();
|
||||
buildParameters.VerifyBuildingResult = true;
|
||||
buildParameters.OutputRoot = defaultOutputRoot;
|
||||
buildParameters.BuildTarget = _buildTarget;
|
||||
buildParameters.BuildVersion = _buildVersionField.value;
|
||||
buildParameters.CompressOption = (ECompressOption)_compressionField.value;
|
||||
buildParameters.AppendFileExtension = _appendExtensionToggle.value;
|
||||
buildParameters.EncryptionServices = CreateEncryptionServicesInstance();
|
||||
buildParameters.ForceRebuild = _forceRebuildToggle.value;
|
||||
buildParameters.BuildinTags = _buildTagsTxt.value;
|
||||
|
||||
AssetBundleBuilder builder = new AssetBundleBuilder();
|
||||
builder.Run(buildParameters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取加密类的类型列表
|
||||
/// </summary>
|
||||
private List<Type> GetEncryptionServicesClassTypes()
|
||||
{
|
||||
List<Type> classTypes = AssemblyUtility.GetAssignableTypes(AssemblyUtility.UnityDefaultAssemblyEditorName, typeof(IEncryptionServices));
|
||||
return classTypes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建加密类的实例
|
||||
/// </summary>
|
||||
private IEncryptionServices CreateEncryptionServicesInstance()
|
||||
{
|
||||
if (_encryptionField.index < 0)
|
||||
return null;
|
||||
var classType = _encryptionServicesClassTypes[_encryptionField.index];
|
||||
return (IEncryptionServices)Activator.CreateInstance(classType);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,13 +0,0 @@
|
||||
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd" editor-extension-mode="True">
|
||||
<uie:Toolbar name="Toolbar" style="display: flex;" />
|
||||
<ui:VisualElement name="BuildContainer">
|
||||
<ui:TextField picking-mode="Ignore" label="Build Output" name="BuildOutput" />
|
||||
<uie:IntegerField label="Build Version" value="0" name="BuildVersion" />
|
||||
<uie:EnumField label="Compression" value="Center" name="Compression" />
|
||||
<ui:VisualElement name="EncryptionContainer" style="height: 24px;" />
|
||||
<ui:Toggle label="Append Extension" name="AppendExtension" style="height: 15px;" />
|
||||
<ui:Toggle label="Force Rebuild" name="ForceRebuild" />
|
||||
<ui:TextField picking-mode="Ignore" label="Buildin Tags" name="BuildinTags" />
|
||||
<ui:Button text="构建" display-tooltip-when-elided="true" name="Build" style="height: 50px; background-color: rgb(40, 106, 42); margin-top: 10px;" />
|
||||
</ui:VisualElement>
|
||||
</ui:UXML>
|
||||
@@ -1,121 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class BuildAssetInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 资源包名称
|
||||
/// </summary>
|
||||
public string BundleName { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 资源路径
|
||||
/// </summary>
|
||||
public string AssetPath { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否为原生资源
|
||||
/// </summary>
|
||||
public bool IsRawAsset { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 不写入资源列表
|
||||
/// </summary>
|
||||
public bool NotWriteToAssetList { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否为主动收集资源
|
||||
/// </summary>
|
||||
public bool IsCollectAsset { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 被依赖次数
|
||||
/// </summary>
|
||||
public int DependCount = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 资源分类标签列表
|
||||
/// </summary>
|
||||
public readonly List<string> AssetTags = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// 依赖的所有资源
|
||||
/// 注意:包括零依赖资源和冗余资源(资源包名无效)
|
||||
/// </summary>
|
||||
public List<BuildAssetInfo> AllDependAssetInfos { private set; get; }
|
||||
|
||||
|
||||
public BuildAssetInfo(string assetPath, bool isRawAsset, bool notWriteToAssetList)
|
||||
{
|
||||
AssetPath = assetPath;
|
||||
IsRawAsset = isRawAsset;
|
||||
NotWriteToAssetList = notWriteToAssetList;
|
||||
IsCollectAsset = true;
|
||||
}
|
||||
public BuildAssetInfo(string assetPath)
|
||||
{
|
||||
AssetPath = assetPath;
|
||||
IsRawAsset = false;
|
||||
NotWriteToAssetList = true;
|
||||
IsCollectAsset = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置所有依赖的资源
|
||||
/// </summary>
|
||||
public void SetAllDependAssetInfos(List<BuildAssetInfo> dependAssetInfos)
|
||||
{
|
||||
if (AllDependAssetInfos != null)
|
||||
throw new System.Exception("Should never get here !");
|
||||
|
||||
AllDependAssetInfos = dependAssetInfos;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置资源包名称
|
||||
/// </summary>
|
||||
public void SetBundleName(string bundleName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(BundleName) == false)
|
||||
throw new System.Exception("Should never get here !");
|
||||
|
||||
BundleName = bundleName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加资源分类标签
|
||||
/// </summary>
|
||||
public void AddAssetTags(List<string> tags)
|
||||
{
|
||||
foreach (var tag in tags)
|
||||
{
|
||||
AddAssetTag(tag);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加资源分类标签
|
||||
/// </summary>
|
||||
public void AddAssetTag(string tag)
|
||||
{
|
||||
if (AssetTags.Contains(tag) == false)
|
||||
{
|
||||
AssetTags.Add(tag);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 资源包名称是否有效
|
||||
/// </summary>
|
||||
public bool BundleNameIsValid()
|
||||
{
|
||||
if (string.IsNullOrEmpty(BundleName))
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class BuildBundleInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 资源包名称
|
||||
/// </summary>
|
||||
public string BundleName { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 参与构建的资源列表
|
||||
/// 注意:不包含零依赖资源
|
||||
/// </summary>
|
||||
public readonly List<BuildAssetInfo> BuildinAssets = new List<BuildAssetInfo>();
|
||||
|
||||
/// <summary>
|
||||
/// 是否为原生文件
|
||||
/// </summary>
|
||||
public bool IsRawFile
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var asset in BuildinAssets)
|
||||
{
|
||||
if (asset.IsRawAsset)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public BuildBundleInfo(string bundleName)
|
||||
{
|
||||
BundleName = bundleName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加一个打包资源
|
||||
/// </summary>
|
||||
public void PackAsset(BuildAssetInfo assetInfo)
|
||||
{
|
||||
if (IsContainsAsset(assetInfo.AssetPath))
|
||||
throw new System.Exception($"Asset is existed : {assetInfo.AssetPath}");
|
||||
|
||||
BuildinAssets.Add(assetInfo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否包含指定资源
|
||||
/// </summary>
|
||||
public bool IsContainsAsset(string assetPath)
|
||||
{
|
||||
foreach (var assetInfo in BuildinAssets)
|
||||
{
|
||||
if (assetInfo.AssetPath == assetPath)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源标签列表
|
||||
/// </summary>
|
||||
public string[] GetAssetTags()
|
||||
{
|
||||
List<string> result = new List<string>(BuildinAssets.Count);
|
||||
foreach (var assetInfo in BuildinAssets)
|
||||
{
|
||||
foreach (var assetTag in assetInfo.AssetTags)
|
||||
{
|
||||
if (result.Contains(assetTag) == false)
|
||||
result.Add(assetTag);
|
||||
}
|
||||
}
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取文件的扩展名
|
||||
/// </summary>
|
||||
public string GetAppendExtension()
|
||||
{
|
||||
if (IsRawFile)
|
||||
return $".{YooAssetSettingsData.Setting.RawFileVariant}";
|
||||
else
|
||||
return $".{YooAssetSettingsData.Setting.AssetBundleFileVariant}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取构建的资源路径列表
|
||||
/// </summary>
|
||||
public string[] GetBuildinAssetPaths()
|
||||
{
|
||||
return BuildinAssets.Select(t => t.AssetPath).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有写入补丁清单的资源
|
||||
/// </summary>
|
||||
public BuildAssetInfo[] GetAllPatchAssetInfos()
|
||||
{
|
||||
return BuildinAssets.Where(t => t.IsCollectAsset && t.NotWriteToAssetList == false).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建AssetBundleBuild类
|
||||
/// </summary>
|
||||
public UnityEditor.AssetBundleBuild CreatePipelineBuild()
|
||||
{
|
||||
// 注意:我们不在支持AssetBundle的变种机制
|
||||
AssetBundleBuild build = new AssetBundleBuild();
|
||||
build.assetBundleName = BundleName;
|
||||
build.assetBundleVariant = string.Empty;
|
||||
build.assetNames = GetBuildinAssetPaths();
|
||||
return build;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class BuildMapContext : IContextObject
|
||||
{
|
||||
/// <summary>
|
||||
/// 参与构建的资源总数
|
||||
/// 说明:包括主动收集的资源以及其依赖的所有资源
|
||||
/// </summary>
|
||||
public int AssetFileCount;
|
||||
|
||||
/// <summary>
|
||||
/// 资源包列表
|
||||
/// </summary>
|
||||
public readonly List<BuildBundleInfo> BundleInfos = new List<BuildBundleInfo>(1000);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 添加一个打包资源
|
||||
/// </summary>
|
||||
public void PackAsset(BuildAssetInfo assetInfo)
|
||||
{
|
||||
if (TryGetBundleInfo(assetInfo.BundleName, out BuildBundleInfo bundleInfo))
|
||||
{
|
||||
bundleInfo.PackAsset(assetInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
BuildBundleInfo newBundleInfo = new BuildBundleInfo(assetInfo.BundleName);
|
||||
newBundleInfo.PackAsset(assetInfo);
|
||||
BundleInfos.Add(newBundleInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有的打包资源
|
||||
/// </summary>
|
||||
public List<BuildAssetInfo> GetAllAssets()
|
||||
{
|
||||
List<BuildAssetInfo> result = new List<BuildAssetInfo>(BundleInfos.Count);
|
||||
foreach (var bundleInfo in BundleInfos)
|
||||
{
|
||||
result.AddRange(bundleInfo.BuildinAssets);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取AssetBundle内包含的标记列表
|
||||
/// </summary>
|
||||
public string[] GetAssetTags(string bundleName)
|
||||
{
|
||||
if (TryGetBundleInfo(bundleName, out BuildBundleInfo bundleInfo))
|
||||
{
|
||||
return bundleInfo.GetAssetTags();
|
||||
}
|
||||
throw new Exception($"Not found {nameof(BuildBundleInfo)} : {bundleName}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取AssetBundle内构建的资源路径列表
|
||||
/// </summary>
|
||||
public string[] GetBuildinAssetPaths(string bundleName)
|
||||
{
|
||||
if (TryGetBundleInfo(bundleName, out BuildBundleInfo bundleInfo))
|
||||
{
|
||||
return bundleInfo.GetBuildinAssetPaths();
|
||||
}
|
||||
throw new Exception($"Not found {nameof(BuildBundleInfo)} : {bundleName}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取构建管线里需要的数据
|
||||
/// </summary>
|
||||
public UnityEditor.AssetBundleBuild[] GetPipelineBuilds()
|
||||
{
|
||||
List<UnityEditor.AssetBundleBuild> builds = new List<UnityEditor.AssetBundleBuild>(BundleInfos.Count);
|
||||
foreach (var bundleInfo in BundleInfos)
|
||||
{
|
||||
if (bundleInfo.IsRawFile == false)
|
||||
builds.Add(bundleInfo.CreatePipelineBuild());
|
||||
}
|
||||
return builds.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否包含资源包
|
||||
/// </summary>
|
||||
public bool IsContainsBundle(string bundleName)
|
||||
{
|
||||
return TryGetBundleInfo(bundleName, out BuildBundleInfo bundleInfo);
|
||||
}
|
||||
|
||||
public bool TryGetBundleInfo(string bundleName, out BuildBundleInfo result)
|
||||
{
|
||||
foreach (var bundleInfo in BundleInfos)
|
||||
{
|
||||
if (bundleInfo.BundleName == bundleName)
|
||||
{
|
||||
result = bundleInfo;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public static class BuildMapHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 执行资源构建上下文
|
||||
/// </summary>
|
||||
public static BuildMapContext SetupBuildMap()
|
||||
{
|
||||
BuildMapContext context = new BuildMapContext();
|
||||
Dictionary<string, BuildAssetInfo> buildAssetDic = new Dictionary<string, BuildAssetInfo>();
|
||||
|
||||
// 0. 检测配置合法性
|
||||
AssetBundleGrouperSettingData.Setting.CheckConfigError();
|
||||
|
||||
// 1. 获取主动收集的资源
|
||||
List<CollectAssetInfo> collectAssetInfos = AssetBundleGrouperSettingData.Setting.GetAllCollectAssets();
|
||||
|
||||
// 2. 录入主动收集的资源
|
||||
foreach (var collectAssetInfo in collectAssetInfos)
|
||||
{
|
||||
if (buildAssetDic.ContainsKey(collectAssetInfo.AssetPath) == false)
|
||||
{
|
||||
var buildAssetInfo = new BuildAssetInfo(collectAssetInfo.AssetPath, collectAssetInfo.IsRawAsset, collectAssetInfo.NotWriteToAssetList);
|
||||
buildAssetInfo.SetBundleName(collectAssetInfo.BundleName);
|
||||
buildAssetInfo.AddAssetTags(collectAssetInfo.AssetTags);
|
||||
buildAssetDic.Add(collectAssetInfo.AssetPath, buildAssetInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"Should never get here !");
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 录入并分析依赖资源
|
||||
foreach (var collectAssetInfo in collectAssetInfos)
|
||||
{
|
||||
foreach (var dependAssetPath in collectAssetInfo.DependAssets)
|
||||
{
|
||||
if (buildAssetDic.ContainsKey(dependAssetPath))
|
||||
{
|
||||
buildAssetDic[dependAssetPath].DependCount++;
|
||||
buildAssetDic[dependAssetPath].AddAssetTags(collectAssetInfo.AssetTags);
|
||||
}
|
||||
else
|
||||
{
|
||||
var buildAssetInfo = new BuildAssetInfo(dependAssetPath);
|
||||
buildAssetInfo.AddAssetTags(collectAssetInfo.AssetTags);
|
||||
buildAssetDic.Add(dependAssetPath, buildAssetInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
context.AssetFileCount = buildAssetDic.Count;
|
||||
|
||||
// 4. 设置主动收集资源的依赖列表
|
||||
foreach (var collectAssetInfo in collectAssetInfos)
|
||||
{
|
||||
var dependAssetInfos = new List<BuildAssetInfo>(collectAssetInfo.DependAssets.Count);
|
||||
foreach (var dependAssetPath in collectAssetInfo.DependAssets)
|
||||
{
|
||||
if (buildAssetDic.TryGetValue(dependAssetPath, out BuildAssetInfo value))
|
||||
dependAssetInfos.Add(value);
|
||||
else
|
||||
throw new Exception("Should never get here !");
|
||||
}
|
||||
buildAssetDic[collectAssetInfo.AssetPath].SetAllDependAssetInfos(dependAssetInfos);
|
||||
}
|
||||
|
||||
// 5. 移除零依赖的资源
|
||||
List<BuildAssetInfo> removeList = new List<BuildAssetInfo>();
|
||||
foreach (KeyValuePair<string, BuildAssetInfo> pair in buildAssetDic)
|
||||
{
|
||||
var buildAssetInfo = pair.Value;
|
||||
if (buildAssetInfo.IsCollectAsset)
|
||||
continue;
|
||||
if (buildAssetInfo.DependCount == 0)
|
||||
removeList.Add(buildAssetInfo);
|
||||
}
|
||||
foreach (var removeValue in removeList)
|
||||
{
|
||||
buildAssetDic.Remove(removeValue.AssetPath);
|
||||
}
|
||||
|
||||
// 6. 设置未命名的资源包
|
||||
IPackRule defaultPackRule = new PackDirectory();
|
||||
foreach (KeyValuePair<string, BuildAssetInfo> pair in buildAssetDic)
|
||||
{
|
||||
var buildAssetInfo = pair.Value;
|
||||
if (buildAssetInfo.BundleNameIsValid() == false)
|
||||
{
|
||||
string bundleName = defaultPackRule.GetBundleName(new PackRuleData(buildAssetInfo.AssetPath));
|
||||
bundleName = AssetBundleCollector.RevisedBundleName(bundleName);
|
||||
buildAssetInfo.SetBundleName(bundleName);
|
||||
}
|
||||
}
|
||||
|
||||
// 7. 构建资源包
|
||||
var allBuildAssets = buildAssetDic.Values.ToList();
|
||||
if (allBuildAssets.Count == 0)
|
||||
throw new Exception("构建的资源列表不能为空");
|
||||
foreach (var assetInfo in allBuildAssets)
|
||||
{
|
||||
context.PackAsset(assetInfo);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 构建参数
|
||||
/// </summary>
|
||||
public class BuildParameters
|
||||
{
|
||||
/// <summary>
|
||||
/// 验证构建结果
|
||||
/// </summary>
|
||||
public bool VerifyBuildingResult = false;
|
||||
|
||||
/// <summary>
|
||||
/// 输出的根目录
|
||||
/// </summary>
|
||||
public string OutputRoot;
|
||||
|
||||
/// <summary>
|
||||
/// 构建的平台
|
||||
/// </summary>
|
||||
public BuildTarget BuildTarget;
|
||||
|
||||
/// <summary>
|
||||
/// 构建的版本(资源版本号)
|
||||
/// </summary>
|
||||
public int BuildVersion;
|
||||
|
||||
/// <summary>
|
||||
/// 启用自动分包机制
|
||||
/// 说明:自动分包机制可以实现资源零冗余
|
||||
/// </summary>
|
||||
public bool EnableAutoCollect = true;
|
||||
|
||||
/// <summary>
|
||||
/// 追加文件扩展名
|
||||
/// </summary>
|
||||
public bool AppendFileExtension = false;
|
||||
|
||||
/// <summary>
|
||||
/// 加密类
|
||||
/// </summary>
|
||||
public IEncryptionServices EncryptionServices;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 强制重新构建整个项目,如果为FALSE则是增量打包
|
||||
/// </summary>
|
||||
public bool ForceRebuild;
|
||||
|
||||
/// <summary>
|
||||
/// 内置资源的标记列表
|
||||
/// 注意:分号为分隔符
|
||||
/// </summary>
|
||||
public string BuildinTags;
|
||||
|
||||
/// <summary>
|
||||
/// 压缩选项
|
||||
/// </summary>
|
||||
public ECompressOption CompressOption;
|
||||
|
||||
/// <summary>
|
||||
/// 文件名附加上哈希值
|
||||
/// </summary>
|
||||
public bool AppendHash = false;
|
||||
|
||||
/// <summary>
|
||||
/// 禁止写入类型树结构(可以降低包体和内存并提高加载效率)
|
||||
/// </summary>
|
||||
public bool DisableWriteTypeTree = false;
|
||||
|
||||
/// <summary>
|
||||
/// 忽略类型树变化
|
||||
/// </summary>
|
||||
public bool IgnoreTypeTreeChanges = true;
|
||||
|
||||
/// <summary>
|
||||
/// 禁用名称查找资源(可以降内存并提高加载效率)
|
||||
/// </summary>
|
||||
public bool DisableLoadAssetByFileName = false;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取内置标记列表
|
||||
/// </summary>
|
||||
public List<string> GetBuildinTags()
|
||||
{
|
||||
return StringUtility.StringToStringList(BuildinTags, ';');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 构建报告
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class BuildReport
|
||||
{
|
||||
/// <summary>
|
||||
/// 汇总信息
|
||||
/// </summary>
|
||||
public ReportSummary Summary = new ReportSummary();
|
||||
|
||||
/// <summary>
|
||||
/// 资源对象列表
|
||||
/// </summary>
|
||||
public List<ReportAssetInfo> AssetInfos = new List<ReportAssetInfo>();
|
||||
|
||||
/// <summary>
|
||||
/// 资源包列表
|
||||
/// </summary>
|
||||
public List<ReportBundleInfo> BundleInfos = new List<ReportBundleInfo>();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源包信息类
|
||||
/// </summary>
|
||||
public ReportBundleInfo GetBundleInfo(string bundleName)
|
||||
{
|
||||
foreach (var bundleInfo in BundleInfos)
|
||||
{
|
||||
if (bundleInfo.BundleName == bundleName)
|
||||
return bundleInfo;
|
||||
}
|
||||
throw new Exception($"Not found bundle : {bundleName}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源信息类
|
||||
/// </summary>
|
||||
public ReportAssetInfo GetAssetInfo(string assetPath)
|
||||
{
|
||||
foreach (var assetInfo in AssetInfos)
|
||||
{
|
||||
if (assetInfo.AssetPath == assetPath)
|
||||
return assetInfo;
|
||||
}
|
||||
throw new Exception($"Not found asset : {assetPath}");
|
||||
}
|
||||
|
||||
|
||||
public static void Serialize(string savePath, BuildReport buildReport)
|
||||
{
|
||||
string json = JsonUtility.ToJson(buildReport, true);
|
||||
FileUtility.CreateFile(savePath, json);
|
||||
}
|
||||
public static BuildReport Deserialize(string jsonData)
|
||||
{
|
||||
BuildReport report = JsonUtility.FromJson<BuildReport>(jsonData);
|
||||
return report;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
[Serializable]
|
||||
public class ReportAssetInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 资源路径
|
||||
/// </summary>
|
||||
public string AssetPath;
|
||||
|
||||
/// <summary>
|
||||
/// 所属资源包名称
|
||||
/// </summary>
|
||||
public string MainBundle;
|
||||
|
||||
/// <summary>
|
||||
/// 依赖的资源包名称列表
|
||||
/// </summary>
|
||||
public List<string> DependBundles = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// 依赖的资源路径列表
|
||||
/// </summary>
|
||||
public List<string> DependAssets = new List<string>();
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
[Serializable]
|
||||
public class ReportBundleInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 资源包名称
|
||||
/// </summary>
|
||||
public string BundleName;
|
||||
|
||||
/// <summary>
|
||||
/// 哈希值
|
||||
/// </summary>
|
||||
public string Hash;
|
||||
|
||||
/// <summary>
|
||||
/// 文件校验码
|
||||
/// </summary>
|
||||
public string CRC;
|
||||
|
||||
/// <summary>
|
||||
/// 文件大小(字节数)
|
||||
/// </summary>
|
||||
public long SizeBytes;
|
||||
|
||||
/// <summary>
|
||||
/// 文件版本
|
||||
/// </summary>
|
||||
public int Version;
|
||||
|
||||
/// <summary>
|
||||
/// Tags
|
||||
/// </summary>
|
||||
public string[] Tags;
|
||||
|
||||
/// <summary>
|
||||
/// Flags
|
||||
/// </summary>
|
||||
public int Flags;
|
||||
}
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
[Serializable]
|
||||
public class ReportSummary
|
||||
{
|
||||
/// <summary>
|
||||
/// 引擎版本
|
||||
/// </summary>
|
||||
public string UnityVersion;
|
||||
|
||||
/// <summary>
|
||||
/// 构建时间
|
||||
/// </summary>
|
||||
public string BuildTime;
|
||||
|
||||
/// <summary>
|
||||
/// 构建耗时(单位:秒)
|
||||
/// </summary>
|
||||
public int BuildSeconds;
|
||||
|
||||
/// <summary>
|
||||
/// 构建平台
|
||||
/// </summary>
|
||||
public BuildTarget BuildTarget;
|
||||
|
||||
/// <summary>
|
||||
/// 构建版本
|
||||
/// </summary>
|
||||
public int BuildVersion;
|
||||
|
||||
/// <summary>
|
||||
/// 启用自动分包机制
|
||||
/// </summary>
|
||||
public bool EnableAutoCollect;
|
||||
|
||||
/// <summary>
|
||||
/// 追加文件扩展名
|
||||
/// </summary>
|
||||
public bool AppendFileExtension;
|
||||
|
||||
/// <summary>
|
||||
/// 自动收集着色器
|
||||
/// </summary>
|
||||
public bool AutoCollectShaders;
|
||||
|
||||
/// <summary>
|
||||
/// 自动收集的着色器资源包名称
|
||||
/// </summary>
|
||||
public string ShadersBundleName;
|
||||
|
||||
/// <summary>
|
||||
/// 加密服务类名称
|
||||
/// </summary>
|
||||
public string EncryptionServicesClassName;
|
||||
|
||||
// 构建参数
|
||||
public bool ForceRebuild;
|
||||
public string BuildinTags;
|
||||
public ECompressOption CompressOption;
|
||||
public bool AppendHash;
|
||||
public bool DisableWriteTypeTree;
|
||||
public bool IgnoreTypeTreeChanges;
|
||||
public bool DisableLoadAssetByFileName;
|
||||
|
||||
// 构建结果
|
||||
public int AssetFileTotalCount;
|
||||
public int AllBundleTotalCount;
|
||||
public long AllBundleTotalSize;
|
||||
public int BuildinBundleTotalCount;
|
||||
public long BuildinBundleTotalSize;
|
||||
public int EncryptedBundleTotalCount;
|
||||
public long EncryptedBundleTotalSize;
|
||||
public int RawBundleTotalCount;
|
||||
public long RawBundleTotalSize;
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class BuildContext
|
||||
{
|
||||
private readonly Dictionary<System.Type, IContextObject> _contextObjects = new Dictionary<System.Type, IContextObject>();
|
||||
|
||||
/// <summary>
|
||||
/// 清空所有情景对象
|
||||
/// </summary>
|
||||
public void ClearAllContext()
|
||||
{
|
||||
_contextObjects.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置情景对象
|
||||
/// </summary>
|
||||
public void SetContextObject(IContextObject contextObject)
|
||||
{
|
||||
if (contextObject == null)
|
||||
throw new ArgumentNullException("contextObject");
|
||||
|
||||
var type = contextObject.GetType();
|
||||
if (_contextObjects.ContainsKey(type))
|
||||
throw new Exception($"Context object {type} is already existed.");
|
||||
|
||||
_contextObjects.Add(type, contextObject);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取情景对象
|
||||
/// </summary>
|
||||
public T GetContextObject<T>() where T : IContextObject
|
||||
{
|
||||
var type = typeof(T);
|
||||
if (_contextObjects.TryGetValue(type, out IContextObject contextObject))
|
||||
{
|
||||
return (T)contextObject;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"Not found context object : {type}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class BuildRunner
|
||||
{
|
||||
/// <summary>
|
||||
/// 执行构建流程
|
||||
/// </summary>
|
||||
/// <returns>如果成功返回TRUE,否则返回FALSE</returns>
|
||||
public static bool Run(List<IBuildTask> pipeline, BuildContext context)
|
||||
{
|
||||
if (pipeline == null)
|
||||
throw new ArgumentNullException("pipeline");
|
||||
if (context == null)
|
||||
throw new ArgumentNullException("context");
|
||||
|
||||
bool succeed = true;
|
||||
for (int i = 0; i < pipeline.Count; i++)
|
||||
{
|
||||
IBuildTask task = pipeline[i];
|
||||
try
|
||||
{
|
||||
task.Run(context);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"Build task {task.GetType().Name} failed : {e}");
|
||||
succeed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 返回运行结果
|
||||
return succeed;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public interface IBuildTask
|
||||
{
|
||||
void Run(BuildContext context);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public interface IContextObject
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,194 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class TaskBuilding : IBuildTask
|
||||
{
|
||||
public class UnityManifestContext : IContextObject
|
||||
{
|
||||
public AssetBundleManifest UnityManifest;
|
||||
}
|
||||
|
||||
void IBuildTask.Run(BuildContext context)
|
||||
{
|
||||
var buildParametersContext = context.GetContextObject<AssetBundleBuilder.BuildParametersContext>();
|
||||
var buildMapContext = context.GetContextObject<BuildMapContext>();
|
||||
|
||||
Debug.Log($"开始构建......");
|
||||
BuildAssetBundleOptions opt = buildParametersContext.GetPipelineBuildOptions();
|
||||
AssetBundleManifest unityManifest = BuildPipeline.BuildAssetBundles(buildParametersContext.PipelineOutputDirectory, buildMapContext.GetPipelineBuilds(), opt, buildParametersContext.Parameters.BuildTarget);
|
||||
if (unityManifest == null)
|
||||
throw new Exception("构建过程中发生错误!");
|
||||
|
||||
UnityManifestContext unityManifestContext = new UnityManifestContext();
|
||||
unityManifestContext.UnityManifest = unityManifest;
|
||||
context.SetContextObject(unityManifestContext);
|
||||
|
||||
// 拷贝原生文件
|
||||
foreach (var bundleInfo in buildMapContext.BundleInfos)
|
||||
{
|
||||
if (bundleInfo.IsRawFile)
|
||||
{
|
||||
string dest = $"{buildParametersContext.PipelineOutputDirectory}/{bundleInfo.BundleName}";
|
||||
foreach(var buildAsset in bundleInfo.BuildinAssets)
|
||||
{
|
||||
if(buildAsset.IsRawAsset)
|
||||
EditorTools.CopyFile(buildAsset.AssetPath, dest, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 验证构建结果
|
||||
if (buildParametersContext.Parameters.VerifyBuildingResult)
|
||||
{
|
||||
VerifyingBuildingResult(context, unityManifest);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证构建结果
|
||||
/// </summary>
|
||||
private void VerifyingBuildingResult(BuildContext context, AssetBundleManifest unityManifest)
|
||||
{
|
||||
var buildParameters = context.GetContextObject<AssetBundleBuilder.BuildParametersContext>();
|
||||
var buildMapContext = context.GetContextObject<BuildMapContext>();
|
||||
string[] buildedBundles = unityManifest.GetAllAssetBundles();
|
||||
|
||||
// 1. 过滤掉原生Bundle
|
||||
List<BuildBundleInfo> expectBundles = new List<BuildBundleInfo>(buildedBundles.Length);
|
||||
foreach(var bundleInfo in buildMapContext.BundleInfos)
|
||||
{
|
||||
if (bundleInfo.IsRawFile == false)
|
||||
expectBundles.Add(bundleInfo);
|
||||
}
|
||||
|
||||
// 2. 验证数量
|
||||
if (buildedBundles.Length != expectBundles.Count)
|
||||
{
|
||||
Debug.LogWarning($"构建过程中可能存在无效的资源,导致和预期构建的Bundle数量不一致!");
|
||||
}
|
||||
|
||||
// 3. 正向验证Bundle
|
||||
foreach (var bundleName in buildedBundles)
|
||||
{
|
||||
if (buildMapContext.IsContainsBundle(bundleName) == false)
|
||||
{
|
||||
throw new Exception($"Should never get here !");
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 反向验证Bundle
|
||||
bool isPass = true;
|
||||
foreach (var expectBundle in expectBundles)
|
||||
{
|
||||
bool isMatch = false;
|
||||
foreach (var buildedBundle in buildedBundles)
|
||||
{
|
||||
if (buildedBundle == expectBundle.BundleName)
|
||||
{
|
||||
isMatch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isMatch == false)
|
||||
{
|
||||
isPass = false;
|
||||
Debug.LogWarning($"没有找到预期构建的Bundle文件 : {expectBundle.BundleName}");
|
||||
}
|
||||
}
|
||||
if(isPass == false)
|
||||
{
|
||||
throw new Exception("构建结果验证没有通过,请参考警告日志!");
|
||||
}
|
||||
|
||||
// 5. 验证Asset
|
||||
int progressValue = 0;
|
||||
foreach (var buildedBundle in buildedBundles)
|
||||
{
|
||||
string filePath = $"{buildParameters.PipelineOutputDirectory}/{buildedBundle}";
|
||||
string[] allBuildinAssetPaths = GetAssetBundleAllAssets(filePath);
|
||||
string[] expectBuildinAssetPaths = buildMapContext.GetBuildinAssetPaths(buildedBundle);
|
||||
if (expectBuildinAssetPaths.Length != allBuildinAssetPaths.Length)
|
||||
{
|
||||
Debug.LogWarning($"构建的Bundle文件内的资源对象数量和预期不匹配 : {buildedBundle}");
|
||||
isPass = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var buildinAssetPath in allBuildinAssetPaths)
|
||||
{
|
||||
var guid = AssetDatabase.AssetPathToGUID(buildinAssetPath);
|
||||
if (string.IsNullOrEmpty(guid))
|
||||
{
|
||||
Debug.LogWarning($"无效的资源路径,请检查路径是否带有特殊符号或中文:{buildinAssetPath}");
|
||||
isPass = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
bool isMatch = false;
|
||||
foreach (var exceptBuildAssetPath in expectBuildinAssetPaths)
|
||||
{
|
||||
var guidExcept = AssetDatabase.AssetPathToGUID(exceptBuildAssetPath);
|
||||
if (guid == guidExcept)
|
||||
{
|
||||
isMatch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isMatch == false)
|
||||
{
|
||||
Debug.LogWarning($"在构建的Bundle文件里发现了没有匹配的资源对象:{buildinAssetPath}");
|
||||
isPass = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
EditorTools.DisplayProgressBar("验证构建结果", ++progressValue, buildedBundles.Length);
|
||||
}
|
||||
EditorTools.ClearProgressBar();
|
||||
if (isPass == false)
|
||||
{
|
||||
throw new Exception("构建结果验证没有通过,请参考警告日志!");
|
||||
}
|
||||
|
||||
// 卸载所有加载的Bundle
|
||||
Debug.Log("构建结果验证成功!");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析.manifest文件并获取资源列表
|
||||
/// </summary>
|
||||
private string[] GetAssetBundleAllAssets(string filePath)
|
||||
{
|
||||
string manifestFilePath = $"{filePath}.manifest";
|
||||
List<string> assetLines = new List<string>();
|
||||
using (StreamReader reader = File.OpenText(manifestFilePath))
|
||||
{
|
||||
string content;
|
||||
bool findTarget = false;
|
||||
while (null != (content = reader.ReadLine()))
|
||||
{
|
||||
if (content.StartsWith("Dependencies:"))
|
||||
break;
|
||||
if (findTarget == false && content.StartsWith("Assets:"))
|
||||
findTarget = true;
|
||||
if (findTarget)
|
||||
{
|
||||
if (content.StartsWith("- "))
|
||||
{
|
||||
string assetPath = content.TrimStart("- ".ToCharArray());
|
||||
assetLines.Add(assetPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return assetLines.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 拷贝内置文件到StreamingAssets
|
||||
/// </summary>
|
||||
public class TaskCopyBuildinFiles : IBuildTask
|
||||
{
|
||||
void IBuildTask.Run(BuildContext context)
|
||||
{
|
||||
// 注意:我们只有在强制重建的时候才会拷贝
|
||||
var buildParameters = context.GetContextObject<AssetBundleBuilder.BuildParametersContext>();
|
||||
if(buildParameters.Parameters.ForceRebuild)
|
||||
{
|
||||
// 清空流目录
|
||||
AssetBundleBuilderHelper.ClearStreamingAssetsFolder();
|
||||
|
||||
// 拷贝内置文件
|
||||
var pipelineOutputDirectory = buildParameters.PipelineOutputDirectory;
|
||||
CopyBuildinFilesToStreaming(pipelineOutputDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
private void CopyBuildinFilesToStreaming(string pipelineOutputDirectory)
|
||||
{
|
||||
// 加载补丁清单
|
||||
PatchManifest patchManifest = AssetBundleBuilderHelper.LoadPatchManifestFile(pipelineOutputDirectory);
|
||||
|
||||
// 拷贝文件列表
|
||||
foreach (var patchBundle in patchManifest.BundleList)
|
||||
{
|
||||
if (patchBundle.IsBuildin == false)
|
||||
continue;
|
||||
|
||||
string sourcePath = $"{pipelineOutputDirectory}/{patchBundle.BundleName}";
|
||||
string destPath = $"{Application.dataPath}/StreamingAssets/{patchBundle.Hash}";
|
||||
Debug.Log($"拷贝内置文件到流目录:{patchBundle.BundleName}");
|
||||
EditorTools.CopyFile(sourcePath, destPath, true);
|
||||
}
|
||||
|
||||
// 拷贝清单文件
|
||||
{
|
||||
string sourcePath = $"{pipelineOutputDirectory}/{YooAssetSettingsData.Setting.PatchManifestFileName}";
|
||||
string destPath = $"{Application.dataPath}/StreamingAssets/{YooAssetSettingsData.Setting.PatchManifestFileName}";
|
||||
EditorTools.CopyFile(sourcePath, destPath, true);
|
||||
}
|
||||
|
||||
// 拷贝清单哈希文件
|
||||
{
|
||||
string sourcePath = $"{pipelineOutputDirectory}/{YooAssetSettingsData.Setting.PatchManifestHashFileName}";
|
||||
string destPath = $"{Application.dataPath}/StreamingAssets/{YooAssetSettingsData.Setting.PatchManifestHashFileName}";
|
||||
EditorTools.CopyFile(sourcePath, destPath, true);
|
||||
}
|
||||
|
||||
// 刷新目录
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 创建补丁清单文件
|
||||
/// </summary>
|
||||
public class TaskCreatePatchManifest : IBuildTask
|
||||
{
|
||||
void IBuildTask.Run(BuildContext context)
|
||||
{
|
||||
var buildParameters = context.GetContextObject<AssetBundleBuilder.BuildParametersContext>();
|
||||
var encryptionContext = context.GetContextObject<TaskEncryption.EncryptionContext>();
|
||||
var buildMapContext = context.GetContextObject<BuildMapContext>();
|
||||
CreatePatchManifestFile(buildParameters, buildMapContext, encryptionContext);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建补丁清单文件到输出目录
|
||||
/// </summary>
|
||||
private void CreatePatchManifestFile(AssetBundleBuilder.BuildParametersContext buildParameters,
|
||||
BuildMapContext buildMapContext, TaskEncryption.EncryptionContext encryptionContext)
|
||||
{
|
||||
// 创建新补丁清单
|
||||
PatchManifest patchManifest = new PatchManifest();
|
||||
patchManifest.ResourceVersion = buildParameters.Parameters.BuildVersion;
|
||||
patchManifest.BuildinTags = buildParameters.Parameters.BuildinTags;
|
||||
patchManifest.BundleList = GetAllPatchBundle(buildParameters, buildMapContext, encryptionContext);
|
||||
patchManifest.AssetList = GetAllPatchAsset(buildMapContext, patchManifest);
|
||||
|
||||
// 创建补丁清单文件
|
||||
string manifestFilePath = $"{buildParameters.PipelineOutputDirectory}/{YooAssetSettingsData.Setting.PatchManifestFileName}";
|
||||
UnityEngine.Debug.Log($"创建补丁清单文件:{manifestFilePath}");
|
||||
PatchManifest.Serialize(manifestFilePath, patchManifest);
|
||||
|
||||
// 创建补丁清单哈希文件
|
||||
string manifestHashFilePath = $"{buildParameters.PipelineOutputDirectory}/{YooAssetSettingsData.Setting.PatchManifestHashFileName}";
|
||||
string manifestHash = HashUtility.FileMD5(manifestFilePath);
|
||||
UnityEngine.Debug.Log($"创建补丁清单哈希文件:{manifestHashFilePath}");
|
||||
FileUtility.CreateFile(manifestHashFilePath, manifestHash);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源包列表
|
||||
/// </summary>
|
||||
private List<PatchBundle> GetAllPatchBundle(AssetBundleBuilder.BuildParametersContext buildParameters,
|
||||
BuildMapContext buildMapContext, TaskEncryption.EncryptionContext encryptionContext)
|
||||
{
|
||||
List<PatchBundle> result = new List<PatchBundle>(1000);
|
||||
|
||||
// 内置标记列表
|
||||
List<string> buildinTags = buildParameters.Parameters.GetBuildinTags();
|
||||
|
||||
// 加载旧补丁清单
|
||||
PatchManifest oldPatchManifest = null;
|
||||
if (buildParameters.Parameters.ForceRebuild == false)
|
||||
{
|
||||
oldPatchManifest = AssetBundleBuilderHelper.LoadPatchManifestFile(buildParameters.PipelineOutputDirectory);
|
||||
}
|
||||
|
||||
foreach (var bundleInfo in buildMapContext.BundleInfos)
|
||||
{
|
||||
var bundleName = bundleInfo.BundleName;
|
||||
string filePath = $"{buildParameters.PipelineOutputDirectory}/{bundleName}";
|
||||
string hash = HashUtility.FileMD5(filePath);
|
||||
string crc = HashUtility.FileCRC32(filePath);
|
||||
long size = FileUtility.GetFileSize(filePath);
|
||||
int version = buildParameters.Parameters.BuildVersion;
|
||||
string[] tags = buildMapContext.GetAssetTags(bundleName);
|
||||
bool isEncrypted = encryptionContext.IsEncryptFile(bundleName);
|
||||
bool isBuildin = IsBuildinBundle(tags, buildinTags);
|
||||
bool isRawFile = bundleInfo.IsRawFile;
|
||||
|
||||
// 附加文件扩展名
|
||||
if (buildParameters.Parameters.AppendFileExtension)
|
||||
{
|
||||
hash += bundleInfo.GetAppendExtension();
|
||||
}
|
||||
|
||||
// 注意:如果文件没有变化使用旧版本号
|
||||
if (oldPatchManifest != null && oldPatchManifest.Bundles.TryGetValue(bundleName, out PatchBundle value))
|
||||
{
|
||||
if (value.Hash == hash)
|
||||
version = value.Version;
|
||||
}
|
||||
|
||||
PatchBundle patchBundle = new PatchBundle(bundleName, hash, crc, size, version, tags);
|
||||
patchBundle.SetFlagsValue(isEncrypted, isBuildin, isRawFile);
|
||||
result.Add(patchBundle);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
private bool IsBuildinBundle(string[] bundleTags, List<string> buildinTags)
|
||||
{
|
||||
// 注意:没有任何标记的Bundle文件默认为内置文件
|
||||
if (bundleTags.Length == 0)
|
||||
return true;
|
||||
|
||||
foreach (var tag in bundleTags)
|
||||
{
|
||||
if (buildinTags.Contains(tag))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源列表
|
||||
/// </summary>
|
||||
private List<PatchAsset> GetAllPatchAsset(BuildMapContext buildMapContext, PatchManifest patchManifest)
|
||||
{
|
||||
List<PatchAsset> result = new List<PatchAsset>(1000);
|
||||
foreach (var bundleInfo in buildMapContext.BundleInfos)
|
||||
{
|
||||
var assetInfos = bundleInfo.GetAllPatchAssetInfos();
|
||||
foreach (var assetInfo in assetInfos)
|
||||
{
|
||||
PatchAsset patchAsset = new PatchAsset();
|
||||
patchAsset.AssetPath = assetInfo.AssetPath;
|
||||
patchAsset.BundleID = GetAssetBundleID(assetInfo.BundleName, patchManifest);
|
||||
patchAsset.DependIDs = GetAssetBundleDependIDs(assetInfo, patchManifest);
|
||||
result.Add(patchAsset);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
private int[] GetAssetBundleDependIDs(BuildAssetInfo assetInfo, PatchManifest patchManifest)
|
||||
{
|
||||
List<int> result = new List<int>();
|
||||
foreach (var dependAssetInfo in assetInfo.AllDependAssetInfos)
|
||||
{
|
||||
if (dependAssetInfo.BundleNameIsValid() == false)
|
||||
continue;
|
||||
int bundleID = GetAssetBundleID(dependAssetInfo.BundleName, patchManifest);
|
||||
if (result.Contains(bundleID) == false)
|
||||
result.Add(bundleID);
|
||||
}
|
||||
return result.ToArray();
|
||||
}
|
||||
private int GetAssetBundleID(string bundleName, PatchManifest patchManifest)
|
||||
{
|
||||
for (int index = 0; index < patchManifest.BundleList.Count; index++)
|
||||
{
|
||||
if (patchManifest.BundleList[index].BundleName == bundleName)
|
||||
return index;
|
||||
}
|
||||
throw new Exception($"Not found bundle name : {bundleName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 制作补丁包
|
||||
/// </summary>
|
||||
public class TaskCreatePatchPackage : IBuildTask
|
||||
{
|
||||
void IBuildTask.Run(BuildContext context)
|
||||
{
|
||||
var buildParameters = context.GetContextObject<AssetBundleBuilder.BuildParametersContext>();
|
||||
CopyPatchFiles(buildParameters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 拷贝补丁文件到补丁包目录
|
||||
/// </summary>
|
||||
private void CopyPatchFiles(AssetBundleBuilder.BuildParametersContext buildParameters)
|
||||
{
|
||||
string packageDirectory = buildParameters.GetPackageDirectory();
|
||||
UnityEngine.Debug.Log($"开始拷贝补丁文件到补丁包目录:{packageDirectory}");
|
||||
|
||||
// 拷贝Report文件
|
||||
{
|
||||
string sourcePath = $"{buildParameters.PipelineOutputDirectory}/{YooAssetSettings.ReportFileName}";
|
||||
string destPath = $"{packageDirectory}/{YooAssetSettings.ReportFileName}";
|
||||
EditorTools.CopyFile(sourcePath, destPath, true);
|
||||
UnityEngine.Debug.Log($"拷贝Report文件到:{destPath}");
|
||||
}
|
||||
|
||||
// 拷贝PatchManifest文件
|
||||
{
|
||||
string sourcePath = $"{buildParameters.PipelineOutputDirectory}/{YooAssetSettingsData.Setting.PatchManifestFileName}";
|
||||
string destPath = $"{packageDirectory}/{YooAssetSettingsData.Setting.PatchManifestFileName}";
|
||||
EditorTools.CopyFile(sourcePath, destPath, true);
|
||||
UnityEngine.Debug.Log($"拷贝PatchManifest文件到:{destPath}");
|
||||
}
|
||||
|
||||
// 拷贝PatchManifest哈希文件
|
||||
{
|
||||
string sourcePath = $"{buildParameters.PipelineOutputDirectory}/{YooAssetSettingsData.Setting.PatchManifestHashFileName}";
|
||||
string destPath = $"{packageDirectory}/{YooAssetSettingsData.Setting.PatchManifestHashFileName}";
|
||||
EditorTools.CopyFile(sourcePath, destPath, true);
|
||||
UnityEngine.Debug.Log($"拷贝PatchManifest哈希文件到:{destPath}");
|
||||
}
|
||||
|
||||
// 拷贝UnityManifest序列化文件
|
||||
{
|
||||
string sourcePath = $"{buildParameters.PipelineOutputDirectory}/{YooAssetSettingsData.Setting.UnityManifestFileName}";
|
||||
string destPath = $"{packageDirectory}/{YooAssetSettingsData.Setting.UnityManifestFileName}";
|
||||
EditorTools.CopyFile(sourcePath, destPath, true);
|
||||
UnityEngine.Debug.Log($"拷贝UnityManifest文件到:{destPath}");
|
||||
}
|
||||
|
||||
// 拷贝UnityManifest文本文件
|
||||
{
|
||||
string sourcePath = $"{buildParameters.PipelineOutputDirectory}/{YooAssetSettingsData.Setting.UnityManifestFileName}.manifest";
|
||||
string destPath = $"{packageDirectory}/{YooAssetSettingsData.Setting.UnityManifestFileName}.manifest";
|
||||
EditorTools.CopyFile(sourcePath, destPath, true);
|
||||
}
|
||||
|
||||
// 拷贝所有补丁文件
|
||||
// 注意:拷贝的补丁文件都是需要玩家热更新的文件
|
||||
int progressValue = 0;
|
||||
PatchManifest patchManifest = AssetBundleBuilderHelper.LoadPatchManifestFile(buildParameters.PipelineOutputDirectory);
|
||||
int patchFileTotalCount = patchManifest.BundleList.Count;
|
||||
foreach (var patchBundle in patchManifest.BundleList)
|
||||
{
|
||||
if (patchBundle.Version == buildParameters.Parameters.BuildVersion)
|
||||
{
|
||||
string sourcePath = $"{buildParameters.PipelineOutputDirectory}/{patchBundle.BundleName}";
|
||||
string destPath = $"{packageDirectory}/{patchBundle.Hash}";
|
||||
EditorTools.CopyFile(sourcePath, destPath, true);
|
||||
UnityEngine.Debug.Log($"拷贝补丁文件到补丁包:{patchBundle.BundleName}");
|
||||
EditorTools.DisplayProgressBar("拷贝补丁文件", ++progressValue, patchFileTotalCount);
|
||||
}
|
||||
}
|
||||
EditorTools.ClearProgressBar();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,218 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 创建报告文件
|
||||
/// </summary>
|
||||
public class TaskCreateReport : IBuildTask
|
||||
{
|
||||
void IBuildTask.Run(BuildContext context)
|
||||
{
|
||||
var buildParameters = context.GetContextObject<AssetBundleBuilder.BuildParametersContext>();
|
||||
var buildMapContext = context.GetContextObject<BuildMapContext>();
|
||||
CreateReportFile(buildParameters, buildMapContext);
|
||||
}
|
||||
|
||||
private void CreateReportFile(AssetBundleBuilder.BuildParametersContext buildParameters, BuildMapContext buildMapContext)
|
||||
{
|
||||
PatchManifest patchManifest = AssetBundleBuilderHelper.LoadPatchManifestFile(buildParameters.PipelineOutputDirectory);
|
||||
BuildReport buildReport = new BuildReport();
|
||||
buildParameters.StopWatch();
|
||||
|
||||
// 概述信息
|
||||
{
|
||||
buildReport.Summary.UnityVersion = UnityEngine.Application.unityVersion;
|
||||
buildReport.Summary.BuildTime = DateTime.Now.ToString();
|
||||
buildReport.Summary.BuildSeconds = buildParameters.GetBuildingSeconds();
|
||||
buildReport.Summary.BuildTarget = buildParameters.Parameters.BuildTarget;
|
||||
buildReport.Summary.BuildVersion = buildParameters.Parameters.BuildVersion;
|
||||
buildReport.Summary.EnableAutoCollect = buildParameters.Parameters.EnableAutoCollect;
|
||||
buildReport.Summary.AppendFileExtension = buildParameters.Parameters.AppendFileExtension;
|
||||
buildReport.Summary.AutoCollectShaders = AssetBundleGrouperSettingData.Setting.AutoCollectShaders;
|
||||
buildReport.Summary.ShadersBundleName = AssetBundleGrouperSettingData.Setting.ShadersBundleName;
|
||||
buildReport.Summary.EncryptionServicesClassName = buildParameters.Parameters.EncryptionServices == null ?
|
||||
"null" : buildParameters.Parameters.EncryptionServices.GetType().FullName;
|
||||
|
||||
// 构建参数
|
||||
buildReport.Summary.ForceRebuild = buildParameters.Parameters.ForceRebuild;
|
||||
buildReport.Summary.BuildinTags = buildParameters.Parameters.BuildinTags;
|
||||
buildReport.Summary.CompressOption = buildParameters.Parameters.CompressOption;
|
||||
buildReport.Summary.AppendHash = buildParameters.Parameters.AppendHash;
|
||||
buildReport.Summary.DisableWriteTypeTree = buildParameters.Parameters.DisableWriteTypeTree;
|
||||
buildReport.Summary.IgnoreTypeTreeChanges = buildParameters.Parameters.IgnoreTypeTreeChanges;
|
||||
buildReport.Summary.DisableLoadAssetByFileName = buildParameters.Parameters.DisableLoadAssetByFileName;
|
||||
|
||||
// 构建结果
|
||||
buildReport.Summary.AssetFileTotalCount = buildMapContext.AssetFileCount;
|
||||
buildReport.Summary.AllBundleTotalCount = GetAllBundleCount(patchManifest);
|
||||
buildReport.Summary.AllBundleTotalSize = GetAllBundleSize(patchManifest);
|
||||
buildReport.Summary.BuildinBundleTotalCount = GetBuildinBundleCount(patchManifest);
|
||||
buildReport.Summary.BuildinBundleTotalSize = GetBuildinBundleSize(patchManifest);
|
||||
buildReport.Summary.EncryptedBundleTotalCount = GetEncryptedBundleCount(patchManifest);
|
||||
buildReport.Summary.EncryptedBundleTotalSize = GetEncryptedBundleSize(patchManifest);
|
||||
buildReport.Summary.RawBundleTotalCount = GetRawBundleCount(patchManifest);
|
||||
buildReport.Summary.RawBundleTotalSize = GetRawBundleSize(patchManifest);
|
||||
}
|
||||
|
||||
// 资源对象列表
|
||||
buildReport.AssetInfos = new List<ReportAssetInfo>(patchManifest.AssetList.Count);
|
||||
foreach (var patchAsset in patchManifest.AssetList)
|
||||
{
|
||||
var mainBundle = patchManifest.BundleList[patchAsset.BundleID];
|
||||
ReportAssetInfo reportAssetInfo = new ReportAssetInfo();
|
||||
reportAssetInfo.AssetPath = patchAsset.AssetPath;
|
||||
reportAssetInfo.MainBundle = mainBundle.BundleName;
|
||||
reportAssetInfo.DependBundles = GetDependBundles(patchManifest, patchAsset);
|
||||
reportAssetInfo.DependAssets = GetDependAssets(buildMapContext, mainBundle.BundleName, patchAsset.AssetPath);
|
||||
buildReport.AssetInfos.Add(reportAssetInfo);
|
||||
}
|
||||
|
||||
// 资源包列表
|
||||
buildReport.BundleInfos = new List<ReportBundleInfo>(patchManifest.BundleList.Count);
|
||||
foreach (var patchBundle in patchManifest.BundleList)
|
||||
{
|
||||
ReportBundleInfo reportBundleInfo = new ReportBundleInfo();
|
||||
reportBundleInfo.BundleName = patchBundle.BundleName;
|
||||
reportBundleInfo.Hash = patchBundle.Hash;
|
||||
reportBundleInfo.CRC = patchBundle.CRC;
|
||||
reportBundleInfo.SizeBytes = patchBundle.SizeBytes;
|
||||
reportBundleInfo.Version = patchBundle.Version;
|
||||
reportBundleInfo.Tags = patchBundle.Tags;
|
||||
reportBundleInfo.Flags = patchBundle.Flags;
|
||||
buildReport.BundleInfos.Add(reportBundleInfo);
|
||||
}
|
||||
|
||||
// 删除旧文件
|
||||
string filePath = $"{buildParameters.PipelineOutputDirectory}/{YooAssetSettings.ReportFileName}";
|
||||
if (File.Exists(filePath))
|
||||
File.Delete(filePath);
|
||||
|
||||
// 序列化文件
|
||||
BuildReport.Serialize(filePath, buildReport);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源对象依赖的所有资源包
|
||||
/// </summary>
|
||||
private List<string> GetDependBundles(PatchManifest patchManifest, PatchAsset patchAsset)
|
||||
{
|
||||
List<string> dependBundles = new List<string>(patchAsset.DependIDs.Length);
|
||||
foreach (int index in patchAsset.DependIDs)
|
||||
{
|
||||
string dependBundleName = patchManifest.BundleList[index].BundleName;
|
||||
dependBundles.Add(dependBundleName);
|
||||
}
|
||||
return dependBundles;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源对象依赖的其它所有资源
|
||||
/// </summary>
|
||||
private List<string> GetDependAssets(BuildMapContext buildMapContext, string bundleName, string assetPath)
|
||||
{
|
||||
List<string> result = new List<string>();
|
||||
if (buildMapContext.TryGetBundleInfo(bundleName, out BuildBundleInfo bundleInfo))
|
||||
{
|
||||
BuildAssetInfo findAssetInfo = null;
|
||||
foreach (var buildinAsset in bundleInfo.BuildinAssets)
|
||||
{
|
||||
if (buildinAsset.AssetPath == assetPath)
|
||||
{
|
||||
findAssetInfo = buildinAsset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (findAssetInfo == null)
|
||||
{
|
||||
throw new Exception($"Not found asset {assetPath} in bunlde {bundleName}");
|
||||
}
|
||||
foreach (var dependAssetInfo in findAssetInfo.AllDependAssetInfos)
|
||||
{
|
||||
result.Add(dependAssetInfo.AssetPath);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"Not found bundle : {bundleName}");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private int GetAllBundleCount(PatchManifest patchManifest)
|
||||
{
|
||||
return patchManifest.BundleList.Count;
|
||||
}
|
||||
private long GetAllBundleSize(PatchManifest patchManifest)
|
||||
{
|
||||
long fileBytes = 0;
|
||||
foreach (var patchBundle in patchManifest.BundleList)
|
||||
{
|
||||
fileBytes += patchBundle.SizeBytes;
|
||||
}
|
||||
return fileBytes;
|
||||
}
|
||||
private int GetBuildinBundleCount(PatchManifest patchManifest)
|
||||
{
|
||||
int fileCount = 0;
|
||||
foreach (var patchBundle in patchManifest.BundleList)
|
||||
{
|
||||
if (patchBundle.IsBuildin)
|
||||
fileCount++;
|
||||
}
|
||||
return fileCount;
|
||||
}
|
||||
private long GetBuildinBundleSize(PatchManifest patchManifest)
|
||||
{
|
||||
long fileBytes = 0;
|
||||
foreach (var patchBundle in patchManifest.BundleList)
|
||||
{
|
||||
if (patchBundle.IsBuildin)
|
||||
fileBytes += patchBundle.SizeBytes;
|
||||
}
|
||||
return fileBytes;
|
||||
}
|
||||
private int GetEncryptedBundleCount(PatchManifest patchManifest)
|
||||
{
|
||||
int fileCount = 0;
|
||||
foreach (var patchBundle in patchManifest.BundleList)
|
||||
{
|
||||
if (patchBundle.IsEncrypted)
|
||||
fileCount++;
|
||||
}
|
||||
return fileCount;
|
||||
}
|
||||
private long GetEncryptedBundleSize(PatchManifest patchManifest)
|
||||
{
|
||||
long fileBytes = 0;
|
||||
foreach (var patchBundle in patchManifest.BundleList)
|
||||
{
|
||||
if (patchBundle.IsEncrypted)
|
||||
fileBytes += patchBundle.SizeBytes;
|
||||
}
|
||||
return fileBytes;
|
||||
}
|
||||
private int GetRawBundleCount(PatchManifest patchManifest)
|
||||
{
|
||||
int fileCount = 0;
|
||||
foreach (var patchBundle in patchManifest.BundleList)
|
||||
{
|
||||
if (patchBundle.IsRawFile)
|
||||
fileCount++;
|
||||
}
|
||||
return fileCount;
|
||||
}
|
||||
private long GetRawBundleSize(PatchManifest patchManifest)
|
||||
{
|
||||
long fileBytes = 0;
|
||||
foreach (var patchBundle in patchManifest.BundleList)
|
||||
{
|
||||
if (patchBundle.IsRawFile)
|
||||
fileBytes += patchBundle.SizeBytes;
|
||||
}
|
||||
return fileBytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class TaskEncryption : IBuildTask
|
||||
{
|
||||
public class EncryptionContext : IContextObject
|
||||
{
|
||||
public List<string> EncryptList;
|
||||
|
||||
/// <summary>
|
||||
/// 检测是否为加密文件
|
||||
/// </summary>
|
||||
public bool IsEncryptFile(string bundleName)
|
||||
{
|
||||
return EncryptList.Contains(bundleName);
|
||||
}
|
||||
}
|
||||
|
||||
void IBuildTask.Run(BuildContext context)
|
||||
{
|
||||
var buildParameters = context.GetContextObject<AssetBundleBuilder.BuildParametersContext>();
|
||||
var buildMapContext = context.GetContextObject<BuildMapContext>();
|
||||
|
||||
EncryptionContext encryptionContext = new EncryptionContext();
|
||||
encryptionContext.EncryptList = EncryptFiles(buildParameters, buildMapContext);
|
||||
context.SetContextObject(encryptionContext);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加密文件
|
||||
/// </summary>
|
||||
private List<string> EncryptFiles(AssetBundleBuilder.BuildParametersContext buildParameters, BuildMapContext buildMapContext)
|
||||
{
|
||||
var encryptionServices = buildParameters.Parameters.EncryptionServices;
|
||||
|
||||
// 加密资源列表
|
||||
List<string> encryptList = new List<string>();
|
||||
|
||||
// 如果没有设置加密类
|
||||
if (encryptionServices == null)
|
||||
return encryptList;
|
||||
|
||||
UnityEngine.Debug.Log($"开始加密资源文件");
|
||||
int progressValue = 0;
|
||||
foreach (var bundleInfo in buildMapContext.BundleInfos)
|
||||
{
|
||||
if (encryptionServices.Check(bundleInfo.BundleName))
|
||||
{
|
||||
if (bundleInfo.IsRawFile)
|
||||
{
|
||||
UnityEngine.Debug.LogWarning($"Encryption not support raw file : {bundleInfo.BundleName}");
|
||||
continue;
|
||||
}
|
||||
|
||||
encryptList.Add(bundleInfo.BundleName);
|
||||
|
||||
// 注意:通过判断文件合法性,规避重复加密一个文件
|
||||
string filePath = $"{buildParameters.PipelineOutputDirectory}/{bundleInfo.BundleName}";
|
||||
byte[] fileData = File.ReadAllBytes(filePath);
|
||||
if (EditorTools.CheckBundleFileValid(fileData))
|
||||
{
|
||||
byte[] bytes = encryptionServices.Encrypt(fileData);
|
||||
File.WriteAllBytes(filePath, bytes);
|
||||
UnityEngine.Debug.Log($"文件加密完成:{filePath}");
|
||||
}
|
||||
}
|
||||
|
||||
// 进度条
|
||||
EditorTools.DisplayProgressBar("加密资源包", ++progressValue, buildMapContext.BundleInfos.Count);
|
||||
}
|
||||
EditorTools.ClearProgressBar();
|
||||
|
||||
return encryptList;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class TaskGetBuildMap : IBuildTask
|
||||
{
|
||||
void IBuildTask.Run(BuildContext context)
|
||||
{
|
||||
var buildMapContext = BuildMapHelper.SetupBuildMap();
|
||||
context.SetContextObject(buildMapContext);
|
||||
|
||||
// 检测构建结果
|
||||
CheckBuildMapContent(buildMapContext);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测构建结果
|
||||
/// </summary>
|
||||
private void CheckBuildMapContent(BuildMapContext buildMapContext)
|
||||
{
|
||||
foreach (var bundleInfo in buildMapContext.BundleInfos)
|
||||
{
|
||||
// 注意:原生文件资源包只能包含一个原生文件
|
||||
bool isRawFile = bundleInfo.IsRawFile;
|
||||
if (isRawFile)
|
||||
{
|
||||
if (bundleInfo.BuildinAssets.Count != 1)
|
||||
throw new Exception("The bundle does not support multiple raw asset : {bundleInfo.BundleName}");
|
||||
continue;
|
||||
}
|
||||
|
||||
// 注意:原生文件不能被其它资源文件依赖
|
||||
foreach (var assetInfo in bundleInfo.BuildinAssets)
|
||||
{
|
||||
if (assetInfo.AllDependAssetInfos != null)
|
||||
{
|
||||
foreach (var dependAssetInfo in assetInfo.AllDependAssetInfos)
|
||||
{
|
||||
if (dependAssetInfo.IsRawAsset)
|
||||
throw new Exception($"{assetInfo.AssetPath} can not depend raw asset : {dependAssetInfo.AssetPath}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class TaskPrepare : IBuildTask
|
||||
{
|
||||
void IBuildTask.Run(BuildContext context)
|
||||
{
|
||||
var buildParameters = context.GetContextObject<AssetBundleBuilder.BuildParametersContext>();
|
||||
buildParameters.BeginWatch();
|
||||
|
||||
// 检测构建平台是否合法
|
||||
if (buildParameters.Parameters.BuildTarget == BuildTarget.NoTarget)
|
||||
throw new Exception("请选择目标平台");
|
||||
|
||||
// 检测构建版本是否合法
|
||||
if (buildParameters.Parameters.BuildVersion <= 0)
|
||||
throw new Exception("请先设置版本号");
|
||||
|
||||
// 检测输出目录是否为空
|
||||
if (string.IsNullOrEmpty(buildParameters.PipelineOutputDirectory))
|
||||
throw new Exception("输出目录不能为空");
|
||||
|
||||
// 增量更新时候的必要检测
|
||||
if (buildParameters.Parameters.ForceRebuild == false)
|
||||
{
|
||||
// 检测历史版本是否存在
|
||||
if (AssetBundleBuilderHelper.HasAnyPackageVersion(buildParameters.Parameters.BuildTarget, buildParameters.Parameters.OutputRoot) == false)
|
||||
throw new Exception("没有发现任何历史版本,请尝试强制重建");
|
||||
|
||||
// 检测构建版本是否合法
|
||||
int maxPackageVersion = AssetBundleBuilderHelper.GetMaxPackageVersion(buildParameters.Parameters.BuildTarget, buildParameters.Parameters.OutputRoot);
|
||||
if (buildParameters.Parameters.BuildVersion <= maxPackageVersion)
|
||||
throw new Exception("构建版本不能小于历史版本");
|
||||
|
||||
// 检测补丁包是否已经存在
|
||||
string packageDirectory = buildParameters.GetPackageDirectory();
|
||||
if (Directory.Exists(packageDirectory))
|
||||
throw new Exception($"补丁包已经存在:{packageDirectory}");
|
||||
|
||||
// 检测内置资源分类标签是否一致
|
||||
PatchManifest oldPatchManifest = AssetBundleBuilderHelper.LoadPatchManifestFile(buildParameters.PipelineOutputDirectory);
|
||||
if (buildParameters.Parameters.BuildinTags != oldPatchManifest.BuildinTags)
|
||||
throw new Exception($"增量更新时内置资源标签必须一致:{buildParameters.Parameters.BuildinTags} != {oldPatchManifest.BuildinTags}");
|
||||
}
|
||||
|
||||
// 如果是强制重建
|
||||
if (buildParameters.Parameters.ForceRebuild)
|
||||
{
|
||||
// 删除平台总目录
|
||||
string platformDirectory = $"{buildParameters.Parameters.OutputRoot}/{buildParameters.Parameters.BuildTarget}";
|
||||
if (EditorTools.DeleteDirectory(platformDirectory))
|
||||
{
|
||||
UnityEngine.Debug.Log($"删除平台总目录:{platformDirectory}");
|
||||
}
|
||||
}
|
||||
|
||||
// 如果输出目录不存在
|
||||
if (EditorTools.CreateDirectory(buildParameters.PipelineOutputDirectory))
|
||||
{
|
||||
UnityEngine.Debug.Log($"创建输出目录:{buildParameters.PipelineOutputDirectory}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// AssetBundle压缩选项
|
||||
/// </summary>
|
||||
public enum ECompressOption
|
||||
{
|
||||
Uncompressed = 0,
|
||||
LZMA,
|
||||
LZ4,
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public interface IEncryptionServices
|
||||
{
|
||||
/// <summary>
|
||||
/// 检测是否需要加密
|
||||
/// </summary>
|
||||
bool Check(string bundleName);
|
||||
|
||||
/// <summary>
|
||||
/// 加密方法
|
||||
/// </summary>
|
||||
/// <param name="fileData">要加密的文件数据</param>
|
||||
/// <returns>返回加密后的字节数据</returns>
|
||||
byte[] Encrypt(byte[] fileData);
|
||||
}
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
#if UNITY_2019_4_OR_NEWER
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.UIElements;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class AssetBundleDebuggerWindow : EditorWindow
|
||||
{
|
||||
[MenuItem("YooAsset/AssetBundle Debugger", false, 104)]
|
||||
public static void ShowExample()
|
||||
{
|
||||
AssetBundleDebuggerWindow wnd = GetWindow<AssetBundleDebuggerWindow>();
|
||||
wnd.titleContent = new GUIContent("资源包调试工具");
|
||||
wnd.minSize = new Vector2(800, 600);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 视图模式
|
||||
/// </summary>
|
||||
private enum EViewMode
|
||||
{
|
||||
/// <summary>
|
||||
/// 内存视图
|
||||
/// </summary>
|
||||
MemoryView,
|
||||
|
||||
/// <summary>
|
||||
/// 资源对象视图
|
||||
/// </summary>
|
||||
AssetView,
|
||||
|
||||
/// <summary>
|
||||
/// 资源包视图
|
||||
/// </summary>
|
||||
BundleView,
|
||||
}
|
||||
|
||||
private ToolbarMenu _viewModeMenu;
|
||||
private AssetListDebuggerViewer _assetListViewer;
|
||||
private BundleListDebuggerViewer _bundleListViewer;
|
||||
|
||||
private EViewMode _viewMode;
|
||||
private readonly DebugReport _debugReport = new DebugReport();
|
||||
private string _searchKeyWord;
|
||||
|
||||
|
||||
public void CreateGUI()
|
||||
{
|
||||
VisualElement root = rootVisualElement;
|
||||
|
||||
// 加载布局文件
|
||||
string rootPath = EditorTools.GetYooAssetPath();
|
||||
string uxml = $"{rootPath}/Editor/AssetBundleDebugger/{nameof(AssetBundleDebuggerWindow)}.uxml";
|
||||
var visualAsset = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(uxml);
|
||||
if (visualAsset == null)
|
||||
{
|
||||
Debug.LogError($"Not found {nameof(AssetBundleDebuggerWindow)}.uxml : {uxml}");
|
||||
return;
|
||||
}
|
||||
visualAsset.CloneTree(root);
|
||||
|
||||
// 采样按钮
|
||||
var sampleBtn = root.Q<Button>("SampleButton");
|
||||
sampleBtn.clicked += SampleBtn_onClick;
|
||||
|
||||
// 视口模式菜单
|
||||
_viewModeMenu = root.Q<ToolbarMenu>("ViewModeMenu");
|
||||
//_viewModeMenu.menu.AppendAction(EViewMode.MemoryView.ToString(), ViewModeMenuAction0, ViewModeMenuFun0);
|
||||
_viewModeMenu.menu.AppendAction(EViewMode.AssetView.ToString(), ViewModeMenuAction1, ViewModeMenuFun1);
|
||||
_viewModeMenu.menu.AppendAction(EViewMode.BundleView.ToString(), ViewModeMenuAction2, ViewModeMenuFun2);
|
||||
|
||||
// 搜索栏
|
||||
var searchField = root.Q<ToolbarSearchField>("SearchField");
|
||||
searchField.RegisterValueChangedCallback(OnSearchKeyWordChange);
|
||||
|
||||
// 加载视图
|
||||
_assetListViewer = new AssetListDebuggerViewer();
|
||||
_assetListViewer.InitViewer();
|
||||
|
||||
// 加载视图
|
||||
_bundleListViewer = new BundleListDebuggerViewer();
|
||||
_bundleListViewer.InitViewer();
|
||||
|
||||
// 显示视图
|
||||
_viewMode = EViewMode.AssetView;
|
||||
_viewModeMenu.text = EViewMode.AssetView.ToString();
|
||||
_assetListViewer.AttachParent(root);
|
||||
}
|
||||
private void SampleBtn_onClick()
|
||||
{
|
||||
YooAssets.GetDebugReport(_debugReport);
|
||||
_assetListViewer.FillViewData(_debugReport, _searchKeyWord);
|
||||
_bundleListViewer.FillViewData(_debugReport, _searchKeyWord);
|
||||
}
|
||||
private void OnSearchKeyWordChange(ChangeEvent<string> e)
|
||||
{
|
||||
_searchKeyWord = e.newValue;
|
||||
_assetListViewer.FillViewData(_debugReport, _searchKeyWord);
|
||||
_bundleListViewer.FillViewData(_debugReport, _searchKeyWord);
|
||||
}
|
||||
private void ViewModeMenuAction1(DropdownMenuAction action)
|
||||
{
|
||||
if (_viewMode != EViewMode.AssetView)
|
||||
{
|
||||
_viewMode = EViewMode.AssetView;
|
||||
VisualElement root = this.rootVisualElement;
|
||||
_viewModeMenu.text = EViewMode.AssetView.ToString();
|
||||
_assetListViewer.AttachParent(root);
|
||||
_bundleListViewer.DetachParent();
|
||||
}
|
||||
}
|
||||
private void ViewModeMenuAction2(DropdownMenuAction action)
|
||||
{
|
||||
if (_viewMode != EViewMode.BundleView)
|
||||
{
|
||||
_viewMode = EViewMode.BundleView;
|
||||
VisualElement root = this.rootVisualElement;
|
||||
_viewModeMenu.text = EViewMode.BundleView.ToString();
|
||||
_assetListViewer.DetachParent();
|
||||
_bundleListViewer.AttachParent(root);
|
||||
}
|
||||
}
|
||||
private DropdownMenuAction.Status ViewModeMenuFun1(DropdownMenuAction action)
|
||||
{
|
||||
if (_viewMode == EViewMode.AssetView)
|
||||
return DropdownMenuAction.Status.Checked;
|
||||
else
|
||||
return DropdownMenuAction.Status.Normal;
|
||||
}
|
||||
private DropdownMenuAction.Status ViewModeMenuFun2(DropdownMenuAction action)
|
||||
{
|
||||
if (_viewMode == EViewMode.BundleView)
|
||||
return DropdownMenuAction.Status.Checked;
|
||||
else
|
||||
return DropdownMenuAction.Status.Normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,7 +0,0 @@
|
||||
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd" editor-extension-mode="True">
|
||||
<uie:Toolbar name="Toolbar" style="display: flex;">
|
||||
<uie:ToolbarButton text="刷新" display-tooltip-when-elided="true" name="SampleButton" style="width: 70px; background-color: rgb(15, 118, 31); -unity-text-align: middle-center; border-top-left-radius: 2px; border-bottom-left-radius: 2px; border-top-right-radius: 2px; border-bottom-right-radius: 2px; border-left-width: 1px; border-right-width: 1px;" />
|
||||
<uie:ToolbarMenu display-tooltip-when-elided="true" name="ViewModeMenu" text="ViewMode" style="width: 100px; flex-grow: 0;" />
|
||||
<uie:ToolbarSearchField focusable="true" name="SearchField" style="flex-grow: 1;" />
|
||||
</uie:Toolbar>
|
||||
</ui:UXML>
|
||||
@@ -1,242 +0,0 @@
|
||||
#if UNITY_2019_4_OR_NEWER
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
internal class AssetListDebuggerViewer
|
||||
{
|
||||
private VisualTreeAsset _visualAsset;
|
||||
private TemplateContainer _root;
|
||||
|
||||
private ListView _assetListView;
|
||||
private ListView _dependListView;
|
||||
private DebugReport _debugReport;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化页面
|
||||
/// </summary>
|
||||
public void InitViewer()
|
||||
{
|
||||
// 加载布局文件
|
||||
string rootPath = EditorTools.GetYooAssetPath();
|
||||
string uxml = $"{rootPath}/Editor/AssetBundleDebugger/VisualViewers/{nameof(AssetListDebuggerViewer)}.uxml";
|
||||
_visualAsset = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(uxml);
|
||||
if (_visualAsset == null)
|
||||
{
|
||||
Debug.LogError($"Not found {nameof(AssetListDebuggerViewer)}.uxml : {uxml}");
|
||||
return;
|
||||
}
|
||||
_root = _visualAsset.CloneTree();
|
||||
_root.style.flexGrow = 1f;
|
||||
|
||||
// 资源列表
|
||||
_assetListView = _root.Q<ListView>("TopListView");
|
||||
_assetListView.makeItem = MakeAssetListViewItem;
|
||||
_assetListView.bindItem = BindAssetListViewItem;
|
||||
#if UNITY_2020_1_OR_NEWER
|
||||
_assetListView.onSelectionChange += AssetListView_onSelectionChange;
|
||||
#else
|
||||
_assetListView.onSelectionChanged += AssetListView_onSelectionChange;
|
||||
#endif
|
||||
|
||||
// 依赖列表
|
||||
_dependListView = _root.Q<ListView>("BottomListView");
|
||||
_dependListView.makeItem = MakeDependListViewItem;
|
||||
_dependListView.bindItem = BindDependListViewItem;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 填充页面数据
|
||||
/// </summary>
|
||||
public void FillViewData(DebugReport debugReport, string searchKeyWord)
|
||||
{
|
||||
_debugReport = debugReport;
|
||||
_assetListView.Clear();
|
||||
_assetListView.itemsSource = FilterViewItems(debugReport, searchKeyWord);
|
||||
}
|
||||
private List<DebugProviderInfo> FilterViewItems(DebugReport debugReport, string searchKeyWord)
|
||||
{
|
||||
var result = new List<DebugProviderInfo>(debugReport.ProviderInfos.Count);
|
||||
foreach (var providerInfo in debugReport.ProviderInfos)
|
||||
{
|
||||
if (string.IsNullOrEmpty(searchKeyWord) == false)
|
||||
{
|
||||
if (providerInfo.AssetPath.Contains(searchKeyWord) == false)
|
||||
continue;
|
||||
}
|
||||
result.Add(providerInfo);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 挂接到父类页面上
|
||||
/// </summary>
|
||||
public void AttachParent(VisualElement parent)
|
||||
{
|
||||
parent.Add(_root);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从父类页面脱离开
|
||||
/// </summary>
|
||||
public void DetachParent()
|
||||
{
|
||||
_root.RemoveFromHierarchy();
|
||||
}
|
||||
|
||||
|
||||
// 资源列表相关
|
||||
private VisualElement MakeAssetListViewItem()
|
||||
{
|
||||
VisualElement element = new VisualElement();
|
||||
element.style.flexDirection = FlexDirection.Row;
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label1";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
label.style.flexGrow = 1f;
|
||||
label.style.width = 280;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label2";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
//label.style.flexGrow = 1f;
|
||||
label.style.width = 100;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label3";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
//label.style.flexGrow = 1f;
|
||||
label.style.width = 120;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
private void BindAssetListViewItem(VisualElement element, int index)
|
||||
{
|
||||
var sourceData = _assetListView.itemsSource as List<DebugProviderInfo>;
|
||||
var providerInfo = sourceData[index];
|
||||
|
||||
// Asset Path
|
||||
var label1 = element.Q<Label>("Label1");
|
||||
label1.text = providerInfo.AssetPath;
|
||||
|
||||
// Ref Count
|
||||
var label2 = element.Q<Label>("Label2");
|
||||
label2.text = providerInfo.RefCount.ToString();
|
||||
|
||||
// Status
|
||||
StyleColor textColor;
|
||||
if (providerInfo.Status == ProviderBase.EStatus.Fail)
|
||||
textColor = new StyleColor(Color.yellow);
|
||||
else
|
||||
textColor = label1.style.color;
|
||||
var label3 = element.Q<Label>("Label3");
|
||||
label3.text = providerInfo.Status.ToString();
|
||||
label3.style.color = textColor;
|
||||
}
|
||||
private void AssetListView_onSelectionChange(IEnumerable<object> objs)
|
||||
{
|
||||
foreach (var item in objs)
|
||||
{
|
||||
DebugProviderInfo providerInfo = item as DebugProviderInfo;
|
||||
FillDependListView(providerInfo);
|
||||
}
|
||||
}
|
||||
|
||||
// 依赖列表相关
|
||||
private VisualElement MakeDependListViewItem()
|
||||
{
|
||||
VisualElement element = new VisualElement();
|
||||
element.style.flexDirection = FlexDirection.Row;
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label1";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
label.style.flexGrow = 1f;
|
||||
label.style.width = 280;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label2";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
//label.style.flexGrow = 1f;
|
||||
label.style.width = 100;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label3";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
//label.style.flexGrow = 1f;
|
||||
label.style.width = 100;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label4";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
//label.style.flexGrow = 1f;
|
||||
label.style.width = 120;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
private void BindDependListViewItem(VisualElement element, int index)
|
||||
{
|
||||
List<DebugBundleInfo> bundles = _dependListView.itemsSource as List<DebugBundleInfo>;
|
||||
DebugBundleInfo bundleInfo = bundles[index];
|
||||
|
||||
// Bundle Name
|
||||
var label1 = element.Q<Label>("Label1");
|
||||
label1.text = bundleInfo.BundleName;
|
||||
|
||||
// Version
|
||||
var label2 = element.Q<Label>("Label2");
|
||||
label2.text = bundleInfo.Version.ToString();
|
||||
|
||||
// Ref Count
|
||||
var label3 = element.Q<Label>("Label3");
|
||||
label3.text = bundleInfo.RefCount.ToString();
|
||||
|
||||
// Status
|
||||
var label4 = element.Q<Label>("Label4");
|
||||
label4.text = bundleInfo.Status.ToString();
|
||||
}
|
||||
private void FillDependListView(DebugProviderInfo providerInfo)
|
||||
{
|
||||
_dependListView.Clear();
|
||||
_dependListView.ClearSelection();
|
||||
_dependListView.itemsSource = providerInfo.BundleInfos;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,19 +0,0 @@
|
||||
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
|
||||
<ui:VisualElement name="TopGroup" style="flex-grow: 1; border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); border-top-color: rgb(0, 0, 0); border-bottom-color: rgb(0, 0, 0); margin-left: 0; margin-right: 0; margin-top: 2px; margin-bottom: 1px; display: flex;">
|
||||
<uie:Toolbar name="TopBar" style="height: 25px; margin-left: 1px; margin-right: 1px;">
|
||||
<uie:ToolbarButton text="Asset Path" display-tooltip-when-elided="true" name="TopBar1" style="width: 280px; -unity-text-align: middle-left; flex-grow: 1;" />
|
||||
<uie:ToolbarButton text="Ref Count" display-tooltip-when-elided="true" name="TopBar2" style="width: 100px; -unity-text-align: middle-left; flex-grow: 0;" />
|
||||
<uie:ToolbarButton text="Status" display-tooltip-when-elided="true" name="TopBar3" style="width: 120px; -unity-text-align: middle-left;" />
|
||||
</uie:Toolbar>
|
||||
<ui:ListView focusable="true" name="TopListView" item-height="18" style="flex-grow: 1;" />
|
||||
</ui:VisualElement>
|
||||
<ui:VisualElement name="BottomGroup" style="height: 200px; border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); border-top-color: rgb(0, 0, 0); border-bottom-color: rgb(0, 0, 0); margin-left: 0; margin-right: 0; margin-top: 1px; margin-bottom: 1px; display: flex;">
|
||||
<uie:Toolbar name="BottomBar" style="height: 25px; margin-left: 1px; margin-right: 1px;">
|
||||
<uie:ToolbarButton text="Depend Bundles" display-tooltip-when-elided="true" name="BottomBar1" style="width: 280px; -unity-text-align: middle-left; flex-grow: 1;" />
|
||||
<uie:ToolbarButton text="Version" display-tooltip-when-elided="true" name="BottomBar2" style="width: 100px; -unity-text-align: middle-left;" />
|
||||
<uie:ToolbarButton text="Ref Count" display-tooltip-when-elided="true" name="BottomBar3" style="width: 100px; -unity-text-align: middle-left;" />
|
||||
<uie:ToolbarButton text="Status" display-tooltip-when-elided="true" name="BottomBar4" style="width: 120px; -unity-text-align: middle-left;" />
|
||||
</uie:Toolbar>
|
||||
<ui:ListView focusable="true" name="BottomListView" item-height="18" style="flex-grow: 1;" />
|
||||
</ui:VisualElement>
|
||||
</ui:UXML>
|
||||
@@ -1,252 +0,0 @@
|
||||
#if UNITY_2019_4_OR_NEWER
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
internal class BundleListDebuggerViewer
|
||||
{
|
||||
private VisualTreeAsset _visualAsset;
|
||||
private TemplateContainer _root;
|
||||
|
||||
private ListView _bundleListView;
|
||||
private ListView _includeListView;
|
||||
private DebugReport _debugReport;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化页面
|
||||
/// </summary>
|
||||
public void InitViewer()
|
||||
{
|
||||
// 加载布局文件
|
||||
string rootPath = EditorTools.GetYooAssetPath();
|
||||
string uxml = $"{rootPath}/Editor/AssetBundleDebugger/VisualViewers/{nameof(BundleListDebuggerViewer)}.uxml";
|
||||
_visualAsset = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(uxml);
|
||||
if (_visualAsset == null)
|
||||
{
|
||||
Debug.LogError($"Not found {nameof(BundleListDebuggerViewer)}.uxml : {uxml}");
|
||||
return;
|
||||
}
|
||||
_root = _visualAsset.CloneTree();
|
||||
_root.style.flexGrow = 1f;
|
||||
|
||||
// 资源列表
|
||||
_bundleListView = _root.Q<ListView>("TopListView");
|
||||
_bundleListView.makeItem = MakeAssetListViewItem;
|
||||
_bundleListView.bindItem = BindAssetListViewItem;
|
||||
|
||||
#if UNITY_2020_1_OR_NEWER
|
||||
_bundleListView.onSelectionChange += BundleListView_onSelectionChange;
|
||||
#else
|
||||
_bundleListView.onSelectionChanged += BundleListView_onSelectionChange;
|
||||
#endif
|
||||
// 依赖列表
|
||||
_includeListView = _root.Q<ListView>("BottomListView");
|
||||
_includeListView.makeItem = MakeIncludeListViewItem;
|
||||
_includeListView.bindItem = BindIncludeListViewItem;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 填充页面数据
|
||||
/// </summary>
|
||||
public void FillViewData(DebugReport debugReport, string searchKeyWord)
|
||||
{
|
||||
_debugReport = debugReport;
|
||||
_bundleListView.Clear();
|
||||
_bundleListView.itemsSource = FilterViewItems(debugReport, searchKeyWord);
|
||||
}
|
||||
private List<DebugBundleInfo> FilterViewItems(DebugReport debugReport, string searchKeyWord)
|
||||
{
|
||||
var result = new List<DebugBundleInfo>(debugReport.ProviderInfos.Count);
|
||||
foreach (var providerInfo in debugReport.ProviderInfos)
|
||||
{
|
||||
foreach(var bundleInfo in providerInfo.BundleInfos)
|
||||
{
|
||||
if (string.IsNullOrEmpty(searchKeyWord) == false)
|
||||
{
|
||||
if (bundleInfo.BundleName.Contains(searchKeyWord) == false)
|
||||
continue;
|
||||
}
|
||||
result.Add(bundleInfo);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 挂接到父类页面上
|
||||
/// </summary>
|
||||
public void AttachParent(VisualElement parent)
|
||||
{
|
||||
parent.Add(_root);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从父类页面脱离开
|
||||
/// </summary>
|
||||
public void DetachParent()
|
||||
{
|
||||
_root.RemoveFromHierarchy();
|
||||
}
|
||||
|
||||
|
||||
// 顶部列表相关
|
||||
private VisualElement MakeAssetListViewItem()
|
||||
{
|
||||
VisualElement element = new VisualElement();
|
||||
element.style.flexDirection = FlexDirection.Row;
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label1";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
label.style.flexGrow = 1f;
|
||||
label.style.width = 280;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label2";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
//label.style.flexGrow = 1f;
|
||||
label.style.width = 100;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label3";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
//label.style.flexGrow = 1f;
|
||||
label.style.width = 100;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label4";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
//label.style.flexGrow = 1f;
|
||||
label.style.width = 120;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
private void BindAssetListViewItem(VisualElement element, int index)
|
||||
{
|
||||
var sourceData = _bundleListView.itemsSource as List<DebugBundleInfo>;
|
||||
var bundleInfo = sourceData[index];
|
||||
|
||||
// Bundle Name
|
||||
var label1 = element.Q<Label>("Label1");
|
||||
label1.text = bundleInfo.BundleName;
|
||||
|
||||
// Version
|
||||
var label2 = element.Q<Label>("Label2");
|
||||
label2.text = bundleInfo.Version.ToString();
|
||||
|
||||
// Ref Count
|
||||
var label3 = element.Q<Label>("Label3");
|
||||
label3.text = bundleInfo.RefCount.ToString();
|
||||
|
||||
// Status
|
||||
StyleColor textColor;
|
||||
if (bundleInfo.Status == AssetBundleLoader.EStatus.Fail)
|
||||
textColor = new StyleColor(Color.yellow);
|
||||
else
|
||||
textColor = label1.style.color;
|
||||
var label4 = element.Q<Label>("Label4");
|
||||
label4.text = bundleInfo.Status.ToString();
|
||||
label4.style.color = textColor;
|
||||
}
|
||||
private void BundleListView_onSelectionChange(IEnumerable<object> objs)
|
||||
{
|
||||
foreach (var item in objs)
|
||||
{
|
||||
DebugBundleInfo bundleInfo = item as DebugBundleInfo;
|
||||
FillIncludeListView(bundleInfo);
|
||||
}
|
||||
}
|
||||
|
||||
// 底部列表相关
|
||||
private VisualElement MakeIncludeListViewItem()
|
||||
{
|
||||
VisualElement element = new VisualElement();
|
||||
element.style.flexDirection = FlexDirection.Row;
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label1";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
label.style.flexGrow = 1f;
|
||||
label.style.width = 280;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label2";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
//label.style.flexGrow = 1f;
|
||||
label.style.width = 100;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label3";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
//label.style.flexGrow = 1f;
|
||||
label.style.width = 100;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
private void BindIncludeListViewItem(VisualElement element, int index)
|
||||
{
|
||||
List<DebugProviderInfo> providers = _includeListView.itemsSource as List<DebugProviderInfo>;
|
||||
DebugProviderInfo providerInfo = providers[index];
|
||||
|
||||
// Asset Path
|
||||
var label1 = element.Q<Label>("Label1");
|
||||
label1.text = providerInfo.AssetPath;
|
||||
|
||||
// Ref Count
|
||||
var label2 = element.Q<Label>("Label2");
|
||||
label2.text = providerInfo.RefCount.ToString();
|
||||
|
||||
// Status
|
||||
var label3 = element.Q<Label>("Label3");
|
||||
label3.text = providerInfo.Status.ToString();
|
||||
}
|
||||
private void FillIncludeListView(DebugBundleInfo bundleInfo)
|
||||
{
|
||||
_includeListView.Clear();
|
||||
_includeListView.ClearSelection();
|
||||
|
||||
List<DebugProviderInfo> source = new List<DebugProviderInfo>();
|
||||
foreach(var providerInfo in _debugReport.ProviderInfos)
|
||||
{
|
||||
if (providerInfo.BundleInfos.Contains(bundleInfo))
|
||||
source.Add(providerInfo);
|
||||
}
|
||||
_includeListView.itemsSource = source;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,19 +0,0 @@
|
||||
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
|
||||
<ui:VisualElement name="TopGroup" style="flex-grow: 1; border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); border-top-color: rgb(0, 0, 0); border-bottom-color: rgb(0, 0, 0); margin-left: 0; margin-right: 0; margin-top: 2px; margin-bottom: 1px; display: flex;">
|
||||
<uie:Toolbar name="TopBar" style="height: 25px; margin-left: 1px; margin-right: 1px;">
|
||||
<uie:ToolbarButton text="Bundle Name" display-tooltip-when-elided="true" name="TopBar1" style="width: 280px; -unity-text-align: middle-left; flex-grow: 1;" />
|
||||
<uie:ToolbarButton text="Version" display-tooltip-when-elided="true" name="TopBar2" style="width: 100px; -unity-text-align: middle-left;" />
|
||||
<uie:ToolbarButton text="Ref Count" display-tooltip-when-elided="true" name="TopBar3" style="width: 100px; -unity-text-align: middle-left;" />
|
||||
<uie:ToolbarButton text="Status" display-tooltip-when-elided="true" name="TopBar4" style="width: 120px; -unity-text-align: middle-left;" />
|
||||
</uie:Toolbar>
|
||||
<ui:ListView focusable="true" name="TopListView" item-height="18" style="flex-grow: 1;" />
|
||||
</ui:VisualElement>
|
||||
<ui:VisualElement name="BottomGroup" style="height: 200px; border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); border-top-color: rgb(0, 0, 0); border-bottom-color: rgb(0, 0, 0); margin-left: 0; margin-right: 0; margin-top: 1px; margin-bottom: 1px; display: flex;">
|
||||
<uie:Toolbar name="BottomBar" style="height: 25px; margin-left: 1px; margin-right: 1px;">
|
||||
<uie:ToolbarButton text="Using Assets" display-tooltip-when-elided="true" name="BottomBar1" style="width: 280px; -unity-text-align: middle-left; flex-grow: 1;" />
|
||||
<uie:ToolbarButton text="Ref Count" display-tooltip-when-elided="true" name="BottomBar3" style="width: 100px; -unity-text-align: middle-left;" />
|
||||
<uie:ToolbarButton text="Status" display-tooltip-when-elided="true" name="BottomBar4" style="width: 120px; -unity-text-align: middle-left;" />
|
||||
</uie:Toolbar>
|
||||
<ui:ListView focusable="true" name="BottomListView" item-height="18" style="flex-grow: 1;" />
|
||||
</ui:VisualElement>
|
||||
</ui:UXML>
|
||||
@@ -1,191 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
[Serializable]
|
||||
public class AssetBundleCollector
|
||||
{
|
||||
/// <summary>
|
||||
/// 收集路径
|
||||
/// 注意:支持文件夹或单个资源文件
|
||||
/// </summary>
|
||||
public string CollectPath = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 打包规则类名
|
||||
/// </summary>
|
||||
public string PackRuleName = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 过滤规则类名
|
||||
/// </summary>
|
||||
public string FilterRuleName = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 不写入资源列表
|
||||
/// </summary>
|
||||
public bool NotWriteToAssetList = false;
|
||||
|
||||
/// <summary>
|
||||
/// 资源分类标签
|
||||
/// </summary>
|
||||
public string AssetTags = string.Empty;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 检测配置错误
|
||||
/// </summary>
|
||||
public void CheckConfigError()
|
||||
{
|
||||
if (AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(CollectPath) == null)
|
||||
throw new Exception($"Invalid collect path : {CollectPath}");
|
||||
|
||||
if (AssetBundleGrouperSettingData.HasPackRuleName(PackRuleName) == false)
|
||||
throw new Exception($"Invalid {nameof(IPackRule)} class type : {PackRuleName}");
|
||||
|
||||
if (AssetBundleGrouperSettingData.HasFilterRuleName(FilterRuleName) == false)
|
||||
throw new Exception($"Invalid {nameof(IFilterRule)} class type : {FilterRuleName}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取打包收集的资源文件
|
||||
/// </summary>
|
||||
public List<CollectAssetInfo> GetAllCollectAssets(AssetBundleGrouper grouper)
|
||||
{
|
||||
Dictionary<string, CollectAssetInfo> result = new Dictionary<string, CollectAssetInfo>(1000);
|
||||
bool isRawAsset = PackRuleName == nameof(PackRawFile);
|
||||
|
||||
// 如果是文件夹
|
||||
if (AssetDatabase.IsValidFolder(CollectPath))
|
||||
{
|
||||
string collectDirectory = CollectPath;
|
||||
string[] findAssets = EditorTools.FindAssets(EAssetSearchType.All, collectDirectory);
|
||||
foreach (string assetPath in findAssets)
|
||||
{
|
||||
if (IsValidateAsset(assetPath) == false)
|
||||
continue;
|
||||
if (IsCollectAsset(assetPath) == false)
|
||||
continue;
|
||||
if (result.ContainsKey(assetPath) == false)
|
||||
{
|
||||
string bundleName = GetBundleName(grouper, assetPath);
|
||||
List<string> assetTags = GetAssetTags(grouper);
|
||||
var collectAssetInfo = new CollectAssetInfo(bundleName, assetPath, assetTags, isRawAsset, NotWriteToAssetList);
|
||||
collectAssetInfo.DependAssets = GetAllDependencies(assetPath);
|
||||
result.Add(assetPath, collectAssetInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"The collecting asset file is existed : {assetPath} in collector : {CollectPath}");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string assetPath = CollectPath;
|
||||
if (result.ContainsKey(assetPath) == false)
|
||||
{
|
||||
if (isRawAsset && NotWriteToAssetList)
|
||||
UnityEngine.Debug.LogWarning($"Are you sure raw file are not write to asset list : {assetPath}");
|
||||
|
||||
string bundleName = GetBundleName(grouper, assetPath);
|
||||
List<string> assetTags = GetAssetTags(grouper);
|
||||
var collectAssetInfo = new CollectAssetInfo(bundleName, assetPath, assetTags, isRawAsset, NotWriteToAssetList);
|
||||
result.Add(assetPath, collectAssetInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"The collecting asset file is existed : {assetPath} in collector : {CollectPath}");
|
||||
}
|
||||
}
|
||||
|
||||
// 返回列表
|
||||
return result.Values.ToList();
|
||||
}
|
||||
|
||||
private bool IsValidateAsset(string assetPath)
|
||||
{
|
||||
if (assetPath.StartsWith("Assets/") == false && assetPath.StartsWith("Packages/") == false)
|
||||
return false;
|
||||
|
||||
if (AssetDatabase.IsValidFolder(assetPath))
|
||||
return false;
|
||||
|
||||
// 注意:忽略编辑器下的类型资源
|
||||
Type type = AssetDatabase.GetMainAssetTypeAtPath(assetPath);
|
||||
if (type == typeof(LightingDataAsset))
|
||||
return false;
|
||||
|
||||
string ext = System.IO.Path.GetExtension(assetPath);
|
||||
if (ext == "" || ext == ".dll" || ext == ".cs" || ext == ".js" || ext == ".boo" || ext == ".meta")
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
private bool IsCollectAsset(string assetPath)
|
||||
{
|
||||
// 如果收集全路径着色器
|
||||
if (AssetBundleGrouperSettingData.Setting.AutoCollectShaders)
|
||||
{
|
||||
Type assetType = AssetDatabase.GetMainAssetTypeAtPath(assetPath);
|
||||
if (assetType == typeof(UnityEngine.Shader))
|
||||
return true;
|
||||
}
|
||||
|
||||
// 根据规则设置过滤资源文件
|
||||
IFilterRule filterRuleInstance = AssetBundleGrouperSettingData.GetFilterRuleInstance(FilterRuleName);
|
||||
return filterRuleInstance.IsCollectAsset(new FilterRuleData(assetPath));
|
||||
}
|
||||
private string GetBundleName(AssetBundleGrouper grouper, string assetPath)
|
||||
{
|
||||
// 如果收集全路径着色器
|
||||
if (AssetBundleGrouperSettingData.Setting.AutoCollectShaders)
|
||||
{
|
||||
System.Type assetType = AssetDatabase.GetMainAssetTypeAtPath(assetPath);
|
||||
if (assetType == typeof(UnityEngine.Shader))
|
||||
{
|
||||
return RevisedBundleName(AssetBundleGrouperSettingData.Setting.ShadersBundleName);
|
||||
}
|
||||
}
|
||||
|
||||
// 根据规则设置获取资源包名称
|
||||
IPackRule packRuleInstance = AssetBundleGrouperSettingData.GetPackRuleInstance(PackRuleName);
|
||||
string bundleName = packRuleInstance.GetBundleName(new PackRuleData(assetPath, CollectPath, grouper.GrouperName));
|
||||
return RevisedBundleName(bundleName);
|
||||
}
|
||||
private List<string> GetAssetTags(AssetBundleGrouper grouper)
|
||||
{
|
||||
List<string> tags = StringUtility.StringToStringList(grouper.AssetTags, ';');
|
||||
List<string> temper = StringUtility.StringToStringList(AssetTags, ';');
|
||||
tags.AddRange(temper);
|
||||
return tags;
|
||||
}
|
||||
private List<string> GetAllDependencies(string mainAssetPath)
|
||||
{
|
||||
List<string> result = new List<string>();
|
||||
string[] depends = AssetDatabase.GetDependencies(mainAssetPath, true);
|
||||
foreach (string assetPath in depends)
|
||||
{
|
||||
if (IsValidateAsset(assetPath))
|
||||
{
|
||||
// 注意:排除主资源对象
|
||||
if (assetPath != mainAssetPath)
|
||||
result.Add(assetPath);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 修正资源包名
|
||||
/// </summary>
|
||||
public static string RevisedBundleName(string bundleName)
|
||||
{
|
||||
return EditorTools.GetRegularPath(bundleName).ToLower();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
[Serializable]
|
||||
public class AssetBundleGrouper
|
||||
{
|
||||
/// <summary>
|
||||
/// 分组名称
|
||||
/// </summary>
|
||||
public string GrouperName = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 分组描述
|
||||
/// </summary>
|
||||
public string GrouperDesc = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 资源分类标签
|
||||
/// </summary>
|
||||
public string AssetTags = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 分组的收集器列表
|
||||
/// </summary>
|
||||
public List<AssetBundleCollector> Collectors = new List<AssetBundleCollector>();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 检测配置错误
|
||||
/// </summary>
|
||||
public void CheckConfigError()
|
||||
{
|
||||
foreach(var collector in Collectors)
|
||||
{
|
||||
collector.CheckConfigError();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取打包收集的资源文件
|
||||
/// </summary>
|
||||
public List<CollectAssetInfo> GetAllCollectAssets()
|
||||
{
|
||||
Dictionary<string, CollectAssetInfo> result = new Dictionary<string, CollectAssetInfo>(10000);
|
||||
foreach(var collector in Collectors)
|
||||
{
|
||||
var temper = collector.GetAllCollectAssets(this);
|
||||
foreach(var assetInfo in temper)
|
||||
{
|
||||
if(result.ContainsKey(assetInfo.AssetPath) == false)
|
||||
{
|
||||
result.Add(assetInfo.AssetPath, assetInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"The collecting asset file is existed : {assetInfo.AssetPath} in grouper : {GrouperName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.Values.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class AssetBundleGrouperConfig
|
||||
{
|
||||
public const string XmlShader = "Shader";
|
||||
public const string XmlAutoCollectShader = "AutoCollectShader";
|
||||
public const string XmlShaderBundleName = "ShaderBundleName";
|
||||
public const string XmlGrouper = "Grouper";
|
||||
public const string XmlGrouperName = "GrouperName";
|
||||
public const string XmlGrouperDesc = "GrouperDesc";
|
||||
public const string XmlCollector = "Collector";
|
||||
public const string XmlDirectory = "CollectPath";
|
||||
public const string XmlPackRule = "PackRule";
|
||||
public const string XmlFilterRule = "FilterRule";
|
||||
public const string XmlNotWriteToAssetList = "NotWriteToAssetList";
|
||||
public const string XmlAssetTags = "AssetTags";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 导入XML配置表
|
||||
/// </summary>
|
||||
public static void ImportXmlConfig(string filePath)
|
||||
{
|
||||
if (File.Exists(filePath) == false)
|
||||
throw new FileNotFoundException(filePath);
|
||||
|
||||
if (Path.GetExtension(filePath) != ".xml")
|
||||
throw new Exception($"Only support xml : {filePath}");
|
||||
|
||||
// 加载配置文件
|
||||
XmlDocument xml = new XmlDocument();
|
||||
xml.Load(filePath);
|
||||
XmlElement root = xml.DocumentElement;
|
||||
|
||||
// 读取着色器配置
|
||||
bool autoCollectShaders = false;
|
||||
string shaderBundleName = string.Empty;
|
||||
var shaderNodeList = root.GetElementsByTagName(XmlShader);
|
||||
if (shaderNodeList.Count > 0)
|
||||
{
|
||||
XmlElement shaderElement = shaderNodeList[0] as XmlElement;
|
||||
if (shaderElement.HasAttribute(XmlAutoCollectShader) == false)
|
||||
throw new Exception($"Not found attribute {XmlAutoCollectShader} in {XmlShader}");
|
||||
if (shaderElement.HasAttribute(XmlShaderBundleName) == false)
|
||||
throw new Exception($"Not found attribute {XmlShaderBundleName} in {XmlShader}");
|
||||
|
||||
autoCollectShaders = shaderElement.GetAttribute(XmlAutoCollectShader) == "True" ? true : false;
|
||||
shaderBundleName = shaderElement.GetAttribute(XmlShaderBundleName);
|
||||
}
|
||||
|
||||
// 读取分组配置
|
||||
List<AssetBundleGrouper> grouperTemper = new List<AssetBundleGrouper>();
|
||||
var grouperNodeList = root.GetElementsByTagName(XmlGrouper);
|
||||
foreach (var grouperNode in grouperNodeList)
|
||||
{
|
||||
XmlElement grouperElement = grouperNode as XmlElement;
|
||||
if (grouperElement.HasAttribute(XmlGrouperName) == false)
|
||||
throw new Exception($"Not found attribute {XmlGrouperName} in {XmlGrouper}");
|
||||
if (grouperElement.HasAttribute(XmlGrouperDesc) == false)
|
||||
throw new Exception($"Not found attribute {XmlGrouperDesc} in {XmlGrouper}");
|
||||
if (grouperElement.HasAttribute(XmlAssetTags) == false)
|
||||
throw new Exception($"Not found attribute {XmlAssetTags} in {XmlGrouper}");
|
||||
|
||||
AssetBundleGrouper grouper = new AssetBundleGrouper();
|
||||
grouper.GrouperName = grouperElement.GetAttribute(XmlGrouperName);
|
||||
grouper.GrouperDesc = grouperElement.GetAttribute(XmlGrouperDesc);
|
||||
grouper.AssetTags = grouperElement.GetAttribute(XmlAssetTags);
|
||||
grouperTemper.Add(grouper);
|
||||
|
||||
// 读取收集器配置
|
||||
var collectorNodeList = grouperElement.GetElementsByTagName(XmlCollector);
|
||||
foreach (var collectorNode in collectorNodeList)
|
||||
{
|
||||
XmlElement collectorElement = collectorNode as XmlElement;
|
||||
if (collectorElement.HasAttribute(XmlDirectory) == false)
|
||||
throw new Exception($"Not found attribute {XmlDirectory} in {XmlCollector}");
|
||||
if (collectorElement.HasAttribute(XmlPackRule) == false)
|
||||
throw new Exception($"Not found attribute {XmlPackRule} in {XmlCollector}");
|
||||
if (collectorElement.HasAttribute(XmlFilterRule) == false)
|
||||
throw new Exception($"Not found attribute {XmlFilterRule} in {XmlCollector}");
|
||||
if (collectorElement.HasAttribute(XmlNotWriteToAssetList) == false)
|
||||
throw new Exception($"Not found attribute {XmlNotWriteToAssetList} in {XmlCollector}");
|
||||
if (collectorElement.HasAttribute(XmlAssetTags) == false)
|
||||
throw new Exception($"Not found attribute {XmlAssetTags} in {XmlCollector}");
|
||||
|
||||
AssetBundleCollector collector = new AssetBundleCollector();
|
||||
collector.CollectPath = collectorElement.GetAttribute(XmlDirectory);
|
||||
collector.PackRuleName = collectorElement.GetAttribute(XmlPackRule);
|
||||
collector.FilterRuleName = collectorElement.GetAttribute(XmlFilterRule);
|
||||
collector.NotWriteToAssetList = collectorElement.GetAttribute(XmlNotWriteToAssetList) == "True" ? true : false;
|
||||
collector.AssetTags = collectorElement.GetAttribute(XmlAssetTags); ;
|
||||
grouper.Collectors.Add(collector);
|
||||
}
|
||||
}
|
||||
|
||||
// 保存配置数据
|
||||
AssetBundleGrouperSettingData.ClearAll();
|
||||
AssetBundleGrouperSettingData.Setting.AutoCollectShaders = autoCollectShaders;
|
||||
AssetBundleGrouperSettingData.Setting.ShadersBundleName = shaderBundleName;
|
||||
AssetBundleGrouperSettingData.Setting.Groupers.AddRange(grouperTemper);
|
||||
AssetBundleGrouperSettingData.SaveFile();
|
||||
Debug.Log($"导入配置完毕!");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导出XML配置表
|
||||
/// </summary>
|
||||
public static void ExportXmlConfig(string savePath)
|
||||
{
|
||||
if (File.Exists(savePath))
|
||||
File.Delete(savePath);
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.AppendLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
|
||||
sb.AppendLine("<root>");
|
||||
sb.AppendLine("</root>");
|
||||
|
||||
XmlDocument xmlDoc = new XmlDocument();
|
||||
xmlDoc.LoadXml(sb.ToString());
|
||||
XmlElement root = xmlDoc.DocumentElement;
|
||||
|
||||
// 设置着色器配置
|
||||
var shaderElement = xmlDoc.CreateElement(XmlShader);
|
||||
shaderElement.SetAttribute(XmlAutoCollectShader, AssetBundleGrouperSettingData.Setting.AutoCollectShaders.ToString());
|
||||
shaderElement.SetAttribute(XmlShaderBundleName, AssetBundleGrouperSettingData.Setting.ShadersBundleName);
|
||||
|
||||
// 设置分组配置
|
||||
foreach (var grouper in AssetBundleGrouperSettingData.Setting.Groupers)
|
||||
{
|
||||
var grouperElement = xmlDoc.CreateElement(XmlGrouper);
|
||||
grouperElement.SetAttribute(XmlGrouperName, grouper.GrouperName);
|
||||
grouperElement.SetAttribute(XmlGrouperDesc, grouper.GrouperDesc);
|
||||
grouperElement.SetAttribute(XmlAssetTags, grouper.AssetTags);
|
||||
root.AppendChild(grouperElement);
|
||||
|
||||
// 设置收集器配置
|
||||
foreach (var collector in grouper.Collectors)
|
||||
{
|
||||
var collectorElement = xmlDoc.CreateElement(XmlCollector);
|
||||
collectorElement.SetAttribute(XmlDirectory, collector.CollectPath);
|
||||
collectorElement.SetAttribute(XmlPackRule, collector.PackRuleName);
|
||||
collectorElement.SetAttribute(XmlFilterRule, collector.FilterRuleName);
|
||||
collectorElement.SetAttribute(XmlNotWriteToAssetList, collector.NotWriteToAssetList.ToString());
|
||||
collectorElement.SetAttribute(XmlAssetTags, collector.AssetTags);
|
||||
grouperElement.AppendChild(collectorElement);
|
||||
}
|
||||
}
|
||||
|
||||
// 生成配置文件
|
||||
xmlDoc.Save(savePath);
|
||||
Debug.Log($"导出配置完毕!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class AssetBundleGrouperSetting : ScriptableObject
|
||||
{
|
||||
/// <summary>
|
||||
/// 自动收集着色器
|
||||
/// </summary>
|
||||
public bool AutoCollectShaders = true;
|
||||
|
||||
/// <summary>
|
||||
/// 自动收集的着色器资源包名称
|
||||
/// </summary>
|
||||
public string ShadersBundleName = "myshaders";
|
||||
|
||||
/// <summary>
|
||||
/// 分组列表
|
||||
/// </summary>
|
||||
public List<AssetBundleGrouper> Groupers = new List<AssetBundleGrouper>();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 检测配置错误
|
||||
/// </summary>
|
||||
public void CheckConfigError()
|
||||
{
|
||||
foreach (var grouper in Groupers)
|
||||
{
|
||||
grouper.CheckConfigError();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取打包收集的资源文件
|
||||
/// </summary>
|
||||
public List<CollectAssetInfo> GetAllCollectAssets()
|
||||
{
|
||||
Dictionary<string, CollectAssetInfo> result = new Dictionary<string, CollectAssetInfo>(10000);
|
||||
foreach (var grouper in Groupers)
|
||||
{
|
||||
var temper = grouper.GetAllCollectAssets();
|
||||
foreach (var assetInfo in temper)
|
||||
{
|
||||
if (result.ContainsKey(assetInfo.AssetPath) == false)
|
||||
{
|
||||
result.Add(assetInfo.AssetPath, assetInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"The collecting asset file is existed : {assetInfo.AssetPath}");
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.Values.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,267 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class AssetBundleGrouperSettingData
|
||||
{
|
||||
private static readonly Dictionary<string, System.Type> _cachePackRuleTypes = new Dictionary<string, System.Type>();
|
||||
private static readonly Dictionary<string, IPackRule> _cachePackRuleInstance = new Dictionary<string, IPackRule>();
|
||||
|
||||
private static readonly Dictionary<string, System.Type> _cacheFilterRuleTypes = new Dictionary<string, System.Type>();
|
||||
private static readonly Dictionary<string, IFilterRule> _cacheFilterRuleInstance = new Dictionary<string, IFilterRule>();
|
||||
|
||||
|
||||
private static AssetBundleGrouperSetting _setting = null;
|
||||
public static AssetBundleGrouperSetting Setting
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_setting == null)
|
||||
LoadSettingData();
|
||||
return _setting;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<string> GetPackRuleNames()
|
||||
{
|
||||
if (_setting == null)
|
||||
LoadSettingData();
|
||||
|
||||
List<string> names = new List<string>();
|
||||
foreach (var pair in _cachePackRuleTypes)
|
||||
{
|
||||
names.Add(pair.Key);
|
||||
}
|
||||
return names;
|
||||
}
|
||||
public static List<string> GetFilterRuleNames()
|
||||
{
|
||||
if (_setting == null)
|
||||
LoadSettingData();
|
||||
|
||||
List<string> names = new List<string>();
|
||||
foreach (var pair in _cacheFilterRuleTypes)
|
||||
{
|
||||
names.Add(pair.Key);
|
||||
}
|
||||
return names;
|
||||
}
|
||||
public static bool HasPackRuleName(string ruleName)
|
||||
{
|
||||
foreach (var pair in _cachePackRuleTypes)
|
||||
{
|
||||
if (pair.Key == ruleName)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static bool HasFilterRuleName(string ruleName)
|
||||
{
|
||||
foreach (var pair in _cacheFilterRuleTypes)
|
||||
{
|
||||
if (pair.Key == ruleName)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载配置文件
|
||||
/// </summary>
|
||||
private static void LoadSettingData()
|
||||
{
|
||||
// 加载配置文件
|
||||
_setting = AssetDatabase.LoadAssetAtPath<AssetBundleGrouperSetting>(EditorDefine.AssetBundleGrouperSettingFilePath);
|
||||
if (_setting == null)
|
||||
{
|
||||
Debug.LogWarning($"Create new {nameof(AssetBundleGrouperSetting)}.asset : {EditorDefine.AssetBundleGrouperSettingFilePath}");
|
||||
_setting = ScriptableObject.CreateInstance<AssetBundleGrouperSetting>();
|
||||
EditorTools.CreateFileDirectory(EditorDefine.AssetBundleGrouperSettingFilePath);
|
||||
AssetDatabase.CreateAsset(Setting, EditorDefine.AssetBundleGrouperSettingFilePath);
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log($"Load {nameof(AssetBundleGrouperSetting)}.asset ok");
|
||||
}
|
||||
|
||||
// IPackRule
|
||||
{
|
||||
// 清空缓存集合
|
||||
_cachePackRuleTypes.Clear();
|
||||
_cachePackRuleInstance.Clear();
|
||||
|
||||
// 获取所有类型
|
||||
List<Type> types = new List<Type>(100)
|
||||
{
|
||||
typeof(PackSeparately),
|
||||
typeof(PackDirectory),
|
||||
typeof(PackCollector),
|
||||
typeof(PackGrouper),
|
||||
typeof(PackRawFile),
|
||||
};
|
||||
var customTypes = AssemblyUtility.GetAssignableTypes(AssemblyUtility.UnityDefaultAssemblyEditorName, typeof(IPackRule));
|
||||
types.AddRange(customTypes);
|
||||
for (int i = 0; i < types.Count; i++)
|
||||
{
|
||||
Type type = types[i];
|
||||
if (_cachePackRuleTypes.ContainsKey(type.Name) == false)
|
||||
_cachePackRuleTypes.Add(type.Name, type);
|
||||
}
|
||||
}
|
||||
|
||||
// IFilterRule
|
||||
{
|
||||
// 清空缓存集合
|
||||
_cacheFilterRuleTypes.Clear();
|
||||
_cacheFilterRuleInstance.Clear();
|
||||
|
||||
// 获取所有类型
|
||||
List<Type> types = new List<Type>(100)
|
||||
{
|
||||
typeof(CollectAll),
|
||||
typeof(CollectScene),
|
||||
typeof(CollectPrefab),
|
||||
typeof(CollectSprite)
|
||||
};
|
||||
var customTypes = AssemblyUtility.GetAssignableTypes(AssemblyUtility.UnityDefaultAssemblyEditorName, typeof(IFilterRule));
|
||||
types.AddRange(customTypes);
|
||||
for (int i = 0; i < types.Count; i++)
|
||||
{
|
||||
Type type = types[i];
|
||||
if (_cacheFilterRuleTypes.ContainsKey(type.Name) == false)
|
||||
_cacheFilterRuleTypes.Add(type.Name, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 存储文件
|
||||
/// </summary>
|
||||
public static void SaveFile()
|
||||
{
|
||||
if (Setting != null)
|
||||
{
|
||||
EditorUtility.SetDirty(Setting);
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清空所有数据
|
||||
/// </summary>
|
||||
public static void ClearAll()
|
||||
{
|
||||
Setting.AutoCollectShaders = false;
|
||||
Setting.ShadersBundleName = string.Empty;
|
||||
Setting.Groupers.Clear();
|
||||
SaveFile();
|
||||
}
|
||||
|
||||
// 实例类相关
|
||||
public static IPackRule GetPackRuleInstance(string ruleName)
|
||||
{
|
||||
if (_cachePackRuleInstance.TryGetValue(ruleName, out IPackRule instance))
|
||||
return instance;
|
||||
|
||||
// 如果不存在创建类的实例
|
||||
if (_cachePackRuleTypes.TryGetValue(ruleName, out Type type))
|
||||
{
|
||||
instance = (IPackRule)Activator.CreateInstance(type);
|
||||
_cachePackRuleInstance.Add(ruleName, instance);
|
||||
return instance;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"{nameof(IPackRule)}类型无效:{ruleName}");
|
||||
}
|
||||
}
|
||||
public static IFilterRule GetFilterRuleInstance(string ruleName)
|
||||
{
|
||||
if (_cacheFilterRuleInstance.TryGetValue(ruleName, out IFilterRule instance))
|
||||
return instance;
|
||||
|
||||
// 如果不存在创建类的实例
|
||||
if (_cacheFilterRuleTypes.TryGetValue(ruleName, out Type type))
|
||||
{
|
||||
instance = (IFilterRule)Activator.CreateInstance(type);
|
||||
_cacheFilterRuleInstance.Add(ruleName, instance);
|
||||
return instance;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"{nameof(IFilterRule)}类型无效:{ruleName}");
|
||||
}
|
||||
}
|
||||
|
||||
// 着色器编辑相关
|
||||
public static void ModifyShader(bool isCollectAllShaders, string shadersBundleName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(shadersBundleName))
|
||||
return;
|
||||
Setting.AutoCollectShaders = isCollectAllShaders;
|
||||
Setting.ShadersBundleName = shadersBundleName;
|
||||
SaveFile();
|
||||
}
|
||||
|
||||
// 资源分组编辑相关
|
||||
public static void CreateGrouper(string grouperName, string grouperDesc, string assetTags, bool saveFile = true)
|
||||
{
|
||||
AssetBundleGrouper grouper = new AssetBundleGrouper();
|
||||
grouper.GrouperName = grouperName;
|
||||
grouper.GrouperDesc = grouperDesc;
|
||||
grouper.AssetTags = assetTags;
|
||||
Setting.Groupers.Add(grouper);
|
||||
|
||||
if (saveFile)
|
||||
SaveFile();
|
||||
}
|
||||
public static void RemoveGrouper(AssetBundleGrouper grouper)
|
||||
{
|
||||
if (Setting.Groupers.Remove(grouper))
|
||||
{
|
||||
SaveFile();
|
||||
}
|
||||
}
|
||||
public static void ModifyGrouper(AssetBundleGrouper grouper)
|
||||
{
|
||||
if (grouper != null)
|
||||
{
|
||||
SaveFile();
|
||||
}
|
||||
}
|
||||
|
||||
// 资源收集器编辑相关
|
||||
public static void CreateCollector(AssetBundleGrouper grouper, string collectPath, string packRuleName, string filterRuleName, bool notWriteToAssetList, bool saveFile = true)
|
||||
{
|
||||
AssetBundleCollector collector = new AssetBundleCollector();
|
||||
collector.CollectPath = collectPath;
|
||||
collector.PackRuleName = packRuleName;
|
||||
collector.FilterRuleName = filterRuleName;
|
||||
collector.NotWriteToAssetList = notWriteToAssetList;
|
||||
grouper.Collectors.Add(collector);
|
||||
|
||||
if (saveFile)
|
||||
SaveFile();
|
||||
}
|
||||
public static void RemoveCollector(AssetBundleGrouper grouper, AssetBundleCollector collector)
|
||||
{
|
||||
if (grouper.Collectors.Remove(collector))
|
||||
{
|
||||
SaveFile();
|
||||
}
|
||||
}
|
||||
public static void ModifyCollector(AssetBundleGrouper grouper, AssetBundleCollector collector)
|
||||
{
|
||||
if (grouper != null && collector != null)
|
||||
{
|
||||
SaveFile();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,430 +0,0 @@
|
||||
#if UNITY_2019_4_OR_NEWER
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class AssetBundleGrouperWindow : EditorWindow
|
||||
{
|
||||
[MenuItem("YooAsset/AssetBundle Grouper", false, 101)]
|
||||
public static void ShowExample()
|
||||
{
|
||||
AssetBundleGrouperWindow window = GetWindow<AssetBundleGrouperWindow>();
|
||||
window.titleContent = new GUIContent("资源包分组工具");
|
||||
window.minSize = new Vector2(800, 600);
|
||||
}
|
||||
|
||||
private List<string> _packRuleList;
|
||||
private List<string> _filterRuleList;
|
||||
private ListView _grouperListView;
|
||||
private ListView _collectorListView;
|
||||
private Toggle _autoCollectShaderToogle;
|
||||
private TextField _shaderBundleNameTxt;
|
||||
private TextField _grouperNameTxt;
|
||||
private TextField _grouperDescTxt;
|
||||
private TextField _grouperAssetTagsTxt;
|
||||
private VisualElement _grouperContainer;
|
||||
|
||||
public void CreateGUI()
|
||||
{
|
||||
VisualElement root = this.rootVisualElement;
|
||||
|
||||
_packRuleList = AssetBundleGrouperSettingData.GetPackRuleNames();
|
||||
_filterRuleList = AssetBundleGrouperSettingData.GetFilterRuleNames();
|
||||
|
||||
// 加载布局文件
|
||||
string rootPath = EditorTools.GetYooAssetPath();
|
||||
string uxml = $"{rootPath}/Editor/AssetBundleGrouper/{nameof(AssetBundleGrouperWindow)}.uxml";
|
||||
var visualAsset = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(uxml);
|
||||
if (visualAsset == null)
|
||||
{
|
||||
Debug.LogError($"Not found {nameof(AssetBundleGrouperWindow)}.uxml : {uxml}");
|
||||
return;
|
||||
}
|
||||
visualAsset.CloneTree(root);
|
||||
|
||||
try
|
||||
{
|
||||
// 导入导出按钮
|
||||
var exportBtn = root.Q<Button>("ExportButton");
|
||||
exportBtn.clicked += ExportBtn_clicked;
|
||||
var importBtn = root.Q<Button>("ImportButton");
|
||||
importBtn.clicked += ImportBtn_clicked;
|
||||
|
||||
// 着色器相关
|
||||
_autoCollectShaderToogle = root.Q<Toggle>("AutoCollectShader");
|
||||
_autoCollectShaderToogle.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
AssetBundleGrouperSettingData.ModifyShader(evt.newValue, _shaderBundleNameTxt.value);
|
||||
_shaderBundleNameTxt.SetEnabled(evt.newValue);
|
||||
});
|
||||
_shaderBundleNameTxt = root.Q<TextField>("ShaderBundleName");
|
||||
_shaderBundleNameTxt.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
AssetBundleGrouperSettingData.ModifyShader(_autoCollectShaderToogle.value, evt.newValue);
|
||||
});
|
||||
|
||||
// 分组列表相关
|
||||
_grouperListView = root.Q<ListView>("GrouperListView");
|
||||
_grouperListView.makeItem = MakeGrouperListViewItem;
|
||||
_grouperListView.bindItem = BindGrouperListViewItem;
|
||||
#if UNITY_2020_1_OR_NEWER
|
||||
_grouperListView.onSelectionChange += GrouperListView_onSelectionChange;
|
||||
#else
|
||||
_grouperListView.onSelectionChanged += GrouperListView_onSelectionChange;
|
||||
#endif
|
||||
|
||||
// 分组添加删除按钮
|
||||
var grouperAddContainer = root.Q("GrouperAddContainer");
|
||||
{
|
||||
var addBtn = grouperAddContainer.Q<Button>("AddBtn");
|
||||
addBtn.clicked += AddGrouperBtn_clicked;
|
||||
var removeBtn = grouperAddContainer.Q<Button>("RemoveBtn");
|
||||
removeBtn.clicked += RemoveGrouperBtn_clicked;
|
||||
}
|
||||
|
||||
// 分组容器
|
||||
_grouperContainer = root.Q("GrouperContainer");
|
||||
|
||||
// 分组信息相关
|
||||
_grouperNameTxt = root.Q<TextField>("GrouperName");
|
||||
_grouperNameTxt.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
var selectGrouper = _grouperListView.selectedItem as AssetBundleGrouper;
|
||||
if (selectGrouper != null)
|
||||
{
|
||||
selectGrouper.GrouperName = evt.newValue;
|
||||
AssetBundleGrouperSettingData.ModifyGrouper(selectGrouper);
|
||||
}
|
||||
});
|
||||
|
||||
_grouperDescTxt = root.Q<TextField>("GrouperDesc");
|
||||
_grouperDescTxt.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
var selectGrouper = _grouperListView.selectedItem as AssetBundleGrouper;
|
||||
if (selectGrouper != null)
|
||||
{
|
||||
selectGrouper.GrouperDesc = evt.newValue;
|
||||
AssetBundleGrouperSettingData.ModifyGrouper(selectGrouper);
|
||||
}
|
||||
});
|
||||
|
||||
_grouperAssetTagsTxt = root.Q<TextField>("GrouperAssetTags");
|
||||
_grouperAssetTagsTxt.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
var selectGrouper = _grouperListView.selectedItem as AssetBundleGrouper;
|
||||
if (selectGrouper != null)
|
||||
{
|
||||
selectGrouper.AssetTags = evt.newValue;
|
||||
AssetBundleGrouperSettingData.ModifyGrouper(selectGrouper);
|
||||
}
|
||||
});
|
||||
|
||||
// 收集列表相关
|
||||
_collectorListView = root.Q<ListView>("CollectorListView");
|
||||
_collectorListView.makeItem = MakeCollectorListViewItem;
|
||||
_collectorListView.bindItem = BindCollectorListViewItem;
|
||||
#if UNITY_2020_1_OR_NEWER
|
||||
_collectorListView.onSelectionChange += CollectorListView_onSelectionChange;
|
||||
#else
|
||||
_collectorListView.onSelectionChanged += CollectorListView_onSelectionChange;
|
||||
#endif
|
||||
|
||||
// 收集添加删除按钮
|
||||
var collectorAddContainer = root.Q("CollectorAddContainer");
|
||||
{
|
||||
var addBtn = collectorAddContainer.Q<Button>("AddBtn");
|
||||
addBtn.clicked += AddCollectorBtn_clicked;
|
||||
var removeBtn = collectorAddContainer.Q<Button>("RemoveBtn");
|
||||
removeBtn.clicked += RemoveCollectorBtn_clicked;
|
||||
}
|
||||
|
||||
// 刷新窗体
|
||||
RefreshWindow();
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Debug.LogError(e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
// 刷新窗体
|
||||
private void RefreshWindow()
|
||||
{
|
||||
_autoCollectShaderToogle.SetValueWithoutNotify(AssetBundleGrouperSettingData.Setting.AutoCollectShaders);
|
||||
_shaderBundleNameTxt.SetEnabled(AssetBundleGrouperSettingData.Setting.AutoCollectShaders);
|
||||
_shaderBundleNameTxt.SetValueWithoutNotify(AssetBundleGrouperSettingData.Setting.ShadersBundleName);
|
||||
_grouperContainer.visible = false;
|
||||
|
||||
FillGrouperViewData();
|
||||
}
|
||||
|
||||
// 导入导出按钮
|
||||
private void ExportBtn_clicked()
|
||||
{
|
||||
string resultPath = EditorTools.OpenFolderPanel("Export XML", "Assets/");
|
||||
if (resultPath != null)
|
||||
{
|
||||
AssetBundleGrouperConfig.ExportXmlConfig($"{resultPath}/{nameof(AssetBundleGrouperConfig)}.xml");
|
||||
}
|
||||
}
|
||||
private void ImportBtn_clicked()
|
||||
{
|
||||
string resultPath = EditorTools.OpenFilePath("Import XML", "Assets/", "xml");
|
||||
if (resultPath != null)
|
||||
{
|
||||
AssetBundleGrouperConfig.ImportXmlConfig(resultPath);
|
||||
RefreshWindow();
|
||||
}
|
||||
}
|
||||
|
||||
// 分组列表相关
|
||||
private void FillGrouperViewData()
|
||||
{
|
||||
_grouperListView.Clear();
|
||||
_grouperListView.ClearSelection();
|
||||
_grouperListView.itemsSource = AssetBundleGrouperSettingData.Setting.Groupers;
|
||||
}
|
||||
private VisualElement MakeGrouperListViewItem()
|
||||
{
|
||||
VisualElement element = new VisualElement();
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label1";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.flexGrow = 1f;
|
||||
label.style.height = 20f;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
private void BindGrouperListViewItem(VisualElement element, int index)
|
||||
{
|
||||
var grouper = AssetBundleGrouperSettingData.Setting.Groupers[index];
|
||||
|
||||
// Grouper Name
|
||||
var textField1 = element.Q<Label>("Label1");
|
||||
if (string.IsNullOrEmpty(grouper.GrouperDesc))
|
||||
textField1.text = grouper.GrouperName;
|
||||
else
|
||||
textField1.text = $"{grouper.GrouperName} ({grouper.GrouperDesc})";
|
||||
}
|
||||
private void GrouperListView_onSelectionChange(IEnumerable<object> objs)
|
||||
{
|
||||
FillCollectorViewData();
|
||||
}
|
||||
private void AddGrouperBtn_clicked()
|
||||
{
|
||||
AssetBundleGrouperSettingData.CreateGrouper("Default Grouper", string.Empty, string.Empty, true);
|
||||
FillGrouperViewData();
|
||||
}
|
||||
private void RemoveGrouperBtn_clicked()
|
||||
{
|
||||
var selectGrouper = _grouperListView.selectedItem as AssetBundleGrouper;
|
||||
if (selectGrouper == null)
|
||||
return;
|
||||
|
||||
AssetBundleGrouperSettingData.RemoveGrouper(selectGrouper);
|
||||
FillGrouperViewData();
|
||||
}
|
||||
|
||||
// 收集列表相关
|
||||
private void FillCollectorViewData()
|
||||
{
|
||||
var selectGrouper = _grouperListView.selectedItem as AssetBundleGrouper;
|
||||
if (selectGrouper == null)
|
||||
{
|
||||
_grouperContainer.visible = false;
|
||||
return;
|
||||
}
|
||||
|
||||
_grouperContainer.visible = true;
|
||||
_collectorListView.Clear();
|
||||
_collectorListView.ClearSelection();
|
||||
_collectorListView.itemsSource = selectGrouper.Collectors;
|
||||
|
||||
_grouperNameTxt.SetValueWithoutNotify(selectGrouper.GrouperName);
|
||||
_grouperDescTxt.SetValueWithoutNotify(selectGrouper.GrouperDesc);
|
||||
_grouperAssetTagsTxt.SetValueWithoutNotify(selectGrouper.AssetTags);
|
||||
}
|
||||
private VisualElement MakeCollectorListViewItem()
|
||||
{
|
||||
VisualElement element = new VisualElement();
|
||||
|
||||
VisualElement elementTop = new VisualElement();
|
||||
elementTop.style.flexDirection = FlexDirection.Row;
|
||||
element.Add(elementTop);
|
||||
|
||||
VisualElement elementBottom = new VisualElement();
|
||||
elementBottom.style.flexDirection = FlexDirection.Row;
|
||||
element.Add(elementBottom);
|
||||
|
||||
// Top VisualElement
|
||||
{
|
||||
var objectField = new ObjectField();
|
||||
objectField.name = "ObjectField1";
|
||||
objectField.label = "Collect Path";
|
||||
objectField.objectType = typeof(UnityEngine.Object);
|
||||
objectField.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
objectField.style.flexGrow = 1f;
|
||||
elementTop.Add(objectField);
|
||||
var label = objectField.Q<Label>();
|
||||
label.style.minWidth = 80;
|
||||
}
|
||||
|
||||
// Bottom VisualElement
|
||||
{
|
||||
var label = new Label();
|
||||
label.style.width = 80;
|
||||
elementBottom.Add(label);
|
||||
}
|
||||
{
|
||||
var popupField = new PopupField<string>(_packRuleList, 0);
|
||||
popupField.name = "PopupField1";
|
||||
popupField.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
popupField.style.width = 150;
|
||||
elementBottom.Add(popupField);
|
||||
}
|
||||
{
|
||||
var popupField = new PopupField<string>(_filterRuleList, 0);
|
||||
popupField.name = "PopupField2";
|
||||
popupField.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
popupField.style.width = 150;
|
||||
elementBottom.Add(popupField);
|
||||
}
|
||||
{
|
||||
var toggle = new Toggle();
|
||||
toggle.name = "Toggle1";
|
||||
toggle.label = "NotWriteToAssetList";
|
||||
toggle.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
toggle.style.width = 150;
|
||||
toggle.style.marginLeft = 20;
|
||||
elementBottom.Add(toggle);
|
||||
var label = toggle.Q<Label>();
|
||||
label.style.minWidth = 130;
|
||||
}
|
||||
{
|
||||
var textField = new TextField();
|
||||
textField.name = "TextField1";
|
||||
textField.label = "Tags";
|
||||
textField.style.width = 100;
|
||||
textField.style.marginLeft = 20;
|
||||
textField.style.flexGrow = 1;
|
||||
elementBottom.Add(textField);
|
||||
var label = textField.Q<Label>();
|
||||
label.style.minWidth = 40;
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
private void BindCollectorListViewItem(VisualElement element, int index)
|
||||
{
|
||||
var selectGrouper = _grouperListView.selectedItem as AssetBundleGrouper;
|
||||
if (selectGrouper == null)
|
||||
return;
|
||||
|
||||
var collector = selectGrouper.Collectors[index];
|
||||
var collectObject = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(collector.CollectPath);
|
||||
if (collectObject != null)
|
||||
collectObject.name = collector.CollectPath;
|
||||
|
||||
// Collect Path
|
||||
var objectField1 = element.Q<ObjectField>("ObjectField1");
|
||||
objectField1.SetValueWithoutNotify(collectObject);
|
||||
objectField1.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
collector.CollectPath = AssetDatabase.GetAssetPath(evt.newValue);
|
||||
objectField1.value.name = collector.CollectPath;
|
||||
AssetBundleGrouperSettingData.ModifyCollector(selectGrouper, collector);
|
||||
});
|
||||
|
||||
// Pack Rule
|
||||
var popupField1 = element.Q<PopupField<string>>("PopupField1");
|
||||
popupField1.index = GetPackRuleIndex(collector.PackRuleName);
|
||||
popupField1.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
collector.PackRuleName = evt.newValue;
|
||||
AssetBundleGrouperSettingData.ModifyCollector(selectGrouper, collector);
|
||||
});
|
||||
|
||||
// Filter Rule
|
||||
var popupField2 = element.Q<PopupField<string>>("PopupField2");
|
||||
popupField2.index = GetFilterRuleIndex(collector.FilterRuleName);
|
||||
popupField2.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
collector.FilterRuleName = evt.newValue;
|
||||
AssetBundleGrouperSettingData.ModifyCollector(selectGrouper, collector);
|
||||
});
|
||||
|
||||
// NotWriteToAssetList
|
||||
var toggle1 = element.Q<Toggle>("Toggle1");
|
||||
toggle1.SetValueWithoutNotify(collector.NotWriteToAssetList);
|
||||
toggle1.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
collector.NotWriteToAssetList = evt.newValue;
|
||||
AssetBundleGrouperSettingData.ModifyCollector(selectGrouper, collector);
|
||||
});
|
||||
|
||||
// Tags
|
||||
var textFiled1 = element.Q<TextField>("TextField1");
|
||||
textFiled1.SetValueWithoutNotify(collector.AssetTags);
|
||||
textFiled1.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
collector.AssetTags = evt.newValue;
|
||||
AssetBundleGrouperSettingData.ModifyCollector(selectGrouper, collector);
|
||||
});
|
||||
}
|
||||
private void CollectorListView_onSelectionChange(IEnumerable<object> objs)
|
||||
{
|
||||
}
|
||||
private void AddCollectorBtn_clicked()
|
||||
{
|
||||
var selectGrouper = _grouperListView.selectedItem as AssetBundleGrouper;
|
||||
if (selectGrouper == null)
|
||||
return;
|
||||
|
||||
AssetBundleGrouperSettingData.CreateCollector(selectGrouper, string.Empty, nameof(PackDirectory), nameof(CollectAll), false);
|
||||
FillCollectorViewData();
|
||||
}
|
||||
private void RemoveCollectorBtn_clicked()
|
||||
{
|
||||
var selectGrouper = _grouperListView.selectedItem as AssetBundleGrouper;
|
||||
if (selectGrouper == null)
|
||||
return;
|
||||
|
||||
var selectCollector = _collectorListView.selectedItem as AssetBundleCollector;
|
||||
if (selectCollector == null)
|
||||
return;
|
||||
|
||||
AssetBundleGrouperSettingData.RemoveCollector(selectGrouper, selectCollector);
|
||||
FillCollectorViewData();
|
||||
}
|
||||
|
||||
private int GetPackRuleIndex(string packRuleName)
|
||||
{
|
||||
for (int i = 0; i < _packRuleList.Count; i++)
|
||||
{
|
||||
if (_packRuleList[i] == packRuleName)
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
private int GetFilterRuleIndex(string filterRuleName)
|
||||
{
|
||||
for (int i = 0; i < _filterRuleList.Count; i++)
|
||||
{
|
||||
if (_filterRuleList[i] == filterRuleName)
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,32 +0,0 @@
|
||||
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd" editor-extension-mode="True">
|
||||
<uie:Toolbar name="Toolbar" style="display: flex;">
|
||||
<uie:ToolbarSearchField focusable="true" name="SearchField" style="width: 300px; flex-grow: 1;" />
|
||||
<ui:Button text="导出" display-tooltip-when-elided="true" name="ExportButton" style="width: 50px; background-color: rgb(56, 147, 58);" />
|
||||
<ui:Button text="导入" display-tooltip-when-elided="true" name="ImportButton" style="width: 50px; background-color: rgb(56, 147, 58);" />
|
||||
</uie:Toolbar>
|
||||
<ui:VisualElement name="ContentContainer" style="flex-grow: 1; flex-direction: row;">
|
||||
<ui:VisualElement name="LeftContainer" style="width: 200px; flex-grow: 0; background-color: rgb(67, 67, 67); border-left-width: 5px; border-right-width: 5px; border-top-width: 5px; border-bottom-width: 5px;">
|
||||
<ui:ListView focusable="true" name="GrouperListView" item-height="20" style="flex-grow: 1;" />
|
||||
<ui:VisualElement name="GrouperAddContainer" style="height: 20px; flex-direction: row; justify-content: center;">
|
||||
<ui:Button text=" - " display-tooltip-when-elided="true" name="RemoveBtn" />
|
||||
<ui:Button text=" + " display-tooltip-when-elided="true" name="AddBtn" />
|
||||
</ui:VisualElement>
|
||||
</ui:VisualElement>
|
||||
<ui:VisualElement name="RightContainer" style="flex-direction: column; flex-grow: 1;">
|
||||
<ui:VisualElement name="ShaderContainer" style="height: 30px; background-color: rgb(67, 67, 67); flex-direction: row; border-left-width: 5px; border-right-width: 5px; border-top-width: 5px; border-bottom-width: 5px;">
|
||||
<ui:Toggle label="Auto Collect Shaders" name="AutoCollectShader" style="width: 196px; -unity-text-align: middle-left;" />
|
||||
<ui:TextField picking-mode="Ignore" label="Shader Bundle Name" name="ShaderBundleName" style="flex-grow: 1; -unity-text-align: middle-left;" />
|
||||
</ui:VisualElement>
|
||||
<ui:VisualElement name="GrouperContainer" style="flex-grow: 1; border-left-width: 5px; border-right-width: 5px; border-top-width: 5px; border-bottom-width: 5px;">
|
||||
<ui:TextField picking-mode="Ignore" label="Grouper Name" name="GrouperName" />
|
||||
<ui:TextField picking-mode="Ignore" label="Grouper Desc" name="GrouperDesc" />
|
||||
<ui:TextField picking-mode="Ignore" label="Grouper Asset Tags" name="GrouperAssetTags" />
|
||||
<ui:VisualElement name="CollectorAddContainer" style="height: 20px; flex-direction: row-reverse;">
|
||||
<ui:Button text=" - " display-tooltip-when-elided="true" name="RemoveBtn" />
|
||||
<ui:Button text=" + " display-tooltip-when-elided="true" name="AddBtn" />
|
||||
</ui:VisualElement>
|
||||
<ui:ListView focusable="true" name="CollectorListView" item-height="50" style="flex-grow: 1;" />
|
||||
</ui:VisualElement>
|
||||
</ui:VisualElement>
|
||||
</ui:VisualElement>
|
||||
</ui:UXML>
|
||||
@@ -1,56 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class CollectAssetInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 资源包名称
|
||||
/// </summary>
|
||||
public string BundleName { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 资源路径
|
||||
/// </summary>
|
||||
public string AssetPath { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 资源分类标签
|
||||
/// </summary>
|
||||
public List<string> AssetTags { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否为原生资源
|
||||
/// </summary>
|
||||
public bool IsRawAsset { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 不写入资源列表
|
||||
/// </summary>
|
||||
public bool NotWriteToAssetList { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 依赖的资源列表
|
||||
/// </summary>
|
||||
public List<string> DependAssets = new List<string>();
|
||||
|
||||
|
||||
public CollectAssetInfo(string bundleName, string assetPath, List<string> assetTags, bool isRawAsset, bool notWriteToAssetList)
|
||||
{
|
||||
BundleName = bundleName;
|
||||
AssetPath = assetPath;
|
||||
AssetTags = assetTags;
|
||||
IsRawAsset = isRawAsset;
|
||||
NotWriteToAssetList = notWriteToAssetList;
|
||||
}
|
||||
public CollectAssetInfo(string assetPath, List<string> assetTags, bool isRawAsset, bool notWriteToAssetList)
|
||||
{
|
||||
BundleName = string.Empty;
|
||||
AssetPath = assetPath;
|
||||
AssetTags = assetTags;
|
||||
IsRawAsset = isRawAsset;
|
||||
NotWriteToAssetList = notWriteToAssetList;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 收集所有资源
|
||||
/// </summary>
|
||||
public class CollectAll : IFilterRule
|
||||
{
|
||||
public bool IsCollectAsset(FilterRuleData data)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 只收集场景
|
||||
/// </summary>
|
||||
public class CollectScene : IFilterRule
|
||||
{
|
||||
public bool IsCollectAsset(FilterRuleData data)
|
||||
{
|
||||
return Path.GetExtension(data.AssetPath) == ".unity";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 只收集预制体
|
||||
/// </summary>
|
||||
public class CollectPrefab : IFilterRule
|
||||
{
|
||||
public bool IsCollectAsset(FilterRuleData data)
|
||||
{
|
||||
return Path.GetExtension(data.AssetPath) == ".prefab";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 只收集精灵类型的资源
|
||||
/// </summary>
|
||||
public class CollectSprite : IFilterRule
|
||||
{
|
||||
public bool IsCollectAsset(FilterRuleData data)
|
||||
{
|
||||
if (AssetDatabase.GetMainAssetTypeAtPath(data.AssetPath) == typeof(Sprite))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 以文件路径作为资源包名
|
||||
/// 注意:每个文件独自打资源包
|
||||
/// </summary>
|
||||
public class PackSeparately : IPackRule
|
||||
{
|
||||
string IPackRule.GetBundleName(PackRuleData data)
|
||||
{
|
||||
return StringUtility.RemoveExtension(data.AssetPath); //"Assets/Config/test.txt" --> "Assets/Config/test"
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 以父类文件夹路径作为资源包名
|
||||
/// 注意:文件夹下所有文件打进一个资源包
|
||||
/// </summary>
|
||||
public class PackDirectory : IPackRule
|
||||
{
|
||||
string IPackRule.GetBundleName(PackRuleData data)
|
||||
{
|
||||
return Path.GetDirectoryName(data.AssetPath); //"Assets/Config/test.txt" --> "Assets/Config"
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 以收集器路径作为资源包名
|
||||
/// 注意:收集器下所有文件打进一个资源包
|
||||
/// </summary>
|
||||
public class PackCollector : IPackRule
|
||||
{
|
||||
string IPackRule.GetBundleName(PackRuleData data)
|
||||
{
|
||||
return StringUtility.RemoveExtension(data.CollectPath);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 以分组名称作为资源包名
|
||||
/// 注意:分组内所有文件打进一个资源包
|
||||
/// </summary>
|
||||
public class PackGrouper : IPackRule
|
||||
{
|
||||
string IPackRule.GetBundleName(PackRuleData data)
|
||||
{
|
||||
return data.GrouperName;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 原生文件打包模式
|
||||
/// 注意:原生文件打包支持:图片,音频,视频,文本
|
||||
/// </summary>
|
||||
public class PackRawFile : IPackRule
|
||||
{
|
||||
string IPackRule.GetBundleName(PackRuleData data)
|
||||
{
|
||||
string extension = StringUtility.RemoveFirstChar(Path.GetExtension(data.AssetPath));
|
||||
if (extension == EAssetFileExtension.unity.ToString() || extension == EAssetFileExtension.prefab.ToString() ||
|
||||
extension == EAssetFileExtension.mat.ToString() || extension == EAssetFileExtension.controller.ToString() ||
|
||||
extension == EAssetFileExtension.fbx.ToString() || extension == EAssetFileExtension.anim.ToString() ||
|
||||
extension == EAssetFileExtension.shader.ToString())
|
||||
{
|
||||
throw new Exception($"{nameof(PackRawFile)} is not support file estension : {extension}");
|
||||
}
|
||||
|
||||
// 注意:原生文件只支持无依赖关系的资源
|
||||
string[] depends = AssetDatabase.GetDependencies(data.AssetPath, true);
|
||||
if (depends.Length != 1)
|
||||
throw new Exception($"{nameof(PackRawFile)} is not support estension : {extension}");
|
||||
|
||||
return StringUtility.RemoveExtension(data.AssetPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public struct FilterRuleData
|
||||
{
|
||||
public string AssetPath;
|
||||
|
||||
public FilterRuleData(string assetPath)
|
||||
{
|
||||
AssetPath = assetPath;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 资源过滤规则接口
|
||||
/// </summary>
|
||||
public interface IFilterRule
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否为收集资源
|
||||
/// </summary>
|
||||
/// <returns>如果收集该资源返回TRUE</returns>
|
||||
bool IsCollectAsset(FilterRuleData data);
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public struct PackRuleData
|
||||
{
|
||||
public string AssetPath;
|
||||
public string CollectPath;
|
||||
public string GrouperName;
|
||||
|
||||
public PackRuleData(string assetPath)
|
||||
{
|
||||
AssetPath = assetPath;
|
||||
CollectPath = string.Empty;
|
||||
GrouperName = string.Empty;
|
||||
}
|
||||
public PackRuleData(string assetPath, string collectPath, string grouperName)
|
||||
{
|
||||
AssetPath = assetPath;
|
||||
CollectPath = collectPath;
|
||||
GrouperName = grouperName;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 资源打包规则接口
|
||||
/// </summary>
|
||||
public interface IPackRule
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取资源打包所属的资源包名称
|
||||
/// </summary>
|
||||
string GetBundleName(PackRuleData data);
|
||||
}
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
#if UNITY_2019_4_OR_NEWER
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class AssetBundleReporterWindow : EditorWindow
|
||||
{
|
||||
[MenuItem("YooAsset/AssetBundle Reporter", false, 103)]
|
||||
public static void ShowExample()
|
||||
{
|
||||
AssetBundleReporterWindow window = GetWindow<AssetBundleReporterWindow>();
|
||||
window.titleContent = new GUIContent("资源包报告工具");
|
||||
window.minSize = new Vector2(800, 600);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 视图模式
|
||||
/// </summary>
|
||||
private enum EViewMode
|
||||
{
|
||||
/// <summary>
|
||||
/// 概览视图
|
||||
/// </summary>
|
||||
Summary,
|
||||
|
||||
/// <summary>
|
||||
/// 资源对象视图
|
||||
/// </summary>
|
||||
AssetView,
|
||||
|
||||
/// <summary>
|
||||
/// 资源包视图
|
||||
/// </summary>
|
||||
BundleView,
|
||||
}
|
||||
|
||||
private ToolbarMenu _viewModeMenu;
|
||||
private SummaryReporterViewer _summaryViewer;
|
||||
private AssetListReporterViewer _assetListViewer;
|
||||
private BundleListReporterViewer _bundleListViewer;
|
||||
|
||||
private EViewMode _viewMode;
|
||||
private string _searchKeyWord;
|
||||
private BuildReport _buildReport;
|
||||
|
||||
|
||||
public void CreateGUI()
|
||||
{
|
||||
VisualElement root = this.rootVisualElement;
|
||||
|
||||
// 加载布局文件
|
||||
string rootPath = EditorTools.GetYooAssetPath();
|
||||
string uxml = $"{rootPath}/Editor/AssetBundleReporter/{nameof(AssetBundleReporterWindow)}.uxml";
|
||||
var visualAsset = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(uxml);
|
||||
if (visualAsset == null)
|
||||
{
|
||||
Debug.LogError($"Not found {nameof(AssetBundleReporterWindow)}.uxml : {uxml}");
|
||||
return;
|
||||
}
|
||||
visualAsset.CloneTree(root);
|
||||
|
||||
// 导入按钮
|
||||
var importBtn = root.Q<Button>("ImportButton");
|
||||
importBtn.clicked += ImportBtn_onClick;
|
||||
|
||||
// 视图模式菜单
|
||||
_viewModeMenu = root.Q<ToolbarMenu>("ViewModeMenu");
|
||||
_viewModeMenu.menu.AppendAction(EViewMode.Summary.ToString(), ViewModeMenuAction0, ViewModeMenuFun0);
|
||||
_viewModeMenu.menu.AppendAction(EViewMode.AssetView.ToString(), ViewModeMenuAction1, ViewModeMenuFun1);
|
||||
_viewModeMenu.menu.AppendAction(EViewMode.BundleView.ToString(), ViewModeMenuAction2, ViewModeMenuFun2);
|
||||
|
||||
// 搜索栏
|
||||
var searchField = root.Q<ToolbarSearchField>("SearchField");
|
||||
searchField.RegisterValueChangedCallback(OnSearchKeyWordChange);
|
||||
|
||||
// 加载视图
|
||||
_summaryViewer = new SummaryReporterViewer();
|
||||
_summaryViewer.InitViewer();
|
||||
|
||||
// 加载视图
|
||||
_assetListViewer = new AssetListReporterViewer();
|
||||
_assetListViewer.InitViewer();
|
||||
|
||||
// 加载视图
|
||||
_bundleListViewer = new BundleListReporterViewer();
|
||||
_bundleListViewer.InitViewer();
|
||||
|
||||
// 显示视图
|
||||
_viewMode = EViewMode.Summary;
|
||||
_viewModeMenu.text = EViewMode.Summary.ToString();
|
||||
_summaryViewer.AttachParent(root);
|
||||
}
|
||||
|
||||
private void ImportBtn_onClick()
|
||||
{
|
||||
string selectFilePath = EditorUtility.OpenFilePanel("导入报告", EditorTools.GetProjectPath(), "json");
|
||||
if (string.IsNullOrEmpty(selectFilePath))
|
||||
return;
|
||||
|
||||
string jsonData = FileUtility.ReadFile(selectFilePath);
|
||||
_buildReport = BuildReport.Deserialize(jsonData);
|
||||
_assetListViewer.FillViewData(_buildReport, _searchKeyWord);
|
||||
_bundleListViewer.FillViewData(_buildReport, _searchKeyWord);
|
||||
_summaryViewer.FillViewData(_buildReport);
|
||||
}
|
||||
private void OnSearchKeyWordChange(ChangeEvent<string> e)
|
||||
{
|
||||
_searchKeyWord = e.newValue;
|
||||
if(_buildReport != null)
|
||||
{
|
||||
_assetListViewer.FillViewData(_buildReport, _searchKeyWord);
|
||||
_bundleListViewer.FillViewData(_buildReport, _searchKeyWord);
|
||||
}
|
||||
}
|
||||
private void ViewModeMenuAction0(DropdownMenuAction action)
|
||||
{
|
||||
if (_viewMode != EViewMode.Summary)
|
||||
{
|
||||
_viewMode = EViewMode.Summary;
|
||||
VisualElement root = this.rootVisualElement;
|
||||
_viewModeMenu.text = EViewMode.Summary.ToString();
|
||||
_summaryViewer.AttachParent(root);
|
||||
_assetListViewer.DetachParent();
|
||||
_bundleListViewer.DetachParent();
|
||||
}
|
||||
}
|
||||
private void ViewModeMenuAction1(DropdownMenuAction action)
|
||||
{
|
||||
if (_viewMode != EViewMode.AssetView)
|
||||
{
|
||||
_viewMode = EViewMode.AssetView;
|
||||
VisualElement root = this.rootVisualElement;
|
||||
_viewModeMenu.text = EViewMode.AssetView.ToString();
|
||||
_summaryViewer.DetachParent();
|
||||
_assetListViewer.AttachParent(root);
|
||||
_bundleListViewer.DetachParent();
|
||||
}
|
||||
}
|
||||
private void ViewModeMenuAction2(DropdownMenuAction action)
|
||||
{
|
||||
if (_viewMode != EViewMode.BundleView)
|
||||
{
|
||||
_viewMode = EViewMode.BundleView;
|
||||
VisualElement root = this.rootVisualElement;
|
||||
_viewModeMenu.text = EViewMode.BundleView.ToString();
|
||||
_summaryViewer.DetachParent();
|
||||
_assetListViewer.DetachParent();
|
||||
_bundleListViewer.AttachParent(root);
|
||||
}
|
||||
}
|
||||
private DropdownMenuAction.Status ViewModeMenuFun0(DropdownMenuAction action)
|
||||
{
|
||||
if (_viewMode == EViewMode.Summary)
|
||||
return DropdownMenuAction.Status.Checked;
|
||||
else
|
||||
return DropdownMenuAction.Status.Normal;
|
||||
}
|
||||
private DropdownMenuAction.Status ViewModeMenuFun1(DropdownMenuAction action)
|
||||
{
|
||||
if (_viewMode == EViewMode.AssetView)
|
||||
return DropdownMenuAction.Status.Checked;
|
||||
else
|
||||
return DropdownMenuAction.Status.Normal;
|
||||
}
|
||||
private DropdownMenuAction.Status ViewModeMenuFun2(DropdownMenuAction action)
|
||||
{
|
||||
if (_viewMode == EViewMode.BundleView)
|
||||
return DropdownMenuAction.Status.Checked;
|
||||
else
|
||||
return DropdownMenuAction.Status.Normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,271 +0,0 @@
|
||||
#if UNITY_2019_4_OR_NEWER
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
internal class AssetListReporterViewer
|
||||
{
|
||||
private VisualTreeAsset _visualAsset;
|
||||
private TemplateContainer _root;
|
||||
|
||||
private ToolbarButton _topBar1;
|
||||
private ToolbarButton _topBar2;
|
||||
private ToolbarButton _topBar3;
|
||||
private ToolbarButton _bottomBar1;
|
||||
private ToolbarButton _bottomBar2;
|
||||
private ToolbarButton _bottomBar3;
|
||||
private ListView _assetListView;
|
||||
private ListView _dependListView;
|
||||
private BuildReport _buildReport;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化页面
|
||||
/// </summary>
|
||||
public void InitViewer()
|
||||
{
|
||||
// 加载布局文件
|
||||
string rootPath = EditorTools.GetYooAssetPath();
|
||||
string uxml = $"{rootPath}/Editor/AssetBundleReporter/VisualViewers/{nameof(AssetListReporterViewer)}.uxml";
|
||||
_visualAsset = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(uxml);
|
||||
if (_visualAsset == null)
|
||||
{
|
||||
Debug.LogError($"Not found {nameof(AssetListReporterViewer)}.uxml : {uxml}");
|
||||
return;
|
||||
}
|
||||
_root = _visualAsset.CloneTree();
|
||||
_root.style.flexGrow = 1f;
|
||||
|
||||
// 顶部按钮栏
|
||||
_topBar1 = _root.Q<ToolbarButton>("TopBar1");
|
||||
_topBar2 = _root.Q<ToolbarButton>("TopBar2");
|
||||
_topBar3 = _root.Q<ToolbarButton>("TopBar3");
|
||||
_topBar1.clicked += TopBar1_clicked;
|
||||
_topBar2.clicked += TopBar2_clicked;
|
||||
_topBar3.clicked += TopBar3_clicked;
|
||||
|
||||
// 底部按钮栏
|
||||
_bottomBar1 = _root.Q<ToolbarButton>("BottomBar1");
|
||||
_bottomBar2 = _root.Q<ToolbarButton>("BottomBar2");
|
||||
_bottomBar3 = _root.Q<ToolbarButton>("BottomBar3");
|
||||
|
||||
// 资源列表
|
||||
_assetListView = _root.Q<ListView>("TopListView");
|
||||
_assetListView.makeItem = MakeAssetListViewItem;
|
||||
_assetListView.bindItem = BindAssetListViewItem;
|
||||
|
||||
#if UNITY_2020_1_OR_NEWER
|
||||
_assetListView.onSelectionChange += AssetListView_onSelectionChange;
|
||||
#else
|
||||
_assetListView.onSelectionChanged += AssetListView_onSelectionChange;
|
||||
#endif
|
||||
// 依赖列表
|
||||
_dependListView = _root.Q<ListView>("BottomListView");
|
||||
_dependListView.makeItem = MakeDependListViewItem;
|
||||
_dependListView.bindItem = BindDependListViewItem;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 填充页面数据
|
||||
/// </summary>
|
||||
public void FillViewData(BuildReport buildReport, string searchKeyWord)
|
||||
{
|
||||
_buildReport = buildReport;
|
||||
_assetListView.Clear();
|
||||
_assetListView.itemsSource = FilterViewItems(buildReport, searchKeyWord);
|
||||
_topBar1.text = $"Asset Path ({_assetListView.itemsSource.Count})";
|
||||
}
|
||||
private List<ReportAssetInfo> FilterViewItems(BuildReport buildReport, string searchKeyWord)
|
||||
{
|
||||
List<ReportAssetInfo> result = new List<ReportAssetInfo>(buildReport.AssetInfos.Count);
|
||||
foreach (var assetInfo in buildReport.AssetInfos)
|
||||
{
|
||||
if(string.IsNullOrEmpty(searchKeyWord) == false)
|
||||
{
|
||||
if (assetInfo.AssetPath.Contains(searchKeyWord) == false)
|
||||
continue;
|
||||
}
|
||||
result.Add(assetInfo);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 挂接到父类页面上
|
||||
/// </summary>
|
||||
public void AttachParent(VisualElement parent)
|
||||
{
|
||||
parent.Add(_root);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从父类页面脱离开
|
||||
/// </summary>
|
||||
public void DetachParent()
|
||||
{
|
||||
_root.RemoveFromHierarchy();
|
||||
}
|
||||
|
||||
|
||||
// 资源列表相关
|
||||
private VisualElement MakeAssetListViewItem()
|
||||
{
|
||||
VisualElement element = new VisualElement();
|
||||
element.style.flexDirection = FlexDirection.Row;
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label1";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
label.style.flexGrow = 1f;
|
||||
label.style.width = 280;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label2";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
//label.style.flexGrow = 1f;
|
||||
label.style.width = 100;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label3";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
label.style.flexGrow = 1f;
|
||||
label.style.width = 145;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
private void BindAssetListViewItem(VisualElement element, int index)
|
||||
{
|
||||
var sourceData = _assetListView.itemsSource as List<ReportAssetInfo>;
|
||||
var assetInfo = sourceData[index];
|
||||
var bundleInfo = _buildReport.GetBundleInfo(assetInfo.MainBundle);
|
||||
|
||||
// Asset Path
|
||||
var label1 = element.Q<Label>("Label1");
|
||||
label1.text = assetInfo.AssetPath;
|
||||
|
||||
// Size
|
||||
var label2 = element.Q<Label>("Label2");
|
||||
label2.text = GetAssetFileSize(assetInfo.AssetPath);
|
||||
|
||||
// Main Bundle
|
||||
var label3 = element.Q<Label>("Label3");
|
||||
label3.text = bundleInfo.BundleName;
|
||||
}
|
||||
private void AssetListView_onSelectionChange(IEnumerable<object> objs)
|
||||
{
|
||||
foreach (var item in objs)
|
||||
{
|
||||
ReportAssetInfo assetInfo = item as ReportAssetInfo;
|
||||
FillDependListView(assetInfo);
|
||||
}
|
||||
}
|
||||
private void TopBar1_clicked()
|
||||
{
|
||||
}
|
||||
private void TopBar2_clicked()
|
||||
{
|
||||
}
|
||||
private void TopBar3_clicked()
|
||||
{
|
||||
}
|
||||
|
||||
// 依赖列表相关
|
||||
private void FillDependListView(ReportAssetInfo assetInfo)
|
||||
{
|
||||
List<ReportBundleInfo> bundles = new List<ReportBundleInfo>();
|
||||
var mainBundle = _buildReport.GetBundleInfo(assetInfo.MainBundle);
|
||||
bundles.Add(mainBundle);
|
||||
foreach(string dependBundleName in assetInfo.DependBundles)
|
||||
{
|
||||
var dependBundle = _buildReport.GetBundleInfo(dependBundleName);
|
||||
bundles.Add(dependBundle);
|
||||
}
|
||||
|
||||
_dependListView.Clear();
|
||||
_dependListView.ClearSelection();
|
||||
_dependListView.itemsSource = bundles;
|
||||
_bottomBar1.text = $"Depend Bundles ({bundles.Count})";
|
||||
}
|
||||
private VisualElement MakeDependListViewItem()
|
||||
{
|
||||
VisualElement element = new VisualElement();
|
||||
element.style.flexDirection = FlexDirection.Row;
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label1";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
label.style.flexGrow = 1f;
|
||||
label.style.width = 280;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label2";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
//label.style.flexGrow = 1f;
|
||||
label.style.width = 100;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label3";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
//label.style.flexGrow = 1f;
|
||||
label.style.width = 250;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
private void BindDependListViewItem(VisualElement element, int index)
|
||||
{
|
||||
List<ReportBundleInfo> bundles = _dependListView.itemsSource as List<ReportBundleInfo>;
|
||||
ReportBundleInfo bundleInfo = bundles[index];
|
||||
|
||||
// Bundle Name
|
||||
var label1 = element.Q<Label>("Label1");
|
||||
label1.text = bundleInfo.BundleName;
|
||||
|
||||
// Size
|
||||
var label2 = element.Q<Label>("Label2");
|
||||
label2.text = (bundleInfo.SizeBytes / 1024f).ToString("f1") + " KB";
|
||||
|
||||
// Hash
|
||||
var label3 = element.Q<Label>("Label3");
|
||||
label3.text = bundleInfo.Hash;
|
||||
}
|
||||
|
||||
private string GetAssetFileSize(string assetPath)
|
||||
{
|
||||
string fullPath = EditorTools.GetProjectPath() + "/" + assetPath;
|
||||
if (File.Exists(fullPath) == false)
|
||||
return "unknown";
|
||||
else
|
||||
return (EditorTools.GetFileSize(fullPath) / 1024f).ToString("f1") + " KB";
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,18 +0,0 @@
|
||||
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
|
||||
<ui:VisualElement name="TopGroup" style="flex-grow: 1; border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); border-top-color: rgb(0, 0, 0); border-bottom-color: rgb(0, 0, 0); margin-left: 0; margin-right: 0; margin-top: 2px; margin-bottom: 1px; display: flex;">
|
||||
<uie:Toolbar name="TopBar" style="height: 25px; margin-left: 1px; margin-right: 1px;">
|
||||
<uie:ToolbarButton text="Asset Path" display-tooltip-when-elided="true" name="TopBar1" style="width: 280px; -unity-text-align: middle-left; flex-grow: 1;" />
|
||||
<uie:ToolbarButton text="Size" display-tooltip-when-elided="true" name="TopBar2" style="width: 100px; -unity-text-align: middle-left; flex-grow: 0;" />
|
||||
<uie:ToolbarButton text="Main Bundle" display-tooltip-when-elided="true" name="TopBar3" style="width: 145px; -unity-text-align: middle-left; flex-grow: 1;" />
|
||||
</uie:Toolbar>
|
||||
<ui:ListView focusable="true" name="TopListView" item-height="18" style="flex-grow: 1;" />
|
||||
</ui:VisualElement>
|
||||
<ui:VisualElement name="BottomGroup" style="height: 200px; border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); border-top-color: rgb(0, 0, 0); border-bottom-color: rgb(0, 0, 0); margin-left: 0; margin-right: 0; margin-top: 1px; margin-bottom: 1px; display: flex;">
|
||||
<uie:Toolbar name="BottomBar" style="height: 25px; margin-left: 1px; margin-right: 1px;">
|
||||
<uie:ToolbarButton text="Depend Bundles" display-tooltip-when-elided="true" name="BottomBar1" style="width: 280px; -unity-text-align: middle-left; flex-grow: 1;" />
|
||||
<uie:ToolbarButton text="Size" display-tooltip-when-elided="true" name="BottomBar2" style="width: 100px; -unity-text-align: middle-left; flex-grow: 0;" />
|
||||
<uie:ToolbarButton text="Hash" display-tooltip-when-elided="true" name="BottomBar3" style="width: 250px; -unity-text-align: middle-left;" />
|
||||
</uie:Toolbar>
|
||||
<ui:ListView focusable="true" name="BottomListView" item-height="18" style="flex-grow: 1;" />
|
||||
</ui:VisualElement>
|
||||
</ui:UXML>
|
||||
@@ -1,301 +0,0 @@
|
||||
#if UNITY_2019_4_OR_NEWER
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
internal class BundleListReporterViewer
|
||||
{
|
||||
private VisualTreeAsset _visualAsset;
|
||||
private TemplateContainer _root;
|
||||
|
||||
private ToolbarButton _topBar1;
|
||||
private ToolbarButton _topBar2;
|
||||
private ToolbarButton _topBar3;
|
||||
private ToolbarButton _topBar4;
|
||||
private ToolbarButton _topBar5;
|
||||
private ToolbarButton _bottomBar1;
|
||||
private ToolbarButton _bottomBar2;
|
||||
private ToolbarButton _bottomBar3;
|
||||
private ListView _bundleListView;
|
||||
private ListView _includeListView;
|
||||
private BuildReport _buildReport;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化页面
|
||||
/// </summary>
|
||||
public void InitViewer()
|
||||
{
|
||||
// 加载布局文件
|
||||
string rootPath = EditorTools.GetYooAssetPath();
|
||||
string uxml = $"{rootPath}/Editor/AssetBundleReporter/VisualViewers/{nameof(BundleListReporterViewer)}.uxml";
|
||||
_visualAsset = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(uxml);
|
||||
if (_visualAsset == null)
|
||||
{
|
||||
Debug.LogError($"Not found {nameof(BundleListReporterViewer)}.uxml : {uxml}");
|
||||
return;
|
||||
}
|
||||
_root = _visualAsset.CloneTree();
|
||||
_root.style.flexGrow = 1f;
|
||||
|
||||
// 顶部按钮栏
|
||||
_topBar1 = _root.Q<ToolbarButton>("TopBar1");
|
||||
_topBar2 = _root.Q<ToolbarButton>("TopBar2");
|
||||
_topBar3 = _root.Q<ToolbarButton>("TopBar3");
|
||||
_topBar4 = _root.Q<ToolbarButton>("TopBar4");
|
||||
_topBar5 = _root.Q<ToolbarButton>("TopBar5");
|
||||
|
||||
// 底部按钮栏
|
||||
_bottomBar1 = _root.Q<ToolbarButton>("BottomBar1");
|
||||
_bottomBar2 = _root.Q<ToolbarButton>("BottomBar2");
|
||||
_bottomBar3 = _root.Q<ToolbarButton>("BottomBar3");
|
||||
|
||||
// 资源包列表
|
||||
_bundleListView = _root.Q<ListView>("TopListView");
|
||||
_bundleListView.makeItem = MakeBundleListViewItem;
|
||||
_bundleListView.bindItem = BindBundleListViewItem;
|
||||
#if UNITY_2020_1_OR_NEWER
|
||||
_bundleListView.onSelectionChange += BundleListView_onSelectionChange;
|
||||
#else
|
||||
_bundleListView.onSelectionChanged += BundleListView_onSelectionChange;
|
||||
#endif
|
||||
|
||||
// 包含列表
|
||||
_includeListView = _root.Q<ListView>("BottomListView");
|
||||
_includeListView.makeItem = MakeIncludeListViewItem;
|
||||
_includeListView.bindItem = BindIncludeListViewItem;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 填充页面数据
|
||||
/// </summary>
|
||||
public void FillViewData(BuildReport buildReport, string searchKeyWord)
|
||||
{
|
||||
_buildReport = buildReport;
|
||||
_bundleListView.Clear();
|
||||
_bundleListView.itemsSource = FilterViewItems(buildReport, searchKeyWord);
|
||||
_topBar1.text = $"Bundle Name ({_bundleListView.itemsSource.Count})";
|
||||
}
|
||||
private List<ReportBundleInfo> FilterViewItems(BuildReport buildReport, string searchKeyWord)
|
||||
{
|
||||
List<ReportBundleInfo> result = new List<ReportBundleInfo>(buildReport.BundleInfos.Count);
|
||||
foreach (var bundleInfo in buildReport.BundleInfos)
|
||||
{
|
||||
if (string.IsNullOrEmpty(searchKeyWord) == false)
|
||||
{
|
||||
if (bundleInfo.BundleName.Contains(searchKeyWord) == false)
|
||||
continue;
|
||||
}
|
||||
result.Add(bundleInfo);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 挂接到父类页面上
|
||||
/// </summary>
|
||||
public void AttachParent(VisualElement parent)
|
||||
{
|
||||
parent.Add(_root);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从父类页面脱离开
|
||||
/// </summary>
|
||||
public void DetachParent()
|
||||
{
|
||||
_root.RemoveFromHierarchy();
|
||||
}
|
||||
|
||||
|
||||
// 顶部列表相关
|
||||
private VisualElement MakeBundleListViewItem()
|
||||
{
|
||||
VisualElement element = new VisualElement();
|
||||
element.style.flexDirection = FlexDirection.Row;
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label1";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
label.style.flexGrow = 1f;
|
||||
label.style.width = 280;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label2";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
//label.style.flexGrow = 1f;
|
||||
label.style.width = 100;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label3";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
//label.style.flexGrow = 1f;
|
||||
label.style.width = 250;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label4";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
//label.style.flexGrow = 1f;
|
||||
label.style.width = 60;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label5";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
label.style.flexGrow = 1f;
|
||||
label.style.width = 80;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
private void BindBundleListViewItem(VisualElement element, int index)
|
||||
{
|
||||
var sourceData = _bundleListView.itemsSource as List<ReportBundleInfo>;
|
||||
var bundleInfo = sourceData[index];
|
||||
|
||||
// Bundle Name
|
||||
var label1 = element.Q<Label>("Label1");
|
||||
label1.text = bundleInfo.BundleName;
|
||||
|
||||
// Size
|
||||
var label2 = element.Q<Label>("Label2");
|
||||
label2.text = (bundleInfo.SizeBytes / 1024f).ToString("f1") + " KB";
|
||||
|
||||
// Hash
|
||||
var label3 = element.Q<Label>("Label3");
|
||||
label3.text = bundleInfo.Hash;
|
||||
|
||||
// Version
|
||||
var label4 = element.Q<Label>("Label4");
|
||||
label4.text = bundleInfo.Version.ToString();
|
||||
|
||||
// Tags
|
||||
var label5 = element.Q<Label>("Label5");
|
||||
label5.text = GetTagsString(bundleInfo.Tags);
|
||||
}
|
||||
private void BundleListView_onSelectionChange(IEnumerable<object> objs)
|
||||
{
|
||||
foreach (var item in objs)
|
||||
{
|
||||
ReportBundleInfo bundleInfo = item as ReportBundleInfo;
|
||||
FillIncludeListView(bundleInfo);
|
||||
}
|
||||
}
|
||||
|
||||
// 底部列表相关
|
||||
private void FillIncludeListView(ReportBundleInfo bundleInfo)
|
||||
{
|
||||
List<string> containsList = new List<string>();
|
||||
foreach (var assetInfo in _buildReport.AssetInfos)
|
||||
{
|
||||
if (assetInfo.MainBundle == bundleInfo.BundleName)
|
||||
containsList.Add(assetInfo.AssetPath);
|
||||
}
|
||||
|
||||
_includeListView.Clear();
|
||||
_includeListView.ClearSelection();
|
||||
_includeListView.itemsSource = containsList;
|
||||
_bottomBar1.text = $"Include Assets ({containsList.Count})";
|
||||
}
|
||||
private VisualElement MakeIncludeListViewItem()
|
||||
{
|
||||
VisualElement element = new VisualElement();
|
||||
element.style.flexDirection = FlexDirection.Row;
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label1";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
label.style.flexGrow = 1f;
|
||||
label.style.width = 280;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label2";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
//assetSizeLabel.style.flexGrow = 1f;
|
||||
label.style.width = 100;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label3";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
//label.style.flexGrow = 1f;
|
||||
label.style.width = 250;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
private void BindIncludeListViewItem(VisualElement element, int index)
|
||||
{
|
||||
List<string> containsList = _includeListView.itemsSource as List<string>;
|
||||
string assetPath = containsList[index];
|
||||
|
||||
// Asset Path
|
||||
var label1 = element.Q<Label>("Label1");
|
||||
label1.text = assetPath;
|
||||
|
||||
// Size
|
||||
var label2 = element.Q<Label>("Label2");
|
||||
label2.text = GetAssetFileSize(assetPath);
|
||||
|
||||
// GUID
|
||||
var label3 = element.Q<Label>("Label3");
|
||||
label3.text = AssetDatabase.AssetPathToGUID(assetPath);
|
||||
}
|
||||
|
||||
private string GetAssetFileSize(string assetPath)
|
||||
{
|
||||
string fullPath = EditorTools.GetProjectPath() + "/" + assetPath;
|
||||
if (File.Exists(fullPath) == false)
|
||||
return "unknown";
|
||||
else
|
||||
return (EditorTools.GetFileSize(fullPath) / 1024f).ToString("f1") + " KB";
|
||||
}
|
||||
private string GetTagsString(string[] tags)
|
||||
{
|
||||
string result = string.Empty;
|
||||
if (tags != null)
|
||||
{
|
||||
for (int i = 0; i < tags.Length; i++)
|
||||
{
|
||||
result += tags[i];
|
||||
result += ";";
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a0319abb8eae03b4b88e8f900fe2276c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,22 +0,0 @@
|
||||
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
|
||||
<ui:VisualElement name="Viewer" style="flex-grow: 1; display: flex;">
|
||||
<ui:VisualElement name="TopGroup" style="flex-grow: 1; border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); border-top-color: rgb(0, 0, 0); border-bottom-color: rgb(0, 0, 0); margin-left: 0; margin-right: 0; margin-top: 2px; margin-bottom: 1px; display: flex;">
|
||||
<uie:Toolbar name="TopBar" style="height: 25px; margin-left: 1px; margin-right: 1px;">
|
||||
<uie:ToolbarButton text="Bundle Name" display-tooltip-when-elided="true" name="TopBar1" style="width: 280px; -unity-text-align: middle-left; flex-grow: 1;" />
|
||||
<uie:ToolbarButton text="Size" display-tooltip-when-elided="true" name="TopBar2" style="width: 100px; -unity-text-align: middle-left; flex-grow: 0;" />
|
||||
<uie:ToolbarButton text="Hash" display-tooltip-when-elided="true" name="TopBar3" style="width: 250px; -unity-text-align: middle-left;" />
|
||||
<uie:ToolbarButton text="Version" display-tooltip-when-elided="true" name="TopBar4" style="width: 60px; -unity-text-align: middle-left;" />
|
||||
<uie:ToolbarButton text="Tags" display-tooltip-when-elided="true" name="TopBar5" style="width: 80px; -unity-text-align: middle-left; flex-grow: 1;" />
|
||||
</uie:Toolbar>
|
||||
<ui:ListView focusable="true" name="TopListView" item-height="18" style="flex-grow: 1;" />
|
||||
</ui:VisualElement>
|
||||
<ui:VisualElement name="BottomGroup" style="height: 200px; border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); border-top-color: rgb(0, 0, 0); border-bottom-color: rgb(0, 0, 0); margin-left: 0; margin-right: 0; margin-top: 1px; margin-bottom: 1px; display: flex;">
|
||||
<uie:Toolbar name="BottomBar" style="height: 25px; margin-left: 1px; margin-right: 1px;">
|
||||
<uie:ToolbarButton text="Include Assets" display-tooltip-when-elided="true" name="BottomBar1" style="width: 280px; -unity-text-align: middle-left; flex-grow: 1;" />
|
||||
<uie:ToolbarButton text="Size" display-tooltip-when-elided="true" name="BottomBar2" style="width: 100px; -unity-text-align: middle-left;" />
|
||||
<uie:ToolbarButton text="GUID" display-tooltip-when-elided="true" name="BottomBar3" style="width: 250px; -unity-text-align: middle-left;" />
|
||||
</uie:Toolbar>
|
||||
<ui:ListView focusable="true" name="BottomListView" item-height="18" style="flex-grow: 1;" />
|
||||
</ui:VisualElement>
|
||||
</ui:VisualElement>
|
||||
</ui:UXML>
|
||||
@@ -1,172 +0,0 @@
|
||||
#if UNITY_2019_4_OR_NEWER
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
internal class SummaryReporterViewer
|
||||
{
|
||||
private class ItemWrapper
|
||||
{
|
||||
public string Title { private set; get; }
|
||||
public string Value { private set; get; }
|
||||
|
||||
public ItemWrapper(string title, string value)
|
||||
{
|
||||
Title = title;
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
|
||||
private VisualTreeAsset _visualAsset;
|
||||
private TemplateContainer _root;
|
||||
|
||||
private ListView _listView;
|
||||
private BuildReport _buildReport;
|
||||
private readonly List<ItemWrapper> _items = new List<ItemWrapper>();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 初始化页面
|
||||
/// </summary>
|
||||
public void InitViewer()
|
||||
{
|
||||
// 加载布局文件
|
||||
string rootPath = EditorTools.GetYooAssetPath();
|
||||
string uxml = $"{rootPath}/Editor/AssetBundleReporter/VisualViewers/{nameof(SummaryReporterViewer)}.uxml";
|
||||
_visualAsset = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(uxml);
|
||||
if (_visualAsset == null)
|
||||
{
|
||||
Debug.LogError($"Not found {nameof(SummaryReporterViewer)}.uxml : {uxml}");
|
||||
return;
|
||||
}
|
||||
_root = _visualAsset.CloneTree();
|
||||
_root.style.flexGrow = 1f;
|
||||
|
||||
// 概述列表
|
||||
_listView = _root.Q<ListView>("ListView");
|
||||
_listView.makeItem = MakeListViewItem;
|
||||
_listView.bindItem = BindListViewItem;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 填充页面数据
|
||||
/// </summary>
|
||||
public void FillViewData(BuildReport buildReport)
|
||||
{
|
||||
_buildReport = buildReport;
|
||||
_listView.Clear();
|
||||
_items.Clear();
|
||||
|
||||
_items.Add(new ItemWrapper("引擎版本", buildReport.Summary.UnityVersion));
|
||||
_items.Add(new ItemWrapper("构建时间", buildReport.Summary.BuildTime));
|
||||
_items.Add(new ItemWrapper("构建耗时", $"{buildReport.Summary.BuildSeconds}秒"));
|
||||
_items.Add(new ItemWrapper("构建平台", $"{buildReport.Summary.BuildTarget}"));
|
||||
_items.Add(new ItemWrapper("构建版本", $"{buildReport.Summary.BuildVersion}"));
|
||||
_items.Add(new ItemWrapper("启用自动分包机制", $"{buildReport.Summary.EnableAutoCollect}"));
|
||||
_items.Add(new ItemWrapper("追加文件扩展名", $"{buildReport.Summary.AppendFileExtension}"));
|
||||
_items.Add(new ItemWrapper("自动收集着色器", $"{buildReport.Summary.AutoCollectShaders}"));
|
||||
_items.Add(new ItemWrapper("着色器资源包名称", $"{buildReport.Summary.ShadersBundleName}"));
|
||||
_items.Add(new ItemWrapper("加密服务类名称", $"{buildReport.Summary.EncryptionServicesClassName}"));
|
||||
|
||||
_items.Add(new ItemWrapper(string.Empty, string.Empty));
|
||||
_items.Add(new ItemWrapper("构建参数", string.Empty));
|
||||
_items.Add(new ItemWrapper("ForceRebuild", $"{buildReport.Summary.ForceRebuild}"));
|
||||
_items.Add(new ItemWrapper("BuildinTags", $"{buildReport.Summary.BuildinTags}"));
|
||||
_items.Add(new ItemWrapper("CompressOption", $"{buildReport.Summary.CompressOption}"));
|
||||
_items.Add(new ItemWrapper("AppendHash", $"{buildReport.Summary.AppendHash}"));
|
||||
_items.Add(new ItemWrapper("DisableWriteTypeTree", $"{buildReport.Summary.DisableWriteTypeTree}"));
|
||||
_items.Add(new ItemWrapper("IgnoreTypeTreeChanges", $"{buildReport.Summary.IgnoreTypeTreeChanges}"));
|
||||
_items.Add(new ItemWrapper("DisableLoadAssetByFileName", $"{buildReport.Summary.DisableLoadAssetByFileName}"));
|
||||
|
||||
_items.Add(new ItemWrapper(string.Empty, string.Empty));
|
||||
_items.Add(new ItemWrapper("构建结果", string.Empty));
|
||||
_items.Add(new ItemWrapper("构建文件总数", $"{buildReport.Summary.AssetFileTotalCount}"));
|
||||
_items.Add(new ItemWrapper("资源包总数", $"{buildReport.Summary.AllBundleTotalCount}"));
|
||||
_items.Add(new ItemWrapper("资源包总大小", ConvertSize(buildReport.Summary.AllBundleTotalSize)));
|
||||
_items.Add(new ItemWrapper("内置资源包总数", $"{buildReport.Summary.BuildinBundleTotalCount}"));
|
||||
_items.Add(new ItemWrapper("内置资源包总大小", ConvertSize(buildReport.Summary.BuildinBundleTotalSize)));
|
||||
_items.Add(new ItemWrapper("加密资源包总数", $"{buildReport.Summary.EncryptedBundleTotalCount}"));
|
||||
_items.Add(new ItemWrapper("加密资源包总大小", ConvertSize(buildReport.Summary.EncryptedBundleTotalSize)));
|
||||
_items.Add(new ItemWrapper("原生资源包总数", $"{buildReport.Summary.RawBundleTotalCount}"));
|
||||
_items.Add(new ItemWrapper("原生资源包总大小", ConvertSize(buildReport.Summary.RawBundleTotalSize)));
|
||||
|
||||
_listView.itemsSource = _items;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 挂接到父类页面上
|
||||
/// </summary>
|
||||
public void AttachParent(VisualElement parent)
|
||||
{
|
||||
parent.Add(_root);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从父类页面脱离开
|
||||
/// </summary>
|
||||
public void DetachParent()
|
||||
{
|
||||
_root.RemoveFromHierarchy();
|
||||
}
|
||||
|
||||
// 列表相关
|
||||
private VisualElement MakeListViewItem()
|
||||
{
|
||||
VisualElement element = new VisualElement();
|
||||
element.style.flexDirection = FlexDirection.Row;
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label1";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
//label.style.flexGrow = 1f;
|
||||
label.style.width = 200;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
{
|
||||
var label = new Label();
|
||||
label.name = "Label2";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
label.style.flexGrow = 1f;
|
||||
label.style.width = 150;
|
||||
element.Add(label);
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
private void BindListViewItem(VisualElement element, int index)
|
||||
{
|
||||
var itemWrapper = _items[index];
|
||||
|
||||
// Title
|
||||
var label1 = element.Q<Label>("Label1");
|
||||
label1.text = itemWrapper.Title;
|
||||
|
||||
// Value
|
||||
var label2 = element.Q<Label>("Label2");
|
||||
label2.text = itemWrapper.Value;
|
||||
}
|
||||
|
||||
private string ConvertSize(long size)
|
||||
{
|
||||
if (size == 0)
|
||||
return "0";
|
||||
if (size < 1024)
|
||||
return $"{size} Bytes";
|
||||
else if (size < 1024 * 1024)
|
||||
return $"{(int)(size / 1024)} KB";
|
||||
else
|
||||
return $"{(int)(size / (1024 * 1024))} MB";
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,9 +0,0 @@
|
||||
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="True">
|
||||
<ui:VisualElement name="TopGroup" style="flex-grow: 1; border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); border-top-color: rgb(0, 0, 0); border-bottom-color: rgb(0, 0, 0); margin-left: 0; margin-right: 0; margin-top: 2px; margin-bottom: 1px; display: flex;">
|
||||
<uie:Toolbar name="TopBar" style="height: 25px; margin-left: 1px; margin-right: 1px;">
|
||||
<uie:ToolbarButton text="概览" display-tooltip-when-elided="true" name="TopBar1" style="width: 200px; -unity-text-align: middle-left; flex-grow: 0;" />
|
||||
<uie:ToolbarButton text="参数" display-tooltip-when-elided="true" name="TopBar2" style="width: 150px; -unity-text-align: middle-left; flex-grow: 1;" />
|
||||
</uie:Toolbar>
|
||||
<ui:ListView focusable="true" name="ListView" item-height="18" style="flex-grow: 1;" />
|
||||
</ui:VisualElement>
|
||||
</ui:UXML>
|
||||
157
Assets/YooAsset/Editor/BundleBuilder/BuildAssetInfo.cs
Normal file
157
Assets/YooAsset/Editor/BundleBuilder/BuildAssetInfo.cs
Normal file
@@ -0,0 +1,157 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 构建资源信息,记录单个资源在构建过程中的元数据
|
||||
/// </summary>
|
||||
public class BuildAssetInfo
|
||||
{
|
||||
private bool _isAddAssetTags = false;
|
||||
private readonly HashSet<string> _referenceBundleNames = new HashSet<string>();
|
||||
private readonly List<string> _assetTags = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// 收集器类型
|
||||
/// </summary>
|
||||
public ECollectorType CollectorType { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 资源包完整名称
|
||||
/// </summary>
|
||||
public string BundleName { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 可寻址地址
|
||||
/// </summary>
|
||||
public string Address { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 资源信息
|
||||
/// </summary>
|
||||
public EditorAssetInfo AssetInfo { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 资源的分类标签
|
||||
/// </summary>
|
||||
public IReadOnlyList<string> AssetTags
|
||||
{
|
||||
get { return _assetTags; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 依赖的所有资源
|
||||
/// 注意:包括零依赖资源和冗余资源(资源包名无效)
|
||||
/// </summary>
|
||||
public List<BuildAssetInfo> AllDependAssetInfos { private set; get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 创建实例
|
||||
/// </summary>
|
||||
/// <param name="collectorType">收集器类型</param>
|
||||
/// <param name="bundleName">所属的资源包名称</param>
|
||||
/// <param name="address">可寻址地址</param>
|
||||
/// <param name="assetInfo">资源信息</param>
|
||||
public BuildAssetInfo(ECollectorType collectorType, string bundleName, string address, EditorAssetInfo assetInfo)
|
||||
{
|
||||
CollectorType = collectorType;
|
||||
BundleName = bundleName;
|
||||
Address = address;
|
||||
AssetInfo = assetInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建零依赖或冗余的实例
|
||||
/// </summary>
|
||||
/// <param name="assetInfo">资源信息</param>
|
||||
public BuildAssetInfo(EditorAssetInfo assetInfo)
|
||||
{
|
||||
CollectorType = ECollectorType.None;
|
||||
BundleName = string.Empty;
|
||||
Address = string.Empty;
|
||||
AssetInfo = assetInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置所有依赖的资源
|
||||
/// </summary>
|
||||
/// <param name="dependAssetInfos">依赖资源信息列表</param>
|
||||
public void SetDependAssetInfos(List<BuildAssetInfo> dependAssetInfos)
|
||||
{
|
||||
if (AllDependAssetInfos != null)
|
||||
throw new YooInternalException("Should never get here.");
|
||||
|
||||
AllDependAssetInfos = dependAssetInfos;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置资源包名称
|
||||
/// </summary>
|
||||
/// <param name="bundleName">资源包完整名称</param>
|
||||
public void SetBundleName(string bundleName)
|
||||
{
|
||||
if (HasBundleName())
|
||||
throw new YooInternalException("Should never get here.");
|
||||
|
||||
BundleName = bundleName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加资源的分类标签
|
||||
/// </summary>
|
||||
/// <remarks>仅在首次调用时生效,不可重复设置。</remarks>
|
||||
/// <param name="tags">资源分类标签列表</param>
|
||||
public void AddAssetTags(List<string> tags)
|
||||
{
|
||||
if (_isAddAssetTags)
|
||||
throw new YooInternalException("Should never get here.");
|
||||
_isAddAssetTags = true;
|
||||
|
||||
foreach (var tag in tags)
|
||||
{
|
||||
if (_assetTags.Contains(tag) == false)
|
||||
{
|
||||
_assetTags.Add(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加关联的资源包名称
|
||||
/// </summary>
|
||||
/// <param name="bundleName">引用该资源的资源包名称</param>
|
||||
public void AddReferenceBundleName(string bundleName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(bundleName))
|
||||
throw new YooInternalException("Should never get here.");
|
||||
|
||||
if (_referenceBundleNames.Contains(bundleName) == false)
|
||||
_referenceBundleNames.Add(bundleName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否已分配资源包名称
|
||||
/// </summary>
|
||||
/// <returns>已分配返回 true,否则返回 false</returns>
|
||||
public bool HasBundleName()
|
||||
{
|
||||
if (string.IsNullOrEmpty(BundleName))
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取关联资源包的数量
|
||||
/// </summary>
|
||||
/// <returns>引用该资源的资源包数量</returns>
|
||||
public int GetReferenceBundleCount()
|
||||
{
|
||||
return _referenceBundleNames.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
234
Assets/YooAsset/Editor/BundleBuilder/BuildBundleInfo.cs
Normal file
234
Assets/YooAsset/Editor/BundleBuilder/BuildBundleInfo.cs
Normal file
@@ -0,0 +1,234 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 构建资源包信息,记录单个资源包在构建过程中的完整元数据
|
||||
/// </summary>
|
||||
public class BuildBundleInfo
|
||||
{
|
||||
#region 补丁文件的关键信息
|
||||
/// <summary>
|
||||
/// Unity引擎生成的哈希值(构建内容的哈希值)
|
||||
/// </summary>
|
||||
public string PackageUnityHash { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// Unity引擎生成的CRC
|
||||
/// </summary>
|
||||
public uint PackageUnityCRC { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 文件哈希值
|
||||
/// </summary>
|
||||
public string PackageFileHash { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 文件 CRC 校验值
|
||||
/// </summary>
|
||||
public uint PackageFileCRC { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 文件大小(字节)
|
||||
/// </summary>
|
||||
public long PackageFileSize { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 构建输出的文件路径
|
||||
/// </summary>
|
||||
public string BuildOutputFilePath { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 补丁包的源文件路径
|
||||
/// </summary>
|
||||
public string PackageSourceFilePath { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 补丁包的目标文件路径
|
||||
/// </summary>
|
||||
public string PackageDestFilePath { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 加密生成文件的路径
|
||||
/// 注意:如果未加密该路径为空
|
||||
/// </summary>
|
||||
public string EncryptedFilePath { set; get; }
|
||||
#endregion
|
||||
|
||||
private readonly Dictionary<string, BuildAssetInfo> _packAssetDictionary = new Dictionary<string, BuildAssetInfo>(100);
|
||||
private readonly List<BuildAssetInfo> _allPackAssets = new List<BuildAssetInfo>(100);
|
||||
|
||||
/// <summary>
|
||||
/// 参与构建的资源列表
|
||||
/// 注意:不包含零依赖资源和冗余资源
|
||||
/// </summary>
|
||||
public IReadOnlyList<BuildAssetInfo> AllPackAssets
|
||||
{
|
||||
get { return _allPackAssets; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 资源包名称
|
||||
/// </summary>
|
||||
public string BundleName { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否已加密
|
||||
/// </summary>
|
||||
public bool Encrypted { set; get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 创建实例
|
||||
/// </summary>
|
||||
/// <param name="bundleName">资源包名称</param>
|
||||
public BuildBundleInfo(string bundleName)
|
||||
{
|
||||
BundleName = bundleName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加一个打包资源
|
||||
/// </summary>
|
||||
/// <param name="buildAsset">待打包的资源信息</param>
|
||||
public void PackAsset(BuildAssetInfo buildAsset)
|
||||
{
|
||||
string assetPath = buildAsset.AssetInfo.AssetPath;
|
||||
if (_packAssetDictionary.ContainsKey(assetPath))
|
||||
throw new YooInternalException($"Should never get here. Asset already exists: '{assetPath}'.");
|
||||
|
||||
_packAssetDictionary.Add(assetPath, buildAsset);
|
||||
_allPackAssets.Add(buildAsset);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否包含指定资源
|
||||
/// </summary>
|
||||
/// <param name="assetPath">资源路径</param>
|
||||
/// <returns>包含返回 true,否则返回 false</returns>
|
||||
public bool IsContainsPackAsset(string assetPath)
|
||||
{
|
||||
return _packAssetDictionary.ContainsKey(assetPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取构建的资源路径列表
|
||||
/// </summary>
|
||||
/// <returns>所有打包资源的路径数组</returns>
|
||||
public string[] GetAllPackAssetPaths()
|
||||
{
|
||||
List<string> results = new List<string>(AllPackAssets.Count);
|
||||
for (int i = 0; i < AllPackAssets.Count; i++)
|
||||
{
|
||||
var packAsset = AllPackAssets[i];
|
||||
results.Add(packAsset.AssetInfo.AssetPath);
|
||||
}
|
||||
return results.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取构建的资源可寻址列表
|
||||
/// </summary>
|
||||
/// <returns>所有打包资源的可寻址地址数组</returns>
|
||||
public string[] GetAllPackAssetAddress()
|
||||
{
|
||||
List<string> results = new List<string>(AllPackAssets.Count);
|
||||
for (int i = 0; i < AllPackAssets.Count; i++)
|
||||
{
|
||||
var packAsset = AllPackAssets[i];
|
||||
results.Add(packAsset.Address);
|
||||
}
|
||||
return results.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取构建的主资源信息
|
||||
/// </summary>
|
||||
/// <param name="assetPath">资源路径</param>
|
||||
/// <returns>对应的构建资源信息</returns>
|
||||
public BuildAssetInfo GetPackAssetInfo(string assetPath)
|
||||
{
|
||||
if (_packAssetDictionary.TryGetValue(assetPath, out BuildAssetInfo value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException($"Could not find pack asset info '{assetPath}' in bundle: '{BundleName}'.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源包内部所有资产
|
||||
/// </summary>
|
||||
/// <returns>资源包包含的所有资源信息列表</returns>
|
||||
public List<EditorAssetInfo> GetBundleContents()
|
||||
{
|
||||
Dictionary<string, EditorAssetInfo> result = new Dictionary<string, EditorAssetInfo>(AllPackAssets.Count);
|
||||
foreach (var packAsset in AllPackAssets)
|
||||
{
|
||||
result.Add(packAsset.AssetInfo.AssetPath, packAsset.AssetInfo);
|
||||
if (packAsset.AllDependAssetInfos != null)
|
||||
{
|
||||
foreach (var dependAssetInfo in packAsset.AllDependAssetInfos)
|
||||
{
|
||||
// 注意:依赖资源里只添加零依赖资源和冗余资源
|
||||
if (dependAssetInfo.HasBundleName() == false)
|
||||
{
|
||||
string dependAssetPath = dependAssetInfo.AssetInfo.AssetPath;
|
||||
if (result.ContainsKey(dependAssetPath) == false)
|
||||
result.Add(dependAssetPath, dependAssetInfo.AssetInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.Values.ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建 Unity 构建管线所需的数据
|
||||
/// </summary>
|
||||
/// <param name="replaceAssetPathWithAddress">是否使用可寻址地址替代资源路径</param>
|
||||
/// <returns>构建管线所需的 AssetBundleBuild 数据</returns>
|
||||
public UnityEditor.AssetBundleBuild CreatePipelineBuild(bool replaceAssetPathWithAddress)
|
||||
{
|
||||
// 注意:我们不再支持AssetBundle的变种机制
|
||||
AssetBundleBuild build = new AssetBundleBuild();
|
||||
build.assetBundleName = BundleName;
|
||||
build.assetBundleVariant = string.Empty;
|
||||
build.assetNames = GetAllPackAssetPaths();
|
||||
if (replaceAssetPathWithAddress)
|
||||
build.addressableNames = GetAllPackAssetAddress();
|
||||
return build;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有写入补丁清单的资源
|
||||
/// </summary>
|
||||
/// <returns>需要写入清单的主资源信息数组</returns>
|
||||
public BuildAssetInfo[] GetAllManifestAssetInfos()
|
||||
{
|
||||
return AllPackAssets.Where(t => t.CollectorType == ECollectorType.MainAssetCollector).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建PackageBundle类
|
||||
/// </summary>
|
||||
internal PackageBundle CreatePackageBundle()
|
||||
{
|
||||
PackageBundle packageBundle = new PackageBundle();
|
||||
packageBundle.BundleName = BundleName;
|
||||
packageBundle.UnityCrc = PackageUnityCRC;
|
||||
packageBundle.FileHash = PackageFileHash;
|
||||
packageBundle.FileCrc = PackageFileCRC;
|
||||
packageBundle.FileSize = PackageFileSize;
|
||||
packageBundle.IsEncrypted = Encrypted;
|
||||
packageBundle.DependentBundleIDs = Array.Empty<int>();
|
||||
return packageBundle;
|
||||
}
|
||||
}
|
||||
}
|
||||
148
Assets/YooAsset/Editor/BundleBuilder/BuildMapContext.cs
Normal file
148
Assets/YooAsset/Editor/BundleBuilder/BuildMapContext.cs
Normal file
@@ -0,0 +1,148 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 构建资源映射上下文,管理构建过程中所有资源包和资源的映射关系
|
||||
/// </summary>
|
||||
[ContextObject]
|
||||
public class BuildMapContext
|
||||
{
|
||||
private readonly Dictionary<string, BuildBundleInfo> _bundleInfoDictionary = new Dictionary<string, BuildBundleInfo>(10000);
|
||||
private readonly List<BuildAssetInfo> _spriteAtlasAssetList = new List<BuildAssetInfo>(10000);
|
||||
private readonly List<ReportIndependentAsset> _independentAssets = new List<ReportIndependentAsset>(1000);
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 参与构建的资源总数
|
||||
/// </summary>
|
||||
/// <remarks>包括主动收集的资源以及其依赖的所有资源。</remarks>
|
||||
public int AssetFileCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 资源收集命令
|
||||
/// </summary>
|
||||
public CollectCommand Command { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 资源包信息列表
|
||||
/// </summary>
|
||||
public Dictionary<string, BuildBundleInfo>.ValueCollection Collection
|
||||
{
|
||||
get
|
||||
{
|
||||
return _bundleInfoDictionary.Values;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 图集资源集合
|
||||
/// </summary>
|
||||
public IReadOnlyList<BuildAssetInfo> SpriteAtlasAssetList
|
||||
{
|
||||
get { return _spriteAtlasAssetList; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 未被依赖的资源列表
|
||||
/// </summary>
|
||||
public IReadOnlyList<ReportIndependentAsset> IndependentAssets
|
||||
{
|
||||
get { return _independentAssets; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 添加一个未被依赖的资源
|
||||
/// </summary>
|
||||
internal void AddIndependentAsset(ReportIndependentAsset asset)
|
||||
{
|
||||
_independentAssets.Add(asset);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加一个打包资源
|
||||
/// </summary>
|
||||
/// <param name="assetInfo">待打包的资源信息</param>
|
||||
public void PackAsset(BuildAssetInfo assetInfo)
|
||||
{
|
||||
string bundleName = assetInfo.BundleName;
|
||||
if (string.IsNullOrEmpty(bundleName))
|
||||
throw new YooInternalException("Should never get here.");
|
||||
|
||||
if (_bundleInfoDictionary.TryGetValue(bundleName, out BuildBundleInfo bundleInfo))
|
||||
{
|
||||
bundleInfo.PackAsset(assetInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
BuildBundleInfo newBundleInfo = new BuildBundleInfo(bundleName);
|
||||
newBundleInfo.PackAsset(assetInfo);
|
||||
_bundleInfoDictionary.Add(bundleName, newBundleInfo);
|
||||
}
|
||||
|
||||
// 统计所有的精灵图集
|
||||
if (assetInfo.AssetInfo.IsSpriteAtlas())
|
||||
{
|
||||
_spriteAtlasAssetList.Add(assetInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否包含指定名称的资源包
|
||||
/// </summary>
|
||||
/// <param name="bundleName">资源包名称</param>
|
||||
/// <returns>包含返回 true,否则返回 false</returns>
|
||||
public bool IsContainsBundle(string bundleName)
|
||||
{
|
||||
return _bundleInfoDictionary.ContainsKey(bundleName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源包信息
|
||||
/// </summary>
|
||||
/// <param name="bundleName">资源包名称</param>
|
||||
/// <returns>对应的资源包构建信息</returns>
|
||||
public BuildBundleInfo GetBundleInfo(string bundleName)
|
||||
{
|
||||
if (_bundleInfoDictionary.TryGetValue(bundleName, out BuildBundleInfo result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
throw new YooInternalException($"Should never get here. Bundle not found: '{bundleName}'.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取构建管线里需要的数据
|
||||
/// </summary>
|
||||
/// <param name="replaceAssetPathWithAddress">是否使用可寻址地址替代资源路径</param>
|
||||
/// <returns>所有资源包的 AssetBundleBuild 数据数组</returns>
|
||||
public UnityEditor.AssetBundleBuild[] GetPipelineBuilds(bool replaceAssetPathWithAddress)
|
||||
{
|
||||
List<UnityEditor.AssetBundleBuild> builds = new List<UnityEditor.AssetBundleBuild>(_bundleInfoDictionary.Count);
|
||||
foreach (var bundleInfo in _bundleInfoDictionary.Values)
|
||||
{
|
||||
builds.Add(bundleInfo.CreatePipelineBuild(replaceAssetPathWithAddress));
|
||||
}
|
||||
return builds.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建空的资源包
|
||||
/// </summary>
|
||||
/// <param name="bundleName">资源包名称</param>
|
||||
public void CreateEmptyBundleInfo(string bundleName)
|
||||
{
|
||||
if (IsContainsBundle(bundleName) == false)
|
||||
{
|
||||
var bundleInfo = new BuildBundleInfo(bundleName);
|
||||
_bundleInfoDictionary.Add(bundleName, bundleInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
249
Assets/YooAsset/Editor/BundleBuilder/BuildParameters.cs
Normal file
249
Assets/YooAsset/Editor/BundleBuilder/BuildParameters.cs
Normal file
@@ -0,0 +1,249 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 构建参数
|
||||
/// </summary>
|
||||
public abstract class BuildParameters
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 构建输出的根目录
|
||||
/// </summary>
|
||||
public string BuildOutputRoot { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 首包资源的根目录
|
||||
/// </summary>
|
||||
public string BundledFileRoot { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 构建管线名称
|
||||
/// </summary>
|
||||
public string BuildPipeline { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 构建资源包类型
|
||||
/// </summary>
|
||||
public int BuildBundleType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 构建的平台
|
||||
/// </summary>
|
||||
public BuildTarget BuildTarget { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 构建的包裹名称
|
||||
/// </summary>
|
||||
public string PackageName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 构建的包裹版本
|
||||
/// </summary>
|
||||
public string PackageVersion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 构建的包裹备注
|
||||
/// </summary>
|
||||
public string PackageNote { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 清空构建缓存文件
|
||||
/// </summary>
|
||||
public bool ClearBuildCacheFiles { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 是否使用资源依赖缓存数据库
|
||||
/// </summary>
|
||||
/// <remarks>开启此项可以极大提高资源收集速度</remarks>
|
||||
public bool UseAssetDependencyDB { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 启用共享资源打包
|
||||
/// </summary>
|
||||
public bool EnableSharePackRule { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 是否对单独引用的共享资源进行独立打包
|
||||
/// </summary>
|
||||
/// <remarks>关闭该选项,单独引用的共享资源将会构建到引用它的资源包内。</remarks>
|
||||
public bool SingleReferencedPackAlone { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 验证构建结果
|
||||
/// </summary>
|
||||
public bool VerifyBuildingResult { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 资源包名称样式
|
||||
/// </summary>
|
||||
public EFileNameStyle FileNameStyle { get; set; } = EFileNameStyle.HashName;
|
||||
|
||||
/// <summary>
|
||||
/// 首包资源的拷贝选项
|
||||
/// </summary>
|
||||
public EBundledCopyOption BundledCopyOption { get; set; } = EBundledCopyOption.None;
|
||||
|
||||
/// <summary>
|
||||
/// 首包资源的拷贝参数
|
||||
/// </summary>
|
||||
public string BundledCopyParams { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 资源包加密器
|
||||
/// </summary>
|
||||
public IBundleEncryptor BundleEncryptor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 资源清单加密器
|
||||
/// </summary>
|
||||
public IManifestEncryptor ManifestEncryptor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 资源清单解密器
|
||||
/// </summary>
|
||||
public IManifestDecryptor ManifestDecryptor { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 检测构建参数是否合法
|
||||
/// </summary>
|
||||
public void CheckBuildParameters()
|
||||
{
|
||||
// 检测当前是否正在构建资源包
|
||||
if (UnityEditor.BuildPipeline.isBuildingPlayer)
|
||||
{
|
||||
string message = BuildLogger.GetErrorMessage(ErrorCode.ThePipelineIsBuiding, "Pipeline build is in progress.");
|
||||
throw new InvalidOperationException(message);
|
||||
}
|
||||
|
||||
// 检测构建参数合法性
|
||||
if (BuildTarget == BuildTarget.NoTarget)
|
||||
{
|
||||
string message = BuildLogger.GetErrorMessage(ErrorCode.NoBuildTarget, "Build target platform is not selected.");
|
||||
throw new ArgumentException(message, nameof(BuildTarget));
|
||||
}
|
||||
if (string.IsNullOrEmpty(BuildOutputRoot))
|
||||
{
|
||||
string message = BuildLogger.GetErrorMessage(ErrorCode.BuildOutputRootIsNullOrEmpty, "Build output root is null or empty.");
|
||||
throw new ArgumentException(message, nameof(BuildOutputRoot));
|
||||
}
|
||||
if (string.IsNullOrEmpty(BundledFileRoot))
|
||||
{
|
||||
string message = BuildLogger.GetErrorMessage(ErrorCode.BundledRootIsNullOrEmpty, "Bundled file root is null or empty.");
|
||||
throw new ArgumentException(message, nameof(BundledFileRoot));
|
||||
}
|
||||
if (string.IsNullOrEmpty(BuildPipeline))
|
||||
{
|
||||
string message = BuildLogger.GetErrorMessage(ErrorCode.BuildPipelineIsNullOrEmpty, "Build pipeline is null or empty.");
|
||||
throw new ArgumentException(message, nameof(BuildPipeline));
|
||||
}
|
||||
if (BuildBundleType == (int)EBundleType.None)
|
||||
{
|
||||
string message = BuildLogger.GetErrorMessage(ErrorCode.BuildBundleTypeIsUnknown, $"Build bundle type is unknown: {BuildBundleType}.");
|
||||
throw new ArgumentException(message, nameof(BuildBundleType));
|
||||
}
|
||||
if (string.IsNullOrEmpty(PackageName))
|
||||
{
|
||||
string message = BuildLogger.GetErrorMessage(ErrorCode.PackageNameIsNullOrEmpty, "Package name is null or empty.");
|
||||
throw new ArgumentException(message, nameof(PackageName));
|
||||
}
|
||||
if (string.IsNullOrEmpty(PackageVersion))
|
||||
{
|
||||
string message = BuildLogger.GetErrorMessage(ErrorCode.PackageVersionIsNullOrEmpty, "Package version is null or empty.");
|
||||
throw new ArgumentException(message, nameof(PackageVersion));
|
||||
}
|
||||
|
||||
// 设置默认备注信息
|
||||
if (string.IsNullOrEmpty(PackageNote))
|
||||
{
|
||||
PackageNote = DateTime.Now.ToString();
|
||||
}
|
||||
|
||||
CheckBuildParametersCore();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取构建管线的输出目录
|
||||
/// </summary>
|
||||
/// <returns>构建管线的输出目录路径</returns>
|
||||
public string GetPipelineOutputDirectory()
|
||||
{
|
||||
return GetPipelineOutputDirectoryCore();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取本次构建的补丁输出目录
|
||||
/// </summary>
|
||||
/// <returns>本次构建的补丁输出目录路径</returns>
|
||||
public string GetPackageOutputDirectory()
|
||||
{
|
||||
return GetPackageOutputDirectoryCore();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取本次构建的补丁根目录
|
||||
/// </summary>
|
||||
/// <returns>本次构建的补丁根目录路径</returns>
|
||||
public string GetPackageRootDirectory()
|
||||
{
|
||||
return GetPackageRootDirectoryCore();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取首包资源的根目录
|
||||
/// </summary>
|
||||
/// <returns>首包资源的根目录路径</returns>
|
||||
public string GetBundledRootDirectory()
|
||||
{
|
||||
return GetBundledRootDirectoryCore();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 执行子类特定的构建参数验证
|
||||
/// </summary>
|
||||
protected virtual void CheckBuildParametersCore() { }
|
||||
|
||||
/// <summary>
|
||||
/// 获取构建管线输出目录的核心实现
|
||||
/// </summary>
|
||||
/// <returns>构建管线的输出目录路径</returns>
|
||||
protected virtual string GetPipelineOutputDirectoryCore()
|
||||
{
|
||||
return $"{BuildOutputRoot}/{BuildTarget}/{PackageName}/{YooAssetSettings.OutputFolderName}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取补丁输出目录的核心实现
|
||||
/// </summary>
|
||||
/// <returns>本次构建的补丁输出目录路径</returns>
|
||||
protected virtual string GetPackageOutputDirectoryCore()
|
||||
{
|
||||
return $"{BuildOutputRoot}/{BuildTarget}/{PackageName}/{PackageVersion}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取补丁根目录的核心实现
|
||||
/// </summary>
|
||||
/// <returns>本次构建的补丁根目录路径</returns>
|
||||
protected virtual string GetPackageRootDirectoryCore()
|
||||
{
|
||||
return $"{BuildOutputRoot}/{BuildTarget}/{PackageName}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取首包资源根目录的核心实现
|
||||
/// </summary>
|
||||
/// <returns>首包资源的根目录路径</returns>
|
||||
protected virtual string GetBundledRootDirectoryCore()
|
||||
{
|
||||
return $"{BundledFileRoot}/{PackageName}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 构建参数上下文
|
||||
/// </summary>
|
||||
[ContextObject]
|
||||
public class BuildParametersContext
|
||||
{
|
||||
/// <summary>
|
||||
/// 构建参数
|
||||
/// </summary>
|
||||
public BuildParameters Parameters { private set; get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 创建实例
|
||||
/// </summary>
|
||||
/// <param name="parameters">构建参数</param>
|
||||
public BuildParametersContext(BuildParameters parameters)
|
||||
{
|
||||
Parameters = parameters;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测构建参数是否合法
|
||||
/// </summary>
|
||||
public void CheckBuildParameters()
|
||||
{
|
||||
Parameters.CheckBuildParameters();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取构建管线的输出目录
|
||||
/// </summary>
|
||||
/// <returns>构建管线的输出目录路径</returns>
|
||||
public string GetPipelineOutputDirectory()
|
||||
{
|
||||
return Parameters.GetPipelineOutputDirectory();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取本次构建的补丁输出目录
|
||||
/// </summary>
|
||||
/// <returns>本次构建的补丁输出目录路径</returns>
|
||||
public string GetPackageOutputDirectory()
|
||||
{
|
||||
return Parameters.GetPackageOutputDirectory();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取本次构建的补丁根目录
|
||||
/// </summary>
|
||||
/// <returns>本次构建的补丁根目录路径</returns>
|
||||
public string GetPackageRootDirectory()
|
||||
{
|
||||
return Parameters.GetPackageRootDirectory();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取首包资源的根目录
|
||||
/// </summary>
|
||||
/// <returns>首包资源的根目录路径</returns>
|
||||
public string GetBundledRootDirectory()
|
||||
{
|
||||
return Parameters.GetBundledRootDirectory();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d110092f543e3fe40a4d3882e1a718e8
|
||||
guid: b84510feab7cbe44a9b6d8ef0b3f559c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d6268d725eec21b4aae819adc1553f0e
|
||||
guid: 431722e1bca52d448825f603789d7e4b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a82eeb6a47cd02c4cb38e851c8ed8784
|
||||
guid: da26c791ca572fe4a818405173661568
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
@@ -0,0 +1,112 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 归档文件构建辅助工具类
|
||||
/// </summary>
|
||||
internal static class ArchiveFileBuildHelper
|
||||
{
|
||||
private const int StreamCopyBufferSize = 81920;
|
||||
|
||||
/// <summary>
|
||||
/// 收集构建资源的归档条目列表,并按 FilePath 字典序排序
|
||||
/// </summary>
|
||||
public static List<ArchiveFileEntry> CollectEntries(IReadOnlyList<BuildAssetInfo> allAssets)
|
||||
{
|
||||
var entries = new List<ArchiveFileEntry>(allAssets.Count);
|
||||
foreach (var asset in allAssets)
|
||||
{
|
||||
string assetPath = asset.AssetInfo.AssetPath;
|
||||
long dataLength = new FileInfo(assetPath).Length;
|
||||
uint crc = HashUtility.ComputeFileCrc32AsUInt(assetPath);
|
||||
entries.Add(new ArchiveFileEntry(assetPath, dataLength, crc));
|
||||
}
|
||||
|
||||
entries.Sort((a, b) => string.Compare(a.AssetPath, b.AssetPath, StringComparison.Ordinal));
|
||||
return entries;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算每个条目的绝对偏移,并写入归档文件
|
||||
/// </summary>
|
||||
/// <param name="outputPath">输出文件路径</param>
|
||||
/// <param name="entries">归档条目列表</param>
|
||||
/// <param name="fileAlignment">文件数据对齐字节数(0 表示不对齐)</param>
|
||||
public static void BuildArchiveFile(string outputPath, List<ArchiveFileEntry> entries, int fileAlignment)
|
||||
{
|
||||
int fileCount = entries.Count;
|
||||
if (fileCount > ArchiveBundleConsts.MaxChildFileCount)
|
||||
throw new InvalidOperationException($"Archive child file count {fileCount} exceeds maximum ({ArchiveBundleConsts.MaxChildFileCount}).");
|
||||
|
||||
// 1. 计算 header 总大小
|
||||
int headerSize = 4 + 4 + 4; // Magic + Version + FileCount
|
||||
foreach (var entry in entries)
|
||||
{
|
||||
byte[] pathBytes = entry.GetPathBytes();
|
||||
// FilePathLen(4) + FilePath(变长) + DataOffset(8) + DataLength(8) + FileCRC(4)
|
||||
headerSize += 4 + pathBytes.Length + 8 + 8 + 4;
|
||||
}
|
||||
|
||||
// 2. 计算每个文件的绝对偏移
|
||||
long currentOffset = headerSize;
|
||||
foreach (var entry in entries)
|
||||
{
|
||||
if (fileAlignment > 0)
|
||||
currentOffset = AlignOffset(currentOffset, fileAlignment);
|
||||
entry.DataOffset = currentOffset;
|
||||
currentOffset += entry.DataLength;
|
||||
}
|
||||
|
||||
// 3. 写入归档文件
|
||||
EditorFileUtility.CreateFileDirectory(outputPath);
|
||||
using (var fs = new FileStream(outputPath, FileMode.Create, FileAccess.Write))
|
||||
using (var writer = new BinaryWriter(fs))
|
||||
{
|
||||
// Header
|
||||
writer.Write(ArchiveBundleConsts.FileMagic);
|
||||
writer.Write(ArchiveBundleConsts.FileVersion);
|
||||
writer.Write(fileCount);
|
||||
|
||||
foreach (var entry in entries)
|
||||
{
|
||||
byte[] pathBytes = entry.GetPathBytes();
|
||||
writer.Write(pathBytes.Length);
|
||||
writer.Write(pathBytes);
|
||||
writer.Write(entry.DataOffset);
|
||||
writer.Write(entry.DataLength);
|
||||
writer.Write(entry.FileCRC);
|
||||
}
|
||||
|
||||
// Data: 按排序后的顺序写入,使用流式拷贝避免大文件 OOM
|
||||
byte[] buffer = new byte[StreamCopyBufferSize];
|
||||
foreach (var entry in entries)
|
||||
{
|
||||
// 填充对齐字节
|
||||
long paddingSize = entry.DataOffset - fs.Position;
|
||||
if (paddingSize > 0)
|
||||
writer.Write(new byte[paddingSize]);
|
||||
|
||||
using (var sourceStream = new FileStream(entry.AssetPath, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
int bytesRead;
|
||||
while ((bytesRead = sourceStream.Read(buffer, 0, buffer.Length)) > 0)
|
||||
{
|
||||
writer.Write(buffer, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将偏移值向上对齐到指定字节边界
|
||||
/// </summary>
|
||||
private static long AlignOffset(long offset, int alignment)
|
||||
{
|
||||
return (offset + alignment - 1) / alignment * alignment;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9466e826c135e994c84961e4b921ca5f
|
||||
guid: 3f8daa3aacb5da8458fc073431da1891
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 归档文件构建管线的构建参数
|
||||
/// </summary>
|
||||
public class ArchiveFileBuildParameters : BuildParameters
|
||||
{
|
||||
private const int MaxFileAlignment = 4096;
|
||||
|
||||
/// <summary>
|
||||
/// 文件哈希值计算包含路径信息
|
||||
/// </summary>
|
||||
public bool IncludePathInHash { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 归档文件内数据对齐字节数(0 表示不对齐)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 对齐后每个子文件的数据偏移会向上取整到该值的整数倍,文件间以零字节填充。
|
||||
/// 推荐值:4(通用对齐)、512(磁盘扇区对齐)、4096(内存页对齐)。
|
||||
/// </remarks>
|
||||
public int FileAlignment { get; set; } = 0;
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void CheckBuildParametersCore()
|
||||
{
|
||||
// ArchiveBundle 不支持资源包加密
|
||||
if (BundleEncryptor != null)
|
||||
{
|
||||
string message = BuildLogger.GetErrorMessage(ErrorCode.BundleEncryptionNotSupported,
|
||||
$"ArchiveFileBuildPipeline does not support bundle encryption. Please remove the BundleEncryptor configuration.");
|
||||
throw new NotSupportedException(message);
|
||||
}
|
||||
|
||||
// 校验文件对齐参数范围
|
||||
if (FileAlignment < 0 || FileAlignment > MaxFileAlignment)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(FileAlignment),
|
||||
$"FileAlignment must be between 0 and {MaxFileAlignment}. Current value: {FileAlignment}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fe50795c51a46884088139b840c1557f
|
||||
guid: 83bdf0f6502d23f49ae900d98f459c7b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 归档文件构建管线,将同一 BundleName 下的多个原始文件合并写入一个归档文件
|
||||
/// </summary>
|
||||
public class ArchiveFileBuildPipeline : IBuildPipeline
|
||||
{
|
||||
/// <summary>
|
||||
/// 执行构建流程
|
||||
/// </summary>
|
||||
public BuildResult Run(BuildParameters buildParameters, bool enableLog)
|
||||
{
|
||||
if (buildParameters is ArchiveFileBuildParameters)
|
||||
{
|
||||
BundleBuilder builder = new BundleBuilder();
|
||||
return builder.Run(buildParameters, GetDefaultBuildPipeline(), enableLog);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Invalid build parameter type: '{buildParameters.GetType().Name}'.", nameof(buildParameters));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取默认的构建流程
|
||||
/// </summary>
|
||||
private List<IBuildTask> GetDefaultBuildPipeline()
|
||||
{
|
||||
List<IBuildTask> pipeline = new List<IBuildTask>
|
||||
{
|
||||
new TaskPrepare_AFBP(),
|
||||
new TaskGetBuildMap_AFBP(),
|
||||
new TaskBuilding_AFBP(),
|
||||
new TaskEncryption_AFBP(),
|
||||
new TaskUpdateBundleInfo_AFBP(),
|
||||
new TaskCreateManifest_AFBP(),
|
||||
new TaskCreateReport_AFBP(),
|
||||
new TaskCreatePackage_AFBP(),
|
||||
new TaskCopyBundledFiles_AFBP(),
|
||||
new TaskCreateCatalog_AFBP()
|
||||
};
|
||||
return pipeline;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 19ef6fc50bd422c4db6fa53cbf0fe226
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,61 @@
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 归档文件条目信息(构建期临时数据结构)
|
||||
/// </summary>
|
||||
internal class ArchiveFileEntry
|
||||
{
|
||||
private byte[] _pathBytes;
|
||||
|
||||
/// <summary>
|
||||
/// 文件路径
|
||||
/// </summary>
|
||||
public readonly string AssetPath;
|
||||
|
||||
/// <summary>
|
||||
/// 文件数据长度
|
||||
/// </summary>
|
||||
public readonly long DataLength;
|
||||
|
||||
/// <summary>
|
||||
/// 文件 CRC32
|
||||
/// </summary>
|
||||
public readonly uint FileCRC;
|
||||
|
||||
/// <summary>
|
||||
/// 数据在归档文件中的绝对偏移
|
||||
/// </summary>
|
||||
public long DataOffset;
|
||||
|
||||
/// <summary>
|
||||
/// 构造归档文件条目
|
||||
/// </summary>
|
||||
public ArchiveFileEntry(string assetPath, long dataLength, uint fileCRC)
|
||||
{
|
||||
if (string.IsNullOrEmpty(assetPath))
|
||||
throw new ArgumentException("Asset path is null or empty.", nameof(assetPath));
|
||||
if (dataLength < 0)
|
||||
throw new ArgumentException($"Invalid data length {dataLength} for '{assetPath}'.", nameof(dataLength));
|
||||
if (dataLength > ArchiveBundleConsts.MaxChildFileSize)
|
||||
throw new ArgumentException($"Child file exceeds maximum size ({ArchiveBundleConsts.MaxChildFileSize} bytes): '{assetPath}' ({dataLength} bytes).", nameof(dataLength));
|
||||
|
||||
AssetPath = assetPath;
|
||||
DataLength = dataLength;
|
||||
FileCRC = fileCRC;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取文件路径的 UTF8 字节缓存
|
||||
/// </summary>
|
||||
public byte[] GetPathBytes()
|
||||
{
|
||||
if (_pathBytes == null)
|
||||
_pathBytes = Encoding.UTF8.GetBytes(AssetPath);
|
||||
return _pathBytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a03062dc3dd175c438fcb92d3e06a33b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e9d6cb1ce5d510645866ad7c122abfab
|
||||
guid: b9dccc7a4589001469444e571235890a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
@@ -0,0 +1,29 @@
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 归档文件构建管线的核心构建任务
|
||||
/// </summary>
|
||||
public class TaskBuilding_AFBP : IBuildTask
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
void IBuildTask.Run(BuildContext context)
|
||||
{
|
||||
var buildMapContext = context.GetContextObject<BuildMapContext>();
|
||||
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
|
||||
var buildParameters = buildParametersContext.Parameters as ArchiveFileBuildParameters;
|
||||
string pipelineOutputDirectory = buildParametersContext.GetPipelineOutputDirectory();
|
||||
|
||||
int progressValue = 0;
|
||||
int fileTotalCount = buildMapContext.Collection.Count;
|
||||
foreach (var bundleInfo in buildMapContext.Collection)
|
||||
{
|
||||
string archiveFilePath = $"{pipelineOutputDirectory}/{bundleInfo.BundleName}";
|
||||
var entries = ArchiveFileBuildHelper.CollectEntries(bundleInfo.AllPackAssets);
|
||||
ArchiveFileBuildHelper.BuildArchiveFile(archiveFilePath, entries, buildParameters.FileAlignment);
|
||||
EditorDialogUtility.DisplayProgressBar("Build archive files", ++progressValue, fileTotalCount);
|
||||
}
|
||||
EditorDialogUtility.ClearProgressBar();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 289e760820002e34b9054a81098d5fa4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using UnityEditor;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 归档文件构建管线的首包资源拷贝任务
|
||||
/// </summary>
|
||||
public class TaskCopyBundledFiles_AFBP : TaskCopyBundledFiles, IBuildTask
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
void IBuildTask.Run(BuildContext context)
|
||||
{
|
||||
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
|
||||
var buildParameters = buildParametersContext.Parameters;
|
||||
var manifestContext = context.GetContextObject<ManifestContext>();
|
||||
if (buildParameters.BundledCopyOption != EBundledCopyOption.None)
|
||||
{
|
||||
CopyBundledFilesToStreaming(buildParametersContext, manifestContext.Manifest);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e4fb32a77b3e799448cf4eae2a97a49e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using UnityEditor;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 归档文件构建管线的资源目录创建任务
|
||||
/// </summary>
|
||||
public class TaskCreateCatalog_AFBP : TaskCreateCatalog, IBuildTask
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
void IBuildTask.Run(BuildContext context)
|
||||
{
|
||||
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
|
||||
if (buildParametersContext.Parameters.BundledCopyOption != EBundledCopyOption.None)
|
||||
{
|
||||
CreateCatalogFile(buildParametersContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 813f7821d87b6f8498ddc4d675512413
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 归档文件构建管线的清单创建任务
|
||||
/// </summary>
|
||||
public class TaskCreateManifest_AFBP : TaskCreateManifest, IBuildTask
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
void IBuildTask.Run(BuildContext context)
|
||||
{
|
||||
CreateManifestFile(false, true, false, context);
|
||||
}
|
||||
|
||||
protected override string[] GetBundleDepends(BuildContext context, string bundleName)
|
||||
{
|
||||
return Array.Empty<string>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 21e10b308293d2e45972a9b4ba143a74
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,23 @@
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 归档文件构建管线的补丁包创建任务
|
||||
/// </summary>
|
||||
public class TaskCreatePackage_AFBP : TaskCreatePackage, IBuildTask
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
void IBuildTask.Run(BuildContext context)
|
||||
{
|
||||
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
|
||||
var buildMapContext = context.GetContextObject<BuildMapContext>();
|
||||
CreatePackagePatch(buildParametersContext, buildMapContext);
|
||||
}
|
||||
|
||||
private void CreatePackagePatch(BuildParametersContext buildParametersContext, BuildMapContext buildMapContext)
|
||||
{
|
||||
string packageOutputDirectory = buildParametersContext.GetPackageOutputDirectory();
|
||||
BuildLogger.Log($"Start making patch package: '{packageOutputDirectory}'.");
|
||||
CopyPackageBundles(buildMapContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 721f0030551d41c40a2c6d3206c3897a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 归档文件构建管线的构建报告创建任务
|
||||
/// </summary>
|
||||
public class TaskCreateReport_AFBP : TaskCreateReport, IBuildTask
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
void IBuildTask.Run(BuildContext context)
|
||||
{
|
||||
var buildParameters = context.GetContextObject<BuildParametersContext>();
|
||||
var buildMapContext = context.GetContextObject<BuildMapContext>();
|
||||
var manifestContext = context.GetContextObject<ManifestContext>();
|
||||
CreateReportFile(buildParameters, buildMapContext, manifestContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3e12187230b544940aeae7cb3c556299
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 归档文件构建管线的加密任务
|
||||
/// </summary>
|
||||
public class TaskEncryption_AFBP : TaskEncryption, IBuildTask
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
void IBuildTask.Run(BuildContext context)
|
||||
{
|
||||
var buildParameters = context.GetContextObject<BuildParametersContext>();
|
||||
var buildMapContext = context.GetContextObject<BuildMapContext>();
|
||||
EncryptingBundleFiles(buildParameters, buildMapContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 16ff5758e3a98b64193c61ca68e94ddd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 归档文件构建管线的构建映射生成任务
|
||||
/// </summary>
|
||||
public class TaskGetBuildMap_AFBP : TaskGetBuildMap, IBuildTask
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
void IBuildTask.Run(BuildContext context)
|
||||
{
|
||||
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
|
||||
var buildMapContext = CreateBuildMap(true, buildParametersContext.Parameters);
|
||||
context.SetContextObject(buildMapContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 409de066b34f4b64fa9eaee790045492
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,31 @@
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 归档文件构建管线的准备任务
|
||||
/// </summary>
|
||||
public class TaskPrepare_AFBP : TaskPrepare, IBuildTask
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
void IBuildTask.Run(BuildContext context)
|
||||
{
|
||||
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
|
||||
var buildParameters = buildParametersContext.Parameters;
|
||||
|
||||
// 检测构建参数
|
||||
buildParametersContext.CheckBuildParameters();
|
||||
|
||||
// 检测未保存场景
|
||||
CheckDirtyScenes();
|
||||
|
||||
// 删除历史缓存
|
||||
if (buildParameters.ClearBuildCacheFiles)
|
||||
{
|
||||
DeletePackageRootDirectory(buildParameters);
|
||||
}
|
||||
|
||||
// 准备输出目录
|
||||
PrepareOutputDirectory(buildParameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f463d370e0512bb4c8d79e22fe149500
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user