Compare commits
1419 Commits
playtest-2
...
release-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c07fee3b3b | ||
|
|
07b635672e | ||
|
|
edc4c7ab2b | ||
|
|
6edcc36f17 | ||
|
|
3a2a6c231e | ||
|
|
cf26e4aa8a | ||
|
|
8ca1da8828 | ||
|
|
5764bc1c1c | ||
|
|
dba7335594 | ||
|
|
1461309dba | ||
|
|
d7e8388600 | ||
|
|
e79d039aa0 | ||
|
|
3d8b3efb9e | ||
|
|
58367fdeac | ||
|
|
63d54952d0 | ||
|
|
5904563653 | ||
|
|
5d0b750a64 | ||
|
|
43e99631a8 | ||
|
|
8cd6d60839 | ||
|
|
047d012fff | ||
|
|
0064543989 | ||
|
|
b61b7b5431 | ||
|
|
0c319e88c3 | ||
|
|
da384af339 | ||
|
|
f98f3d0b39 | ||
|
|
439c366ba2 | ||
|
|
d93c42e89c | ||
|
|
850d26a628 | ||
|
|
c3e79405f7 | ||
|
|
03b23d88d2 | ||
|
|
d5d6cea84c | ||
|
|
fb173af647 | ||
|
|
a1bc31883b | ||
|
|
52854c77c2 | ||
|
|
8f58e41304 | ||
|
|
25525b4155 | ||
|
|
66cc0bd8ff | ||
|
|
01c6127545 | ||
|
|
2794e1f62d | ||
|
|
83c9e9e6dd | ||
|
|
39742d02bb | ||
|
|
f1b68a5207 | ||
|
|
493631cd90 | ||
|
|
9a1ce6945b | ||
|
|
ccf66cde2f | ||
|
|
233e9326f0 | ||
|
|
ba97c99f98 | ||
|
|
37edd072a6 | ||
|
|
00358e9fe8 | ||
|
|
888710cbc5 | ||
|
|
518e00c78a | ||
|
|
f2a20a182e | ||
|
|
a058eb06b2 | ||
|
|
64a7592fed | ||
|
|
bfb076b9bc | ||
|
|
5292272902 | ||
|
|
1db3ce4b59 | ||
|
|
060d544390 | ||
|
|
b0e3364a77 | ||
|
|
d78dde4db1 | ||
|
|
a94b2df865 | ||
|
|
e4bb788fb9 | ||
|
|
6dcc401342 | ||
|
|
26a7e06b40 | ||
|
|
2ba8120d79 | ||
|
|
b9b045098b | ||
|
|
a0682d80c0 | ||
|
|
1ff39761b7 | ||
|
|
bddd058b38 | ||
|
|
8efb717cf4 | ||
|
|
65ac607d90 | ||
|
|
0af653b101 | ||
|
|
175b07c0ff | ||
|
|
585cba8af8 | ||
|
|
2a7525122e | ||
|
|
7f7c293856 | ||
|
|
fbb117705e | ||
|
|
78dea9eecb | ||
|
|
be9f52e029 | ||
|
|
000dd6de7b | ||
|
|
5e8e4dd9d5 | ||
|
|
b31a35d34b | ||
|
|
414b3a03c3 | ||
|
|
a7f42dcf0c | ||
|
|
7bd7f4e56b | ||
|
|
9584c78500 | ||
|
|
bc7a9c14d0 | ||
|
|
c1eacc225d | ||
|
|
e56bbe367d | ||
|
|
6cf9939ab3 | ||
|
|
b2f3b8f2af | ||
|
|
80e897abfb | ||
|
|
d152d21338 | ||
|
|
f4e04ece12 | ||
|
|
e7a07ea9c3 | ||
|
|
f8e6245903 | ||
|
|
7c146a9d5d | ||
|
|
846286c988 | ||
|
|
ba25bc6df4 | ||
|
|
622f9bfe71 | ||
|
|
8df47f5a60 | ||
|
|
d2a0647085 | ||
|
|
0e750a3f25 | ||
|
|
0e6dbe28a8 | ||
|
|
cc0c45bceb | ||
|
|
af3e734561 | ||
|
|
1ac61c5e3e | ||
|
|
5d3622b79d | ||
|
|
b3ddf1ae86 | ||
|
|
17770631a2 | ||
|
|
05f6958286 | ||
|
|
bd9c748b17 | ||
|
|
6b40abb58c | ||
|
|
6d67ab2240 | ||
|
|
8b3512e2f1 | ||
|
|
5b71bee4c8 | ||
|
|
75e7124af0 | ||
|
|
9ad55d5e28 | ||
|
|
9e93edf336 | ||
|
|
5608756a24 | ||
|
|
ebca421856 | ||
|
|
22e61a5700 | ||
|
|
7306de3730 | ||
|
|
10ed3db71d | ||
|
|
04e05d9aed | ||
|
|
caae95f12e | ||
|
|
dfa14f16d3 | ||
|
|
8e007131c9 | ||
|
|
ed4c588701 | ||
|
|
d33806e932 | ||
|
|
e83838e9ff | ||
|
|
b77dcd476c | ||
|
|
836b3a598b | ||
|
|
967b16fc0e | ||
|
|
ee3437d0f6 | ||
|
|
e20c736e3f | ||
|
|
a98d20ea72 | ||
|
|
38486e8184 | ||
|
|
047a09bbbd | ||
|
|
d55e58ea1c | ||
|
|
17afe80a54 | ||
|
|
42bf568d80 | ||
|
|
50157c43de | ||
|
|
41988a1298 | ||
|
|
86058ec19f | ||
|
|
356c750b23 | ||
|
|
26cbb9d9c6 | ||
|
|
4a0b78c1e6 | ||
|
|
fcb7c845ba | ||
|
|
12f9c0bce9 | ||
|
|
47ed79b912 | ||
|
|
a265d11a5f | ||
|
|
8a96c5f7b5 | ||
|
|
5e5456191c | ||
|
|
aae7f56e7d | ||
|
|
3645b3ee13 | ||
|
|
e0f357390c | ||
|
|
9c3cb62838 | ||
|
|
14225b8e79 | ||
|
|
e01bf735d9 | ||
|
|
1904f8ced1 | ||
|
|
3caca8c323 | ||
|
|
dd7ce2d45e | ||
|
|
f793f4548b | ||
|
|
56675a61f5 | ||
|
|
3dd27fcb77 | ||
|
|
13d76f8e9c | ||
|
|
9a2cdcde11 | ||
|
|
155e7320cb | ||
|
|
750fd84494 | ||
|
|
924adc68a9 | ||
|
|
0f8d9d7fb3 | ||
|
|
801aa1156f | ||
|
|
aa0c14c214 | ||
|
|
8fcbb670d8 | ||
|
|
85a26ecdf7 | ||
|
|
480c5edd75 | ||
|
|
fdfa1ddf97 | ||
|
|
80caf1818b | ||
|
|
5c0cd50797 | ||
|
|
8129d5d7dc | ||
|
|
a77b7af5fd | ||
|
|
ecf41722c3 | ||
|
|
39b09780f6 | ||
|
|
98dec6dc8e | ||
|
|
50b1ba3acc | ||
|
|
c3fc7b98f3 | ||
|
|
f5b8b18d86 | ||
|
|
e7c61fac5c | ||
|
|
2640603f6c | ||
|
|
1a011276bf | ||
|
|
bc7cf09287 | ||
|
|
7762241653 | ||
|
|
9489196911 | ||
|
|
e32e060d37 | ||
|
|
5e3fce6820 | ||
|
|
6655b6ba6a | ||
|
|
0b4b003c10 | ||
|
|
380e7e8b20 | ||
|
|
9b3533abc0 | ||
|
|
1409016cbd | ||
|
|
4aa1fb4b86 | ||
|
|
40126c52e8 | ||
|
|
dd600d4590 | ||
|
|
532f420338 | ||
|
|
e25878e78d | ||
|
|
002cc4842a | ||
|
|
eac548ac8b | ||
|
|
3fc4d1b219 | ||
|
|
80e3b8be0d | ||
|
|
fa35f6caa4 | ||
|
|
526cf6059a | ||
|
|
1527e472b6 | ||
|
|
94f7c6db97 | ||
|
|
e3ddb8f757 | ||
|
|
d7d0d371c6 | ||
|
|
527c60daa7 | ||
|
|
c30050396a | ||
|
|
60a8acf4d4 | ||
|
|
5164c3cd7d | ||
|
|
6276e659cd | ||
|
|
298314626e | ||
|
|
0112bc4df7 | ||
|
|
c8dbed938a | ||
|
|
278f35e4aa | ||
|
|
dd38e45f2e | ||
|
|
3e08f9b1b1 | ||
|
|
8392a44314 | ||
|
|
d050d1a4b9 | ||
|
|
56598ce2ff | ||
|
|
2fb72155eb | ||
|
|
030bd4b28d | ||
|
|
b9c40ad3ce | ||
|
|
4490a90332 | ||
|
|
15d6facdb9 | ||
|
|
b80962b365 | ||
|
|
814c6a8713 | ||
|
|
eea89c1d33 | ||
|
|
9ec0367ecb | ||
|
|
f5fe1013ee | ||
|
|
c338d28d35 | ||
|
|
2f962452e5 | ||
|
|
10f5e68f7f | ||
|
|
1cde37f32b | ||
|
|
291899de8a | ||
|
|
cc70669f1a | ||
|
|
c568dfa486 | ||
|
|
ff7daf8727 | ||
|
|
fc72066ed2 | ||
|
|
253ccd6d9b | ||
|
|
01accaeb38 | ||
|
|
46c3bc09a1 | ||
|
|
2f0b7566e5 | ||
|
|
9b8ec714d2 | ||
|
|
5d408fe3c7 | ||
|
|
aa0b7bedf0 | ||
|
|
c5358f7c82 | ||
|
|
158d6e5647 | ||
|
|
e091781104 | ||
|
|
25582cb9f8 | ||
|
|
fece294cc6 | ||
|
|
c3501f68e3 | ||
|
|
c4ee5fbd41 | ||
|
|
9a54074b1b | ||
|
|
10e918c375 | ||
|
|
bbcad99fa7 | ||
|
|
c8198a1a1c | ||
|
|
8d5241f419 | ||
|
|
448b681c5b | ||
|
|
826f7a29b5 | ||
|
|
0629b1e2d2 | ||
|
|
0d9cf63dd2 | ||
|
|
6513bd5fe0 | ||
|
|
f933e3de3f | ||
|
|
88a8d84153 | ||
|
|
8e4f5da791 | ||
|
|
a61d21e501 | ||
|
|
2bcf33661a | ||
|
|
f6df7a06f2 | ||
|
|
de92a2fc0c | ||
|
|
6012f1d592 | ||
|
|
caf676dc33 | ||
|
|
e3ae1bec75 | ||
|
|
b98b517e35 | ||
|
|
5d9f25eef5 | ||
|
|
5bf69eb539 | ||
|
|
09f7778294 | ||
|
|
c8ec5f3579 | ||
|
|
a54c7ecc18 | ||
|
|
0064caf1f4 | ||
|
|
fc2fbd4689 | ||
|
|
0f0793cde5 | ||
|
|
2fed6f61e9 | ||
|
|
3df310df6e | ||
|
|
c2b3a749ca | ||
|
|
2d2220f38f | ||
|
|
7509bf85aa | ||
|
|
64e8088ae4 | ||
|
|
15584b9b34 | ||
|
|
79c1d1b0a6 | ||
|
|
50860614cf | ||
|
|
90d1d3e053 | ||
|
|
3bf83b52fb | ||
|
|
5f57dd7a62 | ||
|
|
8e1185b56f | ||
|
|
26098df2a1 | ||
|
|
9ac9d83745 | ||
|
|
51edd5a3f4 | ||
|
|
fc07f90f91 | ||
|
|
b64dcbf502 | ||
|
|
5694c113be | ||
|
|
01cf5c21a7 | ||
|
|
4206d2e131 | ||
|
|
83968553aa | ||
|
|
aa2aba1250 | ||
|
|
bba9c4b976 | ||
|
|
999eef2ec9 | ||
|
|
f28c8903aa | ||
|
|
f58eabe667 | ||
|
|
86695dfe29 | ||
|
|
9ae452e8d6 | ||
|
|
3e547102d2 | ||
|
|
e883e63c87 | ||
|
|
a904047a16 | ||
|
|
ad1af792e6 | ||
|
|
6c9527d9dc | ||
|
|
da2d461aa8 | ||
|
|
49bfd69707 | ||
|
|
2a02df9411 | ||
|
|
185ba80e99 | ||
|
|
127cbf3f96 | ||
|
|
4bdf675def | ||
|
|
9c944924de | ||
|
|
28f79533eb | ||
|
|
5a834c9500 | ||
|
|
3255218d5c | ||
|
|
9befe377d5 | ||
|
|
f39b4f0750 | ||
|
|
1794625cea | ||
|
|
42092fe6dd | ||
|
|
1a451fe813 | ||
|
|
0e845a9f3a | ||
|
|
2a3c149769 | ||
|
|
7cfcd94e23 | ||
|
|
247a8c9717 | ||
|
|
4afd8ad783 | ||
|
|
dca77956cb | ||
|
|
22c6c3b3f6 | ||
|
|
1e8e5c8f5c | ||
|
|
c0fcc862d6 | ||
|
|
5a3ccdf0c5 | ||
|
|
1bd802c386 | ||
|
|
3a4e2abedd | ||
|
|
f13343ef2e | ||
|
|
2b1ac6a60f | ||
|
|
8aa180c1f4 | ||
|
|
260e420f85 | ||
|
|
1a203afd89 | ||
|
|
c150fd9475 | ||
|
|
566303a8f1 | ||
|
|
10f8364b99 | ||
|
|
7c31f72db6 | ||
|
|
6b6c9639f9 | ||
|
|
7ca9fcdac9 | ||
|
|
20276291ce | ||
|
|
34fc207a6c | ||
|
|
c974e61680 | ||
|
|
09db76f89f | ||
|
|
6bbf878314 | ||
|
|
4cd3195f9f | ||
|
|
6ea2a06e4b | ||
|
|
597dba8584 | ||
|
|
1c1483377c | ||
|
|
0873741983 | ||
|
|
e0afc08e5f | ||
|
|
cb1deacbb2 | ||
|
|
ab1e930ba3 | ||
|
|
10bf85f57e | ||
|
|
17990ab8b7 | ||
|
|
beecb8aeb1 | ||
|
|
6a25d989a7 | ||
|
|
f8776d773d | ||
|
|
3724f46a3e | ||
|
|
915ad7fb7b | ||
|
|
07023b6c35 | ||
|
|
b78b5b22a3 | ||
|
|
eca098b0b4 | ||
|
|
011a20e8b4 | ||
|
|
9c362f7d41 | ||
|
|
99d92ee095 | ||
|
|
b905d343af | ||
|
|
024b564b8c | ||
|
|
9c0e3ac4c9 | ||
|
|
a2205e9031 | ||
|
|
0df9815d2c | ||
|
|
79d6eb4a2b | ||
|
|
0d8557eadb | ||
|
|
70f6fc7a7a | ||
|
|
11f6a8b945 | ||
|
|
e3d71acb05 | ||
|
|
580f1cfe97 | ||
|
|
3d7434f42e | ||
|
|
ef96604f9e | ||
|
|
465f5d295b | ||
|
|
1feb377d43 | ||
|
|
a065fb464e | ||
|
|
e39917ca19 | ||
|
|
318f496bf9 | ||
|
|
ed8a155249 | ||
|
|
40ac5f7b6e | ||
|
|
517754027e | ||
|
|
ef4f478e10 | ||
|
|
92c30b89f8 | ||
|
|
7331a9c4fb | ||
|
|
d2b9e150f1 | ||
|
|
8ba329f1be | ||
|
|
8868eab247 | ||
|
|
f12889e684 | ||
|
|
5c095bc174 | ||
|
|
0c24a08436 | ||
|
|
9762b540b0 | ||
|
|
fd34f2ba99 | ||
|
|
ad6481c8e8 | ||
|
|
7426d47cd5 | ||
|
|
761f62292f | ||
|
|
63b8555bc9 | ||
|
|
3209da4a4a | ||
|
|
aebef4f1c8 | ||
|
|
d3244184c1 | ||
|
|
39e62354a8 | ||
|
|
f525c3808e | ||
|
|
87a0b52ce5 | ||
|
|
4bc9e01516 | ||
|
|
711d05da98 | ||
|
|
3d805ff40d | ||
|
|
0cd140849b | ||
|
|
d6110b9ef0 | ||
|
|
26d1db778e | ||
|
|
f41aa474aa | ||
|
|
0002e80a19 | ||
|
|
759a52d86e | ||
|
|
44fe0396bb | ||
|
|
dd6d8d916e | ||
|
|
5af8f5e2d9 | ||
|
|
c85503811c | ||
|
|
ab431fe9ee | ||
|
|
7ec9958d47 | ||
|
|
cfc74a6dee | ||
|
|
cecdd73e08 | ||
|
|
381e080b11 | ||
|
|
c6a047cb1a | ||
|
|
4c51733e04 | ||
|
|
8f613b80e8 | ||
|
|
10de282daa | ||
|
|
915e123956 | ||
|
|
8cb7a7b8ce | ||
|
|
ce5cf93077 | ||
|
|
1390bb7428 | ||
|
|
3c5b136216 | ||
|
|
66785e606a | ||
|
|
e2239fa50c | ||
|
|
7f7712aa64 | ||
|
|
b1605e115a | ||
|
|
69b2da86be | ||
|
|
18e965e5aa | ||
|
|
24f0c28f56 | ||
|
|
25af51b4ac | ||
|
|
ecd7064cc3 | ||
|
|
477a21e782 | ||
|
|
899d9af62b | ||
|
|
17eca983ef | ||
|
|
2fc219ecd5 | ||
|
|
49a645cd2d | ||
|
|
7cb8da411d | ||
|
|
4bcdf3cf11 | ||
|
|
1b525ff809 | ||
|
|
cdec3fce26 | ||
|
|
7bdf6a953f | ||
|
|
06b20c8ba5 | ||
|
|
9b484b53ec | ||
|
|
9620b4ed46 | ||
|
|
d8908c44d0 | ||
|
|
cfe705531a | ||
|
|
9a2fd38ab6 | ||
|
|
911e7f62de | ||
|
|
403b81bdc9 | ||
|
|
a0714b00b3 | ||
|
|
d5239ee77a | ||
|
|
03ec97f302 | ||
|
|
3255f95ee9 | ||
|
|
4c8fd5e73d | ||
|
|
7179ef0f45 | ||
|
|
6d5918b11d | ||
|
|
81c484d1c9 | ||
|
|
de1044c24c | ||
|
|
e4c31939d9 | ||
|
|
7f48d6796e | ||
|
|
4fd77aec8e | ||
|
|
92fece01de | ||
|
|
d8d987f844 | ||
|
|
de429a4c62 | ||
|
|
c0ca35a4ff | ||
|
|
1bff8559fb | ||
|
|
de98274165 | ||
|
|
59e2228b2a | ||
|
|
96d1408d45 | ||
|
|
ff45ae2d16 | ||
|
|
47950c9113 | ||
|
|
f402ec7898 | ||
|
|
a3c0448e15 | ||
|
|
699b4b1154 | ||
|
|
911db3feb1 | ||
|
|
c790db8e84 | ||
|
|
d6dd392028 | ||
|
|
636b2a8ea7 | ||
|
|
959d3f8bd7 | ||
|
|
193cb929f1 | ||
|
|
f93e270fe4 | ||
|
|
f19953c39a | ||
|
|
59d5ce1bc8 | ||
|
|
43cf7cd074 | ||
|
|
aba76f4b50 | ||
|
|
8021fc3b20 | ||
|
|
7bf4cb85fa | ||
|
|
6dd03bb339 | ||
|
|
14e517cab5 | ||
|
|
cdcfeb6276 | ||
|
|
c77c63a380 | ||
|
|
9921fe8fad | ||
|
|
f848c5d7d4 | ||
|
|
62c47e3b12 | ||
|
|
094986d066 | ||
|
|
d87e02ab41 | ||
|
|
3f415a8fdf | ||
|
|
846371cf3e | ||
|
|
45c77e64ee | ||
|
|
66493031c8 | ||
|
|
384b26db60 | ||
|
|
d66dbeb312 | ||
|
|
ba9611f544 | ||
|
|
b6e56560d4 | ||
|
|
1f047d439f | ||
|
|
5233ae4770 | ||
|
|
562e07264a | ||
|
|
4dab4ed73f | ||
|
|
a97ddffa53 | ||
|
|
8e589e3c16 | ||
|
|
96f72ce842 | ||
|
|
d8de477edb | ||
|
|
694fb6831a | ||
|
|
c16a515224 | ||
|
|
e2eae7973b | ||
|
|
9e3c938706 | ||
|
|
ef665df2e9 | ||
|
|
271a3eea8d | ||
|
|
2f6315b816 | ||
|
|
ac8d408ba7 | ||
|
|
0fdd49c96a | ||
|
|
e390cf8ab0 | ||
|
|
64d700cd70 | ||
|
|
d3db9d3710 | ||
|
|
9eb05a43f9 | ||
|
|
3165ec5359 | ||
|
|
f4699132d6 | ||
|
|
086bdfb4bd | ||
|
|
61fd12c7da | ||
|
|
9979209c34 | ||
|
|
b0c06d4cd9 | ||
|
|
3a617f8934 | ||
|
|
b35a7d9f8d | ||
|
|
67fa079658 | ||
|
|
c9edbd8a80 | ||
|
|
4b49bf03dc | ||
|
|
6cfad6f2ab | ||
|
|
c0c4e7299b | ||
|
|
afda1647fd | ||
|
|
aff6889995 | ||
|
|
65515d54af | ||
|
|
c5b7c43d23 | ||
|
|
dba5adc91c | ||
|
|
0073a03ca4 | ||
|
|
5509d0d2e9 | ||
|
|
fe52e3722e | ||
|
|
3ddd1581f1 | ||
|
|
56efc3930b | ||
|
|
2f8d81a0f7 | ||
|
|
46486073ab | ||
|
|
3dc11eaa05 | ||
|
|
b62ee4d37c | ||
|
|
532afc3ff8 | ||
|
|
9ddb2beced | ||
|
|
1e758ec3e0 | ||
|
|
aa1d44428d | ||
|
|
23da8a24bd | ||
|
|
fef291a27e | ||
|
|
f49e56d660 | ||
|
|
927ab00f4d | ||
|
|
3f870e7e48 | ||
|
|
f2a321186f | ||
|
|
410daecab6 | ||
|
|
966e3bb71a | ||
|
|
652f06f604 | ||
|
|
2a10af2007 | ||
|
|
4cb26c0e3c | ||
|
|
8455dadb3c | ||
|
|
3c19b3df73 | ||
|
|
c796e155e7 | ||
|
|
ce9caec291 | ||
|
|
0330ef2b9e | ||
|
|
872a304714 | ||
|
|
59cc50df4c | ||
|
|
a1fd84fb15 | ||
|
|
317007f7ce | ||
|
|
387212d9ea | ||
|
|
c9ca5e207b | ||
|
|
ce78944a9e | ||
|
|
1fb336b7da | ||
|
|
e4d05407d9 | ||
|
|
f7eca1157e | ||
|
|
a64245fc10 | ||
|
|
ad8038867d | ||
|
|
fb90400524 | ||
|
|
08b25d10c1 | ||
|
|
ba09bbba8e | ||
|
|
0d2e1d7de5 | ||
|
|
22861fca5a | ||
|
|
692ef539f9 | ||
|
|
d07b0e4400 | ||
|
|
9848d1f403 | ||
|
|
83eae029b7 | ||
|
|
99e225c279 | ||
|
|
1785c4e4a8 | ||
|
|
69753f8a08 | ||
|
|
5593b9ffdd | ||
|
|
1b66635670 | ||
|
|
f1b1f3bd52 | ||
|
|
ff611dac32 | ||
|
|
e0a4cb4763 | ||
|
|
a3246866fb | ||
|
|
b94c2fc7c4 | ||
|
|
d530cf22da | ||
|
|
94e5b02a39 | ||
|
|
40533a50c1 | ||
|
|
d4182b1929 | ||
|
|
482129499d | ||
|
|
366cd02761 | ||
|
|
f549e7e5a8 | ||
|
|
4cab7c7fc4 | ||
|
|
e3939d4805 | ||
|
|
2ae6983bc2 | ||
|
|
ad00193a17 | ||
|
|
810667abbc | ||
|
|
a66efd56f2 | ||
|
|
36ba15e7f9 | ||
|
|
d809fb1e7b | ||
|
|
d0bc834a57 | ||
|
|
483ca8cc4c | ||
|
|
06aba5da46 | ||
|
|
106fbcd5af | ||
|
|
f456e41a45 | ||
|
|
7dc3aee4a2 | ||
|
|
c91bee8091 | ||
|
|
82875e15f9 | ||
|
|
d6f8b7d850 | ||
|
|
72fe873b26 | ||
|
|
e9f34b1e21 | ||
|
|
d15ab79370 | ||
|
|
303613b052 | ||
|
|
051c451867 | ||
|
|
ac8a3526a4 | ||
|
|
be47fb55e8 | ||
|
|
5b8fc75d4a | ||
|
|
629e73ac29 | ||
|
|
7e5b861caf | ||
|
|
f3dcc14fca | ||
|
|
fee68d0231 | ||
|
|
83f56d152f | ||
|
|
a04ea789f5 | ||
|
|
94becc3ddc | ||
|
|
8452e1bdf0 | ||
|
|
5a513bc69d | ||
|
|
5a173a2bd3 | ||
|
|
d29b068d59 | ||
|
|
8dbbaca8da | ||
|
|
10a1f7ec1e | ||
|
|
8286dba919 | ||
|
|
bd735059d0 | ||
|
|
147acbf096 | ||
|
|
91aa5302a8 | ||
|
|
2b6328f0ee | ||
|
|
1bc2136771 | ||
|
|
4ad0a52104 | ||
|
|
b9450b0f63 | ||
|
|
03bb74ea84 | ||
|
|
8b4551c605 | ||
|
|
f645049054 | ||
|
|
aa832244fb | ||
|
|
190311c68c | ||
|
|
b8ed9d7da5 | ||
|
|
ca32d51375 | ||
|
|
b0e5bb3718 | ||
|
|
96ebbfe75c | ||
|
|
5c6a6ee350 | ||
|
|
bbf2d68e9d | ||
|
|
59cf76b4ae | ||
|
|
e97440819d | ||
|
|
87cd37a30b | ||
|
|
f406dfa277 | ||
|
|
24039f593c | ||
|
|
cceb4401aa | ||
|
|
f9445cb282 | ||
|
|
706adb6d0b | ||
|
|
dd7e578fe6 | ||
|
|
83d1df19ba | ||
|
|
975fa28f62 | ||
|
|
452f7f7bff | ||
|
|
626db661ab | ||
|
|
9ea3a404a3 | ||
|
|
55c3e9d5bb | ||
|
|
f616a527ee | ||
|
|
a594e9f830 | ||
|
|
45d712d390 | ||
|
|
dbbdc171d2 | ||
|
|
befe22e170 | ||
|
|
b284e82aa7 | ||
|
|
ed5a3338fe | ||
|
|
68dcec87c7 | ||
|
|
39d7e54e7f | ||
|
|
404a4ad578 | ||
|
|
c9d0a7a301 | ||
|
|
54ffdc51b4 | ||
|
|
9e53774299 | ||
|
|
f70a6aafb1 | ||
|
|
c3fa9f7aa8 | ||
|
|
a73ef3affd | ||
|
|
4e5d26a2d1 | ||
|
|
4b1bc7acd4 | ||
|
|
95d29c6910 | ||
|
|
c88ea2bd7c | ||
|
|
af157867d8 | ||
|
|
9476e16df6 | ||
|
|
9c148bf3f0 | ||
|
|
c8c96b9f6b | ||
|
|
108d7764ec | ||
|
|
5396cad2b9 | ||
|
|
2bae3d9d2f | ||
|
|
9cbaa9679d | ||
|
|
6228a962f6 | ||
|
|
1baff27553 | ||
|
|
4855b6bca6 | ||
|
|
ff0c66e38c | ||
|
|
83d2ca07f1 | ||
|
|
26152489f3 | ||
|
|
4ca4d7b5dd | ||
|
|
0dddf12831 | ||
|
|
25c098bad6 | ||
|
|
be9528dcb2 | ||
|
|
965385980f | ||
|
|
ca92cd03db | ||
|
|
cdec95b73a | ||
|
|
76bf3077e9 | ||
|
|
53858a7789 | ||
|
|
b98e25c9a7 | ||
|
|
be46f44bc9 | ||
|
|
fee6d450e4 | ||
|
|
173dc59039 | ||
|
|
950dd4e85c | ||
|
|
6632feb696 | ||
|
|
7b2622e67b | ||
|
|
9e5528ef83 | ||
|
|
3d920670e5 | ||
|
|
4d2afd827f | ||
|
|
9a4d0dfe5e | ||
|
|
2a240e62aa | ||
|
|
7a88adcf96 | ||
|
|
b84d2f2c29 | ||
|
|
2945838eef | ||
|
|
43aa8812b3 | ||
|
|
9a2467dc21 | ||
|
|
5a75625eef | ||
|
|
2f2890596d | ||
|
|
01fa0b357e | ||
|
|
c5f0dad84e | ||
|
|
7f7f4e81a5 | ||
|
|
8b423908ca | ||
|
|
598fe9f956 | ||
|
|
06e8b530ea | ||
|
|
d5c25f73bd | ||
|
|
73fa306719 | ||
|
|
8d0cea6fe4 | ||
|
|
273b57ee69 | ||
|
|
c1578b92e1 | ||
|
|
c69a741c90 | ||
|
|
f8d537c0c5 | ||
|
|
e371159826 | ||
|
|
7d912715bc | ||
|
|
d6449c2902 | ||
|
|
8a3868abd0 | ||
|
|
112047d2b3 | ||
|
|
cd9f584729 | ||
|
|
31741a1ab3 | ||
|
|
eb6440694a | ||
|
|
2c388308c7 | ||
|
|
1c8f744719 | ||
|
|
dfdc893d63 | ||
|
|
669aaab6b4 | ||
|
|
73017d3f5c | ||
|
|
38fa809656 | ||
|
|
0ed21a4acb | ||
|
|
9ae7d98193 | ||
|
|
07e60286f2 | ||
|
|
7f918b8a69 | ||
|
|
4e0ace6ec5 | ||
|
|
dca5f8d27b | ||
|
|
6478276064 | ||
|
|
7d603f97fe | ||
|
|
112fdb32af | ||
|
|
5a78df0318 | ||
|
|
6ac4266847 | ||
|
|
91487b85d0 | ||
|
|
178af8b849 | ||
|
|
853ef12c8f | ||
|
|
62cc2fa4cb | ||
|
|
1f4991833d | ||
|
|
9fedeefdbc | ||
|
|
29a77f7c5c | ||
|
|
a751b8c49d | ||
|
|
baacfc96bb | ||
|
|
8dcd1e8fd1 | ||
|
|
2a7857570a | ||
|
|
2f92b873e8 | ||
|
|
bce52e989f | ||
|
|
a917086969 | ||
|
|
34913ab077 | ||
|
|
9de22add08 | ||
|
|
b2f535d2e0 | ||
|
|
3e7b9a7b5a | ||
|
|
29d03fb133 | ||
|
|
d4aeb157cc | ||
|
|
853e60f76e | ||
|
|
7f3e491ecc | ||
|
|
88dfbe657c | ||
|
|
226fd167e7 | ||
|
|
cedfeab63c | ||
|
|
a882735deb | ||
|
|
61ebe0d0a0 | ||
|
|
ee546750b2 | ||
|
|
267d89a459 | ||
|
|
3b59afcd4f | ||
|
|
8b98448090 | ||
|
|
1d7ca206f4 | ||
|
|
7b7b9d3319 | ||
|
|
e5d45a6961 | ||
|
|
c7f8921cea | ||
|
|
58ebd68478 | ||
|
|
6234f53e2c | ||
|
|
ce0e671ac5 | ||
|
|
739c38d3d8 | ||
|
|
5561ac458b | ||
|
|
c0d0636e08 | ||
|
|
f4da83e920 | ||
|
|
50066ec238 | ||
|
|
dbd076543b | ||
|
|
2d4ed56f76 | ||
|
|
03cdcdd4aa | ||
|
|
0cc440aa1f | ||
|
|
f635835b1c | ||
|
|
3f08f16b9b | ||
|
|
c433ca77c4 | ||
|
|
70a92b80cf | ||
|
|
b3fbefe968 | ||
|
|
f38e4d27be | ||
|
|
c35e3b4bd7 | ||
|
|
b0608936d8 | ||
|
|
56b9d1add7 | ||
|
|
5ce531f2d5 | ||
|
|
c7e76cc26d | ||
|
|
142be86934 | ||
|
|
73dadbc873 | ||
|
|
50d5936846 | ||
|
|
4e86f5b252 | ||
|
|
b6b4df703a | ||
|
|
b17e6900ec | ||
|
|
08a60ca336 | ||
|
|
d8c053253d | ||
|
|
e4271b35dc | ||
|
|
95c34c30ba | ||
|
|
8e42dd95fc | ||
|
|
f2dd0de1ea | ||
|
|
701ef05562 | ||
|
|
c3228cecd0 | ||
|
|
47eacc5b80 | ||
|
|
909152c662 | ||
|
|
0f9221dc5a | ||
|
|
cfc937e8eb | ||
|
|
def0580078 | ||
|
|
3c7015567e | ||
|
|
a00f0b18a0 | ||
|
|
703f3b8c13 | ||
|
|
bf9bcfed68 | ||
|
|
f6dac1fe83 | ||
|
|
731c64c1a7 | ||
|
|
19494c3262 | ||
|
|
cf9a2ee0ef | ||
|
|
93e8bd6644 | ||
|
|
4d0f75353b | ||
|
|
fb035756a0 | ||
|
|
e0a00940af | ||
|
|
e74c3eeb2e | ||
|
|
05bf6d83f2 | ||
|
|
e4b65256de | ||
|
|
d744cfe21b | ||
|
|
6ae7da77ae | ||
|
|
0352884205 | ||
|
|
7c6edab04e | ||
|
|
997501bb12 | ||
|
|
d4f43a399e | ||
|
|
f6ec2163de | ||
|
|
3428b3c4c2 | ||
|
|
8ec16fdbbe | ||
|
|
39f699916c | ||
|
|
4a337185f5 | ||
|
|
298f5ec24f | ||
|
|
16402f26fe | ||
|
|
825743b225 | ||
|
|
c3b3947b9d | ||
|
|
1143f496db | ||
|
|
46d0ce89e9 | ||
|
|
79ced35010 | ||
|
|
18a06eb3bf | ||
|
|
d8c5f1aed3 | ||
|
|
3880326787 | ||
|
|
09d9396123 | ||
|
|
aeccf53e97 | ||
|
|
b1b8b2c14a | ||
|
|
fd9a31168d | ||
|
|
3f11c32c4a | ||
|
|
d65626e87c | ||
|
|
ccb77dee12 | ||
|
|
952da4efec | ||
|
|
49f2bfb460 | ||
|
|
9db92ed8ba | ||
|
|
4e2d76f6ed | ||
|
|
94dd73cb48 | ||
|
|
aeb9f4e441 | ||
|
|
1a4e3053ce | ||
|
|
18914447aa | ||
|
|
7e67a5bb2d | ||
|
|
9eaa0e5765 | ||
|
|
0e16aa339d | ||
|
|
c7b650d6ec | ||
|
|
bcc3cd32ae | ||
|
|
38ffd30b28 | ||
|
|
15bd58ddce | ||
|
|
7247bd1078 | ||
|
|
ac31767aef | ||
|
|
3f68330c70 | ||
|
|
0e71af25f4 | ||
|
|
e610c4d7fc | ||
|
|
0a041fe425 | ||
|
|
1595c6a0ed | ||
|
|
db7a11e8a6 | ||
|
|
53df4c4bfb | ||
|
|
1afcd2b98a | ||
|
|
08ffe1d44d | ||
|
|
66359b7058 | ||
|
|
30ab5c33ea | ||
|
|
0c5fb4c6b0 | ||
|
|
21b0b12948 | ||
|
|
cb3f6435ad | ||
|
|
235ae1fad7 | ||
|
|
1c6470eff3 | ||
|
|
0cf51d8142 | ||
|
|
38e5f70cbe | ||
|
|
56b0da0b13 | ||
|
|
d6f0a03270 | ||
|
|
b1b75ecf2f | ||
|
|
228852a55d | ||
|
|
f6a880e524 | ||
|
|
7e82dc729b | ||
|
|
d91a7c6b35 | ||
|
|
b4068f0ac7 | ||
|
|
b336a1e478 | ||
|
|
55afcddce0 | ||
|
|
ac7bb3c71b | ||
|
|
3aa7ff5a6b | ||
|
|
0b3414c46f | ||
|
|
fdcad8710b | ||
|
|
02a7b092dc | ||
|
|
d43781c604 | ||
|
|
cfbededcc4 | ||
|
|
9ba50a9c5e | ||
|
|
6377269a14 | ||
|
|
a8be81ea2b | ||
|
|
50950cba22 | ||
|
|
210e847904 | ||
|
|
54f7b6430d | ||
|
|
26e823fc25 | ||
|
|
10ea035b42 | ||
|
|
58fb7178ad | ||
|
|
cd358eb985 | ||
|
|
39d4b80323 | ||
|
|
45a4935b01 | ||
|
|
824e2a7b0b | ||
|
|
230d59f655 | ||
|
|
7f191887ec | ||
|
|
499613f105 | ||
|
|
20af2b5c0a | ||
|
|
cbc9d66bee | ||
|
|
c338612b9f | ||
|
|
edd0a7c614 | ||
|
|
1d259e4bc7 | ||
|
|
6c651e9d02 | ||
|
|
a29e0bf4b1 | ||
|
|
9d403d3072 | ||
|
|
184d044f26 | ||
|
|
0473aed2c3 | ||
|
|
db5920e83a | ||
|
|
80555235d7 | ||
|
|
acd842f178 | ||
|
|
a5dacd52e8 | ||
|
|
6e045e864a | ||
|
|
0541b04c3a | ||
|
|
07b2bcbfdf | ||
|
|
0e2b4bb721 | ||
|
|
ab3c06cd04 | ||
|
|
299ee7f82c | ||
|
|
ddd56e6f9b | ||
|
|
839043ea1b | ||
|
|
1e8aea616b | ||
|
|
727a88d82a | ||
|
|
1f54ad3238 | ||
|
|
694fd84188 | ||
|
|
271be551b0 | ||
|
|
fe481d7445 | ||
|
|
7a10ae3dea | ||
|
|
8c39e372e3 | ||
|
|
af6660d6ca | ||
|
|
d0da9d11bf | ||
|
|
0a2d39f15b | ||
|
|
8118a17e3c | ||
|
|
0f6564f31a | ||
|
|
dda6556e17 | ||
|
|
5c1408d4d7 | ||
|
|
aa6e671d89 | ||
|
|
e0de1427e9 | ||
|
|
db16ab4cdc | ||
|
|
ae703d50b2 | ||
|
|
f6c6255f64 | ||
|
|
a569c712f0 | ||
|
|
5c8c8d5e6e | ||
|
|
3f4f1ff75e | ||
|
|
1aa4f57a68 | ||
|
|
3f3ac377b2 | ||
|
|
de12233edc | ||
|
|
b36b101392 | ||
|
|
726449b6fb | ||
|
|
a0d7435550 | ||
|
|
11aed465a8 | ||
|
|
0f953226a6 | ||
|
|
ad181544cd | ||
|
|
df19163ce5 | ||
|
|
4328fbc350 | ||
|
|
7cd9afb6d2 | ||
|
|
1ad8b58f1b | ||
|
|
62e3d548c8 | ||
|
|
ea7abcb585 | ||
|
|
441bffecfc | ||
|
|
2c1ab33893 | ||
|
|
74500c369c | ||
|
|
6e0158039a | ||
|
|
c600239c54 | ||
|
|
93a48c0cf1 | ||
|
|
b88512df43 | ||
|
|
ca6debde66 | ||
|
|
8dd9848636 | ||
|
|
ec9da154ad | ||
|
|
46fc0ef563 | ||
|
|
514c92a998 | ||
|
|
96f9f33776 | ||
|
|
20553a112d | ||
|
|
9e49cad1c2 | ||
|
|
5c6e2a5e42 | ||
|
|
44d7aa14a4 | ||
|
|
bf8e3645cb | ||
|
|
6ea8d4e6d3 | ||
|
|
16c3223f3e | ||
|
|
b98e180361 | ||
|
|
80aade857e | ||
|
|
58700e4c07 | ||
|
|
d364472862 | ||
|
|
5d688a2e27 | ||
|
|
f4fa053a35 | ||
|
|
90373529b0 | ||
|
|
0416b6b429 | ||
|
|
bd991e33ca | ||
|
|
f162c5956e | ||
|
|
e6f717ff04 | ||
|
|
eb0c895e2c | ||
|
|
3af0d2f6a4 | ||
|
|
8f6fe8344b | ||
|
|
cb5307bb17 | ||
|
|
d9acf1a3e5 | ||
|
|
6fc945ac91 | ||
|
|
e5878e8207 | ||
|
|
b982a52086 | ||
|
|
f28ec846e7 | ||
|
|
551814fc32 | ||
|
|
f64a6e273e | ||
|
|
1a428186e9 | ||
|
|
609abb7719 | ||
|
|
aee0728a73 | ||
|
|
120a5fa66b | ||
|
|
71792a8f09 | ||
|
|
0f20133af0 | ||
|
|
40b16e33ba | ||
|
|
8e82f6fa1a | ||
|
|
053f0f5c7f | ||
|
|
7c562059c2 | ||
|
|
cf5cb80c61 | ||
|
|
711378d352 | ||
|
|
7d044a9e1b | ||
|
|
bc93e8cac0 | ||
|
|
578d42614b | ||
|
|
4ea66ea309 | ||
|
|
2cc6e197fa | ||
|
|
2ea0907d66 | ||
|
|
d50d26350e | ||
|
|
b77bddddbc | ||
|
|
3521319095 | ||
|
|
dfc24233f7 | ||
|
|
970eb4d6e1 | ||
|
|
10b7ece62e | ||
|
|
f789aef892 | ||
|
|
bceaecf031 | ||
|
|
74155812d0 | ||
|
|
f49ec8d6b9 | ||
|
|
fd5d441086 | ||
|
|
eb85189c24 | ||
|
|
9bd808fcb8 | ||
|
|
968387eab2 | ||
|
|
f8f1e2a531 | ||
|
|
8707bbd569 | ||
|
|
724df5ad54 | ||
|
|
0f33913bf6 | ||
|
|
d856eb5905 | ||
|
|
ab9e7ce672 | ||
|
|
741e43ab14 | ||
|
|
4b0f66496c | ||
|
|
260fe70e5f | ||
|
|
ae3d7bbe24 | ||
|
|
990eeb844a | ||
|
|
4567bad251 | ||
|
|
aafbeed703 | ||
|
|
002bc20d50 | ||
|
|
19c5c56ab2 | ||
|
|
718b0e7613 | ||
|
|
5b5378ae6c | ||
|
|
67418e0b9d | ||
|
|
ca986688a1 | ||
|
|
97e43cfe40 | ||
|
|
a0ca52491e | ||
|
|
039a42cfef | ||
|
|
e2ab99c0cc | ||
|
|
5daaa99108 | ||
|
|
13244d17f1 | ||
|
|
e8604d172c | ||
|
|
9e0f0d2074 | ||
|
|
3dae071f41 | ||
|
|
d5dbd1b7da | ||
|
|
b1736e5efd | ||
|
|
bd979f65b8 | ||
|
|
d416f0be5c | ||
|
|
45e54e1ca8 | ||
|
|
d29e3f3f0e | ||
|
|
207ee49da3 | ||
|
|
88cb942430 | ||
|
|
765bedb592 | ||
|
|
2c73d8a48d | ||
|
|
750275d08f | ||
|
|
491d38cafe | ||
|
|
6c6da12dd6 | ||
|
|
0b20d1366a | ||
|
|
fa245aaa08 | ||
|
|
9a218f7b52 | ||
|
|
d202e27f79 | ||
|
|
960dddc048 | ||
|
|
9fcc739cd5 | ||
|
|
449cc4a42d | ||
|
|
b8421ba655 | ||
|
|
2ac261c15b | ||
|
|
2bd9cd32f6 | ||
|
|
693c8d96b1 | ||
|
|
42683f5966 | ||
|
|
2478b26a05 | ||
|
|
2608ab3bf6 | ||
|
|
9fc8b81362 | ||
|
|
5093d531bc | ||
|
|
08d75cb55c | ||
|
|
4c24547c26 | ||
|
|
53b9b63ae5 | ||
|
|
cd40b27357 | ||
|
|
3c10d14f60 | ||
|
|
035bc96b37 | ||
|
|
357e74573c | ||
|
|
668c5c7bdd | ||
|
|
7a0d898b1a | ||
|
|
33b6f590e9 | ||
|
|
dd7008d7ee | ||
|
|
9b051a6624 | ||
|
|
62c2c3a1c6 | ||
|
|
8528c5d3a3 | ||
|
|
4cf0610fd9 | ||
|
|
1459ec483c | ||
|
|
028c5b5201 | ||
|
|
41c0d175bd | ||
|
|
9280dd9f2f | ||
|
|
bde16e4e15 | ||
|
|
119f85dbf4 | ||
|
|
ede160f1b6 | ||
|
|
b4c84a11f2 | ||
|
|
2dd558a065 | ||
|
|
3cd9a1e0e4 | ||
|
|
ef92e004c0 | ||
|
|
290a44440c | ||
|
|
5d1ee145e1 | ||
|
|
aba9942a85 | ||
|
|
3aa2bab99f | ||
|
|
d6b8b327d9 | ||
|
|
e1a0d40530 | ||
|
|
48c5803198 | ||
|
|
0580dc4adf | ||
|
|
98ac5a036f | ||
|
|
87d2071007 | ||
|
|
bce9791b56 | ||
|
|
6fba888d45 | ||
|
|
1e08dc6301 | ||
|
|
2d4efc7942 | ||
|
|
bb0531b80f | ||
|
|
e325b5954c | ||
|
|
2be6cf35ac | ||
|
|
7a4fa93ce9 | ||
|
|
f9f6720437 | ||
|
|
cfee4405c7 | ||
|
|
eaa80fab74 | ||
|
|
8fab45ae39 | ||
|
|
6854d9853b | ||
|
|
5ca7218eb6 | ||
|
|
72d6a211af | ||
|
|
f10e3a4d2d | ||
|
|
cfd0e045cb | ||
|
|
4386970bd3 | ||
|
|
c6f0b792d3 | ||
|
|
966f607230 | ||
|
|
9a704e69b2 | ||
|
|
a91ebb4eda | ||
|
|
9fe6671ace | ||
|
|
386211df8c | ||
|
|
ce513ed61a | ||
|
|
3f75e655ce | ||
|
|
d9a423b596 | ||
|
|
30241ddccc | ||
|
|
10c7674433 | ||
|
|
c749fcfce3 | ||
|
|
fe527c1297 | ||
|
|
3b72af2e9b | ||
|
|
2d916e60d9 | ||
|
|
d8d731b321 | ||
|
|
4cc021adfe | ||
|
|
56e929014d | ||
|
|
e0a5350ed6 | ||
|
|
d774817b0e | ||
|
|
3526c05dc8 | ||
|
|
69a74425d9 | ||
|
|
eb1e325fe2 | ||
|
|
ffa0c16ab9 | ||
|
|
30f16e1a7a | ||
|
|
0d0353f8f3 | ||
|
|
637fae87cd | ||
|
|
c39116df84 | ||
|
|
dcef8770a7 | ||
|
|
816722256b | ||
|
|
2b890bdb2f | ||
|
|
882d94a22a | ||
|
|
43a488ed6d | ||
|
|
305fa03355 | ||
|
|
e677be7908 | ||
|
|
eac49ca641 | ||
|
|
2248320af7 | ||
|
|
f61421edd0 | ||
|
|
9bb5e49058 | ||
|
|
16c9f2b873 | ||
|
|
69d30ac71b | ||
|
|
9cf8ac0c3d | ||
|
|
f1a5998049 | ||
|
|
41b76144da | ||
|
|
e30e97037f | ||
|
|
102f1dd858 | ||
|
|
925ca2bb73 | ||
|
|
526bb3e042 | ||
|
|
e8adc357e9 | ||
|
|
130b4d29b4 | ||
|
|
5f357288ee | ||
|
|
26b5fbe9bb | ||
|
|
4650642311 | ||
|
|
e850cb7ff8 | ||
|
|
9fcb0577a5 | ||
|
|
df7dad8aaa | ||
|
|
3080e19bf2 | ||
|
|
f2bfa8e2ee | ||
|
|
2254e48f65 | ||
|
|
443f2bb6b9 | ||
|
|
c82cc7b301 | ||
|
|
63951ac134 | ||
|
|
301007e225 | ||
|
|
5776d351b4 | ||
|
|
484bea106b | ||
|
|
4fd5d9e0c3 | ||
|
|
5375692f1f | ||
|
|
20c0419782 | ||
|
|
c74fe87fc8 | ||
|
|
d5c43c9fda | ||
|
|
5344e60e3d | ||
|
|
52c8c93b30 | ||
|
|
31cb2081c6 | ||
|
|
cad1418199 | ||
|
|
984e081f3b | ||
|
|
282d26b844 | ||
|
|
9516235707 | ||
|
|
409416b55c | ||
|
|
05d0e825fd | ||
|
|
c14f1aa996 | ||
|
|
05953d0d6b | ||
|
|
fdf57b1e63 | ||
|
|
7f640fd701 | ||
|
|
4016b81208 | ||
|
|
7a06ddb8d1 | ||
|
|
c90317fb35 | ||
|
|
55e59e0b53 | ||
|
|
1186d40fda | ||
|
|
1fc3ca284e | ||
|
|
f4e66a3d7a | ||
|
|
71420df0f3 | ||
|
|
5019bb8b6e | ||
|
|
61006ee73b | ||
|
|
9ebdef043c | ||
|
|
93e629584b | ||
|
|
1061f1138f | ||
|
|
5c7e278b93 | ||
|
|
a42ef6b3ea | ||
|
|
ac526f9762 | ||
|
|
d21e9fe093 | ||
|
|
3e493cb93c | ||
|
|
37a55715d0 | ||
|
|
5198ced5aa | ||
|
|
5ce8a643a7 | ||
|
|
53304b3de2 | ||
|
|
a09a6997b4 | ||
|
|
f7212ef757 | ||
|
|
5f36933837 | ||
|
|
a234dd4382 | ||
|
|
31d5d18d65 | ||
|
|
6d527c3668 | ||
|
|
1497c31908 | ||
|
|
6be4e5c266 | ||
|
|
4e22e37192 | ||
|
|
3395f97b20 | ||
|
|
73b6eb568b | ||
|
|
5c61c9d3a9 | ||
|
|
88b705c8ef | ||
|
|
a78001a5cc | ||
|
|
b2454c8b8d | ||
|
|
3f9ffbac80 | ||
|
|
55fd5c3b9b | ||
|
|
db9cfb9ddd | ||
|
|
2d2362a1a6 | ||
|
|
fdc033a63f | ||
|
|
b8eab0614f | ||
|
|
78aff37fe4 | ||
|
|
58aed632a1 | ||
|
|
3969dc9fb6 | ||
|
|
ac27b40f7a | ||
|
|
8e2d422054 | ||
|
|
d69267f71c | ||
|
|
3a7bec1eef | ||
|
|
8006e20dd3 | ||
|
|
5ef651ce6d | ||
|
|
e426d50cc2 | ||
|
|
2f9f539857 | ||
|
|
84e1ed1cf9 | ||
|
|
8cb6e0b229 | ||
|
|
2584aad0c7 | ||
|
|
4065a4f6a2 | ||
|
|
c2197b0adb | ||
|
|
222b29cec6 | ||
|
|
0ac91d3c5e | ||
|
|
d0b4761e07 | ||
|
|
647252b0cb | ||
|
|
795da1b088 | ||
|
|
846971836a | ||
|
|
578f47d3b2 | ||
|
|
d53a765971 | ||
|
|
ca2c9991fe | ||
|
|
47ca19e37d | ||
|
|
86b66b91dd | ||
|
|
06bc14f690 | ||
|
|
d3df8e6abd | ||
|
|
7d02a801ad | ||
|
|
bd69047e8c | ||
|
|
5abe52607d | ||
|
|
46d502e053 | ||
|
|
0d489e638e | ||
|
|
b8a335a88f | ||
|
|
0d671ae407 | ||
|
|
e10074d153 | ||
|
|
f92b59e6db | ||
|
|
f39f7fc23e | ||
|
|
02e4de61eb | ||
|
|
cedcb3d84f |
21
.gitignore
vendored
21
.gitignore
vendored
@@ -10,32 +10,22 @@ obj
|
||||
mods/*/*.dll
|
||||
|
||||
# Red Alert binary files
|
||||
*.[mM][iI][xX]
|
||||
*.[aA][uU][dD]
|
||||
|
||||
# Crap generated by OpenRa
|
||||
sheet-*.png
|
||||
log.txt
|
||||
|
||||
*.rep
|
||||
mods/*/packages/*.[mM][iI][xX]
|
||||
|
||||
#binary stuff
|
||||
/*.dll
|
||||
*.pdb
|
||||
*.mdb
|
||||
/*.exe
|
||||
OpenRA
|
||||
OpenRA.app
|
||||
*.exe
|
||||
|
||||
# backup files by various editors
|
||||
*~
|
||||
*.orig
|
||||
# dependency DLLs (different for every platform!)
|
||||
cg.dll
|
||||
cgGL.dll
|
||||
glfw.dll
|
||||
|
||||
/OpenRa.Gl.dll
|
||||
settings.ini
|
||||
|
||||
#monodevelop
|
||||
*.pidb
|
||||
@@ -43,6 +33,9 @@ settings.ini
|
||||
|
||||
packaging/windows/*.exe
|
||||
|
||||
# osx crap
|
||||
.DS_Store
|
||||
|
||||
# osx build crap
|
||||
packaging/osx/launcher/build/
|
||||
packaging/osx/launcher/OpenRA.xcodeproj/*.pbxuser
|
||||
@@ -53,4 +46,4 @@ temp.o
|
||||
temp.s
|
||||
|
||||
*.config
|
||||
*.resources
|
||||
*.resources
|
||||
|
||||
3
AUTHORS
3
AUTHORS
@@ -6,4 +6,5 @@ The OpenRA developers are:
|
||||
* Matthew Bowra-Dean
|
||||
* Paul Chote
|
||||
* Alli Witheford
|
||||
* Joakim Lindberg
|
||||
* Joakim Lindberg
|
||||
* Andrew Riedi
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.IO;
|
||||
using OpenRA.FileFormats;
|
||||
using System.IO;
|
||||
|
||||
namespace FileExtractor
|
||||
{
|
||||
@@ -17,10 +17,8 @@ namespace FileExtractor
|
||||
}
|
||||
|
||||
var mods = args[0].Split(',');
|
||||
var manifest = new Manifest(mods);
|
||||
|
||||
foreach (var folder in manifest.Folders) FileSystem.Mount(folder);
|
||||
foreach (var pkg in manifest.Packages) FileSystem.Mount(pkg);
|
||||
var manifest = new Manifest(mods);
|
||||
FileSystem.LoadFromManifest( manifest );
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
75
HACKING
75
HACKING
@@ -5,43 +5,82 @@ There are n main sections to OpenRA: UI, Rendering, unit behaviour, ...
|
||||
All units/structures/most things in the map are Actors. Actors contain a collection of traits.
|
||||
Traits consist of an info class and a class that does stuff
|
||||
|
||||
Actor assembly is done via the mod's yaml files. A section exists for each actor type, and within that section we list the traits the actor should have. These get looked up in the loaded mod DLLs. Each trait can contain properties, which are automatically loaded into the corresponding fields on the trait's ITraitInfo.
|
||||
Actor assembly is done via the mod's yaml files. A section exists for each actor type,
|
||||
and within that section we list the traits the actor should have.
|
||||
These get looked up in the loaded mod DLLs. Each trait can contain properties,
|
||||
which are automatically loaded into the corresponding fields on the trait's ITraitInfo.
|
||||
|
||||
- Traits: look at TraitInterfaces.cs
|
||||
We've tried to make individual traits implement as self-contained a unit of functionality as possible - all cross-trait references should be in terms of an interface from TraitInterfaces.cs.
|
||||
We've tried to make individual traits implement as self-contained a unit of functionality
|
||||
as possible - all cross-trait references should be in terms of an interface from
|
||||
TraitInterfaces.cs.
|
||||
|
||||
- Things an actor can be *doing* are represented as IActivity implementations. Actor has a queue of these. There's a standard set of activities in OpenRa.Game/Traits/Activities, and mods tend to define more as they need them. (RA defines various special-infantry actions as activities).
|
||||
- Things an actor can be *doing* are represented as IActivity implementations.
|
||||
Actor has a queue of these. There's a standard set of activities in
|
||||
OpenRa.Game/Traits/Activities, and mods tend to define more as they need them. (RA
|
||||
defines various special-infantry actions as activities).
|
||||
|
||||
- Units offer orders they can perform (given context) through traits that implement IIssueOrder. Every trait with this interface is given a chance to generate orders for the current context.
|
||||
- Units offer orders they can perform (given context) through traits that implement IIssueOrder.
|
||||
Every trait with this interface is given a chance to generate orders for the current context.
|
||||
|
||||
- For more complex things that require modal UI (like special abilities, RA-style sell/repair buttons, etc) we have IOrderGenerator implementations. This can completely replace the normal actors-provide-orders model temporarily. IOGs wiring is provided through OpenRa.Game/Controller.cs (ToggleInputMode<T>, CancelInputMode)
|
||||
- For more complex things that require modal UI (like special abilities,
|
||||
RA-style sell/repair buttons, etc) we have IOrderGenerator implementations. This can
|
||||
completely replace the normal actors-provide-orders model temporarily. IOGs wiring is
|
||||
provided through OpenRa.Game/Controller.cs (ToggleInputMode<T>, CancelInputMode)
|
||||
|
||||
- Things that don't affect gameplay, or (increasingly) are just transient are implemented as IEffect, rather than real Actors. This is similar to the temp ents mechanism in many other game engines.
|
||||
- Things that don't affect gameplay, or (increasingly) are just transient are implemented as
|
||||
IEffect, rather than real Actors. This is similar to the temp ents mechanism in many other
|
||||
game engines.
|
||||
|
||||
- Most player-level or global-level game behavior is implemented as traits on special Player and World actors. These are accessible via Player.PlayerActor and World.WorldActor. This includes production queue support, ore/tiberium growth, various palette manipulation magic.
|
||||
- Most player-level or global-level game behavior is implemented as traits on special Player
|
||||
and World actors. These are accessible via Player.PlayerActor and World.WorldActor. This
|
||||
includes production queue support, ore/tiberium growth, various palette manipulation magic.
|
||||
|
||||
- Many traits can be modified by adding an appropriate IFooModifier implementation to the unit. This includes rendering, where IRenderModifier allows you to define an arbitrary transform on the Renderables emitted by the actor's IRender implementation(s). Examples are things like cloaking, invisibility to certain players, flying units with shadows, etc. Other modifiers can affect movement speed, damage taken, weapon firepower, etc.
|
||||
- Many traits can be modified by adding an appropriate IFooModifier implementation to the unit.
|
||||
This includes rendering, where IRenderModifier allows you to define an arbitrary transform on
|
||||
the Renderables emitted by the actor's IRender implementation(s). Examples are things like
|
||||
cloaking, invisibility to certain players, flying units with shadows, etc. Other modifiers
|
||||
can affect movement speed, damage taken, weapon firepower, etc.
|
||||
|
||||
Game code is collected into "Mod" units. Mods can be added prior to starting the game. Currently there is no dependancy mechanism, but provided you are doing additions or overrides you can add multiple mods without problem.
|
||||
Game code is collected into "Mod" units. Mods can be added prior to starting the game.
|
||||
Currently there is no dependancy mechanism, but provided you are doing additions or overrides
|
||||
you can add multiple mods without problem.
|
||||
Everything is a mod (including RA - which is loaded by default).
|
||||
|
||||
The contents of the mod is defined in a manifest file mod.yaml. This lists the packages containing art assets (typically .mix files), yaml files defining actor defintions, and ini files containing legacy information that have yet to be ported over to the (relatively new) yaml system.
|
||||
The contents of the mod is defined in a manifest file mod.yaml. This lists the packages
|
||||
containing art assets (typically .mix files), yaml files defining actor defintions,
|
||||
and ini files containing legacy information that have yet to be ported over to
|
||||
the (relatively new) yaml system.
|
||||
|
||||
The unit artwork itself must be defined in a Sequences file (typically Sequences.xml; check mod.yaml for a list of what the mod uses); the format is self explanatory. There is also the SequenceEditor tool to make this easy.
|
||||
The unit artwork itself must be defined in a Sequences file (typically Sequences.xml;
|
||||
check mod.yaml for a list of what the mod uses); the format is self explanatory. There is
|
||||
also the SequenceEditor tool to make this easy.
|
||||
|
||||
Chrome artwork is similarly defined in Chrome.xml. Chrome is already mod dependent. Sortof ;) mod-dependent *behavior* would be nice too, not just skinning. This is a property of the traits however; once we port UI into traits this will become a non-issue.
|
||||
Chrome artwork is similarly defined in Chrome.xml. Chrome is already mod dependent. Sortof ;)
|
||||
mod-dependent *behavior* would be nice too, not just skinning. This is a property of the traits
|
||||
however; once we port UI into traits this will become a non-issue.
|
||||
|
||||
Rendering
|
||||
OpenRa.Game/Chrome.cs is the user interface.
|
||||
Three renderers (SpriteRenderer, LineRenderer, Rgba?Renderer) render most stuff. Don't forget to flush the renderer (if you want to see anything).
|
||||
Three renderers (SpriteRenderer, LineRenderer, Rgba?Renderer) render most stuff. Don't forget
|
||||
to flush the renderer (if you want to see anything).
|
||||
|
||||
UserSettings stores the data loaded from settings.ini (or defaults). Eventually we need to be able to save values changed in game into settings.ini (not yet implemented)
|
||||
UserSettings stores the data loaded from settings.ini (or defaults). Eventually we need to be
|
||||
able to save values changed in game into settings.ini (not yet implemented)
|
||||
|
||||
Bugs: There is a list of known bugs and features at http://openra.res0l.net/projects/openra/issues . There's also a few at http://github.com/chrisforbes/OpenRA/issues (which won't be ported over, but no more bugs should be added here).
|
||||
Bugs: There is a list of known bugs and features at http://bugs.open-ra.org/ .
|
||||
|
||||
We also have a website at http://www.open-ra.org/ .
|
||||
|
||||
As far as using git, get your own repository on github. You probably want to set up the gitbot to spam irc when you make commits (its nice to know). Push your changes into your git repository, and it will/might :P be merged into chrisforbes/OpenRA . Alli: setup howto for this?
|
||||
Our IRC channel is #openra on irc.freenode.net .
|
||||
|
||||
As far as using git, get your own repository on github. You probably want to set up the gitbot
|
||||
to spam irc when you make commits (its nice to know). Push your changes into your git
|
||||
repository, and it will/might :P be merged into http://github.com/OpenRA/OpenRA .
|
||||
See http://help.github.com/ for working with GitHub and see http://progit.org/ for working
|
||||
with Git.
|
||||
|
||||
|
||||
|
||||
Other things we probably want to put in here:
|
||||
- A guide on how to add a generic unit via yaml using existing traits
|
||||
@@ -50,6 +89,6 @@ Other things we probably want to put in here:
|
||||
- VFS (OpenRa.FileFormats.FileSystem, Package, Folder classes)
|
||||
- Trait inheritance (and the magicness of ^ActorType)
|
||||
- Removing inherited traits (prepend `-` to the trait name)
|
||||
- Multiple instances of a trait (`@` and all subsequent characters are ignored for the purposes
|
||||
of looking up the trait.
|
||||
- Multiple instances of a trait (`@` and all subsequent characters are ignored for
|
||||
the purposes of looking up the trait.
|
||||
|
||||
|
||||
119
INSTALL
119
INSTALL
@@ -1,44 +1,51 @@
|
||||
Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean,
|
||||
Paul Chote, Alli Witheford.
|
||||
|
||||
This file is part of OpenRA.
|
||||
Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
This file is part of OpenRA, which is free software. It is made
|
||||
available to you under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation. For more information,
|
||||
see LICENSE.
|
||||
|
||||
OpenRA is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
To run OpenRA, several files are needed from the original game disks.
|
||||
|
||||
OpenRA is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
The required files for the Red Alert mod are:
|
||||
EITHER:
|
||||
* conquer.mix
|
||||
* temperat.mix
|
||||
* interior.mix
|
||||
* snow.mix
|
||||
* sounds.mix
|
||||
* allies.mix
|
||||
* russian.mix
|
||||
OR:
|
||||
* main.mix
|
||||
AND:
|
||||
* redalert.mix
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
These need to be copied into the mods/ra/packages/ directory.
|
||||
|
||||
To compile OpenRA, open the OpenRA.sln solution in the main folder,
|
||||
or build it from the command-line with MSBuild.
|
||||
|
||||
To run OpenRA, several files from the original game’s install need
|
||||
to be copied to the root of the project directory. The required files are:
|
||||
The required files for the Command and Conquer mod are:
|
||||
* cclocal.mix
|
||||
* speech.mix
|
||||
* conquer.mix
|
||||
* sounds.mix
|
||||
* tempicnh.mix
|
||||
* temperat.mix
|
||||
* winter.mix
|
||||
* desert.mix
|
||||
|
||||
redalert.mix
|
||||
conquer.mix
|
||||
temperat.mix
|
||||
interior.mix
|
||||
snow.mix
|
||||
sounds.mix
|
||||
allies.mix
|
||||
russian.mix
|
||||
general.mix
|
||||
|
||||
hires1.mix
|
||||
expand2.mix
|
||||
These need to be copied into the mods/cnc/packages/ directory.
|
||||
If you have a case-sensitive filesystem you must change the filenames to
|
||||
lower case.
|
||||
|
||||
Red Alert has been released by EA Games as freeware so it shouldn’t
|
||||
be too hard to find a legal copy of the CD images. Unfortunately the
|
||||
installer is 16-bit and so won’t run on 64-bit operating systems. This
|
||||
can be worked around by using the Red Alert Setup Manager
|
||||
The files can be downloaded from:
|
||||
http://open-ra.org/get-dependency.php?file=ra-packages for the Red Alert files and
|
||||
http://open-ra.org/get-dependency.php?file=cnc-packages for the Command & Conquer files.
|
||||
|
||||
Alternatively:
|
||||
Red Alert and C&C have been released by EA Games as freeware. They can be
|
||||
downloaded from http://www.commandandconquer.com/classic
|
||||
Unfortunately the installer is 16-bit and so won’t run on 64-bit operating
|
||||
systems. This can be worked around by using the Red Alert Setup Manager
|
||||
(http://ra.afraid.org/html/downloads/utilities-3.html).
|
||||
Make sure you apply the no-CD protection fix so all the files needed
|
||||
are installed to the hard drive.
|
||||
@@ -46,12 +53,50 @@ are installed to the hard drive.
|
||||
Dependencies - Make sure you have these installed, or you'll
|
||||
have very strange errors.
|
||||
|
||||
|
||||
WINDOWS:
|
||||
|
||||
* .NET Framework >= 3.5-SP1
|
||||
(http://www.microsoft.com/downloads/details.aspx?FamilyID=AB99342F-5D1A-413D-8319-81DA479AB0D7&displaylang=en)
|
||||
* Tao Framework >= 2.1.0
|
||||
(http://sourceforge.net/projects/taoframework/)
|
||||
(required libs: Tao.OpenGL, Tao.Cg, Tao.Platform.Windows)
|
||||
This is now bundled with OpenRA, copy the files in thirdparty/Tao to the game root directory.
|
||||
* OpenAL >= 1.1
|
||||
(http://connect.creativelabs.com/openal/Downloads/oalinst.zip)
|
||||
* Cg Toolkit >= 2.2
|
||||
(http://developer.download.nvidia.com/cg/Cg_2.2/Cg-2.2_October2009_Setup.exe)
|
||||
(http://developer.download.nvidia.com/cg/Cg_2.2/Cg-2.2_October2009_Setup.exe)
|
||||
|
||||
To compile OpenRA, open the OpenRA.sln solution in the main folder,
|
||||
or build it from the command-line with MSBuild.
|
||||
|
||||
Run the game with `OpenRA.Game.exe Game.Mods=ra` for Red Alert
|
||||
or `OpenRA.Game.exe Game.Mods=cnc` for Command & Conquer
|
||||
|
||||
|
||||
UBUNTU (substitute comparable packages for other linux distros):
|
||||
|
||||
* mono-gmcs
|
||||
* freetype
|
||||
* libmono-corlib1.0-cil
|
||||
* libmono-winforms2.0-cil
|
||||
* libopenal1
|
||||
* libsdl1.2-dev
|
||||
* nvidia-cg-toolkit (download the latest version from
|
||||
http://developer.nvidia.com/object/cg_download.html)
|
||||
|
||||
OpenRA is incompatible with Compiz, please disable desktop effects when trying
|
||||
to run OpenRA or the game will crash.
|
||||
|
||||
You will need to copy the Tao dependencies (.dll and .config) from the
|
||||
thirdparty/Tao directory into the game root, or install them permanently into
|
||||
your GAC with the following script
|
||||
|
||||
#!/bin/sh
|
||||
gacutil -i thirdparty/Tao/Tao.Cg.dll
|
||||
gacutil -i thirdparty/Tao/Tao.OpenGl.dll
|
||||
gacutil -i thirdparty/Tao/Tao.OpenAl.dll
|
||||
gacutil -i thirdparty/Tao/Tao.Sdl.dll
|
||||
gacutil -i thirdparty/Tao/Tao.FreeType.dll
|
||||
|
||||
To compile OpenRA, run `make' from the command line.
|
||||
Run the game with `mono OpenRA.Game.exe Game.Mods=ra` for Red Alert
|
||||
or `mono OpenRA.Game.exe Game.Mods=cnc` for Command & Conquer
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean,
|
||||
Paul Chote, Alli Witheford.
|
||||
|
||||
This file is part of OpenRA.
|
||||
|
||||
OpenRA is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenRA is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
To compile OpenRA, open the OpenRA.sln solution in the main folder,
|
||||
or build it from the command-line with MSBuild.
|
||||
|
||||
To run OpenRA, several files from the original game’s install need
|
||||
to be copied to the root of the project directory. The required files are:
|
||||
|
||||
redalert.mix
|
||||
conquer.mix
|
||||
temperat.mix
|
||||
interior.mix
|
||||
snow.mix
|
||||
sounds.mix
|
||||
allies.mix
|
||||
russian.mix
|
||||
general.mix
|
||||
|
||||
hires1.mix
|
||||
expand2.mix
|
||||
|
||||
Red Alert has been released by EA Games as freeware so it shouldn’t
|
||||
be too hard to find a legal copy of the CD images. Unfortunately the
|
||||
installer is 16-bit and so won’t run on 64-bit operating systems. This
|
||||
can be worked around by using the Red Alert Setup Manager
|
||||
(http://ra.afraid.org/html/downloads/utilities-3.html).
|
||||
Make sure you apply the no-CD protection fix so all the files needed
|
||||
are installed to the hard drive.
|
||||
|
||||
Dependencies - Make sure you have these installed, or you'll
|
||||
have very strange errors.
|
||||
|
||||
* mono-gmcs
|
||||
* libglfw2
|
||||
* nvidia-cg-toolkit
|
||||
* libmono-*
|
||||
150
Makefile
150
Makefile
@@ -1,7 +1,7 @@
|
||||
CSC = gmcs
|
||||
CSFLAGS = -nologo -warn:4 -debug:+ -debug:full -optimize- -codepage:utf8 -unsafe
|
||||
DEFINE = DEBUG;TRACE
|
||||
PROGRAMS =fileformats gl game ra cnc aftermath seqed mapcvtr editor ralint filex tsbuild
|
||||
PROGRAMS = fileformats rcg rgl rnull game ra cnc seqed editor ralint filex tsbuild utility winlaunch
|
||||
prefix = /usr/local
|
||||
datarootdir = $(prefix)/share
|
||||
datadir = $(datarootdir)
|
||||
@@ -16,17 +16,32 @@ COMMON_LIBS = System.dll System.Core.dll System.Drawing.dll System.Xml.dll
|
||||
fileformats_SRCS = $(shell find OpenRA.FileFormats/ -iname '*.cs')
|
||||
fileformats_TARGET = OpenRA.FileFormats.dll
|
||||
fileformats_KIND = library
|
||||
fileformats_LIBS = $(COMMON_LIBS) thirdparty/Tao/Tao.Sdl.dll WindowsBase.dll
|
||||
fileformats_LIBS = $(COMMON_LIBS) thirdparty/Tao/Tao.Sdl.dll System.Windows.Forms.dll thirdparty/ICSharpCode.SharpZipLib.dll
|
||||
|
||||
gl_SRCS = $(shell find OpenRA.Gl/ -iname '*.cs')
|
||||
gl_TARGET = OpenRA.Gl.dll
|
||||
gl_KIND = library
|
||||
gl_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
||||
gl_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll \
|
||||
thirdparty/Tao/Tao.Cg.dll thirdparty/Tao/Tao.OpenGl.dll thirdparty/Tao/Tao.Sdl.dll \
|
||||
$(gl_DEPS) $(game_TARGET)
|
||||
rcg_SRCS = $(shell find OpenRA.Renderer.Cg/ -iname '*.cs')
|
||||
rcg_TARGET = OpenRA.Renderer.Cg.dll
|
||||
rcg_KIND = library
|
||||
rcg_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
||||
rcg_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll \
|
||||
thirdparty/Tao/Tao.Cg.dll thirdparty/Tao/Tao.OpenGl.dll thirdparty/Tao/Tao.Sdl.dll \
|
||||
$(rcg_DEPS) $(game_TARGET)
|
||||
|
||||
game_SRCS = $(shell find OpenRA.Game/ -iname '*.cs')
|
||||
rgl_SRCS = $(shell find OpenRA.Renderer.Gl/ -iname '*.cs')
|
||||
rgl_TARGET = OpenRA.Renderer.Gl.dll
|
||||
rgl_KIND = library
|
||||
rgl_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
||||
rgl_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll \
|
||||
thirdparty/Tao/Tao.Cg.dll thirdparty/Tao/Tao.OpenGl.dll thirdparty/Tao/Tao.Sdl.dll \
|
||||
$(rgl_DEPS) $(game_TARGET)
|
||||
|
||||
rnull_SRCS = $(shell find OpenRA.Renderer.Null/ -iname '*.cs')
|
||||
rnull_TARGET = OpenRA.Renderer.Null.dll
|
||||
rnull_KIND = library
|
||||
rnull_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
||||
rnull_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll \
|
||||
$(rnull_DEPS) $(game_TARGET)
|
||||
|
||||
game_SRCS = $(shell find OpenRA.Game/ -iname '*.cs')
|
||||
game_TARGET = OpenRA.Game.exe
|
||||
game_KIND = winexe
|
||||
game_DEPS = $(fileformats_TARGET)
|
||||
@@ -46,40 +61,29 @@ cnc_KIND = library
|
||||
cnc_DEPS = $(fileformats_TARGET) $(game_TARGET) $(ra_TARGET)
|
||||
cnc_LIBS = $(COMMON_LIBS) $(cnc_DEPS)
|
||||
|
||||
aftermath_SRCS = $(shell find OpenRA.Mods.Aftermath/ -iname '*.cs')
|
||||
aftermath_TARGET = mods/aftermath/OpenRA.Mods.Aftermath.dll
|
||||
aftermath_KIND = library
|
||||
aftermath_DEPS = $(fileformats_TARGET) $(game_TARGET) $(ra_TARGET)
|
||||
aftermath_LIBS = $(COMMON_LIBS) $(aftermath_DEPS)
|
||||
|
||||
seqed_SRCS = $(shell find SequenceEditor/ -iname '*.cs')
|
||||
seqed_TARGET = SequenceEditor.exe
|
||||
seqed_KIND = winexe
|
||||
seqed_DEPS = $(fileformats_TARGET)
|
||||
seqed_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll $(seqed_DEPS)
|
||||
seqed_EXTRA = -resource:SequenceEditor.Form1.resources
|
||||
|
||||
editor_SRCS = $(shell find OpenRA.Editor/ -iname '*.cs')
|
||||
editor_TARGET = OpenRA.Editor.exe
|
||||
editor_KIND = winexe
|
||||
editor_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
||||
editor_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll System.Data.dll $(editor_DEPS)
|
||||
editor_EXTRA = -resource:OpenRA.Editor.Form1.resources
|
||||
|
||||
mapcvtr_SRCS = $(shell find MapConverter/ -iname '*.cs')
|
||||
mapcvtr_TARGET = MapConverter.exe
|
||||
mapcvtr_KIND = winexe
|
||||
mapcvtr_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
||||
mapcvtr_LIBS = $(COMMON_LIBS) $(mapcvtr_DEPS)
|
||||
editor_EXTRA = -resource:OpenRA.Editor.Form1.resources -resource:OpenRA.Editor.MapSelect.resources
|
||||
|
||||
ralint_SRCS = $(shell find RALint/ -iname '*.cs')
|
||||
ralint_TARGET = RALint.exe
|
||||
ralint_KIND = winexe
|
||||
ralint_KIND = exe
|
||||
ralint_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
||||
ralint_LIBS = $(COMMON_LIBS) $(ralint_DEPS)
|
||||
|
||||
filex_SRCS = $(shell find FileExtractor/ -iname '*.cs')
|
||||
filex_TARGET = FileExtractor.exe
|
||||
filex_KIND = winexe
|
||||
filex_KIND = exe
|
||||
filex_DEPS = $(fileformats_TARGET)
|
||||
filex_LIBS = $(COMMON_LIBS) $(filex_DEPS)
|
||||
|
||||
@@ -90,54 +94,80 @@ tsbuild_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
||||
tsbuild_LIBS = $(COMMON_LIBS) $(tsbuild_DEPS) System.Windows.Forms.dll
|
||||
tsbuild_EXTRA = -resource:OpenRA.TilesetBuilder.Form1.resources
|
||||
|
||||
utility_SRCS = $(shell find OpenRA.Utility/ -iname '*.cs')
|
||||
utility_TARGET = OpenRA.Utility.exe
|
||||
utility_KIND = exe
|
||||
utility_DEPS = $(fileformats_TARGET) thirdparty/ICSharpCode.SharpZipLib.dll
|
||||
utility_LIBS = $(COMMON_LIBS) $(utility_DEPS)
|
||||
|
||||
winlaunch_SRCS = $(shell find OpenRA.Launcher/ -iname '*.cs')
|
||||
winlaunch_TARGET = OpenRA.Launcher.exe
|
||||
winlaunch_KIND = winexe
|
||||
winlaunch_DEPS =
|
||||
winlaunch_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll
|
||||
winlaunch_EXTRA = -resource:OpenRA.Launcher.MainForm.resources \
|
||||
-resource:OpenRA.Launcher.InstallPackagesDialog.resources \
|
||||
-resource:OpenRA.Launcher.ConfigureModsDialog.resources
|
||||
|
||||
# -platform:x86
|
||||
|
||||
.SUFFIXES:
|
||||
.PHONY: clean all game tool default mods mod_ra mod_aftermath mod_cnc install uninstall editor_res editor tsbuild ralint seqed mapcvtr filex
|
||||
|
||||
game: $(fileformats_TARGET) $(gl_TARGET) $(game_TARGET) $(ra_TARGET) $(cnc_TARGET) $(aftermath_TARGET)
|
||||
.PHONY: clean all game tool default mods mod_ra mod_cnc install uninstall editor_res editor tsbuild ralint seqed filex utility winlaunch
|
||||
core: game editor
|
||||
package: game editor utility
|
||||
all: game tools
|
||||
tools: editor ralint seqed filex tsbuild utility winlaunch
|
||||
game: $(fileformats_TARGET) $(rcg_TARGET) $(rgl_TARGET) $(rnull_TARGET) $(game_TARGET) $(ra_TARGET) $(cnc_TARGET)
|
||||
|
||||
clean:
|
||||
@-rm *.exe *.dll *.mdb mods/**/*.dll mods/**/*.mdb *.resources
|
||||
|
||||
distclean: clean
|
||||
|
||||
CORE = fileformats gl game seqed mapcvtr
|
||||
CORE = fileformats rcg rgl rnull game editor utility winlaunch
|
||||
|
||||
install: all
|
||||
@-echo "Installing OpenRA to $(INSTALL_DIR)"
|
||||
@$(INSTALL_PROGRAM) -d $(INSTALL_DIR)
|
||||
@$(INSTALL_PROGRAM) $(foreach prog,$(CORE),$($(prog)_TARGET)) $(INSTALL_DIR)
|
||||
|
||||
@$(INSTALL_PROGRAM) -d $(INSTALL_DIR)/mods/aftermath
|
||||
@$(INSTALL_PROGRAM) $(aftermath_TARGET) $(INSTALL_DIR)/mods/aftermath
|
||||
@-cp $(foreach f,$(shell ls mods/aftermath --hide=*.dll),mods/aftermath/$(f)) $(INSTALL_DIR)/mods/aftermath
|
||||
@cp -r mods/aftermath/packages $(INSTALL_DIR)/mods/aftermath
|
||||
|
||||
|
||||
@$(INSTALL_PROGRAM) -d $(INSTALL_DIR)/mods/cnc
|
||||
@$(INSTALL_PROGRAM) $(cnc_TARGET) $(INSTALL_DIR)/mods/cnc
|
||||
@-cp $(foreach f,$(shell ls mods/cnc --hide=*.dll),mods/cnc/$(f)) $(INSTALL_DIR)/mods/cnc
|
||||
@cp -r mods/cnc/maps $(INSTALL_DIR)/mods/cnc
|
||||
@cp -r mods/cnc/chrome $(INSTALL_DIR)/mods/cnc
|
||||
@cp -r mods/cnc/bits $(INSTALL_DIR)/mods/cnc
|
||||
@cp -r mods/cnc/rules $(INSTALL_DIR)/mods/cnc
|
||||
@cp -r mods/cnc/sequences $(INSTALL_DIR)/mods/cnc
|
||||
@cp -r mods/cnc/tilesets $(INSTALL_DIR)/mods/cnc
|
||||
@cp -r mods/cnc/uibits $(INSTALL_DIR)/mods/cnc
|
||||
|
||||
@$(INSTALL_PROGRAM) -d $(INSTALL_DIR)/mods/ra
|
||||
@$(INSTALL_PROGRAM) $(ra_TARGET) $(INSTALL_DIR)/mods/ra
|
||||
@-cp $(foreach f,$(shell ls mods/ra --hide=*.dll),mods/ra/$(f)) $(INSTALL_DIR)/mods/ra
|
||||
@cp -r mods/ra/maps $(INSTALL_DIR)/mods/ra
|
||||
@cp -r mods/ra/bits $(INSTALL_DIR)/mods/ra
|
||||
@cp -r mods/ra/chrome $(INSTALL_DIR)/mods/ra
|
||||
@cp -r mods/ra/rules $(INSTALL_DIR)/mods/ra
|
||||
@cp -r mods/ra/tilesets $(INSTALL_DIR)/mods/ra
|
||||
@cp -r mods/ra/uibits $(INSTALL_DIR)/mods/ra
|
||||
|
||||
@cp -r shaders $(INSTALL_DIR)
|
||||
@cp *.ttf $(INSTALL_DIR)
|
||||
@-cp *.ini $(INSTALL_DIR)
|
||||
@cp -r thirdparty $(INSTALL_DIR)
|
||||
@cp --parents -r thirdparty/Tao $(INSTALL_DIR)
|
||||
@$(INSTALL_PROGRAM) thirdparty/WindowsBase.dll $(INSTALL_DIR)
|
||||
@$(INSTALL_PROGRAM) thirdparty/ICSharpCode.SharpZipLib.dll $(INSTALL_DIR)
|
||||
@-$(INSTALL_PROGRAM) VERSION $(INSTALL_DIR)
|
||||
|
||||
@echo "#!/bin/sh" > openra
|
||||
@echo "cd "$(datadir)"/openra" >> openra
|
||||
@echo "mono "$(datadir)"/openra/OpenRA.Game.exe" >> openra
|
||||
@echo "mono "$(datadir)"/openra/OpenRA.Game.exe SupportDir=~/.openra \"$$""@\"" >> openra
|
||||
@$(INSTALL_PROGRAM) -d $(BIN_INSTALL_DIR)
|
||||
@$(INSTALL_PROGRAM) -m +rx openra $(BIN_INSTALL_DIR)
|
||||
|
||||
@echo "OpenRA is now installed. You will now want to download"
|
||||
@echo "http://open-ra.org/packages/ra-packages.zip and"
|
||||
@echo "http://open-ra.org/packages/cnc-packages.zip"
|
||||
@echo "http://open-ra.org/get-dependency.php?file=ra-packages and"
|
||||
@echo "http://open-ra.org/get-dependency.php?file=cnc-packages"
|
||||
@echo "and extract their contents to"
|
||||
@echo "$(INSTALL_DIR)/mods/ra/packages and "
|
||||
@echo "$(INSTALL_DIR)/mods/cnc/packages respectively."
|
||||
@@ -150,28 +180,41 @@ uninstall:
|
||||
|
||||
mod_ra: $(ra_TARGET) $(ralint_TARGET)
|
||||
mono RALint.exe ra
|
||||
mod_aftermath: $(aftermath_TARGET) $(ralint_TARGET)
|
||||
mono RALint.exe ra aftermath
|
||||
mod_cnc: $(cnc_TARGET) $(ralint_TARGET)
|
||||
mono RALint.exe cnc
|
||||
mods: mod_ra mod_cnc
|
||||
|
||||
editor_res:
|
||||
resgen2 OpenRA.Editor/Form1.resx OpenRA.Editor.Form1.resources
|
||||
editor: editor_res $(editor_TARGET)
|
||||
OpenRA.Editor.MapSelect.resources:
|
||||
resgen2 OpenRA.Editor/MapSelect.resx OpenRA.Editor.MapSelect.resources 1> /dev/null
|
||||
|
||||
OpenRA.Editor.Form1.resources:
|
||||
resgen2 OpenRA.Editor/Form1.resx OpenRA.Editor.Form1.resources 1> /dev/null
|
||||
editor: OpenRA.Editor.MapSelect.resources OpenRA.Editor.Form1.resources $(editor_TARGET)
|
||||
ralint: $(ralint_TARGET)
|
||||
seqed: $(seqed_TARGET)
|
||||
mapcvtr: $(mapcvtr_TARGET)
|
||||
seqed: SequenceEditor.Form1.resources $(seqed_TARGET)
|
||||
SequenceEditor.Form1.resources:
|
||||
resgen2 SequenceEditor/Form1.resx SequenceEditor.Form1.resources 1> /dev/null
|
||||
filex: $(filex_TARGET)
|
||||
tsbuild: tsbuild_res $(tsbuild_TARGET)
|
||||
tsbuild_res:
|
||||
resgen2 OpenRA.TilesetBuilder/Form1.resx OpenRA.TilesetBuilder.Form1.resources
|
||||
tools: editor ralint seqed mapcvtr filex tsbuild
|
||||
all: game tools
|
||||
tsbuild: OpenRA.TilesetBuilder.Form1.resources $(tsbuild_TARGET)
|
||||
OpenRA.TilesetBuilder.Form1.resources:
|
||||
resgen2 OpenRA.TilesetBuilder/Form1.resx OpenRA.TilesetBuilder.Form1.resources 1> /dev/null
|
||||
|
||||
utility: $(utility_TARGET)
|
||||
winlaunch: OpenRA.Launcher.MainForm.resources OpenRA.Launcher.InstallPackagesDialog.resources \
|
||||
OpenRA.Launcher.ConfigureModsDialog.resources $(winlaunch_TARGET)
|
||||
OpenRA.Launcher.MainForm.resources:
|
||||
resgen2 OpenRA.Launcher/MainForm.resx OpenRA.Launcher.MainForm.resources 1> /dev/null
|
||||
OpenRA.Launcher.InstallPackagesDialog.resources:
|
||||
resgen2 OpenRA.Launcher/InstallPackagesDialog.resx OpenRA.Launcher.InstallPackagesDialog.resources 1> /dev/null
|
||||
OpenRA.Launcher.ConfigureModsDialog.resources:
|
||||
resgen2 OpenRA.Launcher/ConfigureModsDialog.resx OpenRA.Launcher.ConfigureModsDialog.resources 1> /dev/null
|
||||
|
||||
fixheader: packaging/fixheader.cs
|
||||
@$(CSC) packaging/fixheader.cs $(CSFLAGS) -out:fixheader.exe -t:exe $(COMMON_LIBS:%=-r:%)
|
||||
|
||||
define BUILD_ASSEMBLY
|
||||
|
||||
$$($(1)_TARGET): $$($(1)_SRCS) Makefile $$($(1)_DEPS)
|
||||
$$($(1)_TARGET): $$($(1)_SRCS) Makefile $$($(1)_DEPS) fixheader
|
||||
@echo CSC $$(@)
|
||||
@$(CSC) $$($(1)_LIBS:%=-r:%) \
|
||||
-out:$$(@) $(CSFLAGS) $$($(1)_FLAGS) \
|
||||
@@ -179,6 +222,7 @@ $$($(1)_TARGET): $$($(1)_SRCS) Makefile $$($(1)_DEPS)
|
||||
-t:"$$($(1)_KIND)" \
|
||||
$$($(1)_EXTRA) \
|
||||
$$($(1)_SRCS)
|
||||
@mono fixheader.exe $$(@)
|
||||
endef
|
||||
|
||||
$(foreach prog,$(PROGRAMS),$(eval $(call BUILD_ASSEMBLY,$(prog))))
|
||||
|
||||
@@ -1,363 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using OpenRA;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace MapConverter
|
||||
{
|
||||
public class MapConverter
|
||||
{
|
||||
// Mapping from ra overlay index to type string
|
||||
static string[] raOverlayNames =
|
||||
{
|
||||
"sbag", "cycl", "brik", "fenc", "wood",
|
||||
"gold01", "gold02", "gold03", "gold04",
|
||||
"gem01", "gem02", "gem03", "gem04",
|
||||
"v12", "v13", "v14", "v15", "v16", "v17", "v18",
|
||||
"fpls", "wcrate", "scrate", "barb", "sbag",
|
||||
};
|
||||
|
||||
static Dictionary< string, Pair<byte,byte> > overlayResourceMapping = new Dictionary<string, Pair<byte, byte>>()
|
||||
{
|
||||
// RA Gems, Gold
|
||||
{ "gold01", new Pair<byte,byte>(1,0) },
|
||||
{ "gold02", new Pair<byte,byte>(1,1) },
|
||||
{ "gold03", new Pair<byte,byte>(1,2) },
|
||||
{ "gold04", new Pair<byte,byte>(1,3) },
|
||||
|
||||
{ "gem01", new Pair<byte,byte>(2,0) },
|
||||
{ "gem02", new Pair<byte,byte>(2,1) },
|
||||
{ "gem03", new Pair<byte,byte>(2,2) },
|
||||
{ "gem04", new Pair<byte,byte>(2,3) },
|
||||
|
||||
// cnc tiberium
|
||||
{ "ti1", new Pair<byte,byte>(1,0) },
|
||||
{ "ti2", new Pair<byte,byte>(1,1) },
|
||||
{ "ti3", new Pair<byte,byte>(1,2) },
|
||||
{ "ti4", new Pair<byte,byte>(1,3) },
|
||||
{ "ti5", new Pair<byte,byte>(1,4) },
|
||||
{ "ti6", new Pair<byte,byte>(1,5) },
|
||||
{ "ti7", new Pair<byte,byte>(1,6) },
|
||||
{ "ti8", new Pair<byte,byte>(1,7) },
|
||||
{ "ti9", new Pair<byte,byte>(1,8) },
|
||||
{ "ti10", new Pair<byte,byte>(1,9) },
|
||||
{ "ti11", new Pair<byte,byte>(1,10) },
|
||||
{ "ti12", new Pair<byte,byte>(1,11) },
|
||||
};
|
||||
|
||||
static Dictionary<string, string> overlayActorMapping = new Dictionary<string,string>() {
|
||||
// Fences
|
||||
{"sbag","sbag"},
|
||||
{"cycl","cycl"},
|
||||
{"brik","brik"},
|
||||
{"fenc","fenc"},
|
||||
{"wood","wood"},
|
||||
|
||||
// Fields
|
||||
{"v12","v12"},
|
||||
{"v13","v13"},
|
||||
{"v14","v14"},
|
||||
{"v15","v15"},
|
||||
{"v16","v16"},
|
||||
{"v17","v17"},
|
||||
{"v18","v18"},
|
||||
|
||||
// Crates
|
||||
{"wcrate","crate"},
|
||||
{"scrate","crate"},
|
||||
};
|
||||
|
||||
int MapSize;
|
||||
int ActorCount = 0;
|
||||
Map Map = new Map();
|
||||
|
||||
public MapConverter(string[] args)
|
||||
{
|
||||
if (args.Length != 3)
|
||||
{
|
||||
Console.WriteLine("usage: MapConverter mod[,mod]* input-map.ini output-map.yaml");
|
||||
return;
|
||||
}
|
||||
|
||||
Game.InitializeEngineWithMods(args[0].Split(','));
|
||||
ConvertIniMap(args[1]);
|
||||
Save(args[2]);
|
||||
}
|
||||
|
||||
enum IniMapFormat { RedAlert = 3, /* otherwise, cnc (2 variants exist, we don't care to differentiate) */ };
|
||||
|
||||
public void ConvertIniMap(string iniFile)
|
||||
{
|
||||
var file = new IniFile(FileSystem.Open(iniFile));
|
||||
var basic = file.GetSection("Basic");
|
||||
var map = file.GetSection("Map");
|
||||
var legacyMapFormat = (IniMapFormat)int.Parse(basic.GetValue("NewINIFormat", "0"));
|
||||
var XOffset = int.Parse(map.GetValue("X", "0"));
|
||||
var YOffset = int.Parse(map.GetValue("Y", "0"));
|
||||
var Width = int.Parse(map.GetValue("Width", "0"));
|
||||
var Height = int.Parse(map.GetValue("Height", "0"));
|
||||
MapSize = (legacyMapFormat == IniMapFormat.RedAlert) ? 128 : 64;
|
||||
|
||||
Map.Title = basic.GetValue("Name", "(null)");
|
||||
Map.Author = "Westwood Studios";
|
||||
Map.Tileset = Truncate(map.GetValue("Theater", "TEMPERAT"), 8);
|
||||
Map.MapSize.X = MapSize;
|
||||
Map.MapSize.Y = MapSize;
|
||||
Map.TopLeft = new int2 (XOffset, YOffset);
|
||||
Map.BottomRight = new int2(XOffset+Width,YOffset+Height);
|
||||
Map.Selectable = true;
|
||||
|
||||
if (legacyMapFormat == IniMapFormat.RedAlert)
|
||||
{
|
||||
UnpackRATileData(ReadPackedSection(file.GetSection("MapPack")));
|
||||
UnpackRAOverlayData(ReadPackedSection(file.GetSection("OverlayPack")));
|
||||
ReadRATrees(file);
|
||||
// TODO: Fixme
|
||||
//tileset = new TileSet("tileSet.til","templates.ini",fileMapping[Pair.New("ra",Map.Tileset)].First);
|
||||
}
|
||||
else // CNC
|
||||
{
|
||||
UnpackCncTileData(FileSystem.Open(iniFile.Substring(0,iniFile.Length-4)+".bin"));
|
||||
ReadCncOverlay(file);
|
||||
ReadCncTrees(file);
|
||||
|
||||
// TODO: Fixme
|
||||
//tileset = new TileSet("tileSet.til","templates.ini",fileMapping[Pair.New("cnc",Map.Tileset)].First);
|
||||
}
|
||||
|
||||
LoadActors(file, "STRUCTURES");
|
||||
LoadActors(file, "UNITS");
|
||||
LoadActors(file, "INFANTRY");
|
||||
LoadSmudges(file, "SMUDGE");
|
||||
|
||||
var wp = file.GetSection("Waypoints")
|
||||
.Where(kv => int.Parse(kv.Value) > 0)
|
||||
.Select(kv => Pair.New(int.Parse(kv.Key),
|
||||
LocationFromMapOffset( int.Parse( kv.Value ), MapSize )))
|
||||
.Where(a => a.First < 8)
|
||||
.ToArray();
|
||||
|
||||
Map.PlayerCount = wp.Count();
|
||||
|
||||
foreach (var kv in wp)
|
||||
Map.Waypoints.Add("spawn"+kv.First, kv.Second);
|
||||
}
|
||||
|
||||
static int2 LocationFromMapOffset(int offset, int mapSize)
|
||||
{
|
||||
return new int2(offset % mapSize, offset / mapSize);
|
||||
}
|
||||
|
||||
static MemoryStream ReadPackedSection(IniSection mapPackSection)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 1; ; i++)
|
||||
{
|
||||
string line = mapPackSection.GetValue(i.ToString(), null);
|
||||
if (line == null)
|
||||
break;
|
||||
|
||||
sb.Append(line.Trim());
|
||||
}
|
||||
|
||||
byte[] data = Convert.FromBase64String(sb.ToString());
|
||||
List<byte[]> chunks = new List<byte[]>();
|
||||
BinaryReader reader = new BinaryReader(new MemoryStream(data));
|
||||
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
uint length = reader.ReadUInt32() & 0xdfffffff;
|
||||
byte[] dest = new byte[8192];
|
||||
byte[] src = reader.ReadBytes((int)length);
|
||||
|
||||
/*int actualLength =*/ Format80.DecodeInto(src, dest);
|
||||
|
||||
chunks.Add(dest);
|
||||
}
|
||||
}
|
||||
catch (EndOfStreamException) { }
|
||||
|
||||
MemoryStream ms = new MemoryStream();
|
||||
foreach (byte[] chunk in chunks)
|
||||
ms.Write(chunk, 0, chunk.Length);
|
||||
|
||||
ms.Position = 0;
|
||||
|
||||
return ms;
|
||||
}
|
||||
|
||||
static byte ReadByte( Stream s )
|
||||
{
|
||||
int ret = s.ReadByte();
|
||||
if( ret == -1 )
|
||||
throw new NotImplementedException();
|
||||
return (byte)ret;
|
||||
}
|
||||
|
||||
static ushort ReadWord(Stream s)
|
||||
{
|
||||
ushort ret = ReadByte(s);
|
||||
ret |= (ushort)(ReadByte(s) << 8);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void UnpackRATileData( MemoryStream ms )
|
||||
{
|
||||
Map.MapTiles = new TileReference<ushort, byte>[ MapSize, MapSize ];
|
||||
for( int i = 0 ; i < MapSize ; i++ )
|
||||
for( int j = 0 ; j < MapSize ; j++ )
|
||||
Map.MapTiles[i,j] = new TileReference<ushort,byte>();
|
||||
|
||||
for( int j = 0 ; j < MapSize ; j++ )
|
||||
for( int i = 0 ; i < MapSize ; i++ )
|
||||
Map.MapTiles[i,j].type = ReadWord(ms);
|
||||
|
||||
for( int j = 0 ; j < MapSize ; j++ )
|
||||
for( int i = 0 ; i < MapSize ; i++ )
|
||||
{
|
||||
Map.MapTiles[i,j].index = ReadByte(ms);
|
||||
if( Map.MapTiles[i,j].type == 0xff || Map.MapTiles[i,j].type == 0xffff )
|
||||
Map.MapTiles[i,j].index = byte.MaxValue;
|
||||
}
|
||||
}
|
||||
|
||||
void UnpackRAOverlayData( MemoryStream ms )
|
||||
{
|
||||
Map.MapResources = new TileReference<byte, byte>[ MapSize, MapSize ];
|
||||
for( int j = 0 ; j < MapSize ; j++ )
|
||||
for( int i = 0 ; i < MapSize ; i++ )
|
||||
{
|
||||
byte o = ReadByte( ms );
|
||||
var res = Pair.New((byte)0,(byte)0);
|
||||
|
||||
if (o != 255 && overlayResourceMapping.ContainsKey(raOverlayNames[o]))
|
||||
res = overlayResourceMapping[raOverlayNames[o]];
|
||||
|
||||
Map.MapResources[i,j] = new TileReference<byte,byte>(res.First, res.Second);
|
||||
|
||||
if (o != 255 && overlayActorMapping.ContainsKey(raOverlayNames[o]))
|
||||
Map.Actors.Add("Actor"+ActorCount, new ActorReference("Actor"+ActorCount++, overlayActorMapping[raOverlayNames[o]], new int2(i,j), "Neutral"));
|
||||
}
|
||||
}
|
||||
|
||||
void ReadRATrees( IniFile file )
|
||||
{
|
||||
IniSection terrain = file.GetSection( "TERRAIN", true );
|
||||
if( terrain == null )
|
||||
return;
|
||||
|
||||
foreach( KeyValuePair<string, string> kv in terrain )
|
||||
{
|
||||
var loc = int.Parse( kv.Key );
|
||||
Map.Actors.Add("Actor"+ActorCount, new ActorReference("Actor"+ActorCount++,kv.Value.ToLowerInvariant(), new int2(loc % MapSize, loc / MapSize), "Neutral" ) );
|
||||
}
|
||||
}
|
||||
|
||||
void UnpackCncTileData( Stream ms )
|
||||
{
|
||||
Map.MapTiles = new TileReference<ushort, byte>[ MapSize, MapSize ];
|
||||
for( int i = 0 ; i < MapSize ; i++ )
|
||||
for( int j = 0 ; j < MapSize ; j++ )
|
||||
Map.MapTiles[i,j] = new TileReference<ushort,byte>();
|
||||
|
||||
for( int j = 0 ; j < MapSize ; j++ )
|
||||
for( int i = 0 ; i < MapSize ; i++ )
|
||||
{
|
||||
Map.MapTiles[i,j].type = ReadByte(ms);
|
||||
Map.MapTiles[i,j].index = ReadByte(ms);
|
||||
|
||||
if( Map.MapTiles[i,j].type == 0xff )
|
||||
Map.MapTiles[i,j].index = byte.MaxValue;
|
||||
}
|
||||
}
|
||||
|
||||
void ReadCncOverlay( IniFile file )
|
||||
{
|
||||
IniSection overlay = file.GetSection( "OVERLAY", true );
|
||||
if( overlay == null )
|
||||
return;
|
||||
|
||||
Map.MapResources = new TileReference<byte, byte>[ MapSize, MapSize ];
|
||||
foreach( KeyValuePair<string, string> kv in overlay )
|
||||
{
|
||||
var loc = int.Parse( kv.Key );
|
||||
int2 cell = new int2(loc % MapSize, loc / MapSize);
|
||||
|
||||
var res = Pair.New((byte)0,(byte)0);
|
||||
if (overlayResourceMapping.ContainsKey(kv.Value.ToLower()))
|
||||
res = overlayResourceMapping[kv.Value.ToLower()];
|
||||
|
||||
Map.MapResources[ cell.X, cell.Y ] = new TileReference<byte,byte>(res.First, res.Second);
|
||||
|
||||
if (overlayActorMapping.ContainsKey(kv.Value.ToLower()))
|
||||
Map.Actors.Add("Actor"+ActorCount, new ActorReference("Actor"+ActorCount++, overlayActorMapping[kv.Value.ToLower()], new int2(cell.X,cell.Y), "Neutral"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ReadCncTrees( IniFile file )
|
||||
{
|
||||
IniSection terrain = file.GetSection( "TERRAIN", true );
|
||||
if( terrain == null )
|
||||
return;
|
||||
|
||||
foreach( KeyValuePair<string, string> kv in terrain )
|
||||
{
|
||||
var loc = int.Parse( kv.Key );
|
||||
Map.Actors.Add("Actor"+ActorCount, new ActorReference("Actor"+ActorCount++, kv.Value.Split(',')[0].ToLowerInvariant(), new int2(loc % MapSize, loc / MapSize),"Neutral"));
|
||||
}
|
||||
}
|
||||
|
||||
void LoadActors(IniFile file, string section)
|
||||
{
|
||||
foreach (var s in file.GetSection(section, true))
|
||||
{
|
||||
//num=owner,type,health,location,facing,...
|
||||
var parts = s.Value.Split( ',' );
|
||||
var loc = int.Parse(parts[3]);
|
||||
if (parts[0] == "")
|
||||
parts[0] = "Neutral";
|
||||
Map.Actors.Add("Actor"+ActorCount, new ActorReference("Actor"+ActorCount++, parts[1].ToLowerInvariant(), new int2(loc % MapSize, loc / MapSize), parts[0]));
|
||||
}
|
||||
}
|
||||
|
||||
void LoadSmudges(IniFile file, string section)
|
||||
{
|
||||
foreach (var s in file.GetSection(section, true))
|
||||
{
|
||||
//loc=type,loc,depth
|
||||
var parts = s.Value.Split( ',' );
|
||||
var loc = int.Parse(parts[1]);
|
||||
Map.Smudges.Add(new SmudgeReference(parts[0].ToLowerInvariant(),new int2(loc % MapSize, loc / MapSize),int.Parse(parts[2])));
|
||||
}
|
||||
}
|
||||
static string Truncate( string s, int maxLength )
|
||||
{
|
||||
return s.Length <= maxLength ? s : s.Substring(0,maxLength );
|
||||
}
|
||||
|
||||
public void Save(string filepath)
|
||||
{
|
||||
Directory.CreateDirectory(filepath);
|
||||
|
||||
Map.Package = new Folder(filepath);
|
||||
Map.Save(filepath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||
<security>
|
||||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
</assembly>
|
||||
@@ -18,7 +18,7 @@ namespace OpenRA.Editor
|
||||
{
|
||||
public Bitmap Bitmap;
|
||||
public ActorInfo Info;
|
||||
public bool Centered;
|
||||
public EditorAppearanceInfo Appearance;
|
||||
}
|
||||
|
||||
class BrushTemplate
|
||||
|
||||
476
OpenRA.Editor/Form1.Designer.cs
generated
Normal file → Executable file
476
OpenRA.Editor/Form1.Designer.cs
generated
Normal file → Executable file
@@ -30,8 +30,9 @@
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
|
||||
this.toolStripContainer1 = new System.Windows.Forms.ToolStripContainer();
|
||||
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
|
||||
this.splitContainer2 = new System.Windows.Forms.SplitContainer();
|
||||
this.pmMiniMap = new System.Windows.Forms.PictureBox();
|
||||
this.tabControl1 = new System.Windows.Forms.TabControl();
|
||||
this.tabPage1 = new System.Windows.Forms.TabPage();
|
||||
this.tilePalette = new System.Windows.Forms.FlowLayoutPanel();
|
||||
@@ -39,48 +40,53 @@
|
||||
this.actorPalette = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.tabPage3 = new System.Windows.Forms.TabPage();
|
||||
this.resourcePalette = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.toolStrip1 = new System.Windows.Forms.ToolStrip();
|
||||
this.toolStripButton3 = new System.Windows.Forms.ToolStripButton();
|
||||
this.toolStripButton5 = new System.Windows.Forms.ToolStripButton();
|
||||
this.toolStripButton4 = new System.Windows.Forms.ToolStripButton();
|
||||
this.toolStripButton1 = new System.Windows.Forms.ToolStripButton();
|
||||
this.toolStripButton6 = new System.Windows.Forms.ToolStripButton();
|
||||
this.toolStripButton7 = new System.Windows.Forms.ToolStripButton();
|
||||
this.toolStripButton2 = new System.Windows.Forms.ToolStripButton();
|
||||
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
|
||||
this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.newToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.openToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.saveToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.saveAsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.cCRedAlertMapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.bitmapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuExport = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuMinimapToPNG = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.exotToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.propertiesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.resizeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.spawnpointsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.layersFloaterToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.tt = new System.Windows.Forms.ToolTip(this.components);
|
||||
this.folderBrowser = new System.Windows.Forms.FolderBrowserDialog();
|
||||
this.saveFileDialog = new System.Windows.Forms.SaveFileDialog();
|
||||
this.splitContainer3 = new System.Windows.Forms.SplitContainer();
|
||||
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
|
||||
this.toolStripStatusLabelFiller = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.toolStripStatusLabelMousePosition = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.surface1 = new OpenRA.Editor.Surface();
|
||||
this.toolStripContainer1.ContentPanel.SuspendLayout();
|
||||
this.toolStripContainer1.TopToolStripPanel.SuspendLayout();
|
||||
this.toolStripContainer1.SuspendLayout();
|
||||
this.splitContainer1.Panel1.SuspendLayout();
|
||||
this.splitContainer1.Panel2.SuspendLayout();
|
||||
this.splitContainer1.SuspendLayout();
|
||||
this.splitContainer2.Panel1.SuspendLayout();
|
||||
this.splitContainer2.Panel2.SuspendLayout();
|
||||
this.splitContainer2.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pmMiniMap)).BeginInit();
|
||||
this.tabControl1.SuspendLayout();
|
||||
this.tabPage1.SuspendLayout();
|
||||
this.tabPage2.SuspendLayout();
|
||||
this.tabPage3.SuspendLayout();
|
||||
this.toolStrip1.SuspendLayout();
|
||||
this.menuStrip1.SuspendLayout();
|
||||
this.splitContainer3.Panel1.SuspendLayout();
|
||||
this.splitContainer3.Panel2.SuspendLayout();
|
||||
this.splitContainer3.SuspendLayout();
|
||||
this.statusStrip1.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// toolStripContainer1
|
||||
//
|
||||
//
|
||||
// toolStripContainer1.ContentPanel
|
||||
//
|
||||
this.toolStripContainer1.ContentPanel.Controls.Add(this.splitContainer1);
|
||||
this.toolStripContainer1.ContentPanel.Size = new System.Drawing.Size(985, 680);
|
||||
this.toolStripContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.toolStripContainer1.Location = new System.Drawing.Point(0, 0);
|
||||
this.toolStripContainer1.Name = "toolStripContainer1";
|
||||
this.toolStripContainer1.Size = new System.Drawing.Size(985, 705);
|
||||
this.toolStripContainer1.TabIndex = 1;
|
||||
this.toolStripContainer1.Text = "toolStripContainer1";
|
||||
//
|
||||
// toolStripContainer1.TopToolStripPanel
|
||||
//
|
||||
this.toolStripContainer1.TopToolStripPanel.Controls.Add(this.toolStrip1);
|
||||
//
|
||||
// splitContainer1
|
||||
//
|
||||
this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
@@ -89,36 +95,67 @@
|
||||
//
|
||||
// splitContainer1.Panel1
|
||||
//
|
||||
this.splitContainer1.Panel1.Controls.Add(this.tabControl1);
|
||||
this.splitContainer1.Panel1.Controls.Add(this.splitContainer2);
|
||||
//
|
||||
// splitContainer1.Panel2
|
||||
//
|
||||
this.splitContainer1.Panel2.Controls.Add(this.surface1);
|
||||
this.splitContainer1.Size = new System.Drawing.Size(985, 680);
|
||||
this.splitContainer1.Size = new System.Drawing.Size(985, 744);
|
||||
this.splitContainer1.SplitterDistance = 198;
|
||||
this.splitContainer1.TabIndex = 0;
|
||||
//
|
||||
// splitContainer2
|
||||
//
|
||||
this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.splitContainer2.Location = new System.Drawing.Point(0, 0);
|
||||
this.splitContainer2.Name = "splitContainer2";
|
||||
this.splitContainer2.Orientation = System.Windows.Forms.Orientation.Horizontal;
|
||||
//
|
||||
// splitContainer2.Panel1
|
||||
//
|
||||
this.splitContainer2.Panel1.Controls.Add(this.pmMiniMap);
|
||||
//
|
||||
// splitContainer2.Panel2
|
||||
//
|
||||
this.splitContainer2.Panel2.Controls.Add(this.tabControl1);
|
||||
this.splitContainer2.Size = new System.Drawing.Size(198, 744);
|
||||
this.splitContainer2.SplitterDistance = 164;
|
||||
this.splitContainer2.TabIndex = 1;
|
||||
//
|
||||
// pmMiniMap
|
||||
//
|
||||
this.pmMiniMap.BackColor = System.Drawing.Color.Black;
|
||||
this.pmMiniMap.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
|
||||
this.pmMiniMap.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.pmMiniMap.Location = new System.Drawing.Point(0, 0);
|
||||
this.pmMiniMap.Name = "pmMiniMap";
|
||||
this.pmMiniMap.Size = new System.Drawing.Size(198, 164);
|
||||
this.pmMiniMap.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
|
||||
this.pmMiniMap.TabIndex = 1;
|
||||
this.pmMiniMap.TabStop = false;
|
||||
//
|
||||
// tabControl1
|
||||
//
|
||||
this.tabControl1.Alignment = System.Windows.Forms.TabAlignment.Left;
|
||||
this.tabControl1.Controls.Add(this.tabPage1);
|
||||
this.tabControl1.Controls.Add(this.tabPage2);
|
||||
this.tabControl1.Controls.Add(this.tabPage3);
|
||||
this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tabControl1.Location = new System.Drawing.Point(0, 0);
|
||||
this.tabControl1.Margin = new System.Windows.Forms.Padding(3, 3, 3, 0);
|
||||
this.tabControl1.Multiline = true;
|
||||
this.tabControl1.Name = "tabControl1";
|
||||
this.tabControl1.Padding = new System.Drawing.Point(6, 0);
|
||||
this.tabControl1.SelectedIndex = 0;
|
||||
this.tabControl1.Size = new System.Drawing.Size(198, 680);
|
||||
this.tabControl1.Size = new System.Drawing.Size(198, 576);
|
||||
this.tabControl1.TabIndex = 0;
|
||||
//
|
||||
// tabPage1
|
||||
//
|
||||
this.tabPage1.Controls.Add(this.tilePalette);
|
||||
this.tabPage1.Location = new System.Drawing.Point(23, 4);
|
||||
this.tabPage1.Location = new System.Drawing.Point(4, 20);
|
||||
this.tabPage1.Name = "tabPage1";
|
||||
this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tabPage1.Size = new System.Drawing.Size(171, 672);
|
||||
this.tabPage1.Size = new System.Drawing.Size(190, 552);
|
||||
this.tabPage1.TabIndex = 0;
|
||||
this.tabPage1.Text = "Templates";
|
||||
this.tabPage1.UseVisualStyleBackColor = true;
|
||||
@@ -130,16 +167,16 @@
|
||||
this.tilePalette.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tilePalette.Location = new System.Drawing.Point(3, 3);
|
||||
this.tilePalette.Name = "tilePalette";
|
||||
this.tilePalette.Size = new System.Drawing.Size(165, 666);
|
||||
this.tilePalette.Size = new System.Drawing.Size(184, 546);
|
||||
this.tilePalette.TabIndex = 1;
|
||||
//
|
||||
// tabPage2
|
||||
//
|
||||
this.tabPage2.Controls.Add(this.actorPalette);
|
||||
this.tabPage2.Location = new System.Drawing.Point(23, 4);
|
||||
this.tabPage2.Location = new System.Drawing.Point(4, 20);
|
||||
this.tabPage2.Name = "tabPage2";
|
||||
this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tabPage2.Size = new System.Drawing.Size(171, 672);
|
||||
this.tabPage2.Size = new System.Drawing.Size(190, 552);
|
||||
this.tabPage2.TabIndex = 1;
|
||||
this.tabPage2.Text = "Actors";
|
||||
this.tabPage2.UseVisualStyleBackColor = true;
|
||||
@@ -151,15 +188,15 @@
|
||||
this.actorPalette.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.actorPalette.Location = new System.Drawing.Point(3, 3);
|
||||
this.actorPalette.Name = "actorPalette";
|
||||
this.actorPalette.Size = new System.Drawing.Size(165, 666);
|
||||
this.actorPalette.Size = new System.Drawing.Size(184, 546);
|
||||
this.actorPalette.TabIndex = 2;
|
||||
//
|
||||
// tabPage3
|
||||
//
|
||||
this.tabPage3.Controls.Add(this.resourcePalette);
|
||||
this.tabPage3.Location = new System.Drawing.Point(23, 4);
|
||||
this.tabPage3.Location = new System.Drawing.Point(4, 20);
|
||||
this.tabPage3.Name = "tabPage3";
|
||||
this.tabPage3.Size = new System.Drawing.Size(171, 672);
|
||||
this.tabPage3.Size = new System.Drawing.Size(190, 552);
|
||||
this.tabPage3.TabIndex = 2;
|
||||
this.tabPage3.Text = "Resources";
|
||||
this.tabPage3.UseVisualStyleBackColor = true;
|
||||
@@ -171,99 +208,250 @@
|
||||
this.resourcePalette.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.resourcePalette.Location = new System.Drawing.Point(0, 0);
|
||||
this.resourcePalette.Name = "resourcePalette";
|
||||
this.resourcePalette.Size = new System.Drawing.Size(171, 672);
|
||||
this.resourcePalette.Size = new System.Drawing.Size(190, 552);
|
||||
this.resourcePalette.TabIndex = 3;
|
||||
//
|
||||
// toolStrip1
|
||||
// menuStrip1
|
||||
//
|
||||
this.toolStrip1.Dock = System.Windows.Forms.DockStyle.None;
|
||||
this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.toolStripButton3,
|
||||
this.toolStripButton5,
|
||||
this.toolStripButton4,
|
||||
this.toolStripButton1,
|
||||
this.toolStripButton6,
|
||||
this.toolStripButton7,
|
||||
this.toolStripButton2});
|
||||
this.toolStrip1.Location = new System.Drawing.Point(3, 0);
|
||||
this.toolStrip1.Name = "toolStrip1";
|
||||
this.toolStrip1.Size = new System.Drawing.Size(480, 25);
|
||||
this.toolStrip1.TabIndex = 0;
|
||||
this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.fileToolStripMenuItem,
|
||||
this.mapToolStripMenuItem,
|
||||
this.toolsToolStripMenuItem});
|
||||
this.menuStrip1.Location = new System.Drawing.Point(0, 0);
|
||||
this.menuStrip1.Name = "menuStrip1";
|
||||
this.menuStrip1.Size = new System.Drawing.Size(985, 24);
|
||||
this.menuStrip1.TabIndex = 1;
|
||||
this.menuStrip1.Text = "menuStrip1";
|
||||
//
|
||||
// toolStripButton3
|
||||
// fileToolStripMenuItem
|
||||
//
|
||||
this.toolStripButton3.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton3.Image")));
|
||||
this.toolStripButton3.ImageTransparentColor = System.Drawing.Color.Magenta;
|
||||
this.toolStripButton3.Name = "toolStripButton3";
|
||||
this.toolStripButton3.Size = new System.Drawing.Size(51, 22);
|
||||
this.toolStripButton3.Text = "New";
|
||||
this.toolStripButton3.Click += new System.EventHandler(this.NewClicked);
|
||||
this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.newToolStripMenuItem,
|
||||
this.toolStripSeparator1,
|
||||
this.openToolStripMenuItem,
|
||||
this.saveToolStripMenuItem,
|
||||
this.saveAsToolStripMenuItem,
|
||||
this.toolStripSeparator2,
|
||||
this.toolStripMenuItem1,
|
||||
this.mnuExport,
|
||||
this.toolStripSeparator3,
|
||||
this.exotToolStripMenuItem});
|
||||
this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
|
||||
this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20);
|
||||
this.fileToolStripMenuItem.Text = "&File";
|
||||
//
|
||||
// toolStripButton5
|
||||
// newToolStripMenuItem
|
||||
//
|
||||
this.toolStripButton5.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton5.Image")));
|
||||
this.toolStripButton5.ImageTransparentColor = System.Drawing.Color.Magenta;
|
||||
this.toolStripButton5.Name = "toolStripButton5";
|
||||
this.toolStripButton5.Size = new System.Drawing.Size(56, 22);
|
||||
this.toolStripButton5.Text = "Open";
|
||||
this.toolStripButton5.Click += new System.EventHandler(this.OpenClicked);
|
||||
this.newToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("newToolStripMenuItem.Image")));
|
||||
this.newToolStripMenuItem.ImageTransparentColor = System.Drawing.Color.Fuchsia;
|
||||
this.newToolStripMenuItem.Name = "newToolStripMenuItem";
|
||||
this.newToolStripMenuItem.Size = new System.Drawing.Size(123, 22);
|
||||
this.newToolStripMenuItem.Text = "&New...";
|
||||
this.newToolStripMenuItem.Click += new System.EventHandler(this.NewClicked);
|
||||
//
|
||||
// toolStripButton4
|
||||
// toolStripSeparator1
|
||||
//
|
||||
this.toolStripButton4.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton4.Image")));
|
||||
this.toolStripButton4.ImageTransparentColor = System.Drawing.Color.Magenta;
|
||||
this.toolStripButton4.Name = "toolStripButton4";
|
||||
this.toolStripButton4.Size = new System.Drawing.Size(51, 22);
|
||||
this.toolStripButton4.Text = "Save";
|
||||
this.toolStripButton4.Click += new System.EventHandler(this.SaveClicked);
|
||||
this.toolStripSeparator1.Name = "toolStripSeparator1";
|
||||
this.toolStripSeparator1.Size = new System.Drawing.Size(120, 6);
|
||||
//
|
||||
// toolStripButton1
|
||||
// openToolStripMenuItem
|
||||
//
|
||||
this.toolStripButton1.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton1.Image")));
|
||||
this.toolStripButton1.ImageTransparentColor = System.Drawing.Color.Magenta;
|
||||
this.toolStripButton1.Name = "toolStripButton1";
|
||||
this.toolStripButton1.Size = new System.Drawing.Size(76, 22);
|
||||
this.toolStripButton1.Text = "Save As...";
|
||||
this.toolStripButton1.Click += new System.EventHandler(this.SaveAsClicked);
|
||||
this.openToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("openToolStripMenuItem.Image")));
|
||||
this.openToolStripMenuItem.Name = "openToolStripMenuItem";
|
||||
this.openToolStripMenuItem.Size = new System.Drawing.Size(123, 22);
|
||||
this.openToolStripMenuItem.Text = "&Open...";
|
||||
this.openToolStripMenuItem.Click += new System.EventHandler(this.OpenClicked);
|
||||
//
|
||||
// toolStripButton6
|
||||
// saveToolStripMenuItem
|
||||
//
|
||||
this.toolStripButton6.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton6.Image")));
|
||||
this.toolStripButton6.ImageTransparentColor = System.Drawing.Color.Magenta;
|
||||
this.toolStripButton6.Name = "toolStripButton6";
|
||||
this.toolStripButton6.Size = new System.Drawing.Size(59, 22);
|
||||
this.toolStripButton6.Text = "Resize";
|
||||
this.toolStripButton6.Click += new System.EventHandler(this.ResizeClicked);
|
||||
this.saveToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("saveToolStripMenuItem.Image")));
|
||||
this.saveToolStripMenuItem.Name = "saveToolStripMenuItem";
|
||||
this.saveToolStripMenuItem.Size = new System.Drawing.Size(123, 22);
|
||||
this.saveToolStripMenuItem.Text = "&Save";
|
||||
this.saveToolStripMenuItem.Click += new System.EventHandler(this.SaveClicked);
|
||||
//
|
||||
// toolStripButton7
|
||||
// saveAsToolStripMenuItem
|
||||
//
|
||||
this.toolStripButton7.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton7.Image")));
|
||||
this.toolStripButton7.ImageTransparentColor = System.Drawing.Color.Magenta;
|
||||
this.toolStripButton7.Name = "toolStripButton7";
|
||||
this.toolStripButton7.Size = new System.Drawing.Size(80, 22);
|
||||
this.toolStripButton7.Text = "Properties";
|
||||
this.toolStripButton7.Click += new System.EventHandler(this.PropertiesClicked);
|
||||
this.saveAsToolStripMenuItem.Name = "saveAsToolStripMenuItem";
|
||||
this.saveAsToolStripMenuItem.Size = new System.Drawing.Size(123, 22);
|
||||
this.saveAsToolStripMenuItem.Text = "Save &As...";
|
||||
this.saveAsToolStripMenuItem.Click += new System.EventHandler(this.SaveAsClicked);
|
||||
//
|
||||
// toolStripButton2
|
||||
// toolStripSeparator2
|
||||
//
|
||||
this.toolStripButton2.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton2.Image")));
|
||||
this.toolStripButton2.ImageTransparentColor = System.Drawing.Color.Magenta;
|
||||
this.toolStripButton2.Name = "toolStripButton2";
|
||||
this.toolStripButton2.Size = new System.Drawing.Size(95, 22);
|
||||
this.toolStripButton2.Text = "Spawnpoints";
|
||||
this.toolStripButton2.Click += new System.EventHandler(this.SpawnPointsClicked);
|
||||
this.toolStripSeparator2.Name = "toolStripSeparator2";
|
||||
this.toolStripSeparator2.Size = new System.Drawing.Size(120, 6);
|
||||
//
|
||||
// toolStripMenuItem1
|
||||
//
|
||||
this.toolStripMenuItem1.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.cCRedAlertMapToolStripMenuItem,
|
||||
this.bitmapToolStripMenuItem});
|
||||
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
|
||||
this.toolStripMenuItem1.Size = new System.Drawing.Size(123, 22);
|
||||
this.toolStripMenuItem1.Text = "&Import";
|
||||
//
|
||||
// cCRedAlertMapToolStripMenuItem
|
||||
//
|
||||
this.cCRedAlertMapToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("cCRedAlertMapToolStripMenuItem.Image")));
|
||||
this.cCRedAlertMapToolStripMenuItem.Name = "cCRedAlertMapToolStripMenuItem";
|
||||
this.cCRedAlertMapToolStripMenuItem.Size = new System.Drawing.Size(195, 22);
|
||||
this.cCRedAlertMapToolStripMenuItem.Text = "&C&&C / Red Alert Map...";
|
||||
this.cCRedAlertMapToolStripMenuItem.Click += new System.EventHandler(this.ImportLegacyMapClicked);
|
||||
//
|
||||
// bitmapToolStripMenuItem
|
||||
//
|
||||
this.bitmapToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("bitmapToolStripMenuItem.Image")));
|
||||
this.bitmapToolStripMenuItem.Name = "bitmapToolStripMenuItem";
|
||||
this.bitmapToolStripMenuItem.Size = new System.Drawing.Size(195, 22);
|
||||
this.bitmapToolStripMenuItem.Text = "&Bitmap...";
|
||||
this.bitmapToolStripMenuItem.Visible = false;
|
||||
//
|
||||
// mnuExport
|
||||
//
|
||||
this.mnuExport.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.mnuMinimapToPNG});
|
||||
this.mnuExport.Name = "mnuExport";
|
||||
this.mnuExport.Size = new System.Drawing.Size(123, 22);
|
||||
this.mnuExport.Text = "&Export";
|
||||
//
|
||||
// mnuMinimapToPNG
|
||||
//
|
||||
this.mnuMinimapToPNG.Image = ((System.Drawing.Image)(resources.GetObject("mnuMinimapToPNG.Image")));
|
||||
this.mnuMinimapToPNG.Name = "mnuMinimapToPNG";
|
||||
this.mnuMinimapToPNG.Size = new System.Drawing.Size(163, 22);
|
||||
this.mnuMinimapToPNG.Text = "Minimap to PNG";
|
||||
this.mnuMinimapToPNG.Click += new System.EventHandler(this.mnuMinimapToPNG_Click);
|
||||
//
|
||||
// toolStripSeparator3
|
||||
//
|
||||
this.toolStripSeparator3.Name = "toolStripSeparator3";
|
||||
this.toolStripSeparator3.Size = new System.Drawing.Size(120, 6);
|
||||
//
|
||||
// exotToolStripMenuItem
|
||||
//
|
||||
this.exotToolStripMenuItem.Name = "exotToolStripMenuItem";
|
||||
this.exotToolStripMenuItem.Size = new System.Drawing.Size(123, 22);
|
||||
this.exotToolStripMenuItem.Text = "E&xit";
|
||||
this.exotToolStripMenuItem.Click += new System.EventHandler(this.CloseClicked);
|
||||
//
|
||||
// mapToolStripMenuItem
|
||||
//
|
||||
this.mapToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.propertiesToolStripMenuItem,
|
||||
this.resizeToolStripMenuItem,
|
||||
this.toolStripSeparator4,
|
||||
this.spawnpointsToolStripMenuItem});
|
||||
this.mapToolStripMenuItem.Name = "mapToolStripMenuItem";
|
||||
this.mapToolStripMenuItem.Size = new System.Drawing.Size(43, 20);
|
||||
this.mapToolStripMenuItem.Text = "&Map";
|
||||
//
|
||||
// propertiesToolStripMenuItem
|
||||
//
|
||||
this.propertiesToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("propertiesToolStripMenuItem.Image")));
|
||||
this.propertiesToolStripMenuItem.Name = "propertiesToolStripMenuItem";
|
||||
this.propertiesToolStripMenuItem.Size = new System.Drawing.Size(142, 22);
|
||||
this.propertiesToolStripMenuItem.Text = "&Properties...";
|
||||
this.propertiesToolStripMenuItem.Click += new System.EventHandler(this.PropertiesClicked);
|
||||
//
|
||||
// resizeToolStripMenuItem
|
||||
//
|
||||
this.resizeToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("resizeToolStripMenuItem.Image")));
|
||||
this.resizeToolStripMenuItem.Name = "resizeToolStripMenuItem";
|
||||
this.resizeToolStripMenuItem.Size = new System.Drawing.Size(142, 22);
|
||||
this.resizeToolStripMenuItem.Text = "&Resize...";
|
||||
this.resizeToolStripMenuItem.Click += new System.EventHandler(this.ResizeClicked);
|
||||
//
|
||||
// toolStripSeparator4
|
||||
//
|
||||
this.toolStripSeparator4.Name = "toolStripSeparator4";
|
||||
this.toolStripSeparator4.Size = new System.Drawing.Size(139, 6);
|
||||
//
|
||||
// spawnpointsToolStripMenuItem
|
||||
//
|
||||
this.spawnpointsToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("spawnpointsToolStripMenuItem.Image")));
|
||||
this.spawnpointsToolStripMenuItem.Name = "spawnpointsToolStripMenuItem";
|
||||
this.spawnpointsToolStripMenuItem.Size = new System.Drawing.Size(142, 22);
|
||||
this.spawnpointsToolStripMenuItem.Text = "&Spawnpoints";
|
||||
this.spawnpointsToolStripMenuItem.Click += new System.EventHandler(this.SpawnPointsClicked);
|
||||
//
|
||||
// toolsToolStripMenuItem
|
||||
//
|
||||
this.toolsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.layersFloaterToolStripMenuItem});
|
||||
this.toolsToolStripMenuItem.Name = "toolsToolStripMenuItem";
|
||||
this.toolsToolStripMenuItem.Size = new System.Drawing.Size(48, 20);
|
||||
this.toolsToolStripMenuItem.Text = "Tools";
|
||||
this.toolsToolStripMenuItem.Visible = false;
|
||||
//
|
||||
// layersFloaterToolStripMenuItem
|
||||
//
|
||||
this.layersFloaterToolStripMenuItem.Name = "layersFloaterToolStripMenuItem";
|
||||
this.layersFloaterToolStripMenuItem.Size = new System.Drawing.Size(144, 22);
|
||||
this.layersFloaterToolStripMenuItem.Text = "Layers floater";
|
||||
this.layersFloaterToolStripMenuItem.Click += new System.EventHandler(this.layersFloaterToolStripMenuItem_Click);
|
||||
//
|
||||
// tt
|
||||
//
|
||||
this.tt.ShowAlways = true;
|
||||
//
|
||||
// saveFileDialog
|
||||
//
|
||||
this.saveFileDialog.DefaultExt = "*.png";
|
||||
this.saveFileDialog.Filter = "PNG Image (*.png)|";
|
||||
this.saveFileDialog.Title = "Export minimap to PNG";
|
||||
//
|
||||
// splitContainer3
|
||||
//
|
||||
this.splitContainer3.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.splitContainer3.FixedPanel = System.Windows.Forms.FixedPanel.Panel1;
|
||||
this.splitContainer3.IsSplitterFixed = true;
|
||||
this.splitContainer3.Location = new System.Drawing.Point(0, 0);
|
||||
this.splitContainer3.Name = "splitContainer3";
|
||||
this.splitContainer3.Orientation = System.Windows.Forms.Orientation.Horizontal;
|
||||
//
|
||||
// splitContainer3.Panel1
|
||||
//
|
||||
this.splitContainer3.Panel1.Controls.Add(this.menuStrip1);
|
||||
//
|
||||
// splitContainer3.Panel2
|
||||
//
|
||||
this.splitContainer3.Panel2.Controls.Add(this.splitContainer1);
|
||||
this.splitContainer3.Size = new System.Drawing.Size(985, 773);
|
||||
this.splitContainer3.SplitterDistance = 25;
|
||||
this.splitContainer3.TabIndex = 6;
|
||||
//
|
||||
// statusStrip1
|
||||
//
|
||||
this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.toolStripStatusLabelFiller,
|
||||
this.toolStripStatusLabelMousePosition});
|
||||
this.statusStrip1.Location = new System.Drawing.Point(0, 751);
|
||||
this.statusStrip1.Name = "statusStrip1";
|
||||
this.statusStrip1.Size = new System.Drawing.Size(985, 22);
|
||||
this.statusStrip1.TabIndex = 7;
|
||||
this.statusStrip1.Text = "statusStrip1";
|
||||
//
|
||||
// toolStripStatusLabelFiller
|
||||
//
|
||||
this.toolStripStatusLabelFiller.Name = "toolStripStatusLabelFiller";
|
||||
this.toolStripStatusLabelFiller.Size = new System.Drawing.Size(948, 17);
|
||||
this.toolStripStatusLabelFiller.Spring = true;
|
||||
//
|
||||
// toolStripStatusLabelMousePosition
|
||||
//
|
||||
this.toolStripStatusLabelMousePosition.Name = "toolStripStatusLabelMousePosition";
|
||||
this.toolStripStatusLabelMousePosition.RightToLeft = System.Windows.Forms.RightToLeft.Yes;
|
||||
this.toolStripStatusLabelMousePosition.Size = new System.Drawing.Size(22, 17);
|
||||
this.toolStripStatusLabelMousePosition.Text = "0,0";
|
||||
//
|
||||
// surface1
|
||||
//
|
||||
this.surface1.BackColor = System.Drawing.Color.Black;
|
||||
this.surface1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.surface1.Location = new System.Drawing.Point(0, 0);
|
||||
this.surface1.Name = "surface1";
|
||||
this.surface1.Size = new System.Drawing.Size(783, 680);
|
||||
this.surface1.Size = new System.Drawing.Size(783, 744);
|
||||
this.surface1.TabIndex = 5;
|
||||
this.surface1.Text = "surface1";
|
||||
//
|
||||
@@ -271,53 +459,83 @@
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(985, 705);
|
||||
this.Controls.Add(this.toolStripContainer1);
|
||||
this.ClientSize = new System.Drawing.Size(985, 773);
|
||||
this.Controls.Add(this.statusStrip1);
|
||||
this.Controls.Add(this.splitContainer3);
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.KeyPreview = true;
|
||||
this.MainMenuStrip = this.menuStrip1;
|
||||
this.Name = "Form1";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "OpenRA Editor";
|
||||
this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyUp);
|
||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.OnFormClosing);
|
||||
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);
|
||||
this.toolStripContainer1.ContentPanel.ResumeLayout(false);
|
||||
this.toolStripContainer1.TopToolStripPanel.ResumeLayout(false);
|
||||
this.toolStripContainer1.TopToolStripPanel.PerformLayout();
|
||||
this.toolStripContainer1.ResumeLayout(false);
|
||||
this.toolStripContainer1.PerformLayout();
|
||||
this.splitContainer1.Panel1.ResumeLayout(false);
|
||||
this.splitContainer1.Panel2.ResumeLayout(false);
|
||||
this.splitContainer1.ResumeLayout(false);
|
||||
this.splitContainer2.Panel1.ResumeLayout(false);
|
||||
this.splitContainer2.Panel2.ResumeLayout(false);
|
||||
this.splitContainer2.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.pmMiniMap)).EndInit();
|
||||
this.tabControl1.ResumeLayout(false);
|
||||
this.tabPage1.ResumeLayout(false);
|
||||
this.tabPage2.ResumeLayout(false);
|
||||
this.tabPage3.ResumeLayout(false);
|
||||
this.toolStrip1.ResumeLayout(false);
|
||||
this.toolStrip1.PerformLayout();
|
||||
this.menuStrip1.ResumeLayout(false);
|
||||
this.menuStrip1.PerformLayout();
|
||||
this.splitContainer3.Panel1.ResumeLayout(false);
|
||||
this.splitContainer3.Panel1.PerformLayout();
|
||||
this.splitContainer3.Panel2.ResumeLayout(false);
|
||||
this.splitContainer3.ResumeLayout(false);
|
||||
this.statusStrip1.ResumeLayout(false);
|
||||
this.statusStrip1.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.ToolStripContainer toolStripContainer1;
|
||||
private System.Windows.Forms.SplitContainer splitContainer1;
|
||||
private System.Windows.Forms.ToolTip tt;
|
||||
private System.Windows.Forms.ToolStrip toolStrip1;
|
||||
private System.Windows.Forms.ToolStripButton toolStripButton1;
|
||||
private System.Windows.Forms.TabControl tabControl1;
|
||||
private System.Windows.Forms.TabPage tabPage1;
|
||||
private System.Windows.Forms.FlowLayoutPanel tilePalette;
|
||||
private System.Windows.Forms.TabPage tabPage2;
|
||||
private System.Windows.Forms.ToolStripButton toolStripButton2;
|
||||
private System.Windows.Forms.FlowLayoutPanel actorPalette;
|
||||
private System.Windows.Forms.TabPage tabPage3;
|
||||
private System.Windows.Forms.FlowLayoutPanel resourcePalette;
|
||||
private System.Windows.Forms.ToolStripButton toolStripButton3;
|
||||
private System.Windows.Forms.ToolStripButton toolStripButton5;
|
||||
private System.Windows.Forms.ToolStripButton toolStripButton4;
|
||||
private System.Windows.Forms.FolderBrowserDialog folderBrowser;
|
||||
private System.Windows.Forms.ToolStripButton toolStripButton6;
|
||||
private System.Windows.Forms.ToolStripButton toolStripButton7;
|
||||
private System.Windows.Forms.FlowLayoutPanel resourcePalette;
|
||||
private Surface surface1;
|
||||
private System.Windows.Forms.MenuStrip menuStrip1;
|
||||
private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem newToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem openToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
|
||||
private System.Windows.Forms.ToolStripMenuItem saveToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem saveAsToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator2;
|
||||
private System.Windows.Forms.ToolStripMenuItem exotToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem1;
|
||||
private System.Windows.Forms.ToolStripMenuItem cCRedAlertMapToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem bitmapToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator3;
|
||||
private System.Windows.Forms.ToolStripMenuItem mapToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem propertiesToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem resizeToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator4;
|
||||
private System.Windows.Forms.ToolStripMenuItem spawnpointsToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem toolsToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem layersFloaterToolStripMenuItem;
|
||||
private System.Windows.Forms.PictureBox pmMiniMap;
|
||||
private System.Windows.Forms.SplitContainer splitContainer2;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuExport;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuMinimapToPNG;
|
||||
private System.Windows.Forms.SaveFileDialog saveFileDialog;
|
||||
private System.Windows.Forms.SplitContainer splitContainer3;
|
||||
private System.Windows.Forms.StatusStrip statusStrip1;
|
||||
private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabelMousePosition;
|
||||
private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabelFiller;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
323
OpenRA.Editor/Form1.cs
Normal file → Executable file
323
OpenRA.Editor/Form1.cs
Normal file → Executable file
@@ -11,12 +11,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Editor
|
||||
@@ -32,22 +31,25 @@ namespace OpenRA.Editor
|
||||
|
||||
Text = "OpenRA Editor (mod:{0})".F(currentMod);
|
||||
|
||||
var manifest = new Manifest(new[] { currentMod });
|
||||
Game.LoadModAssemblies(manifest);
|
||||
Game.modData = new ModData(currentMod);
|
||||
|
||||
FileSystem.UnmountAll();
|
||||
foreach (var folder in manifest.Folders) FileSystem.Mount(folder);
|
||||
foreach (var pkg in manifest.Packages) FileSystem.Mount(pkg);
|
||||
Rules.LoadRules(Game.modData.Manifest, new Map());
|
||||
|
||||
Rules.LoadRules(manifest, new Map());
|
||||
|
||||
folderBrowser.SelectedPath = new string[] { Environment.CurrentDirectory, "mods", currentMod, "maps" }
|
||||
.Aggregate(Path.Combine);
|
||||
surface1.AfterChange += OnMapChanged;
|
||||
surface1.MousePositionChanged += s => toolStripStatusLabelMousePosition.Text = s;
|
||||
}
|
||||
|
||||
void OnMapChanged()
|
||||
{
|
||||
MakeDirty();
|
||||
pmMiniMap.Image = Minimap.AddStaticResources(surface1.Map, Minimap.TerrainBitmap(surface1.Map, true));
|
||||
}
|
||||
|
||||
void MakeDirty() { dirty = true; }
|
||||
string loadedMapName;
|
||||
string currentMod = "ra";
|
||||
TileSet tileset;
|
||||
bool dirty = false;
|
||||
|
||||
void LoadMap(string mapname)
|
||||
{
|
||||
@@ -57,17 +59,20 @@ namespace OpenRA.Editor
|
||||
|
||||
loadedMapName = mapname;
|
||||
|
||||
var manifest = new Manifest(new[] { currentMod });
|
||||
Game.LoadModAssemblies(manifest);
|
||||
|
||||
FileSystem.UnmountAll();
|
||||
foreach (var folder in manifest.Folders) FileSystem.Mount(folder);
|
||||
foreach (var pkg in manifest.Packages) FileSystem.Mount(pkg);
|
||||
Game.modData = new ModData(currentMod);
|
||||
|
||||
// load the map
|
||||
var map = new Map(new Folder(mapname));
|
||||
var map = new Map(new Folder(mapname, 0));
|
||||
|
||||
PrepareMapResources(manifest, map);
|
||||
// upgrade maps that have no player definitions. editor doesnt care,
|
||||
// but this breaks the game pretty badly.
|
||||
if (map.Players.Count == 0)
|
||||
map.Players.Add("Neutral", new PlayerReference("Neutral",
|
||||
Rules.Info["world"].Traits.WithInterface<CountryInfo>().First().Race, true, true));
|
||||
|
||||
PrepareMapResources(Game.modData.Manifest, map);
|
||||
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
void NewMap(Map map)
|
||||
@@ -78,34 +83,31 @@ namespace OpenRA.Editor
|
||||
|
||||
loadedMapName = null;
|
||||
|
||||
var manifest = new Manifest(new[] { currentMod });
|
||||
Game.LoadModAssemblies(manifest);
|
||||
Game.modData = new ModData(currentMod);
|
||||
|
||||
FileSystem.UnmountAll();
|
||||
foreach (var folder in manifest.Folders) FileSystem.Mount(folder);
|
||||
foreach (var pkg in manifest.Packages) FileSystem.Mount(pkg);
|
||||
PrepareMapResources(Game.modData.Manifest, map);
|
||||
|
||||
PrepareMapResources(manifest, map);
|
||||
MakeDirty();
|
||||
}
|
||||
|
||||
// this code is insanely stupid, and mostly my fault -- chrisf
|
||||
void PrepareMapResources(Manifest manifest, Map map)
|
||||
{
|
||||
Rules.LoadRules(manifest, map);
|
||||
Rules.LoadRules(manifest, map);
|
||||
tileset = Rules.TileSets[map.Theater];
|
||||
tileset.LoadTiles();
|
||||
var palette = new Palette(FileSystem.Open(tileset.Palette), true);
|
||||
|
||||
surface1.Bind(map, tileset, palette);
|
||||
|
||||
surface1.Bind(map, tileset, palette);
|
||||
// construct the palette of tiles
|
||||
var palettes = new[] { tilePalette, actorPalette, resourcePalette };
|
||||
foreach (var p in palettes) { p.Visible = false; p.SuspendLayout(); }
|
||||
|
||||
foreach (var t in tileset.Templates)
|
||||
{
|
||||
try
|
||||
{
|
||||
var bitmap = RenderTemplate(tileset, (ushort)t.Key, palette);
|
||||
var bitmap = RenderUtils.RenderTemplate(tileset, (ushort)t.Key, palette);
|
||||
var ibox = new PictureBox
|
||||
{
|
||||
Image = bitmap,
|
||||
@@ -119,7 +121,6 @@ namespace OpenRA.Editor
|
||||
|
||||
var template = t.Value;
|
||||
tilePalette.Controls.Add(ibox);
|
||||
|
||||
tt.SetToolTip(ibox,
|
||||
"{1}:{0} ({2}x{3})".F(
|
||||
template.Image,
|
||||
@@ -137,23 +138,25 @@ namespace OpenRA.Editor
|
||||
try
|
||||
{
|
||||
var info = Rules.Info[a];
|
||||
var template = RenderActor(info, tileset, palette);
|
||||
if (!info.Traits.Contains<RenderSimpleInfo>()) continue;
|
||||
var template = RenderUtils.RenderActor(info, tileset, palette);
|
||||
var ibox = new PictureBox
|
||||
{
|
||||
Image = template.Bitmap,
|
||||
Width = template.Bitmap.Width / 2,
|
||||
Height = template.Bitmap.Height / 2,
|
||||
SizeMode = PictureBoxSizeMode.StretchImage
|
||||
Width = 32,
|
||||
Height = 32,
|
||||
SizeMode = PictureBoxSizeMode.Zoom,
|
||||
BorderStyle = BorderStyle.FixedSingle
|
||||
};
|
||||
|
||||
|
||||
ibox.Click += (_, e) => surface1.SetActor(template);
|
||||
|
||||
actorPalette.Controls.Add(ibox);
|
||||
|
||||
tt.SetToolTip(ibox,
|
||||
"{0}:{1}".F(
|
||||
info.Name,
|
||||
info.Category));
|
||||
"{0}".F(
|
||||
info.Name));
|
||||
|
||||
actorTemplates.Add(template);
|
||||
}
|
||||
@@ -168,15 +171,18 @@ namespace OpenRA.Editor
|
||||
{
|
||||
try
|
||||
{
|
||||
var template = RenderResourceType(a, tileset.Extensions, palette);
|
||||
var template = RenderUtils.RenderResourceType(a, tileset.Extensions, palette);
|
||||
var ibox = new PictureBox
|
||||
{
|
||||
Image = template.Bitmap,
|
||||
Width = template.Bitmap.Width,
|
||||
Height = template.Bitmap.Height,
|
||||
SizeMode = PictureBoxSizeMode.StretchImage
|
||||
Width = 32,
|
||||
Height = 32,
|
||||
SizeMode = PictureBoxSizeMode.Zoom,
|
||||
BorderStyle = BorderStyle.FixedSingle
|
||||
};
|
||||
|
||||
|
||||
|
||||
ibox.Click += (_, e) => surface1.SetResource(template);
|
||||
|
||||
resourcePalette.Controls.Add(ibox);
|
||||
@@ -193,103 +199,12 @@ namespace OpenRA.Editor
|
||||
|
||||
surface1.BindResourceTemplates(resourceTemplates);
|
||||
|
||||
foreach (var p in palettes) { p.Visible = true; p.ResumeLayout(); }
|
||||
}
|
||||
|
||||
static Bitmap RenderTemplate(TileSet ts, ushort n, Palette p)
|
||||
{
|
||||
var template = ts.Templates[n];
|
||||
var tile = ts.Tiles[n];
|
||||
|
||||
var bitmap = new Bitmap(24 * template.Size.X, 24 * template.Size.Y);
|
||||
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
|
||||
|
||||
unsafe
|
||||
foreach (var p in palettes)
|
||||
{
|
||||
int* q = (int*)data.Scan0.ToPointer();
|
||||
var stride = data.Stride >> 2;
|
||||
|
||||
for (var u = 0; u < template.Size.X; u++)
|
||||
for (var v = 0; v < template.Size.Y; v++)
|
||||
if (tile.TileBitmapBytes[u + v * template.Size.X] != null)
|
||||
{
|
||||
var rawImage = tile.TileBitmapBytes[u + v * template.Size.X];
|
||||
for (var i = 0; i < 24; i++)
|
||||
for (var j = 0; j < 24; j++)
|
||||
q[(v * 24 + j) * stride + u * 24 + i] = p.GetColor(rawImage[i + 24 * j]).ToArgb();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < 24; i++)
|
||||
for (var j = 0; j < 24; j++)
|
||||
q[(v * 24 + j) * stride + u * 24 + i] = Color.Transparent.ToArgb();
|
||||
}
|
||||
}
|
||||
|
||||
bitmap.UnlockBits(data);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
static ActorTemplate RenderActor(ActorInfo info, TileSet tileset, Palette p)
|
||||
{
|
||||
var ri = info.Traits.Get<RenderSimpleInfo>();
|
||||
string image = null;
|
||||
if (ri.OverrideTheater != null)
|
||||
for (int i = 0; i < ri.OverrideTheater.Length; i++)
|
||||
if (ri.OverrideTheater[i] == tileset.Id)
|
||||
image = ri.OverrideImage[i];
|
||||
|
||||
image = image ?? ri.Image ?? info.Name;
|
||||
using (var s = FileSystem.OpenWithExts(image, tileset.Extensions))
|
||||
{
|
||||
var shp = new ShpReader(s);
|
||||
var frame = shp[0];
|
||||
|
||||
var bitmap = new Bitmap(shp.Width, shp.Height);
|
||||
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
|
||||
|
||||
unsafe
|
||||
{
|
||||
int* q = (int*)data.Scan0.ToPointer();
|
||||
var stride = data.Stride >> 2;
|
||||
|
||||
for (var i = 0; i < shp.Width; i++)
|
||||
for (var j = 0; j < shp.Height; j++)
|
||||
q[j * stride + i] = p.GetColor(frame.Image[i + shp.Width * j]).ToArgb();
|
||||
}
|
||||
|
||||
bitmap.UnlockBits(data);
|
||||
return new ActorTemplate { Bitmap = bitmap, Info = info, Centered = !info.Traits.Contains<BuildingInfo>() };
|
||||
}
|
||||
}
|
||||
|
||||
static ResourceTemplate RenderResourceType(ResourceTypeInfo info, string[] exts, Palette p)
|
||||
{
|
||||
var image = info.SpriteNames[0];
|
||||
using (var s = FileSystem.OpenWithExts(image, exts))
|
||||
{
|
||||
var shp = new ShpReader(s);
|
||||
var frame = shp[shp.ImageCount - 1];
|
||||
|
||||
var bitmap = new Bitmap(shp.Width, shp.Height);
|
||||
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
|
||||
|
||||
unsafe
|
||||
{
|
||||
int* q = (int*)data.Scan0.ToPointer();
|
||||
var stride = data.Stride >> 2;
|
||||
|
||||
for (var i = 0; i < shp.Width; i++)
|
||||
for (var j = 0; j < shp.Height; j++)
|
||||
q[j * stride + i] = p.GetColor(frame.Image[i + shp.Width * j]).ToArgb();
|
||||
}
|
||||
|
||||
bitmap.UnlockBits(data);
|
||||
return new ResourceTemplate { Bitmap = bitmap, Info = info, Value = shp.ImageCount - 1 };
|
||||
p.Visible = true;
|
||||
p.ResumeLayout();
|
||||
}
|
||||
pmMiniMap.Image = Minimap.AddStaticResources(surface1.Map, Minimap.TerrainBitmap(surface1.Map, true));
|
||||
}
|
||||
|
||||
void ResizeClicked(object sender, EventArgs e)
|
||||
@@ -318,7 +233,7 @@ namespace OpenRA.Editor
|
||||
surface1.Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SaveClicked(object sender, EventArgs e)
|
||||
{
|
||||
if (loadedMapName == null)
|
||||
@@ -326,29 +241,63 @@ namespace OpenRA.Editor
|
||||
else
|
||||
{
|
||||
surface1.Map.PlayerCount = surface1.Map.Waypoints.Count;
|
||||
surface1.Map.Package = new Folder(loadedMapName);
|
||||
surface1.Map.Save(loadedMapName);
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SaveAsClicked(object sender, EventArgs e)
|
||||
{
|
||||
folderBrowser.ShowNewFolderButton = true;
|
||||
|
||||
if (DialogResult.OK == folderBrowser.ShowDialog())
|
||||
using (var nms = new MapSelect())
|
||||
{
|
||||
nms.MapFolderPath = new string[] { Environment.CurrentDirectory, "mods", currentMod, "maps" }
|
||||
.Aggregate(Path.Combine);
|
||||
|
||||
loadedMapName = folderBrowser.SelectedPath;
|
||||
SaveClicked(sender, e);
|
||||
nms.txtNew.ReadOnly = false;
|
||||
nms.btnOk.Text = "Save";
|
||||
nms.txtNew.Text = "unnamed";
|
||||
nms.txtPathOut.ReadOnly = false;
|
||||
|
||||
if (DialogResult.OK == nms.ShowDialog())
|
||||
{
|
||||
if (nms.txtNew.Text == "")
|
||||
nms.txtNew.Text = "unnamed";
|
||||
|
||||
string mapfoldername = Path.Combine(nms.MapFolderPath, nms.txtNew.Text);
|
||||
loadedMapName = mapfoldername;
|
||||
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(mapfoldername);
|
||||
}
|
||||
catch (Exception ed)
|
||||
{
|
||||
MessageBox.Show("Directory creation failed: {0}", ed.ToString());
|
||||
}
|
||||
|
||||
SaveClicked(sender, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OpenClicked(object sender, EventArgs e)
|
||||
{
|
||||
folderBrowser.ShowNewFolderButton = true;
|
||||
using (var nms = new MapSelect())
|
||||
{
|
||||
nms.MapFolderPath = new string[] { Environment.CurrentDirectory, "mods", currentMod, "maps" }
|
||||
.Aggregate(Path.Combine);
|
||||
|
||||
if (DialogResult.OK == folderBrowser.ShowDialog())
|
||||
LoadMap(folderBrowser.SelectedPath);
|
||||
nms.txtNew.ReadOnly = true;
|
||||
nms.txtPathOut.ReadOnly = true;
|
||||
nms.btnOk.Text = "Open";
|
||||
|
||||
if (DialogResult.OK == nms.ShowDialog())
|
||||
{
|
||||
string mapfoldername = Path.Combine(nms.MapFolderPath, nms.txtNew.Text);
|
||||
LoadMap(mapfoldername);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NewClicked(object sender, EventArgs e)
|
||||
@@ -361,13 +310,12 @@ namespace OpenRA.Editor
|
||||
|
||||
if (DialogResult.OK == nmd.ShowDialog())
|
||||
{
|
||||
var map = new Map();
|
||||
var map = new Map(nmd.theater.SelectedItem as string);
|
||||
|
||||
map.Resize((int)nmd.width.Value, (int)nmd.height.Value);
|
||||
|
||||
map.TopLeft = new int2((int)nmd.cordonLeft.Value, (int)nmd.cordonTop.Value);
|
||||
map.BottomRight = new int2((int)nmd.cordonRight.Value, (int)nmd.cordonBottom.Value);
|
||||
map.Tileset = nmd.theater.SelectedItem as string;
|
||||
map.Players.Add("Neutral", new PlayerReference("Neutral", Rules.Info["world"].Traits.WithInterface<CountryInfo>().First().Race, true, true));
|
||||
NewMap(map);
|
||||
}
|
||||
@@ -396,5 +344,82 @@ namespace OpenRA.Editor
|
||||
void SpawnPointsClicked(object sender, EventArgs e) { surface1.SetWaypoint(new WaypointTemplate()); }
|
||||
void Form1_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Space) surface1.IsPanning = true; }
|
||||
void Form1_KeyUp(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Space) surface1.IsPanning = false; }
|
||||
|
||||
void CloseClicked(object sender, EventArgs e)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
void ImportLegacyMapClicked(object sender, EventArgs e)
|
||||
{
|
||||
var currentDirectory = Directory.GetCurrentDirectory();
|
||||
using (var ofd = new OpenFileDialog { Filter = "Legacy maps (*.ini;*.mpr)|*.ini;*.mpr" })
|
||||
if (DialogResult.OK == ofd.ShowDialog())
|
||||
{
|
||||
Directory.SetCurrentDirectory( currentDirectory );
|
||||
/* massive hack: we should be able to call NewMap() with the imported Map object,
|
||||
* but something's not right internally in it, unless loaded via the real maploader */
|
||||
|
||||
var savePath = Path.Combine(Path.GetTempPath(), "OpenRA.Import");
|
||||
Directory.CreateDirectory(savePath);
|
||||
|
||||
var map = LegacyMapImporter.Import(ofd.FileName);
|
||||
map.Players.Add("Neutral", new PlayerReference("Neutral",
|
||||
Rules.Info["world"].Traits.WithInterface<CountryInfo>().First().Race, true, true));
|
||||
|
||||
map.Save(savePath);
|
||||
LoadMap(savePath);
|
||||
loadedMapName = null; /* editor needs to think this hasnt been saved */
|
||||
|
||||
Directory.Delete(savePath, true);
|
||||
MakeDirty();
|
||||
}
|
||||
}
|
||||
|
||||
void OnFormClosing(object sender, FormClosingEventArgs e)
|
||||
{
|
||||
if (!dirty) return;
|
||||
|
||||
switch (MessageBox.Show("The map has been modified since it was last saved. " + "\r\n" + "Save changes now?",
|
||||
"Unsaved Changes", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation))
|
||||
{
|
||||
case DialogResult.Yes: SaveClicked(null, EventArgs.Empty); break;
|
||||
case DialogResult.No: break;
|
||||
case DialogResult.Cancel: e.Cancel = true; break;
|
||||
}
|
||||
}
|
||||
|
||||
private void layersFloaterToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
var pb = new PaletteBox();
|
||||
pb.Show();
|
||||
}
|
||||
|
||||
private void mnuMinimapToPNG_Click(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
saveFileDialog.InitialDirectory = new string[] { Environment.CurrentDirectory, "maps" }
|
||||
.Aggregate(Path.Combine);
|
||||
|
||||
FileInfo file = new FileInfo(loadedMapName + ".png");
|
||||
string name = file.Name;
|
||||
saveFileDialog.FileName = name;
|
||||
|
||||
saveFileDialog.ShowDialog();
|
||||
if (saveFileDialog.FileName == "")
|
||||
{
|
||||
saveFileDialog.FileName = name;
|
||||
}
|
||||
else
|
||||
{
|
||||
Bitmap png = new Bitmap(pmMiniMap.Image);
|
||||
|
||||
png.Save(saveFileDialog.FileName, System.Drawing.Imaging.ImageFormat.Png);
|
||||
}
|
||||
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
496
OpenRA.Editor/Form1.resx
Normal file → Executable file
496
OpenRA.Editor/Form1.resx
Normal file → Executable file
@@ -117,119 +117,441 @@
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="toolStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>77, 17</value>
|
||||
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>198, 17</value>
|
||||
</metadata>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="toolStripButton3.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<data name="newToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIISURBVDhPpZP7S1NxGMbPPxKaXVUkMEq8IpKUCoY/hGgI
|
||||
ymqkDYYXcCjDZOANURSjCNGFQUTsl4GXVMxKk62YU4fXQpaIlygHQxBRH8/zwvyaIAYe+HLgnPN8nue9
|
||||
HA3nvDTq63oW/jm13XOwvPTB3DYFY5MH+bXfcN8ygfTSMSSXfESicQDxBqdYHwH29g9w2tnZ3UcguIvN
|
||||
rR3417exuBJE5N1n/wfwLgXEOc38Bc6xNRHb+/y4nm49G0Bnit2zf9H6bkliE/jKuYxrd6oVgDWfjB+K
|
||||
TWeKMyrGEVfowITvD9re/9ABVQrAhh0HHK+ZselMMaN/mvwtDb+aVqkA7HYIwIj3ysfluPTorJnP6Ezx
|
||||
oHsD1s5ZXEktUwCOioB5f1CEPR9+wTG6iuiserTo8dkwng7HT/R+XUPF8xlcTjErAOdMcW6NW8STiwG8
|
||||
7vej8oUPN/PsEv3t8Ao0TZP3T1u8uJRkUgAuSYHtO97oLxmXd5t9Ho8aPTK+GzntqNfrLm2fFoihwYOI
|
||||
xGIF4KjoGBLzY1OrF9k6OOFxnwDC4wxIMX1G0pMhgVyMNyoA13PAtS7OrJk1PrC69LUdQWxuF6IybHrX
|
||||
LRI7JrtZdoDAo1XmbjMyD+tjSXxGcXRmnYg5ttD9QuxDhN0uUgDOmbvNTpPOJaGAo2K36cyaGZvOFIfd
|
||||
KlSA8/zRh9ABIDUG+1JpAAAAAElFTkSuQmCC
|
||||
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHNSURBVDhPjZNdTxNREIb5LV54azSRxJ8gt95445XGa/8A
|
||||
CU0MMVgIWNmgRSioGN0AapQaISAWrEaITQTkQyhL2WbbWtt1+7ll+7h7SDdBocskk3Mm58xzZt7JaWmx
|
||||
bTdyk9/rPsz0fbYmz2JqfvSdHhJLPpxzTzMUid13F0D3k/h41V57iU+dI7/dfTqA8zKGBLUohjpurxER
|
||||
7/24i/RkSnj/47csLsWOB27IZ1DmrlDQJrHIU8q8EbE63UrD7oVe09p243iIqEAPQGVOQJxKRJwfdgE9
|
||||
gxO8X1wRkIWv/1Ri7A0QD5/HSrWT/HTNTgwIDapayAV0DTwXyQ0/IqwSvXU4hWQn6uwl4usPKCl9pGI+
|
||||
F2DV6zwaX2BQjgjIiZPpHXrpJjU2di7lao2sXmLiwwYXL18/GeB/KP8HqJgH5Iwy++k/yDOrzQF3+p8d
|
||||
AZi1A/RCleQvg81ElrHwt+aA232jLqBmWRjFKlq2wM/9HLGtFCOvPjcHdHQPCYBl1SmWTdK5IvFknu/b
|
||||
GaIrKsEX880B7V1B6rZq5cqhaIqms7aT4cuqyuyygvR0xhvgiOao7Qjm9Byyyw7K80hj0wRGw94tOGPy
|
||||
cs8fetoLfwGP5fd9L1vD4gAAAABJRU5ErkJggg==
|
||||
</value>
|
||||
</data>
|
||||
<data name="toolStripButton5.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<data name="openToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIISURBVDhPpZP7S1NxGMbPPxKaXVUkMEq8IpKUCoY/hGgI
|
||||
ymqkDYYXcCjDZOANURSjCNGFQUTsl4GXVMxKk62YU4fXQpaIlygHQxBRH8/zwvyaIAYe+HLgnPN8nue9
|
||||
HA3nvDTq63oW/jm13XOwvPTB3DYFY5MH+bXfcN8ygfTSMSSXfESicQDxBqdYHwH29g9w2tnZ3UcguIvN
|
||||
rR3417exuBJE5N1n/wfwLgXEOc38Bc6xNRHb+/y4nm49G0Bnit2zf9H6bkliE/jKuYxrd6oVgDWfjB+K
|
||||
TWeKMyrGEVfowITvD9re/9ABVQrAhh0HHK+ZselMMaN/mvwtDb+aVqkA7HYIwIj3ysfluPTorJnP6Ezx
|
||||
oHsD1s5ZXEktUwCOioB5f1CEPR9+wTG6iuiserTo8dkwng7HT/R+XUPF8xlcTjErAOdMcW6NW8STiwG8
|
||||
7vej8oUPN/PsEv3t8Ao0TZP3T1u8uJRkUgAuSYHtO97oLxmXd5t9Ho8aPTK+GzntqNfrLm2fFoihwYOI
|
||||
xGIF4KjoGBLzY1OrF9k6OOFxnwDC4wxIMX1G0pMhgVyMNyoA13PAtS7OrJk1PrC69LUdQWxuF6IybHrX
|
||||
LRI7JrtZdoDAo1XmbjMyD+tjSXxGcXRmnYg5ttD9QuxDhN0uUgDOmbvNTpPOJaGAo2K36cyaGZvOFIfd
|
||||
KlSA8/zRh9ABIDUG+1JpAAAAAElFTkSuQmCC
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
|
||||
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsMAAALDAE/QCLIAAACeklE
|
||||
QVQ4T6WTWUiUURiG/4suurJIjUIwskQsEANDqosQpUVNKbdCSRPKrQVDMddmXEedGdcpFXNGnUYdrSzF
|
||||
sEIoFInQcqHE1CwoKsXUUMnt6Z+RLMtA8OK5OZz3Oe/5OEcAhPWwpnBaodZZmqfjWmY5GSo98XJNwq9D
|
||||
1yQIilLhFaYIMIQuxZaZJ4uy6FS1T2BUIUKdNsdPhL9pqpEp/ne18PiiE94RCjzDco0C+rs1zIzXGvkx
|
||||
pmNuRI2+XEG9NjV5NYlXuBLP0DzcQwoQaiuUTI9VrQgvfC5irjeSqrJMKovTURcmU5KbxE15HAWyGNH5
|
||||
e/BCtSab6a+a5ZMXxTD9cdAbsir/CG6Xyvj+qcRY2xBurss28lCfRYNOxr3KdPTqFHQlUspV17mVl0Cx
|
||||
Mg5VdqyxjVBZks7k+3wMtYdaJdRXKVkYksJw6kreiWuD8dAXBa8j6Krx5UqwR4WgVqUwMZAJH+Tcr1bQ
|
||||
/ki+tOnPK7wKhA5v5tvcmHnsxNsKOy6ePTohCvYKpXkSvr2RMtyWSL1OzuKgBHpClwRdwWLwNPPtHsy0
|
||||
HGGy6RCjdfuQhllzxsUs1zBMoUiZyGh3LHe02XQ+E5v0RYqC89AZwOLzk8w+Pc5U82HG6h34Um1LR9pm
|
||||
/N2scLAxsTEKVFlx9LQkcVebBQNJ8FKs+8KH2VZ3pp44Md7gyIjejo+a3fTKTZGE7MJ+j0Xj8lPOz4ih
|
||||
tjyT3gfhdOQIy7TLN9Ai20hj8iZqEsxRx1hw4+oO/F13LjraW7ouC3JSo8mRXCAjNoj4y36GyXLO14VT
|
||||
xw7gfNCO/XbW2FpZYLndjK1bTNhmarLyIa3nKxuyPwG9D9E7Fbto+QAAAABJRU5ErkJggg==
|
||||
</value>
|
||||
</data>
|
||||
<data name="toolStripButton4.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<data name="saveToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIISURBVDhPpZP7S1NxGMbPPxKaXVUkMEq8IpKUCoY/hGgI
|
||||
ymqkDYYXcCjDZOANURSjCNGFQUTsl4GXVMxKk62YU4fXQpaIlygHQxBRH8/zwvyaIAYe+HLgnPN8nue9
|
||||
HA3nvDTq63oW/jm13XOwvPTB3DYFY5MH+bXfcN8ygfTSMSSXfESicQDxBqdYHwH29g9w2tnZ3UcguIvN
|
||||
rR3417exuBJE5N1n/wfwLgXEOc38Bc6xNRHb+/y4nm49G0Bnit2zf9H6bkliE/jKuYxrd6oVgDWfjB+K
|
||||
TWeKMyrGEVfowITvD9re/9ABVQrAhh0HHK+ZselMMaN/mvwtDb+aVqkA7HYIwIj3ysfluPTorJnP6Ezx
|
||||
oHsD1s5ZXEktUwCOioB5f1CEPR9+wTG6iuiserTo8dkwng7HT/R+XUPF8xlcTjErAOdMcW6NW8STiwG8
|
||||
7vej8oUPN/PsEv3t8Ao0TZP3T1u8uJRkUgAuSYHtO97oLxmXd5t9Ho8aPTK+GzntqNfrLm2fFoihwYOI
|
||||
xGIF4KjoGBLzY1OrF9k6OOFxnwDC4wxIMX1G0pMhgVyMNyoA13PAtS7OrJk1PrC69LUdQWxuF6IybHrX
|
||||
LRI7JrtZdoDAo1XmbjMyD+tjSXxGcXRmnYg5ttD9QuxDhN0uUgDOmbvNTpPOJaGAo2K36cyaGZvOFIfd
|
||||
KlSA8/zRh9ABIDUG+1JpAAAAAElFTkSuQmCC
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
|
||||
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsMAAALDAE/QCLIAAACMklE
|
||||
QVQ4T6WT3UuTcRTH9y90303QRbc1NYZrMRs86hzKsmFoIb09kqZpunxJUqxMxZYvkK1w6sTlahJOKvIF
|
||||
TJEUMZaSlZkrWuJQU3QiGHz7nZ+wn0vrQh84Nw98Puc553wfBQDFXorDL18EQOXuXEGHaxlPHItoafbj
|
||||
kXUW9XU/YLnnxd3yaZSWfEZR4Qfk5Y7japaHoVBwAYF9vUBd7Tq9/Oeztr4BfVIfTic95xUUuJ4tcUFl
|
||||
xa//wv7FNRw3voJSKcN0yikEjrYFLigt+bmjgDoT/NW3hDCDG4UFMzhpbBUCW+McF1w3f9km2Aq/n/Lj
|
||||
kORCTvYkEuJtQtDwwMcFmVfGQwR/w0MeH/ZrHZDlURgMViGorfnOBfKl0aBgJ7h35Bv2RTYj5cwbxMbW
|
||||
C0FV5Qx6usFOCaSeH4bp7CDfNi2MZqbPps6bcD8STa8hSRYhuFU2hS43WAaAVvtvdvdVlN+Z50ulhdHM
|
||||
GemeIByX0AmdrkIIbhRNwtkONNk2WHAC0Cdnh5TxnBnJl4t557h4Bsc4odWWCYE5b4LBQM39AO9MAgXL
|
||||
WJhawtinOUxMz0POvY0T+g4Oq6Ps0GiKhYBiaX2I4GeTgOC0/Gp89C7AO7uMazctCNfaGdyC8GOPoY7M
|
||||
F4KM9Hds7hU+80GdEweOSHjaNQB39xB6+kcw+HYM0QYTlJpGRDD4sKoBKlVOiCDx4oUBHk9KGIWE7kyn
|
||||
om3Twmhm6kpF8NGITCGgn2K39QfkKu4LIHJHnwAAAABJRU5ErkJggg==
|
||||
</value>
|
||||
</data>
|
||||
<data name="toolStripButton1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<data name="cCRedAlertMapToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIISURBVDhPpZP7S1NxGMbPPxKaXVUkMEq8IpKUCoY/hGgI
|
||||
ymqkDYYXcCjDZOANURSjCNGFQUTsl4GXVMxKk62YU4fXQpaIlygHQxBRH8/zwvyaIAYe+HLgnPN8nue9
|
||||
HA3nvDTq63oW/jm13XOwvPTB3DYFY5MH+bXfcN8ygfTSMSSXfESicQDxBqdYHwH29g9w2tnZ3UcguIvN
|
||||
rR3417exuBJE5N1n/wfwLgXEOc38Bc6xNRHb+/y4nm49G0Bnit2zf9H6bkliE/jKuYxrd6oVgDWfjB+K
|
||||
TWeKMyrGEVfowITvD9re/9ABVQrAhh0HHK+ZselMMaN/mvwtDb+aVqkA7HYIwIj3ysfluPTorJnP6Ezx
|
||||
oHsD1s5ZXEktUwCOioB5f1CEPR9+wTG6iuiserTo8dkwng7HT/R+XUPF8xlcTjErAOdMcW6NW8STiwG8
|
||||
7vej8oUPN/PsEv3t8Ao0TZP3T1u8uJRkUgAuSYHtO97oLxmXd5t9Ho8aPTK+GzntqNfrLm2fFoihwYOI
|
||||
xGIF4KjoGBLzY1OrF9k6OOFxnwDC4wxIMX1G0pMhgVyMNyoA13PAtS7OrJk1PrC69LUdQWxuF6IybHrX
|
||||
LRI7JrtZdoDAo1XmbjMyD+tjSXxGcXRmnYg5ttD9QuxDhN0uUgDOmbvNTpPOJaGAo2K36cyaGZvOFIfd
|
||||
KlSA8/zRh9ABIDUG+1JpAAAAAElFTkSuQmCC
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAACH
|
||||
DwAAjA8AAP1SAACBQAAAfXkAAOmLAAA85QAAGcxzPIV3AAAKOWlDQ1BQaG90b3Nob3AgSUNDIHByb2Zp
|
||||
bGUAAEjHnZZ3VFTXFofPvXd6oc0wAlKG3rvAANJ7k15FYZgZYCgDDjM0sSGiAhFFRJoiSFDEgNFQJFZE
|
||||
sRAUVLAHJAgoMRhFVCxvRtaLrqy89/Ly++Osb+2z97n77L3PWhcAkqcvl5cGSwGQyhPwgzyc6RGRUXTs
|
||||
AIABHmCAKQBMVka6X7B7CBDJy82FniFyAl8EAfB6WLwCcNPQM4BOB/+fpFnpfIHomAARm7M5GSwRF4g4
|
||||
JUuQLrbPipgalyxmGCVmvihBEcuJOWGRDT77LLKjmNmpPLaIxTmns1PZYu4V8bZMIUfEiK+ICzO5nCwR
|
||||
3xKxRoowlSviN+LYVA4zAwAUSWwXcFiJIjYRMYkfEuQi4uUA4EgJX3HcVyzgZAvEl3JJS8/hcxMSBXQd
|
||||
li7d1NqaQffkZKVwBALDACYrmcln013SUtOZvBwAFu/8WTLi2tJFRbY0tba0NDQzMv2qUP91829K3NtF
|
||||
ehn4uWcQrf+L7a/80hoAYMyJarPziy2uCoDOLQDI3fti0zgAgKSobx3Xv7oPTTwviQJBuo2xcVZWlhGX
|
||||
wzISF/QP/U+Hv6GvvmckPu6P8tBdOfFMYYqALq4bKy0lTcinZ6QzWRy64Z+H+B8H/nUeBkGceA6fwxNF
|
||||
hImmjMtLELWbx+YKuGk8Opf3n5r4D8P+pMW5FonS+BFQY4yA1HUqQH7tBygKESDR+8Vd/6NvvvgwIH55
|
||||
4SqTi3P/7zf9Z8Gl4iWDm/A5ziUohM4S8jMX98TPEqABAUgCKpAHykAd6ABDYAasgC1wBG7AG/iDEBAJ
|
||||
VgMWSASpgA+yQB7YBApBMdgJ9oBqUAcaQTNoBcdBJzgFzoNL4Bq4AW6D+2AUTIBnYBa8BgsQBGEhMkSB
|
||||
5CEVSBPSh8wgBmQPuUG+UBAUCcVCCRAPEkJ50GaoGCqDqqF6qBn6HjoJnYeuQIPQXWgMmoZ+h97BCEyC
|
||||
qbASrAUbwwzYCfaBQ+BVcAK8Bs6FC+AdcCXcAB+FO+Dz8DX4NjwKP4PnEIAQERqiihgiDMQF8UeikHiE
|
||||
j6xHipAKpAFpRbqRPuQmMorMIG9RGBQFRUcZomxRnqhQFAu1BrUeVYKqRh1GdaB6UTdRY6hZ1Ec0Ga2I
|
||||
1kfboL3QEegEdBa6EF2BbkK3oy+ib6Mn0K8xGAwNo42xwnhiIjFJmLWYEsw+TBvmHGYQM46Zw2Kx8lh9
|
||||
rB3WH8vECrCF2CrsUexZ7BB2AvsGR8Sp4Mxw7rgoHA+Xj6vAHcGdwQ3hJnELeCm8Jt4G749n43PwpfhG
|
||||
fDf+On4Cv0CQJmgT7AghhCTCJkIloZVwkfCA8JJIJKoRrYmBRC5xI7GSeIx4mThGfEuSIemRXEjRJCFp
|
||||
B+kQ6RzpLuklmUzWIjuSo8gC8g5yM/kC+RH5jQRFwkjCS4ItsUGiRqJDYkjiuSReUlPSSXK1ZK5kheQJ
|
||||
yeuSM1J4KS0pFymm1HqpGqmTUiNSc9IUaVNpf+lU6RLpI9JXpKdksDJaMm4ybJkCmYMyF2TGKQhFneJC
|
||||
YVE2UxopFykTVAxVm+pFTaIWU7+jDlBnZWVkl8mGyWbL1sielh2lITQtmhcthVZKO04bpr1borTEaQln
|
||||
yfYlrUuGlszLLZVzlOPIFcm1yd2WeydPl3eTT5bfJd8p/1ABpaCnEKiQpbBf4aLCzFLqUtulrKVFS48v
|
||||
vacIK+opBimuVTyo2K84p6Ss5KGUrlSldEFpRpmm7KicpFyufEZ5WoWiYq/CVSlXOavylC5Ld6Kn0Cvp
|
||||
vfRZVUVVT1Whar3qgOqCmrZaqFq+WpvaQ3WCOkM9Xr1cvUd9VkNFw08jT6NF454mXpOhmai5V7NPc15L
|
||||
Wytca6tWp9aUtpy2l3audov2Ax2yjoPOGp0GnVu6GF2GbrLuPt0berCehV6iXo3edX1Y31Kfq79Pf9AA
|
||||
bWBtwDNoMBgxJBk6GWYathiOGdGMfI3yjTqNnhtrGEcZ7zLuM/5oYmGSYtJoct9UxtTbNN+02/R3Mz0z
|
||||
llmN2S1zsrm7+QbzLvMXy/SXcZbtX3bHgmLhZ7HVosfig6WVJd+y1XLaSsMq1qrWaoRBZQQwShiXrdHW
|
||||
ztYbrE9Zv7WxtBHYHLf5zdbQNtn2iO3Ucu3lnOWNy8ft1OyYdvV2o/Z0+1j7A/ajDqoOTIcGh8eO6o5s
|
||||
xybHSSddpySno07PnU2c+c7tzvMuNi7rXM65Iq4erkWuA24ybqFu1W6P3NXcE9xb3Gc9LDzWepzzRHv6
|
||||
eO7yHPFS8mJ5NXvNelt5r/Pu9SH5BPtU+zz21fPl+3b7wX7efrv9HqzQXMFb0ekP/L38d/s/DNAOWBPw
|
||||
YyAmMCCwJvBJkGlQXlBfMCU4JvhI8OsQ55DSkPuhOqHC0J4wybDosOaw+XDX8LLw0QjjiHUR1yIVIrmR
|
||||
XVHYqLCopqi5lW4r96yciLaILoweXqW9KnvVldUKq1NWn46RjGHGnIhFx4bHHol9z/RnNjDn4rziauNm
|
||||
WS6svaxnbEd2OXuaY8cp40zG28WXxU8l2CXsTphOdEisSJzhunCruS+SPJPqkuaT/ZMPJX9KCU9pS8Wl
|
||||
xqae5Mnwknm9acpp2WmD6frphemja2zW7Fkzy/fhN2VAGasyugRU0c9Uv1BHuEU4lmmfWZP5Jiss60S2
|
||||
dDYvuz9HL2d7zmSue+63a1FrWWt78lTzNuWNrXNaV78eWh+3vmeD+oaCDRMbPTYe3kTYlLzpp3yT/LL8
|
||||
V5vDN3cXKBVsLBjf4rGlpVCikF84stV2a9021DbutoHt5turtn8sYhddLTYprih+X8IqufqN6TeV33za
|
||||
Eb9joNSydP9OzE7ezuFdDrsOl0mX5ZaN7/bb3VFOLy8qf7UnZs+VimUVdXsJe4V7Ryt9K7uqNKp2Vr2v
|
||||
Tqy+XeNc01arWLu9dn4fe9/Qfsf9rXVKdcV17w5wD9yp96jvaNBqqDiIOZh58EljWGPft4xvm5sUmoqb
|
||||
PhziHRo9HHS4t9mqufmI4pHSFrhF2DJ9NProje9cv+tqNWytb6O1FR8Dx4THnn4f+/3wcZ/jPScYJ1p/
|
||||
0Pyhtp3SXtQBdeR0zHYmdo52RXYNnvQ+2dNt293+o9GPh06pnqo5LXu69AzhTMGZT2dzz86dSz83cz7h
|
||||
/HhPTM/9CxEXbvUG9g5c9Ll4+ZL7pQt9Tn1nL9tdPnXF5srJq4yrndcsr3X0W/S3/2TxU/uA5UDHdavr
|
||||
XTesb3QPLh88M+QwdP6m681Lt7xuXbu94vbgcOjwnZHokdE77DtTd1PuvriXeW/h/sYH6AdFD6UeVjxS
|
||||
fNTws+7PbaOWo6fHXMf6Hwc/vj/OGn/2S8Yv7ycKnpCfVEyqTDZPmU2dmnafvvF05dOJZ+nPFmYKf5X+
|
||||
tfa5zvMffnP8rX82YnbiBf/Fp99LXsq/PPRq2aueuYC5R69TXy/MF72Rf3P4LeNt37vwd5MLWe+x7ys/
|
||||
6H7o/ujz8cGn1E+f/gUDmPP8usTo0wAAAAlwSFlzAAALDAAACwwBP0AiyAAAAN5JREFUOE+FUwEOAyEI
|
||||
8+k+7X7GoFBWmZdtISYgtS3csrXsFtvzf2Mv8/8d4Hkec2SLM+IHzJsjdwVAcxQrtl8OsDgBxPMGgKJG
|
||||
SQkwMlI2zSCS+cuL0YCceHEDAcBbM6gTQOhDDpnBxHqVOsmgdYvmfCxk7q+JpDZN4yQOJhOAOtmslGna
|
||||
MYE3AN2HeBEmyvhYZ44mL5rRXkijgoAZAA3nCVBzbzM5vuE8x8xmbGIzqE1LkNwHOO2RZmZOjQYTjoWF
|
||||
g/YYr+qn2QBQSl2ofL8oC6Wb2hIOM8WD+bXOex/mMAFDkP1eQgAAAABJRU5ErkJggg==
|
||||
</value>
|
||||
</data>
|
||||
<data name="toolStripButton6.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<data name="bitmapToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIISURBVDhPpZP7S1NxGMbPPxKaXVUkMEq8IpKUCoY/hGgI
|
||||
ymqkDYYXcCjDZOANURSjCNGFQUTsl4GXVMxKk62YU4fXQpaIlygHQxBRH8/zwvyaIAYe+HLgnPN8nue9
|
||||
HA3nvDTq63oW/jm13XOwvPTB3DYFY5MH+bXfcN8ygfTSMSSXfESicQDxBqdYHwH29g9w2tnZ3UcguIvN
|
||||
rR3417exuBJE5N1n/wfwLgXEOc38Bc6xNRHb+/y4nm49G0Bnit2zf9H6bkliE/jKuYxrd6oVgDWfjB+K
|
||||
TWeKMyrGEVfowITvD9re/9ABVQrAhh0HHK+ZselMMaN/mvwtDb+aVqkA7HYIwIj3ysfluPTorJnP6Ezx
|
||||
oHsD1s5ZXEktUwCOioB5f1CEPR9+wTG6iuiserTo8dkwng7HT/R+XUPF8xlcTjErAOdMcW6NW8STiwG8
|
||||
7vej8oUPN/PsEv3t8Ao0TZP3T1u8uJRkUgAuSYHtO97oLxmXd5t9Ho8aPTK+GzntqNfrLm2fFoihwYOI
|
||||
xGIF4KjoGBLzY1OrF9k6OOFxnwDC4wxIMX1G0pMhgVyMNyoA13PAtS7OrJk1PrC69LUdQWxuF6IybHrX
|
||||
LRI7JrtZdoDAo1XmbjMyD+tjSXxGcXRmnYg5ttD9QuxDhN0uUgDOmbvNTpPOJaGAo2K36cyaGZvOFIfd
|
||||
KlSA8/zRh9ABIDUG+1JpAAAAAElFTkSuQmCC
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
|
||||
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsMAAALDAE/QCLIAAACR0lE
|
||||
QVQ4T6WTXUiTARSGdxkRRBdB0IUREV1EKRFEYYuQAklL8sKQfphUoJSUWJbLxAVZWqyBio5WajorM1PL
|
||||
xExUlLQfbU5n0lygRerMP/qxOZ92vpjfCKLAi3P5Puc957xHA2gWUoo49147gWUqbSPrdjOXChrQm56S
|
||||
lFVFvKEcXaqV2OQiohMt7Esw+6Ro5gGeWfhbff0BY9NzDI3N0f/JS6fLy7rd6f8HcNsdOI6EYD8cjK3V
|
||||
roiLawdYu+vivwHSWcQM1THz/DQv96+ixeHlVvU71oQFAGTmP+37bdsPBf8WZ4fRFhVEXdcsBQ9srN6Z
|
||||
pjqQhQUCAmcW29JZxA8fvaWyY5YcawdBOy6oANm2H9A3MMypDLNS7b1flJnFtnQWcVmrB2NhMytD9SpA
|
||||
TiUA5+CYInQOjWPrH2V7RBzmijdo9x5VKr+yj6ImD9nmelZsS1UBcme/+OPIJIOfv/Gi201ZXQ/hMfFU
|
||||
Peuktqnbd3QN+U/cXM6tYfmW8ypAQiKdh91TTE7PYHNOYKl6z916F3m+eSNjT1B4vxHjzWoFYrhRwbLN
|
||||
51SAJOynx8vo5Ay9rimKHzu5XtJDpuU1WZY2Eg1WgrXRJOpNxKdcUyBLN6WoAInnyPh3XvW6KW/4MC9O
|
||||
z2ki+Wo1CWklROkMCiT8wEm0kXEsCTmrAiTbDtcEpTVdZOS1oDfWk5xZ6RPeQZeUR8zxK0Qe1BO65xjr
|
||||
t0YotXhjAEAeQ7It8ZSESUjkznIq2bYsTGYW29JZxIs2nFEdLOSdfwFwpvLxRKIY2AAAAABJRU5ErkJg
|
||||
gg==
|
||||
</value>
|
||||
</data>
|
||||
<data name="toolStripButton7.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<data name="mnuMinimapToPNG.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIISURBVDhPpZP7S1NxGMbPPxKaXVUkMEq8IpKUCoY/hGgI
|
||||
ymqkDYYXcCjDZOANURSjCNGFQUTsl4GXVMxKk62YU4fXQpaIlygHQxBRH8/zwvyaIAYe+HLgnPN8nue9
|
||||
HA3nvDTq63oW/jm13XOwvPTB3DYFY5MH+bXfcN8ygfTSMSSXfESicQDxBqdYHwH29g9w2tnZ3UcguIvN
|
||||
rR3417exuBJE5N1n/wfwLgXEOc38Bc6xNRHb+/y4nm49G0Bnit2zf9H6bkliE/jKuYxrd6oVgDWfjB+K
|
||||
TWeKMyrGEVfowITvD9re/9ABVQrAhh0HHK+ZselMMaN/mvwtDb+aVqkA7HYIwIj3ysfluPTorJnP6Ezx
|
||||
oHsD1s5ZXEktUwCOioB5f1CEPR9+wTG6iuiserTo8dkwng7HT/R+XUPF8xlcTjErAOdMcW6NW8STiwG8
|
||||
7vej8oUPN/PsEv3t8Ao0TZP3T1u8uJRkUgAuSYHtO97oLxmXd5t9Ho8aPTK+GzntqNfrLm2fFoihwYOI
|
||||
xGIF4KjoGBLzY1OrF9k6OOFxnwDC4wxIMX1G0pMhgVyMNyoA13PAtS7OrJk1PrC69LUdQWxuF6IybHrX
|
||||
LRI7JrtZdoDAo1XmbjMyD+tjSXxGcXRmnYg5ttD9QuxDhN0uUgDOmbvNTpPOJaGAo2K36cyaGZvOFIfd
|
||||
KlSA8/zRh9ABIDUG+1JpAAAAAElFTkSuQmCC
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
|
||||
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsMAAALDAE/QCLIAAACR0lE
|
||||
QVQ4T6WTXUiTARSGdxkRRBdB0IUREV1EKRFEYYuQAklL8sKQfphUoJSUWJbLxAVZWqyBio5WajorM1PL
|
||||
xExUlLQfbU5n0lygRerMP/qxOZ92vpjfCKLAi3P5Puc957xHA2gWUoo49147gWUqbSPrdjOXChrQm56S
|
||||
lFVFvKEcXaqV2OQiohMt7Esw+6Ro5gGeWfhbff0BY9NzDI3N0f/JS6fLy7rd6f8HcNsdOI6EYD8cjK3V
|
||||
roiLawdYu+vivwHSWcQM1THz/DQv96+ixeHlVvU71oQFAGTmP+37bdsPBf8WZ4fRFhVEXdcsBQ9srN6Z
|
||||
pjqQhQUCAmcW29JZxA8fvaWyY5YcawdBOy6oANm2H9A3MMypDLNS7b1flJnFtnQWcVmrB2NhMytD9SpA
|
||||
TiUA5+CYInQOjWPrH2V7RBzmijdo9x5VKr+yj6ImD9nmelZsS1UBcme/+OPIJIOfv/Gi201ZXQ/hMfFU
|
||||
Peuktqnbd3QN+U/cXM6tYfmW8ypAQiKdh91TTE7PYHNOYKl6z916F3m+eSNjT1B4vxHjzWoFYrhRwbLN
|
||||
51SAJOynx8vo5Ay9rimKHzu5XtJDpuU1WZY2Eg1WgrXRJOpNxKdcUyBLN6WoAInnyPh3XvW6KW/4MC9O
|
||||
z2ki+Wo1CWklROkMCiT8wEm0kXEsCTmrAiTbDtcEpTVdZOS1oDfWk5xZ6RPeQZeUR8zxK0Qe1BO65xjr
|
||||
t0YotXhjAEAeQ7It8ZSESUjkznIq2bYsTGYW29JZxIs2nFEdLOSdfwFwpvLxRKIY2AAAAABJRU5ErkJg
|
||||
gg==
|
||||
</value>
|
||||
</data>
|
||||
<data name="toolStripButton2.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<data name="propertiesToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIISURBVDhPpZP7S1NxGMbPPxKaXVUkMEq8IpKUCoY/hGgI
|
||||
ymqkDYYXcCjDZOANURSjCNGFQUTsl4GXVMxKk62YU4fXQpaIlygHQxBRH8/zwvyaIAYe+HLgnPN8nue9
|
||||
HA3nvDTq63oW/jm13XOwvPTB3DYFY5MH+bXfcN8ygfTSMSSXfESicQDxBqdYHwH29g9w2tnZ3UcguIvN
|
||||
rR3417exuBJE5N1n/wfwLgXEOc38Bc6xNRHb+/y4nm49G0Bnit2zf9H6bkliE/jKuYxrd6oVgDWfjB+K
|
||||
TWeKMyrGEVfowITvD9re/9ABVQrAhh0HHK+ZselMMaN/mvwtDb+aVqkA7HYIwIj3ysfluPTorJnP6Ezx
|
||||
oHsD1s5ZXEktUwCOioB5f1CEPR9+wTG6iuiserTo8dkwng7HT/R+XUPF8xlcTjErAOdMcW6NW8STiwG8
|
||||
7vej8oUPN/PsEv3t8Ao0TZP3T1u8uJRkUgAuSYHtO97oLxmXd5t9Ho8aPTK+GzntqNfrLm2fFoihwYOI
|
||||
xGIF4KjoGBLzY1OrF9k6OOFxnwDC4wxIMX1G0pMhgVyMNyoA13PAtS7OrJk1PrC69LUdQWxuF6IybHrX
|
||||
LRI7JrtZdoDAo1XmbjMyD+tjSXxGcXRmnYg5ttD9QuxDhN0uUgDOmbvNTpPOJaGAo2K36cyaGZvOFIfd
|
||||
KlSA8/zRh9ABIDUG+1JpAAAAAElFTkSuQmCC
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
|
||||
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsMAAALDAE/QCLIAAACCklE
|
||||
QVQ4T6WT30tTUQDHz39QD0UQSpAPIkgPyR60AiUiyoGBL4qZjOyt0tZP9tBDk1AsXIhj93ILdd27DPPH
|
||||
3VwrUrdK2ioJHAgVOdoPaQsarBg43L6ec+akuRsEPnw5D4fP5/vlXg4BQHaSf8LjjwdqaTA2cg+y1Ith
|
||||
qxmi5Tas/SYWk+QRoPgmtNsLcPq7GYX8+XoTqaUL+KR2cAmDxeBgqeBv2NhWzwUFOBk4g5/zRxB3V8Es
|
||||
38AtbzuIw/0RLMrMeyhTs2CzGdRtaOTn1dajvLkAR9VKLNvLcHmoExddzSDKzAfkcjkkEtEiOLxoQpdB
|
||||
z+Er7ScQUg/DL5TD2bsfl5oPoKWnCZ3jehDZGeAC1hwL3uXNs55Jep7Gis/AJWxyTeVe1FXvhq5qH6oP
|
||||
7nlw/NoxGByNIKPT77CezSEeD6Pn+jlEIiGk6X8N+F9zyfLYIZzUVUCwT0J36jy9yX83KjDq7zSADE8t
|
||||
cGB7kpksFt76YDzbgMWVFLzBX0WCTcku8mjiTSm8lkUslcHnH2kK/+aw6k+UCJiESE+9XCApz2Gzu5Gk
|
||||
sEVy4r6got82vRV5blVbIDyZ21rAZrPmL7w5P5s1KxQWXRFtgU15lV8ge2AbdXPY8pAuEIsXWJ6FtAVW
|
||||
+SWSmXWssuZ4vnl+s5nNFl1hMLjP8U1bMGR/wS/+N9tf7o6eMpNtADko6xybtEXLAAAAAElFTkSuQmCC
|
||||
</value>
|
||||
</data>
|
||||
<data name="resizeToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
|
||||
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsMAAALDAE/QCLIAAADLklE
|
||||
QVQ4T3WS60/ScRjFf39CL3rR1ovurduWbbU2t7ZqdlkXt7Lrym6O1VoXcdYqQ54wKlGxABE1CzWF0nIm
|
||||
lZcoTbyUNJFIzDJSJK+E0qy8wInvz+i2erazfd+cz3m+zw4nTS+FLOeZNim3Vp6UU5sqvf5MSZqnyjhV
|
||||
pfKUvEx54kqp8rCkWHVQVKSJPHtbs+tUgSYiOicVAMfEqfR1dVFCGSqrX94cHQeN/aXhbyD3Zz91uf3U
|
||||
9tFHTQ4fzVtH9BOQVdKcW2F6/eKkWA1zcxu6vUAQMmCzk/3AErLtDyFrrY035z16T3PXin8B5LfqZE6P
|
||||
HyZzKw5FX+Yh4XtjwZKZGV3lNPIkhhojplON3Uc3S9/Q7LDfADKtKYklMsgTkwV7joixKHQr2Nq2fSET
|
||||
5uQwqtsyjcot45R510ozV8f/2iAhsyolCNh9WIyFoRGYHbIGfYN+SVd7Nznzk8ll0FLzKxdZO3xkaOjG
|
||||
GYUxcIIfRxSlPU4N/rn1fS8JJVlU1WCT3npggVLfAIWuHjJtNRIyjIhTPEKM7D6OSop4RcXpwZ2Wl11l
|
||||
gHanmze/c36ioc8jyRlFjSzljxl2daI9Pwuv1Cnw9PRjZeQ1cCcSS68Fza6+IXL2fCG7w0ssmc3o2IR8
|
||||
gbc1PQU9NUp48sNRcUyAkPBL4AIlUbLk3gEvS6YXrW6p0dx9UZ5n4gHjzBmYAAPPYwRwazeiMXYWqjcs
|
||||
wLSVInAHRYWq0TEf9Q+NUEsg+fr9t2nF1U71leyqn+u3vPuIl2298HZ2wnxkO5q2LYOtxoKpK86D23tW
|
||||
r+7zfCVzywAVGT/QVV2LvNDo0Eo0j3mAtbUTiRnFOJ94Axp9LfIKK5Ctq0RDmw9TQuPAsW7bHYNUYLCQ
|
||||
JL2GRAqjtMDYwV+8wzUAWeY9eIfHYW0fxNodxyGWZeOSPBvzl27C5OXnwG0T5irmr79wgdWTNYyVJFL8
|
||||
kAeo8wyBA/rx2jGErBIH0nXPsWmPEHcM9YgURGPS0jMTZfiXGKDfM4Y0fVOgA/UgRQWECTpExaqxUyDF
|
||||
wuUbJjb4H0AQfxtrDqiweLMUc8LEmLEqnv9zUMzM9B1/cM83lepxTAAAAABJRU5ErkJggg==
|
||||
</value>
|
||||
</data>
|
||||
<data name="spawnpointsToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
|
||||
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsMAAALDAE/QCLIAAABrUlE
|
||||
QVQ4T6WTWyhDcRzHl8g1D/IkxZ4mjcgDB0U5ubbVbJLkkubJSt7w6M1eENHUENrktmzJ3HKEiSh7US5l
|
||||
QiK5JUXpy/9f/9O2zhY59at//c/n87uc35EBkP0nAsL6Bi33E9CpeBINJElHthIkvBNKChh8YVPi1Cpn
|
||||
Eo7ANSnJwQUMfnLEobVejZbaCnis8VRiyFSgXJ4QWOAPO5fXYJ2xo1HD48QcRSV5CfHSAn94fV0gL9Jn
|
||||
eVWAtjgXRwPhrJ18Ngc6g2AwkzhXBJTmZ+GgN8xHwgRgPXtnZvDH5xde3j6x6BTAcxk47JFRCUnOBAWF
|
||||
2WkQhC2xbH/49uEd59evGLfYoJAnEkGjKCCHyjqDDzw72YOpUSMmTF0w93VS2H32iLmlXSSlcuIgxT1Q
|
||||
VTf7CAj87IjFgy2Gfk4Cu9x3sNhd0oIyXZMoID2TzPez0biyREKvK6bw6t4NxuYDCEo0ZFsBNjBStmci
|
||||
Asb2Kmj4HAovbF5ieHpHugJeXUfhja19rGzsYai7DcemULj7Q1DEpWNkzgXTDzxo3ZYWFKlq6cVvw2eR
|
||||
vP+uv56/AehVvkSccelEAAAAAElFTkSuQmCC
|
||||
</value>
|
||||
</data>
|
||||
<metadata name="tt.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<metadata name="folderBrowser.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>182, 17</value>
|
||||
<metadata name="saveFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>76, 17</value>
|
||||
</metadata>
|
||||
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>313, 17</value>
|
||||
</metadata>
|
||||
<metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>45</value>
|
||||
</metadata>
|
||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
AAABAAIAMDAAAAEAIACoJQAAJgAAACAgAAABACAAqBAAAM4lAAAoAAAAMAAAAGAAAAABACAAAAAAAAAk
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAQAAAAQAAAAJQAA
|
||||
ADcAAAA+AAAAOAAAACoAAAAYAAAACwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAUAAAApAAAAVAAAAGIBAQFNAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAASAAAAOgAA
|
||||
AFkAAAA6AAAAMQEBAUYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
|
||||
AAoAAAAkAAAAUQAAAHkAAACJAAAAhQAAAHMAAABTAAAAMAAAABUAAAAGAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAIAAAAkAAAAaQEBAZYCAgLaAAAAWgAAAAsAAAABAAAAAAAAAAAAAAAAAAAABwAA
|
||||
AB8AAABMAAAAfwAAAHkAAAA8AgIAwgEBAWkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAQAAAA8AAAA9AAAAgwAAALMAAADFHRcU3QAAAMMAAACgAAAAdwAAAEUAAAAeAAAABwAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASAAAAUgAAAJgDBATpAgIG/wEAAI8AAAAYAAAABAAA
|
||||
AAIAAAAOAAAALgAAAGIAAACVAAAApgEAAJUEBADsAwQK/wAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABYAAABPAAAAngAAAMx3YFX3jXZv/5RuY/9mT0X2GxENygcG
|
||||
BYsAAABKAAAAGgAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAKAAAAQAAAAJMBAQHRBApN/wQK
|
||||
U/8CAADQAQEARwAAACkAAABIAAAAeQAAAKMAAAC5AgAA1QQGJf8FC1v/AQEHrAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABwAAACEAAABcAAAApQICAtOFc2z8hnJt/5h6
|
||||
cf+hfXL/mHty/3VkXewZExGLAAAAOQAAAAwAAAABAAAAAQAAAAIAAAAFAAAACAAAABAAAAAqAAAAYwAA
|
||||
AKABAAC8AwAV+QUWxv8ED4P/BgcX/AEAALAAAACWAAAAsQAAAMkEBArzBAli/wMOtf8CCVD/AwIAbAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAEAAAADQAAAB1AAAAsgcE
|
||||
BNmHcGj8mYiB/6GMhf+lkIj/moiB/5qIgP9dTUfqAgICYAAAACAAAAAGAAAABAAAAAoAAAAZAAAAKgAA
|
||||
AEEAAABqAQEBmgEBAbkHCw7dBgcH+QEAi/8FHf//AgG0/wIABP8GFRntBiIw6wcYHf8BAET/AgR6/wMF
|
||||
X/8DACD5AAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAFAAAAGwAA
|
||||
AE8AAACXAAAAxQwLCuGSfHX9momC/5yLg/+cjIX/mYaA/5aGf/+MdWv/GhUSoQAAAEAAAAAXAAAAEAAA
|
||||
AB8AAAA+AAAAZgAAAIwAAACtCQkJx0A5N+UYdqT/JsXu/wgdZ/8AAIr/Cyx0/x6Rwf8luf3/Jbv//yCd
|
||||
3P8TYIj/FWaB/xdtjf8EDhfkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAEAAAAIAAAAKQAAAG4AAACxBwYD1HdiWPmcioL/mYiA/56Nhf+ejoX/lYV//5WGf/+Wgnv/U0M96AAA
|
||||
AHUAAAA4AAAALwAAAEYAAABzAAAApAAAAMIkGRHhIBkT6F1WVfYqPUb/KM3//yOt5f8NN0b/J8r+/ybE
|
||||
+P8ZfqT/G4ay/x6Tz/8hpej/IKTl/xuLwf8FExmmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAIAAAANAAAANwAAAIQAAAC+IhoW5Jt2av+Qfnf/no6G/5WHgP+vnpb/koJ7/5iG
|
||||
f/+Zh4D/k4B6/kU4M8UAAABvAAAAagAAAIcAAACsAAAAzAMDAt+FW0z8fV5R/VtQS/2PgHn/UUhH/yKV
|
||||
tf8z////I62//wcXX/8CBMz/AABw/w9HXv8muv3/Iq30/xh0p/8BAABfAAAABAAAAAIAAAABAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAYAAAAWAAAASAAAAJQAAADESzkz86CCd/+mlI3/rJyT/4Z5
|
||||
cf+djIX/m4qD/5CAef9xZF7/jHx1/3BiWe0GBQSzAAAAsAAAAMQBAQDWCgUE5U83KfaCa2D/lH11/3hp
|
||||
Y/+QgHn/noyF/xQODf8SU4X/CBuY/wUK//8BAOn/Cypv/yfC5v8luvf/IJvN/yKx+f8MKzrlAAAAIgAA
|
||||
ABAAAAAHAAAAAwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAwAAAAqAAAAZgAAAKgAAADMVEdA+LKg
|
||||
mP+pmZH/rp+U/4Z3b/9+cGr/joB5/4R3cf9zZ1//dmhi/4p5cv8fHRjlAAAA3AYEBOQgGhfzV0U4/pqA
|
||||
df+wnpX/no6F/4V1bv9yZF7/ERIX/wUNzf8AAJ//AgK+/wAA8v8LJlr/K9bh/y/w//8NO0r/EEh+/ynZ
|
||||
//8SVHj/AAAAywAAAEgAAAAnAAAAEgAAAAQAAAABAAAAAAAAAAAAAAABAAAABAAAABcAAABIAAAAjwAA
|
||||
AMAAAADZZlxV+rSkmv+4qZ//oZGJ/419dv+QgHn/eGlh/35waP+Nf3b/emxl/5KCe/9kVEr+GxQO+Ug9
|
||||
OP2Mf3j+loZ+/52LhP+qmpH/oZGI/15STf8ICTL/CB30/wUTzv8il4j/HYac/wgcRf8qz93/NP///xZg
|
||||
av8AAJb/D0W8/y3h/f8TWZ7/AQBY/wYEAPABAQCJAAAAQwAAAB0AAAAIAAAAAAAAAAAAAAABAAAACQAA
|
||||
ACgAAABoAAAArQAAANCCaV74pJSN/8i4rf+omY//koF6/4t7dP9+b2j/koB5/5uJgv+UhHz/iXlx/3Bh
|
||||
XP9lW1f/UEM8/4F0bf+jk4r/m4qC/52Nhf+gj4f/OjIs/wgUf/8KKv//AgDw/xlhU/87////L+b//y3g
|
||||
8P8w7v//F2N//wAAqP8BAP//E1SY/y7n//8PPn//AADr/wYWv/8GCCv/AQMEuQAAAEkAAAAWAAAAAAAA
|
||||
AAAAAAAEAAAAEQAAADwAAACCAAAAvCUbGOKhjoT+sKCW/7ionf+Yh4D/gHBp/3hoYP+KeHH/kYF4/5+P
|
||||
h/+Xhn//h3hx/3hoYf+XhoD/cF5V/5WEff+ejYX/nYyF/21hWv8LCQz/ChmV/wop//8IJPr/Ch/z/wcS
|
||||
of8eiZD/Nv///zP///8jrKD/AABe/wYZ//8CAJ3/H4+m/yrT/v8IGoz/BAzS/wUWy/8GFKX/BQYm/wUG
|
||||
BOUBAQFBAAAAAAAAAAEAAAAHAAAAHgAAAFUAAACbAAAAyUc/Ou6ejYX/pJOL/6WUjP+ejoX/iXpz/4t7
|
||||
cv+Xh37/mId//5+Ohv+pmI//koJ5/5GBeP+cjIP/dGNb/4t7dP+bioP/iHx2/zEtKf8hHyT/KipE/yYk
|
||||
Jv8lIiX/ISEp/xkSPP8REA7/Gnh5/zb//f86//D/IqGV/wAAlf8NMYr/Nv///xhkgf8eKzT/KDg//xca
|
||||
Hf8lLDP/ERUd/wYHCu0BAQFxAAAAAAAAAAEAAAAMAAAAMAAAAHQAAAC0AwMD1WleWfidjYT/pZSL/5yK
|
||||
g/+OfHX/hnly/5CBef+Pfnb/m4uA/6aTiP+di4P/moqC/5mJgf+VhX3/lIN7/5eFfv+gjof/nIqE/5iH
|
||||
gP+djYT/kIF4/5CAeP+Le3P/hnZv/4x9df+UhX3/SD04/xA6bf8XW6z/EESi/wYMPv8y+f//JKu7/1uA
|
||||
kv+Nx+P/kcvn/1d4jv9KVmr/LD9N/xIfKacAAAAUAAAAAAAAAAIAAAAQAAAARAAAAJMAAADGKSYj5KWV
|
||||
jP+woJb/pZSM/4V0b/+MfXb/nYyE/5iJgf+UhHv/pI+G/6GRh/+Qf3j/lYR9/6CRiv+ZiID/mYeA/5mI
|
||||
gf+ci4P/n46G/5iIf/+KenP/gXBo/31tZf+GdG3/iHdv/4d1b/+LhYP/WGRm/wYASP8AAP//BAmf/zHr
|
||||
4f8jrK3/WH6O/3y71P+JxeH/jcjj/4292f9FWWj+JC86+QkPE3EAAAANAAAAAAAAAAIAAAATAAAAUAAA
|
||||
AKIAAADNh3p0/K2dk/+snZL/no2F/4N0bf+RgXr/jXx1/5yLg/+YiID/mYiA/5ODfP+NfHX/mYiB/56M
|
||||
hf+Yh4D/nY2E/5CBeP+Sgnr/loZ+/5qJgf+nl47/nY2E/5SEe/+PfXb/e3Rx/1Zocv9fg5L/Pml+/x4s
|
||||
Pf8OKmv/Ip6E/xhrdf9kjqD/i8zm/4HC3P+Fwdz/iL7X/32xyv8xPkn/Hiw28wUIClcAAAAMAAAAAAAA
|
||||
AAIAAAARAAAATQAAAKEAAADWqZqR/6STi/+ikon/b2Nd/3xqZP9wYlr/fm5n/4p5cv+OfXb/i3t0/4V1
|
||||
bv+MfHX/loR9/5qJgf+WhX3/jn53/4h3b/+Id2//mYmA/6OSiv+hkYn/qJiP/5uNhP9zdnj/T2h6/0uO
|
||||
rf9UlbP/Z7LP/052hv8RMD3/CSPV/woMIf+GxOD/gsbf/3+/3P+Dvdf/erDJ/3epwv9jla//HTxM6wAD
|
||||
BEQAAAAFAAAAAAAAAAMAAAAQAAAASgAAAJ4AAADQopOK/56Mhf+gj4f/kX95/4NzbP+DdG3/fGxl/35u
|
||||
Z/96a2P/dGZf/4R0bf+Nfnb/i3pz/5B/d/+TgXj/nY2E/5+Ohv+di4T/o5KK/6CPiP+fjof/oJGJ/2Vw
|
||||
dv8/X3T/Y6XF/1WiyP9cosb/drzY/3e51P8JD3b/Ch/e/z1WXv9/wNr/gL3W/4C92v+GxN3/baK9/4G8
|
||||
1P9/wuH/ETJIlwAAABQAAAACAAAAAQAAAAYAAAAXAAAAUAAAAKIAAADMjoJ5/6iYj/+qmpH/oI+H/5GB
|
||||
ev+SgXr/lYN8/5GBev+RgXn/koF6/41+dv+Le3L/jXdt/4x6c/+XhX3/mYeA/5iHgP+ejYX/opKJ/5qK
|
||||
gf+NfnX/a3By/zhhdv9orsv/YKvP/0uZv/9krc3/c7zZ/3u72P8sP1P/Cg8t/2qbrv9zrsf/e7TN/4W/
|
||||
2P+FwNv/erbR/3Oiwv9pqsf/AwkOUgAAAAgAAAABAAAAAwAAAA0AAAAoAAAAZQAAAKwAAADQm4yE/7Sl
|
||||
mv+klIv/oI+H/5iGgP+Le3T/lIN8/5ODfP+Ug33/lIJ7/5iHf/+ch3//kX54/3JjXf+Ugnz/loV+/5WE
|
||||
ff+ai4L/jHx0/4NzbP+HhYP/R2p//1iny/+Iyeb/O3Wo/0+fwv9vvNv/eL/c/3m72P9LcH7/DAoA/4jG
|
||||
3v93uNH/fL3X/4zD2/9/udX/f8De/4y+1/87cJDxAQIDLgAAAAcAAAAAAAAABwAAABwAAABKAAAAiQAA
|
||||
AL4AAADap5iP/66elf+hkIj/oI+I/5SDfP+Qf3j/koB5/5KAef+aioL/lYR8/56Ohf+ci4T/mIZ//4Ry
|
||||
bP+RgXr/momC/458df97bmX/gGRU/4l2bP9Qh6b/XqrO/2Oozf9hp8v/Ya3O/2q72v94vdz/gcbi/3y9
|
||||
2/9nnbD/U3OB/4zN5/+Bw9z/gL7a/32zyf92sMn/iMfg/3251f8pUWjIAQEBIQAAAAIAAAAAAAAADQAA
|
||||
ADQAAAB1AAAAsAAAAM8pIyDsrJuS/56Nhf+ejIX/k4J7/4Z1bv+Pfnf/kYF6/4d1b/+cjIP/mouD/5qI
|
||||
gf+UhH3/i3pz/4t5cv+XhX7/koB5/2teVf94fH//dK/I/2e42P9RkL7/YrDR/1qoyf9eqsv/WqbJ/3bB
|
||||
3v97w9//fcTh/32+3P+DxN//g8Db/4TJ4/9/v93/gbzX/3Kmv/9qqMD/i7/b/1N/p/8ZLjp9AgQEFgAA
|
||||
AAAAAAAAAAAAGAAAAEwAAACWAAAAxickIemAcWj/loV+/4t5cv9/bmf/fW1m/3BjW/96aGL/bmBZ/31t
|
||||
Zv+Ne3X/koF6/4x8df+FdW7/i3t0/5SCe/+Qf3j/gnFq/2trav9rtdT/bLTU/2KjyP9tt9f/X6XI/2Ow
|
||||
zf9Zp8r/Z7DQ/3m/3v+Axd//fL3b/3/B3v+IzOb/h8nk/4rL5P+ExeP/hMXe/2qeuf92scb/oc7q/0yC
|
||||
pv8OHihoAQEBDQAAAAAAAAAAAAAAJwAAAGMAAACqBwYG03FjXvqTgnv/bl9Y/3dnYP91Z2D/d2dg/3Bg
|
||||
W/98bGX/gnNs/3trZP+BcGj/fGxk/3NlXv+EdG3/lIV9/6COh/+NfHX/ZF5a/0p5nP9ajar/WJO9/3K+
|
||||
2v9/vdz/YKPG/2muzv9cqcn/ZbHR/3K72P9+wN3/hcXi/4fI5P+Jy+T/f8Dc/4fF3/+NzOX/iMbf/3m3
|
||||
0f9nlrT/b5uz/yhVb+YFCw5KAAEBCQAAAAAAAAAAAAAAQAAAAIMAAAC7CAUF21BEPv5uYFj/hndw/4l6
|
||||
cv+KenT/momB/5KBev+RgXr/k4F6/5mJgv+Tgnr/iHdw/4p5c/+ThH3/m4yF/6CPiP+CdXH/TnKL/0tv
|
||||
k/8hITb/M0Zh/2OjyP90u9j/abHO/2etzf9cqMn/Z7HR/3e92f95u9j/eb7b/5PV8P+Mzeb/fsPd/3/D
|
||||
3f+Szeb/h8Lf/3/A3v+Mu9T/RnGF/hEiMcwAAABAAAAABwAAAAAAAAAAAAAAXgAAAKQAAADMKCUj6ZmH
|
||||
gP+ejIX/lIN8/5iHf/+YiH//mYeA/5OCe/+UhH3/hXRu/4x6dP+SgHn/mYeA/5qJgf+bioP/loV+/4h3
|
||||
cf9bXl//bLrc/3S/4P9LdJj/KiNI/z1ehf9mr9L/d77b/1uoy/9Vo8b/bLDN/3q/3P97vdr/hMrj/5LQ
|
||||
7P+Oz+v/iMzm/4TF3/+Gwdz/hMbh/4rO6P+Oxd7/PGyF/hocHNUCAwNeAAABEQAAAAEAAAAAAAAAdQAA
|
||||
ALUAAADekIB7/pODev+ejob/mIeA/6iXj/+jkor/mIZ//5KAef+RgHn/jn12/5qIgf+cioP/no2F/6OR
|
||||
iv+hkYj/iHdw/2JVTf9NfJX/YqrR/3O31/93weH/VoKj/2+y0f9ppM3/ebvb/1Kfxf9nsdD/YKPG/3G3
|
||||
1v96vNn/gsTg/4rL5/+FyuT/gsTh/4jK5v+Fw93/d7/b/5zT7/97r8//Y6vF/zVZaNwRGx5dAAABEgAA
|
||||
AAIAAAAAAAAAiQAAAL8jHxzoq5yR/56Nhf+hkIj/rJyT/6mZkP+qmpH/m4uD/5KBev+WhX3/kH55/5WD
|
||||
fP+VhH3/oo+J/6iXj/+cjIP/c2Ja/3xwaP9WncX/abLS/3O62f9qtNT/d8Hd/3vD4P+MxuP/Y6bM/1up
|
||||
yv9qtdT/ZK3M/3jA3f95wN//hMrl/4rM5/+Ky+X/hcbk/4rO6P98u9v/hMni/6zZ9f9km77/K1V37gkQ
|
||||
FGoBAQEHAAAAAAAAAAAAAAAAAAAAngAAAMlZUEzxoI+H/6uckv+omI//oZCJ/6STi/+ikIr/nImD/5aE
|
||||
ff+aiIH/j313/4x7dP+UhH3/m4mC/6SUi/+Ugnv/cVxO/3ymuv9KibL/dLnZ/3rB3v9fpsj/b73b/3G5
|
||||
1v99x+P/ZLLQ/02Xwf9rtNj/fMXh/3O52P91vt3/eb7b/37A3f+HyOL/js/p/4/Q6v+Dx+T/erPX/5XL
|
||||
5/9Jl7v+GjJBrgEBAQoAAAAAAAAAAAAAAAAAAAAAAAAApw0NDdaIeHD9kX95/6qbkf+unpX/j395/459
|
||||
dv+pmJD/n46H/56Ohf+gkIj/kH95/4x8dv+JeXL/kIB4/5WFfP9yZmH/b36H/2aqzv9nr8//esLe/3m/
|
||||
3v9rtdT/arbW/2iz0P9rvdr/UqbG/2q41P9gqs3/crjX/2Spzf+AyeT/f8Hd/3m+2/+Cx+H/k9Ht/4rH
|
||||
5P+Fx+T/mc7p/2amxP8nSF36AAAAawAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqBUSEN2Ug3r9lYV8/6OT
|
||||
iv+klIv/l4V+/4p6dP+omI//p5aO/56Ohf+WhX3/j394/3hoZP9uXFb/emtk/3NnXv9ydXn/bLXV/2Sp
|
||||
zv92vdz/fcbh/3zE4f9xu9v/Z67Q/16kx/9QnMD/Xq/O/2Wy0f94wN3/c7jV/3q83P9encj/gsrj/33C
|
||||
3v+CxN//jMjk/4bI4/+Lz+n/lM/q/0d+nf8sLiv3BQYHTwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArg8P
|
||||
DdqSgX38qZiQ/6WVjP+ci4P/lYR9/419d/+KeHH/opGJ/5WFfP91YlX/hGpX/2ZkY/9HUlj/OFVn/1eQ
|
||||
tf9fpcj/Y6jP/3W+3f96wt7/drrX/36/3f9+x+L/bbjV/2241f9hsc7/ZrTS/2u41P92udX/h83o/4fI
|
||||
5f97wd3/dr3a/3K72/+DxuL/hsfj/3jA3P+c0+//fLPT/2avyf5HfZLyHzI3SwAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAux0aGuGWhH39rp6V/6qbkf+Yh3//koB6/5B/ef+Rf3j/fWtk/4huXf+jrK//d7jX/2Ow
|
||||
1v9kstb/Up3I/2Wlyv9krdD/Y6/S/2y52f9ut9b/er3Z/4PG4v99wt7/f8Xh/3jE4P91wd7/bbrW/3W9
|
||||
2v99w97/hMnl/4jL5/+BxuD/i8/p/3m+3v+Izef/fbzc/4XK4/+s2fX/ZZ7C/y1dhOwTJzK9FxobTQAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAxzo0Muqbi4T/saKY/7Cgl/+fjYb/kIB6/49+d/+Bcmn/fGxg/3u7
|
||||
1P9sqc3/Z6vP/2Kny/9vuNf/abfW/3O72P95w9//cLjV/3C+2v9wuNX/gsTh/33A3/9wudb/db7b/2i1
|
||||
0v9uutf/cLzY/4HG4v+P0er/icvk/4XH4v+Ozej/itDr/43S7P+O0Ov/hcnm/3q02P+TyeX+SZu//yNH
|
||||
XKEHBwcnCgkITAAAAAEAAAAAAAAAAAAAAAAAAAABCwsNtZKEfPicjIX/sqKY/66elP+hj4n/opGJ/5GC
|
||||
ef+OfnP/icbj/1qdw/9ZmL//f8Xh/3fA3f91wd3/eb7d/4PL5f+EyuP/fsbg/3e+3f93vNv/gMHe/3u9
|
||||
3P9wt9T/dbnW/2m21f9rtNP/cbnW/3693f9dh7T/Ypa8/4bH4f9zp8f/gsLf/47M6P+R0On/jtDs/5jP
|
||||
6v9mp8X/GTJFrgAAACYCAgISAgMDEwYGBxAAAAAAAAAAAAAAAAAAAAABExMTgJCGffWdj4f/t6ee/6iX
|
||||
jv+tnJT/pZWM/5KBc/+WtML/ZqbL/2Gkyv9xvt3/fMXh/3rB3v93vdz/g8nl/37E4P90vdn/ecDd/3nA
|
||||
3f97vdz/d7jV/3a71/96wd7/fr/d/3G41f9zuNX/hcfk/1yMtP9Fa5n/LUd8/2yhxP9RcJj/cqPG/4nC
|
||||
3/+MyuP/hc3n/5PO6v9Hf5//AwUFYgAAAB8AAAAHBAMDCAsLDBoEBAQHAAAAAAAAAAAAAAAAAAAADwcH
|
||||
BzMPDg1MPTk2ro6EevKbjYT/o5SK/6GKev95vNn/aqrO/3O61/99xOP/esLe/37E3/96xd//e8Pf/3i9
|
||||
2v9qstL/a7bT/3W+2v9wtNH/dLnV/2+20/9yvdf/eLnW/36+2/+Mzur/i9Pt/16cxP85XpP/Q1mD/2CV
|
||||
vf9roMP/jMfi/4nF4f+DyOL/hMnm/2yfwv5lvNn/TImj2wAAABMAAAADAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAABAAAABgAAABYAAAA4FBIQlIKCgux4qsn3dKvM/H/A3f+Ky+j/i8nl/4HG
|
||||
4v94vdz/gsLf/4TI4v90u9j/dbva/3W51v9xuNf/bbXS/3O82f99vtz/ervZ/4jK5f+T1fL/iMvn/3m8
|
||||
3v98vt3/TnWg/1qQvP96ttf/h8jk/1aErf9qs9P/n9Tv/2ufv/8lUoL+ECQ0jwAAAAwAAAABAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAEAAAACgAAAB4OEBFRHiktejZN
|
||||
WKdagZTVaY2i4GiRpPF+ssv/kdPv/5DV8f+Fy+f/hMPf/4bI5P9/xuP/ebzb/3m92v94vNn/fMHd/4/Q
|
||||
6v+W1PD/l9jy/4fF4f9HcqH/aqHI/3Ot0f9Mf6v/h8Xi/3y93f8lTIL/iL/f/3Cx1P8mTG3QAAAAHwAA
|
||||
AAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAABAAAAAwAAAAcDBAQYBQYHJQYICTsNEhVlJTM8w1Buf/9Zeo7/i87q/4PE4P+SzOn/icbj/3e4
|
||||
1f97wt//isbi/5PR7f+b2PX/ldPp/4S72v9hmcL/ZqHI/1mMuv+Gw+D/aaPK/1CLuf9hibj/ic3n/kh4
|
||||
qf8OGCV2AAAADQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAFAAAADgAAADIAAAByJzlD0Xmz
|
||||
zvx/vNn/gb/e/3W20/+Exd//k8vn/5nU7/+V0Oz/mNTw/5/a8v9xrtL/UIW0/1WBsP80YJn/h8Pi/4fN
|
||||
6P9nmsb/SYqz/1+WsvIHCw4+AAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAQAAAAPAAAAHxAVGmwxSVajUHqN00Jkdsg8WWW2NlFewXOftfSc1PD/kc7r/4O72/9zrtH/bpzE/2OL
|
||||
u/9Zi73/ib3d/2WSvf9oiLf/TYCr/z9phdIDBQcsAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAMAAAAHAwQFFAEBARUAAAAUAAAAJQYHCFUyQkquUnmO7m+i
|
||||
yf9oosb/cKPC/1N4rP9ZgKz/isPg/2SXwv9Yibf/OnGf/xkoSawAAAAbAAAAAQAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAA
|
||||
AAcAAAAPAAAAGwUGB2UGBgiAIC40vHGbv/pnm8H+jcfg/1yJvf+Bt9f/T4Op+Q8bInUAAAANAAAAAQAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAALAAAAGgkLD1UfLDWMITVCrT1ced93pMf/c6bE/BMd
|
||||
IVUAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAIAAAAIAAAAFgID
|
||||
AysUHSFgHC02gQAAAAoAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AB/gfgP
|
||||
AAD8AD+AcA8AAPwAH8AADwAA/AAPgAAfAAD4AAAAAB8AAPgAAAAAHwAA8AAAAAA/AADwAAAAAD8AAPAA
|
||||
AAAABwAA4AAAAAABAADgAAAAAAAAAMAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAIAAAAAAAAAAgAAAAAAA
|
||||
AACAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAEAAAAA
|
||||
AAAAAwAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAABAAAAAAAAAAEAAAAAAAAABwAAAAAAAAAP
|
||||
AAAAAAAAAB8AAAAAAAAAHwAAAAAAAAAfAAAAAAAAAB8AAAAAAAAADgAAAAAAAAAOAAAAAAAAAAcAAAAA
|
||||
AAAAPwAAwAAAAAA/AADwAAAAAH8AAP8AAAAA/wAA//gAAAD/AAD//wAAAP8AAP//wAAA/wAA///+AAD/
|
||||
AAD////wAf8AAP////wB/wAAKAAAACAAAABAAAAAAQAgAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAABAAAAEQAAADsAAABeAAAAXwAAAEIAAAAeAAAACAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAFQAAAF8CAgKIAAAAMAAAAAMAAAAAAAAAAAAAAAQAAAAhAAAAXQAAAFMBAQB6AQEBLAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAmAAAAgwAAALwdFxTdAAAAsgAAAHcAAAAyAAAABwAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAJAAAAUgICAsECAgb/AQAAVAAAAAQAAAAIAAAALgAAAHwAAACmAgIAwQME
|
||||
Cv8AAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABgAAADkAAACiQTYw5Yp0bv+ObWP9WkVA5SYg
|
||||
HJQAAAAqAAAABQAAAAEAAAACAAAABAAAABIAAABSAQEBsAQFMPwEC2f0BAQLogEAAG4AAACVAQECxgMF
|
||||
MeoEC2L/AwIEjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAQAAAAVQAAALJIOzbrmYiB/6OO
|
||||
h/+aiIH/fGtk9QICAmAAAAATAAAABAAAABIAAAAqAAAAVgEBAZoFBgjLBgcH+QMPxf8CAbT/BAsO9gYi
|
||||
MOsEDDH/AgR6/wMDP/wAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAACIAAACCAwICzWxd
|
||||
V/aaiYH/nY2F/5eGgP+UgXn/Ny0nxQAAAEIAAAAgAAAARgAAAIUJBgS4FBEO2DdQXvcnyff/DkGI/xl7
|
||||
uf8ho9f/IKHZ/x2Ox/8bhbP/DkZf4wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAANwAA
|
||||
AKEiGhbklnpx/56Ohv+ik4v/koJ7/5mHgP+TgHr+Ih0amgAAAGoAAACaAAAAzEQvJ+59XlH9dmlj/lFI
|
||||
R/8rytr/I62//wUOlv8AAHD/G4Gu/yKt9P8MOlSvAAAABAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAgAA
|
||||
ABUAAABXAAAAs09BOvaplIz/rZ6U/4p8dP+VhX7/f3Fq/4FybP9IQDrhAAAAxgoJB90wJh3yh29k/ZmG
|
||||
ff+AcWr/WE9O/wscgP8FD6v/BQzN/xuAqP8iqsr/GHKm/xqDq/kAAAB3AAAAIgAAAAsAAAACAAAAAAAA
|
||||
AAEAAAAEAAAAMAAAAI8AAADNZlxV+rannf+hkYn/j394/3hpYf+GeG//emxl/3trY/8bFA75a15Y/paG
|
||||
fv+kk4v/oZGI/zMuQP8IHfT/FFWr/x2GnP8ZdpH/NP///wswgP8PRbz/IJ3O/wEAWP8EAwC9AAAAQwAA
|
||||
ABMAAAAAAAAAAgAAAA0AAABUAAAAtVNGP+qqmpL/sKGX/4l5cv+Dc2z/koF5/5qJgf+IeXH/emtm/2BR
|
||||
Sf+Wh3//nIuE/25iXf8iJmH/CSPe/wYQ8v8ff6H/M/P//y3f5P8MMm//AwfR/xlyn/8chcL/Agbf/wYS
|
||||
l/8DBBXcAgICYgAAAAAAAAAEAAAAHgAAAHgAAADJcmZg96STi/+ikYn/iXpz/5GBeP+Yh3//pJOL/5KC
|
||||
ef+Xh37/dGNb/5ODfP+IfHb/KSYn/yoqRP8mIyb/ISEp/xURJf8aeHn/OP/3/yKhlf8HGZD/Nv///xtI
|
||||
W/8oOD//HiMo/xEVHf8DBQWvAAAAAAAAAAgAAAA6AAAAoRcVEt2XiH/+pZSM/49+eP+Sg3v/k4R7/6CN
|
||||
g/+ejIP/mIeA/5qKgv+XhX7/nIqD/56Mhf+Whn7/iXlw/4h4cP+Hd2//jX95/1BRT/8MJpn/Cieh/yOo
|
||||
s/8+laX/fLLL/4/K5f9deY//KTZD/AcMEE8AAAAAAAAACwAAAFAAAAC4h3p0/K2dk/+ejYX/int0/418
|
||||
df+aioL/mYiA/5CAef+ZiIH/m4qD/52NhP+Rgnn/loZ+/6GQiP+djYT/koF5/3t0cf9bdoL/Pml+/xYr
|
||||
VP8inoT/Pn2L/4vM5v+Dwtz/iL7X/1d4iv8eLDbzAwQFMgAAAAAAAAAKAAAATAAAALqml47/oZGI/4Bx
|
||||
a/99bWb/fW1m/4R0bf+AcWr/iXly/5F/eP+VhHz/loZ+/5OCev+ejoX/oZGJ/6SVjP9tdXr/WYeg/1Wa
|
||||
vP9vt9T/OFyE/woh2v9Teo//gcLb/4LA2/90qcP/d6/K/xc2S8EAAQEYAAAAAQAAAA8AAABQAAAAt46C
|
||||
ef+pmZD/oI+H/5KBev+Vg3z/kYF6/5KBev+MfXT/jXdt/5KAeP+Zh4D/m4qD/6KSif+UhHv/a3By/1CI
|
||||
of9gq8//WKPG/3O82f9UfZb/Cg8t/2+lu/97tM3/hcDa/3q20f9upsX/AwkOUgAAAAUAAAAFAAAAJwAA
|
||||
AHcAAADFoZKK/6qakf+gj4j/koF6/5OCe/+VhH7/lYN8/5yKgv+Vgnz/h3dw/5iHgP+Pf3f/hnBk/3l+
|
||||
gf9Tiqf/abDT/06Ru/9otdX/fcPf/2qiuf8wP0H/hMTd/36+2f+AuNH/hMTf/1uPqu4BAgIoAAAAAwAA
|
||||
AA0AAABVAAAAsBUREd6sm5L/no2F/5OCe/+LenP/kYF6/5KBef+ai4P/l4Z//4t6c/+Rf3j/koB5/3Jt
|
||||
av90r8j/XKTL/2Kw0f9cqcr/WqbJ/3nC3/99xOH/gMHe/4PA2/+CxOD/gbzX/26nwP+Lv9v/NlZxvgIE
|
||||
BBYAAAAAAAAAIAAAAHwDAgLNal9Z+YJya/9+bmf/empj/3ZmYP94amP/gnFq/4d3b/+Dc2z/kIB5/5WD
|
||||
fP9zaGL/X4qh/2Kkyf9xttb/YKTH/2GszP9msdH/e8Dd/4HB3/+GyeP/g8Xg/4nJ4/+Gxt//cKjC/4i1
|
||||
z/8iQFOmAQEBCwAAAAAAAABAAAAAnwgFBdtfUkv/hndw/4p6c/+aiYH/koF6/5OBev+Whn7/iHdw/49/
|
||||
eP+bjIX/kYJ9/05yi/82SGX/M0Zh/2yv0P9psc7/YqvL/2ex0f94vNn/eb7b/5DR6/9+w93/icji/4fC
|
||||
3/+Gvtn/RnGF/gkRGYYAAAAHAAAAAAAAAGoAAADBXVJO9JuKgv+WhX7/n4+G/5mHgP+Tgnv/inly/5WD
|
||||
ff+cioP/n46G/49+d/9lam3/Z7LX/2urzP9AU3b/X5m+/3i92/9bp8r/ZqrK/3m82v+Dx+L/jM7p/4XI
|
||||
5P+GxeD/fsPe/4zG4f9QjKb/GCUqnAAAARIAAAABAAAAiREQD9SrnJH/oI+H/6yck/+qmpH/m4uD/5SD
|
||||
fP+Qfnn/lYR9/6KPif+ikon/c2Ja/2mHl/9pstL/b7fX/3fB3f+ExeL/Y6bM/2Ovz/9krcz/ecDe/4TK
|
||||
5f+KzOb/hcbk/4PF4v+EyeL/iLra/ytVd+4FCQs5AAAAAAAAAAAAAACjPDYz5JmHgP+rnJL/mIiB/6CP
|
||||
h/+ejIX/nIuD/5B+eP+Ofnf/loV9/5CBef9wbWv/ZaPD/3e+3P9wt9b/bbrZ/3G82f9brMv/YazP/3e/
|
||||
3P9zu9r/fMDc/4HE3/+R0Ov/icrm/4rB4P9blLH+DRohjQEBAQMAAAAAAAAAAAAAAKhVSkbtlYV8/6SU
|
||||
i/+XhX7/mYmC/6eWjv+aioH/j394/3NiXf96a2T/c25s/2y11f9ts9X/fcbh/3fA3v9nrtD/V6DE/16v
|
||||
zv9vudf/c7jV/2yt0v+CyuP/gMPf/4zI5P+JzOb/lM/q/zlWY/sFBgdPAAAAAAAAAAAAAAAAAAAAtVZM
|
||||
SO2sm5P/oZGI/5SCfP+PfXf/kH53/46BeP9+kZf/Xoaa/0V5mP9gosb/Y6zR/3O82/94vNj/f8Tg/3a/
|
||||
2/9vvNn/arfU/3W92f+Gy+f/g8fj/4HG4v9+xOH/gsLg/5LO6f9xqcv/PG2F5xsmKUwAAAAAAAAAAAAA
|
||||
AAAAAADHa19a9bGimP+ol4//kIB6/4h4cP98bGD/dLLR/2erz/9psNH/abfW/3a/3P9wuNX/cLvY/4LE
|
||||
4f93vdv/db7b/2u41f9wvNj/iMzm/4nL5P+KyuX/itDr/47R7P+Fyeb/h7/f/0mbv/8VJzJkCgkITAAA
|
||||
AAEAAAAAAAAAARAQEJuXioL7taWb/6qZkP+kk4v/ko6J/3i21/9ipsv/fsXh/3jA3f9+xOH/f8bh/3zD
|
||||
3/95vt3/fL3a/3e82v96vNr/brfV/3vA3f9gj7j/SG+c/26gwf96s9P/jsrl/4rP6v92sc//DhwliAEB
|
||||
ARgDAwMOBgYGDQAAAAAAAAABAAAADwsLCkA9OTaulImA+aOUiv+No6r/aqrO/3i/3f96wt7/fMXf/3vD
|
||||
3/9xuNb/a7bT/3O51v90udX/cbrV/3i51v+FxuP/i9Pt/0x9rP9DWYP/ZpvA/4zH4v+Gx+L/hMnm/2mu
|
||||
zv9MiaPbAAAACwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAMAAAAVCgkIT0NPWJVJan27Zpas33mq
|
||||
xPB4ssz8isvn/4TJ5f99v93/e8De/3O51/95vdv/e77b/5HR7f+Q0u3/ca3Q/1yLtP9lncT/h8fj/1mR
|
||||
uP+Uyuf/Snuh9AgSGlcAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
|
||||
AAMCAgIQBQYHJQoND1AlMzzDVXSH/4vO6v+LyOX/icbj/3m92v+KxuL/l9Xx/5XT6f9zqs7/ZqHI/3Co
|
||||
zf9po8r/WYq5/4nN5/4rSGe7AAAADQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAcAAAAuFB0ieE9zhsNonLbpXo+k32SNo+CQxeD9ldHu/4K9
|
||||
3P9fkbz/Un6x/4jA4P9vocn/S4Wv/ypEU4wAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABQMEBRQBAQEVAAAAJRwl
|
||||
KoJSeY7ubKLI/3Cjwv9WfKz/isPg/16Qvf86cZ//DRQlZAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAEAAAABAAAABgAAAA4DAwQ+ERcaa0BccbdWfpDWZY+092GVtvsJDxE3AAAAAQAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABQAAABYLEBJGHC02gQAAAAYAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAADwD4MD8AeAA+AAAAfgAAAH4AAAD+AAAAPAAAAAgAAAAIAAAACAAAAAgAAAAIAA
|
||||
AACAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAAAAAAAAwAAAAMAAAAHAAAABwAAAAIAAAACAAAAD4AA
|
||||
AA/4AAAf/4AAH//wAB///gAf///wPw==
|
||||
</value>
|
||||
</data>
|
||||
</root>
|
||||
470
OpenRA.Editor/LegacyMapImporter.cs
Normal file
470
OpenRA.Editor/LegacyMapImporter.cs
Normal file
@@ -0,0 +1,470 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using OpenRA;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Traits;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
|
||||
namespace OpenRA.Editor
|
||||
{
|
||||
public class LegacyMapImporter
|
||||
{
|
||||
// Mapping from ra overlay index to type string
|
||||
static string[] raOverlayNames =
|
||||
{
|
||||
"sbag", "cycl", "brik", "fenc", "wood",
|
||||
"gold01", "gold02", "gold03", "gold04",
|
||||
"gem01", "gem02", "gem03", "gem04",
|
||||
"v12", "v13", "v14", "v15", "v16", "v17", "v18",
|
||||
"fpls", "wcrate", "scrate", "barb", "sbag",
|
||||
};
|
||||
|
||||
static Dictionary<string, Pair<byte, byte>> overlayResourceMapping = new Dictionary<string, Pair<byte, byte>>()
|
||||
{
|
||||
// RA Gems, Gold
|
||||
{ "gold01", new Pair<byte,byte>(1,0) },
|
||||
{ "gold02", new Pair<byte,byte>(1,1) },
|
||||
{ "gold03", new Pair<byte,byte>(1,2) },
|
||||
{ "gold04", new Pair<byte,byte>(1,3) },
|
||||
|
||||
{ "gem01", new Pair<byte,byte>(2,0) },
|
||||
{ "gem02", new Pair<byte,byte>(2,1) },
|
||||
{ "gem03", new Pair<byte,byte>(2,2) },
|
||||
{ "gem04", new Pair<byte,byte>(2,3) },
|
||||
|
||||
// cnc tiberium
|
||||
{ "ti1", new Pair<byte,byte>(1,0) },
|
||||
{ "ti2", new Pair<byte,byte>(1,1) },
|
||||
{ "ti3", new Pair<byte,byte>(1,2) },
|
||||
{ "ti4", new Pair<byte,byte>(1,3) },
|
||||
{ "ti5", new Pair<byte,byte>(1,4) },
|
||||
{ "ti6", new Pair<byte,byte>(1,5) },
|
||||
{ "ti7", new Pair<byte,byte>(1,6) },
|
||||
{ "ti8", new Pair<byte,byte>(1,7) },
|
||||
{ "ti9", new Pair<byte,byte>(1,8) },
|
||||
{ "ti10", new Pair<byte,byte>(1,9) },
|
||||
{ "ti11", new Pair<byte,byte>(1,10) },
|
||||
{ "ti12", new Pair<byte,byte>(1,11) },
|
||||
};
|
||||
|
||||
static Dictionary<string, string> overlayActorMapping = new Dictionary<string, string>() {
|
||||
// Fences
|
||||
{"sbag","sbag"},
|
||||
{"cycl","cycl"},
|
||||
{"brik","brik"},
|
||||
{"fenc","fenc"},
|
||||
{"wood","wood"},
|
||||
|
||||
// Fields
|
||||
{"v12","v12"},
|
||||
{"v13","v13"},
|
||||
{"v14","v14"},
|
||||
{"v15","v15"},
|
||||
{"v16","v16"},
|
||||
{"v17","v17"},
|
||||
{"v18","v18"},
|
||||
|
||||
// Crates
|
||||
// {"wcrate","crate"},
|
||||
// {"scrate","crate"},
|
||||
};
|
||||
|
||||
static Dictionary<string,Pair<Color,Color>> namedColorMapping = new Dictionary<string, Pair<Color, Color>>()
|
||||
{
|
||||
{"gold",Pair.New(Color.FromArgb(246,214,121),Color.FromArgb(40,32,8))},
|
||||
{"blue",Pair.New(Color.FromArgb(226,230,246),Color.FromArgb(8,20,52))},
|
||||
{"red",Pair.New(Color.FromArgb(255,20,0),Color.FromArgb(56,0,0))},
|
||||
{"neutral",Pair.New(Color.FromArgb(238,238,238),Color.FromArgb(44,28,24))},
|
||||
{"orange",Pair.New(Color.FromArgb(255,230,149),Color.FromArgb(56,0,0))},
|
||||
{"teal",Pair.New(Color.FromArgb(93,194,165),Color.FromArgb(0,32,32))},
|
||||
{"salmon",Pair.New(Color.FromArgb(210,153,125),Color.FromArgb(56,0,0))},
|
||||
{"green",Pair.New(Color.FromArgb(160,240,140),Color.FromArgb(20,20,20))},
|
||||
{"white",Pair.New(Color.FromArgb(255,255,255),Color.FromArgb(75,75,75))},
|
||||
{"black",Pair.New(Color.FromArgb(80,80,80),Color.FromArgb(5,5,5))},
|
||||
};
|
||||
|
||||
int MapSize;
|
||||
int ActorCount = 0;
|
||||
Map Map = new Map();
|
||||
List<string> Players = new List<string>();
|
||||
|
||||
LegacyMapImporter(string filename)
|
||||
{
|
||||
ConvertIniMap(filename);
|
||||
}
|
||||
|
||||
public static Map Import(string filename)
|
||||
{
|
||||
var converter = new LegacyMapImporter(filename);
|
||||
return converter.Map;
|
||||
}
|
||||
|
||||
enum IniMapFormat { RedAlert = 3, /* otherwise, cnc (2 variants exist, we don't care to differentiate) */ };
|
||||
|
||||
public void ConvertIniMap(string iniFile)
|
||||
{
|
||||
var file = new IniFile(FileSystem.Open(iniFile));
|
||||
var basic = file.GetSection("Basic");
|
||||
var map = file.GetSection("Map");
|
||||
var legacyMapFormat = (IniMapFormat)int.Parse(basic.GetValue("NewINIFormat", "0"));
|
||||
var XOffset = int.Parse(map.GetValue("X", "0"));
|
||||
var YOffset = int.Parse(map.GetValue("Y", "0"));
|
||||
var Width = int.Parse(map.GetValue("Width", "0"));
|
||||
var Height = int.Parse(map.GetValue("Height", "0"));
|
||||
MapSize = (legacyMapFormat == IniMapFormat.RedAlert) ? 128 : 64;
|
||||
|
||||
Map.Title = basic.GetValue("Name", "(null)");
|
||||
Map.Author = "Westwood Studios";
|
||||
Map.Tileset = Truncate(map.GetValue("Theater", "TEMPERAT"), 8);
|
||||
Map.MapSize.X = MapSize;
|
||||
Map.MapSize.Y = MapSize;
|
||||
Map.TopLeft = new int2(XOffset, YOffset);
|
||||
Map.BottomRight = new int2(XOffset + Width, YOffset + Height);
|
||||
Map.Selectable = true;
|
||||
|
||||
if (legacyMapFormat == IniMapFormat.RedAlert)
|
||||
{
|
||||
UnpackRATileData(ReadPackedSection(file.GetSection("MapPack")));
|
||||
UnpackRAOverlayData(ReadPackedSection(file.GetSection("OverlayPack")));
|
||||
ReadRATrees(file);
|
||||
}
|
||||
else // CNC
|
||||
{
|
||||
UnpackCncTileData(FileSystem.Open(iniFile.Substring(0, iniFile.Length - 4) + ".bin"));
|
||||
ReadCncOverlay(file);
|
||||
ReadCncTrees(file);
|
||||
}
|
||||
|
||||
LoadActors(file, "STRUCTURES");
|
||||
LoadActors(file, "UNITS");
|
||||
LoadActors(file, "INFANTRY");
|
||||
LoadSmudges(file, "SMUDGE");
|
||||
|
||||
foreach (var p in Players)
|
||||
LoadPlayer(file, p, (legacyMapFormat == IniMapFormat.RedAlert));
|
||||
|
||||
var wp = file.GetSection("Waypoints")
|
||||
.Where(kv => int.Parse(kv.Value) > 0)
|
||||
.Select(kv => Pair.New(int.Parse(kv.Key),
|
||||
LocationFromMapOffset(int.Parse(kv.Value), MapSize)))
|
||||
.ToArray();
|
||||
|
||||
Map.PlayerCount = wp.Count();
|
||||
|
||||
foreach (var kv in wp)
|
||||
Map.Waypoints.Add("spawn" + kv.First, kv.Second);
|
||||
}
|
||||
|
||||
static int2 LocationFromMapOffset(int offset, int mapSize)
|
||||
{
|
||||
return new int2(offset % mapSize, offset / mapSize);
|
||||
}
|
||||
|
||||
static MemoryStream ReadPackedSection(IniSection mapPackSection)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 1; ; i++)
|
||||
{
|
||||
string line = mapPackSection.GetValue(i.ToString(), null);
|
||||
if (line == null)
|
||||
break;
|
||||
|
||||
sb.Append(line.Trim());
|
||||
}
|
||||
|
||||
byte[] data = Convert.FromBase64String(sb.ToString());
|
||||
List<byte[]> chunks = new List<byte[]>();
|
||||
BinaryReader reader = new BinaryReader(new MemoryStream(data));
|
||||
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
uint length = reader.ReadUInt32() & 0xdfffffff;
|
||||
byte[] dest = new byte[8192];
|
||||
byte[] src = reader.ReadBytes((int)length);
|
||||
|
||||
/*int actualLength =*/
|
||||
Format80.DecodeInto(src, dest);
|
||||
|
||||
chunks.Add(dest);
|
||||
}
|
||||
}
|
||||
catch (EndOfStreamException) { }
|
||||
|
||||
MemoryStream ms = new MemoryStream();
|
||||
foreach (byte[] chunk in chunks)
|
||||
ms.Write(chunk, 0, chunk.Length);
|
||||
|
||||
ms.Position = 0;
|
||||
|
||||
return ms;
|
||||
}
|
||||
|
||||
static byte ReadByte(Stream s)
|
||||
{
|
||||
int ret = s.ReadByte();
|
||||
if (ret == -1)
|
||||
throw new NotImplementedException();
|
||||
return (byte)ret;
|
||||
}
|
||||
|
||||
static ushort ReadWord(Stream s)
|
||||
{
|
||||
ushort ret = ReadByte(s);
|
||||
ret |= (ushort)(ReadByte(s) << 8);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void UnpackRATileData(MemoryStream ms)
|
||||
{
|
||||
Map.MapTiles = new TileReference<ushort, byte>[MapSize, MapSize];
|
||||
for (int i = 0; i < MapSize; i++)
|
||||
for (int j = 0; j < MapSize; j++)
|
||||
Map.MapTiles[i, j] = new TileReference<ushort, byte>();
|
||||
|
||||
for (int j = 0; j < MapSize; j++)
|
||||
for (int i = 0; i < MapSize; i++)
|
||||
Map.MapTiles[i, j].type = ReadWord(ms);
|
||||
|
||||
for (int j = 0; j < MapSize; j++)
|
||||
for (int i = 0; i < MapSize; i++)
|
||||
{
|
||||
Map.MapTiles[i, j].index = ReadByte(ms);
|
||||
if (Map.MapTiles[i, j].type == 0xff || Map.MapTiles[i, j].type == 0xffff)
|
||||
Map.MapTiles[i, j].index = byte.MaxValue;
|
||||
}
|
||||
}
|
||||
|
||||
void UnpackRAOverlayData(MemoryStream ms)
|
||||
{
|
||||
Map.MapResources = new TileReference<byte, byte>[MapSize, MapSize];
|
||||
for (int j = 0; j < MapSize; j++)
|
||||
for (int i = 0; i < MapSize; i++)
|
||||
{
|
||||
byte o = ReadByte(ms);
|
||||
var res = Pair.New((byte)0, (byte)0);
|
||||
|
||||
if (o != 255 && overlayResourceMapping.ContainsKey(raOverlayNames[o]))
|
||||
res = overlayResourceMapping[raOverlayNames[o]];
|
||||
|
||||
Map.MapResources[i, j] = new TileReference<byte, byte>(res.First, res.Second);
|
||||
|
||||
if (o != 255 && overlayActorMapping.ContainsKey(raOverlayNames[o]))
|
||||
Map.Actors.Add("Actor" + ActorCount++,
|
||||
new ActorReference(overlayActorMapping[raOverlayNames[o]])
|
||||
{
|
||||
new LocationInit( new int2(i, j) ),
|
||||
new OwnerInit( "Neutral" )
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void ReadRATrees(IniFile file)
|
||||
{
|
||||
IniSection terrain = file.GetSection("TERRAIN", true);
|
||||
if (terrain == null)
|
||||
return;
|
||||
|
||||
foreach (KeyValuePair<string, string> kv in terrain)
|
||||
{
|
||||
var loc = int.Parse(kv.Key);
|
||||
Map.Actors.Add("Actor" + ActorCount++,
|
||||
new ActorReference(kv.Value.ToLowerInvariant())
|
||||
{
|
||||
new LocationInit(new int2(loc % MapSize, loc / MapSize)),
|
||||
new OwnerInit("Neutral")
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void UnpackCncTileData(Stream ms)
|
||||
{
|
||||
Map.MapTiles = new TileReference<ushort, byte>[MapSize, MapSize];
|
||||
for (int i = 0; i < MapSize; i++)
|
||||
for (int j = 0; j < MapSize; j++)
|
||||
Map.MapTiles[i, j] = new TileReference<ushort, byte>();
|
||||
|
||||
for (int j = 0; j < MapSize; j++)
|
||||
for (int i = 0; i < MapSize; i++)
|
||||
{
|
||||
Map.MapTiles[i, j].type = ReadByte(ms);
|
||||
Map.MapTiles[i, j].index = ReadByte(ms);
|
||||
|
||||
if (Map.MapTiles[i, j].type == 0xff)
|
||||
Map.MapTiles[i, j].index = byte.MaxValue;
|
||||
}
|
||||
}
|
||||
|
||||
void ReadCncOverlay(IniFile file)
|
||||
{
|
||||
IniSection overlay = file.GetSection("OVERLAY", true);
|
||||
if (overlay == null)
|
||||
return;
|
||||
|
||||
Map.MapResources = new TileReference<byte, byte>[MapSize, MapSize];
|
||||
foreach (KeyValuePair<string, string> kv in overlay)
|
||||
{
|
||||
var loc = int.Parse(kv.Key);
|
||||
int2 cell = new int2(loc % MapSize, loc / MapSize);
|
||||
|
||||
var res = Pair.New((byte)0, (byte)0);
|
||||
if (overlayResourceMapping.ContainsKey(kv.Value.ToLower()))
|
||||
res = overlayResourceMapping[kv.Value.ToLower()];
|
||||
|
||||
Map.MapResources[cell.X, cell.Y] = new TileReference<byte, byte>(res.First, res.Second);
|
||||
|
||||
if (overlayActorMapping.ContainsKey(kv.Value.ToLower()))
|
||||
Map.Actors.Add("Actor" + ActorCount++,
|
||||
new ActorReference(overlayActorMapping[kv.Value.ToLower()])
|
||||
{
|
||||
new LocationInit(cell),
|
||||
new OwnerInit("Neutral")
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void ReadCncTrees(IniFile file)
|
||||
{
|
||||
IniSection terrain = file.GetSection("TERRAIN", true);
|
||||
if (terrain == null)
|
||||
return;
|
||||
|
||||
foreach (KeyValuePair<string, string> kv in terrain)
|
||||
{
|
||||
var loc = int.Parse(kv.Key);
|
||||
Map.Actors.Add("Actor" + ActorCount++,
|
||||
new ActorReference(kv.Value.Split(',')[0].ToLowerInvariant())
|
||||
{
|
||||
new LocationInit(new int2(loc % MapSize, loc / MapSize)),
|
||||
new OwnerInit("Neutral")
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void LoadActors(IniFile file, string section)
|
||||
{
|
||||
foreach (var s in file.GetSection(section, true))
|
||||
{
|
||||
//Structures: num=owner,type,health,location,turret-facing,trigger
|
||||
//Units: num=owner,type,health,location,facing,action,trigger
|
||||
//Infantry: num=owner,type,health,location,subcell,action,facing,trigger
|
||||
var parts = s.Value.Split(',');
|
||||
var loc = int.Parse(parts[3]);
|
||||
if (parts[0] == "")
|
||||
parts[0] = "Neutral";
|
||||
|
||||
|
||||
if (!Players.Contains(parts[0]))
|
||||
Players.Add(parts[0]);
|
||||
|
||||
var stance = ActorStance.Stance.None;
|
||||
switch(parts[5])
|
||||
{
|
||||
case "Area Guard":
|
||||
case "Guard":
|
||||
stance = ActorStance.Stance.Guard;
|
||||
break;
|
||||
case "Defend Base":
|
||||
stance = ActorStance.Stance.Defend;
|
||||
break;
|
||||
case "Hunt":
|
||||
case "Rampage":
|
||||
case "Attack Base":
|
||||
case "Attack Units":
|
||||
case "Attack Civil.":
|
||||
case "Attack Tarcom":
|
||||
stance = ActorStance.Stance.Hunt;
|
||||
break;
|
||||
case "Retreat":
|
||||
case "Return":
|
||||
stance = ActorStance.Stance.Retreat;
|
||||
break;
|
||||
// do we care about `Harvest' and `Sticky'?
|
||||
}
|
||||
|
||||
var actor = new ActorReference(parts[1].ToLowerInvariant())
|
||||
{
|
||||
new LocationInit(new int2(loc % MapSize, loc / MapSize)),
|
||||
new OwnerInit(parts[0]),
|
||||
new HealthInit(float.Parse(parts[2], NumberFormatInfo.InvariantInfo)/256),
|
||||
new FacingInit((section == "INFANTRY") ? int.Parse(parts[6]) : int.Parse(parts[4])),
|
||||
new ActorStanceInit(stance),
|
||||
};
|
||||
|
||||
if (section == "INFANTRY")
|
||||
actor.Add(new SubcellInit(int.Parse(parts[4])));
|
||||
|
||||
Map.Actors.Add("Actor" + ActorCount++,actor);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void LoadSmudges(IniFile file, string section)
|
||||
{
|
||||
foreach (var s in file.GetSection(section, true))
|
||||
{
|
||||
//loc=type,loc,depth
|
||||
var parts = s.Value.Split(',');
|
||||
var loc = int.Parse(parts[1]);
|
||||
Map.Smudges.Add(new SmudgeReference(parts[0].ToLowerInvariant(), new int2(loc % MapSize, loc / MapSize), int.Parse(parts[2])));
|
||||
}
|
||||
}
|
||||
|
||||
void LoadPlayer(IniFile file, string section, bool isRA)
|
||||
{
|
||||
var c = (section == "BadGuy") ? "red" :
|
||||
(isRA) ? "blue" : "gold";
|
||||
|
||||
var color = namedColorMapping[c];
|
||||
|
||||
var pr = new PlayerReference
|
||||
{
|
||||
Name = section,
|
||||
OwnsWorld = (section == "Neutral"),
|
||||
NonCombatant = (section == "Neutral"),
|
||||
Race = (isRA) ? ((section == "BadGuy") ? "soviet" : "allies") : ((section == "BadGuy") ? "nod" : "gdi"),
|
||||
Color = color.First,
|
||||
Color2 = color.Second,
|
||||
};
|
||||
|
||||
var Neutral = new List<string>(){"Neutral"};
|
||||
foreach (var s in file.GetSection(section, true))
|
||||
{
|
||||
Console.WriteLine(s.Key);
|
||||
switch(s.Key)
|
||||
{
|
||||
case "Credits":
|
||||
pr.InitialCash = int.Parse(s.Value);
|
||||
break;
|
||||
case "Allies":
|
||||
pr.Allies = s.Value.Split(',').Intersect(Players).Except(Neutral).ToArray();
|
||||
pr.Enemies = s.Value.Split(',').SymmetricDifference(Players).Except(Neutral).ToArray();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Map.Players.Add(section, pr);
|
||||
}
|
||||
|
||||
static string Truncate(string s, int maxLength)
|
||||
{
|
||||
return s.Length <= maxLength ? s : s.Substring(0, maxLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
375
OpenRA.Editor/MapSelect.Designer.cs
generated
Normal file
375
OpenRA.Editor/MapSelect.Designer.cs
generated
Normal file
@@ -0,0 +1,375 @@
|
||||
namespace OpenRA.Editor
|
||||
{
|
||||
partial class MapSelect
|
||||
{
|
||||
/// <summary>
|
||||
/// TODO
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// TODO
|
||||
/// </summary>
|
||||
/// <param name="disposing">TODO</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Код, автоматически созданный конструктором форм Windows
|
||||
|
||||
/// <summary>
|
||||
/// TODO
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MapSelect));
|
||||
this.MapList = new System.Windows.Forms.ListView();
|
||||
this.colMapName = new System.Windows.Forms.ColumnHeader("(отсутствует)");
|
||||
this.MapIconsList = new System.Windows.Forms.ImageList(this.components);
|
||||
this.btnCancel = new System.Windows.Forms.Button();
|
||||
this.btnOk = new System.Windows.Forms.Button();
|
||||
this.lblNew = new System.Windows.Forms.Label();
|
||||
this.txtNew = new System.Windows.Forms.TextBox();
|
||||
this.pbMinimap = new System.Windows.Forms.PictureBox();
|
||||
this.pnlBottom = new System.Windows.Forms.Panel();
|
||||
this.txtPathOut = new System.Windows.Forms.TextBox();
|
||||
this.lblPathOut = new System.Windows.Forms.Label();
|
||||
this.lblPath = new System.Windows.Forms.Label();
|
||||
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
|
||||
this.lblMapList = new System.Windows.Forms.Label();
|
||||
this.txtDesc = new System.Windows.Forms.TextBox();
|
||||
this.lblDesc = new System.Windows.Forms.Label();
|
||||
this.txtTheater = new System.Windows.Forms.TextBox();
|
||||
this.lblTheater = new System.Windows.Forms.Label();
|
||||
this.txtAuthor = new System.Windows.Forms.TextBox();
|
||||
this.lblAuthor = new System.Windows.Forms.Label();
|
||||
this.txtTitle = new System.Windows.Forms.TextBox();
|
||||
this.lblMapName = new System.Windows.Forms.Label();
|
||||
this.lblMinimap = new System.Windows.Forms.Label();
|
||||
this.pictureBox1 = new System.Windows.Forms.PictureBox();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pbMinimap)).BeginInit();
|
||||
this.pnlBottom.SuspendLayout();
|
||||
this.splitContainer1.Panel1.SuspendLayout();
|
||||
this.splitContainer1.Panel2.SuspendLayout();
|
||||
this.splitContainer1.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// MapList
|
||||
//
|
||||
this.MapList.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||
this.MapList.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
|
||||
this.colMapName});
|
||||
this.MapList.FullRowSelect = true;
|
||||
this.MapList.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;
|
||||
this.MapList.LargeImageList = this.MapIconsList;
|
||||
this.MapList.Location = new System.Drawing.Point(15, 25);
|
||||
this.MapList.MultiSelect = false;
|
||||
this.MapList.Name = "MapList";
|
||||
this.MapList.Size = new System.Drawing.Size(273, 294);
|
||||
this.MapList.SmallImageList = this.MapIconsList;
|
||||
this.MapList.StateImageList = this.MapIconsList;
|
||||
this.MapList.TabIndex = 0;
|
||||
this.MapList.UseCompatibleStateImageBehavior = false;
|
||||
this.MapList.View = System.Windows.Forms.View.Details;
|
||||
this.MapList.SelectedIndexChanged += new System.EventHandler(this.MapList_SelectedIndexChanged);
|
||||
//
|
||||
// colMapName
|
||||
//
|
||||
this.colMapName.Text = "Map name";
|
||||
this.colMapName.Width = 240;
|
||||
//
|
||||
// MapIconsList
|
||||
//
|
||||
this.MapIconsList.ColorDepth = System.Windows.Forms.ColorDepth.Depth32Bit;
|
||||
this.MapIconsList.ImageSize = new System.Drawing.Size(24, 24);
|
||||
this.MapIconsList.TransparentColor = System.Drawing.Color.Transparent;
|
||||
//
|
||||
// btnCancel
|
||||
//
|
||||
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||
this.btnCancel.Location = new System.Drawing.Point(407, 35);
|
||||
this.btnCancel.Name = "btnCancel";
|
||||
this.btnCancel.Size = new System.Drawing.Size(75, 23);
|
||||
this.btnCancel.TabIndex = 3;
|
||||
this.btnCancel.Text = "Cancel";
|
||||
this.btnCancel.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// btnOk
|
||||
//
|
||||
this.btnOk.DialogResult = System.Windows.Forms.DialogResult.OK;
|
||||
this.btnOk.Location = new System.Drawing.Point(326, 35);
|
||||
this.btnOk.Name = "btnOk";
|
||||
this.btnOk.Size = new System.Drawing.Size(75, 23);
|
||||
this.btnOk.TabIndex = 2;
|
||||
this.btnOk.Text = "Open";
|
||||
this.btnOk.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// lblNew
|
||||
//
|
||||
this.lblNew.AutoSize = true;
|
||||
this.lblNew.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
|
||||
this.lblNew.Location = new System.Drawing.Point(12, 40);
|
||||
this.lblNew.Name = "lblNew";
|
||||
this.lblNew.Size = new System.Drawing.Size(69, 13);
|
||||
this.lblNew.TabIndex = 3;
|
||||
this.lblNew.Text = "Map name:";
|
||||
//
|
||||
// txtNew
|
||||
//
|
||||
this.txtNew.BackColor = System.Drawing.SystemColors.Window;
|
||||
this.txtNew.Location = new System.Drawing.Point(88, 37);
|
||||
this.txtNew.Name = "txtNew";
|
||||
this.txtNew.ReadOnly = true;
|
||||
this.txtNew.Size = new System.Drawing.Size(232, 20);
|
||||
this.txtNew.TabIndex = 1;
|
||||
//
|
||||
// pbMinimap
|
||||
//
|
||||
this.pbMinimap.BackColor = System.Drawing.Color.Black;
|
||||
this.pbMinimap.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
|
||||
this.pbMinimap.Location = new System.Drawing.Point(32, 25);
|
||||
this.pbMinimap.Name = "pbMinimap";
|
||||
this.pbMinimap.Size = new System.Drawing.Size(124, 124);
|
||||
this.pbMinimap.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
|
||||
this.pbMinimap.TabIndex = 5;
|
||||
this.pbMinimap.TabStop = false;
|
||||
//
|
||||
// pnlBottom
|
||||
//
|
||||
this.pnlBottom.Controls.Add(this.pictureBox1);
|
||||
this.pnlBottom.Controls.Add(this.txtPathOut);
|
||||
this.pnlBottom.Controls.Add(this.lblPathOut);
|
||||
this.pnlBottom.Controls.Add(this.lblPath);
|
||||
this.pnlBottom.Controls.Add(this.btnCancel);
|
||||
this.pnlBottom.Controls.Add(this.btnOk);
|
||||
this.pnlBottom.Controls.Add(this.txtNew);
|
||||
this.pnlBottom.Controls.Add(this.lblNew);
|
||||
this.pnlBottom.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||
this.pnlBottom.Location = new System.Drawing.Point(0, 332);
|
||||
this.pnlBottom.MaximumSize = new System.Drawing.Size(0, 70);
|
||||
this.pnlBottom.Name = "pnlBottom";
|
||||
this.pnlBottom.Size = new System.Drawing.Size(494, 70);
|
||||
this.pnlBottom.TabIndex = 6;
|
||||
//
|
||||
// txtPathOut
|
||||
//
|
||||
this.txtPathOut.BackColor = System.Drawing.SystemColors.Window;
|
||||
this.txtPathOut.Location = new System.Drawing.Point(55, 10);
|
||||
this.txtPathOut.Name = "txtPathOut";
|
||||
this.txtPathOut.ReadOnly = true;
|
||||
this.txtPathOut.Size = new System.Drawing.Size(265, 20);
|
||||
this.txtPathOut.TabIndex = 0;
|
||||
this.txtPathOut.TextChanged += new System.EventHandler(this.txtPathOut_TextChanged);
|
||||
//
|
||||
// lblPathOut
|
||||
//
|
||||
this.lblPathOut.AutoSize = true;
|
||||
this.lblPathOut.Location = new System.Drawing.Point(55, 13);
|
||||
this.lblPathOut.Name = "lblPathOut";
|
||||
this.lblPathOut.Size = new System.Drawing.Size(0, 13);
|
||||
this.lblPathOut.TabIndex = 6;
|
||||
//
|
||||
// lblPath
|
||||
//
|
||||
this.lblPath.AutoSize = true;
|
||||
this.lblPath.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
|
||||
this.lblPath.Location = new System.Drawing.Point(12, 13);
|
||||
this.lblPath.Name = "lblPath";
|
||||
this.lblPath.Size = new System.Drawing.Size(37, 13);
|
||||
this.lblPath.TabIndex = 5;
|
||||
this.lblPath.Text = "Path:";
|
||||
//
|
||||
// splitContainer1
|
||||
//
|
||||
this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.splitContainer1.Location = new System.Drawing.Point(0, 0);
|
||||
this.splitContainer1.Name = "splitContainer1";
|
||||
//
|
||||
// splitContainer1.Panel1
|
||||
//
|
||||
this.splitContainer1.Panel1.Controls.Add(this.lblMapList);
|
||||
this.splitContainer1.Panel1.Controls.Add(this.MapList);
|
||||
//
|
||||
// splitContainer1.Panel2
|
||||
//
|
||||
this.splitContainer1.Panel2.Controls.Add(this.txtDesc);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.lblDesc);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.txtTheater);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.lblTheater);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.txtAuthor);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.lblAuthor);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.txtTitle);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.lblMapName);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.lblMinimap);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.pbMinimap);
|
||||
this.splitContainer1.Size = new System.Drawing.Size(494, 332);
|
||||
this.splitContainer1.SplitterDistance = 300;
|
||||
this.splitContainer1.TabIndex = 7;
|
||||
//
|
||||
// lblMapList
|
||||
//
|
||||
this.lblMapList.AutoSize = true;
|
||||
this.lblMapList.Location = new System.Drawing.Point(12, 9);
|
||||
this.lblMapList.Name = "lblMapList";
|
||||
this.lblMapList.Size = new System.Drawing.Size(81, 13);
|
||||
this.lblMapList.TabIndex = 1;
|
||||
this.lblMapList.Text = "Available maps:";
|
||||
//
|
||||
// txtDesc
|
||||
//
|
||||
this.txtDesc.BackColor = System.Drawing.SystemColors.ButtonFace;
|
||||
this.txtDesc.Location = new System.Drawing.Point(16, 289);
|
||||
this.txtDesc.Name = "txtDesc";
|
||||
this.txtDesc.ReadOnly = true;
|
||||
this.txtDesc.Size = new System.Drawing.Size(162, 20);
|
||||
this.txtDesc.TabIndex = 14;
|
||||
//
|
||||
// lblDesc
|
||||
//
|
||||
this.lblDesc.AutoSize = true;
|
||||
this.lblDesc.Location = new System.Drawing.Point(13, 273);
|
||||
this.lblDesc.Name = "lblDesc";
|
||||
this.lblDesc.Size = new System.Drawing.Size(63, 13);
|
||||
this.lblDesc.TabIndex = 13;
|
||||
this.lblDesc.Text = "Description:";
|
||||
//
|
||||
// txtTheater
|
||||
//
|
||||
this.txtTheater.BackColor = System.Drawing.SystemColors.ButtonFace;
|
||||
this.txtTheater.Location = new System.Drawing.Point(16, 252);
|
||||
this.txtTheater.Name = "txtTheater";
|
||||
this.txtTheater.ReadOnly = true;
|
||||
this.txtTheater.Size = new System.Drawing.Size(162, 20);
|
||||
this.txtTheater.TabIndex = 12;
|
||||
//
|
||||
// lblTheater
|
||||
//
|
||||
this.lblTheater.AutoSize = true;
|
||||
this.lblTheater.Location = new System.Drawing.Point(13, 236);
|
||||
this.lblTheater.Name = "lblTheater";
|
||||
this.lblTheater.Size = new System.Drawing.Size(47, 13);
|
||||
this.lblTheater.TabIndex = 11;
|
||||
this.lblTheater.Text = "Theater:";
|
||||
//
|
||||
// txtAuthor
|
||||
//
|
||||
this.txtAuthor.BackColor = System.Drawing.SystemColors.ButtonFace;
|
||||
this.txtAuthor.Location = new System.Drawing.Point(16, 214);
|
||||
this.txtAuthor.Name = "txtAuthor";
|
||||
this.txtAuthor.ReadOnly = true;
|
||||
this.txtAuthor.Size = new System.Drawing.Size(162, 20);
|
||||
this.txtAuthor.TabIndex = 10;
|
||||
//
|
||||
// lblAuthor
|
||||
//
|
||||
this.lblAuthor.AutoSize = true;
|
||||
this.lblAuthor.Location = new System.Drawing.Point(13, 198);
|
||||
this.lblAuthor.Name = "lblAuthor";
|
||||
this.lblAuthor.Size = new System.Drawing.Size(41, 13);
|
||||
this.lblAuthor.TabIndex = 9;
|
||||
this.lblAuthor.Text = "Author:";
|
||||
//
|
||||
// txtTitle
|
||||
//
|
||||
this.txtTitle.BackColor = System.Drawing.SystemColors.ButtonFace;
|
||||
this.txtTitle.Location = new System.Drawing.Point(16, 177);
|
||||
this.txtTitle.Name = "txtTitle";
|
||||
this.txtTitle.ReadOnly = true;
|
||||
this.txtTitle.Size = new System.Drawing.Size(162, 20);
|
||||
this.txtTitle.TabIndex = 8;
|
||||
//
|
||||
// lblMapName
|
||||
//
|
||||
this.lblMapName.AutoSize = true;
|
||||
this.lblMapName.Location = new System.Drawing.Point(13, 161);
|
||||
this.lblMapName.Name = "lblMapName";
|
||||
this.lblMapName.Size = new System.Drawing.Size(30, 13);
|
||||
this.lblMapName.TabIndex = 7;
|
||||
this.lblMapName.Text = "Title:";
|
||||
//
|
||||
// lblMinimap
|
||||
//
|
||||
this.lblMinimap.AutoSize = true;
|
||||
this.lblMinimap.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
|
||||
this.lblMinimap.Location = new System.Drawing.Point(29, 9);
|
||||
this.lblMinimap.Name = "lblMinimap";
|
||||
this.lblMinimap.Size = new System.Drawing.Size(71, 13);
|
||||
this.lblMinimap.TabIndex = 6;
|
||||
this.lblMinimap.Text = "Map preview:";
|
||||
//
|
||||
// pictureBox1
|
||||
//
|
||||
this.pictureBox1.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox1.Image")));
|
||||
this.pictureBox1.Location = new System.Drawing.Point(336, -9);
|
||||
this.pictureBox1.Name = "pictureBox1";
|
||||
this.pictureBox1.Size = new System.Drawing.Size(54, 35);
|
||||
this.pictureBox1.TabIndex = 7;
|
||||
this.pictureBox1.TabStop = false;
|
||||
this.pictureBox1.Visible = false;
|
||||
//
|
||||
// MapSelect
|
||||
//
|
||||
this.AcceptButton = this.btnOk;
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.CancelButton = this.btnCancel;
|
||||
this.ClientSize = new System.Drawing.Size(494, 402);
|
||||
this.Controls.Add(this.splitContainer1);
|
||||
this.Controls.Add(this.pnlBottom);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "MapSelect";
|
||||
this.ShowIcon = false;
|
||||
this.ShowInTaskbar = false;
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||
this.Text = "Select map";
|
||||
this.Load += new System.EventHandler(this.MapSelect_Load);
|
||||
((System.ComponentModel.ISupportInitialize)(this.pbMinimap)).EndInit();
|
||||
this.pnlBottom.ResumeLayout(false);
|
||||
this.pnlBottom.PerformLayout();
|
||||
this.splitContainer1.Panel1.ResumeLayout(false);
|
||||
this.splitContainer1.Panel1.PerformLayout();
|
||||
this.splitContainer1.Panel2.ResumeLayout(false);
|
||||
this.splitContainer1.Panel2.PerformLayout();
|
||||
this.splitContainer1.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public System.Windows.Forms.ListView MapList;
|
||||
public System.Windows.Forms.Button btnCancel;
|
||||
public System.Windows.Forms.Button btnOk;
|
||||
public System.Windows.Forms.Label lblNew;
|
||||
public System.Windows.Forms.TextBox txtNew;
|
||||
public System.Windows.Forms.ColumnHeader colMapName;
|
||||
public System.Windows.Forms.ImageList MapIconsList;
|
||||
public System.Windows.Forms.PictureBox pbMinimap;
|
||||
public System.Windows.Forms.Panel pnlBottom;
|
||||
public System.Windows.Forms.SplitContainer splitContainer1;
|
||||
public System.Windows.Forms.Label lblMinimap;
|
||||
public System.Windows.Forms.TextBox txtTheater;
|
||||
public System.Windows.Forms.Label lblTheater;
|
||||
public System.Windows.Forms.TextBox txtAuthor;
|
||||
public System.Windows.Forms.Label lblAuthor;
|
||||
public System.Windows.Forms.TextBox txtTitle;
|
||||
public System.Windows.Forms.Label lblMapName;
|
||||
public System.Windows.Forms.TextBox txtDesc;
|
||||
public System.Windows.Forms.Label lblDesc;
|
||||
public System.Windows.Forms.Label lblMapList;
|
||||
public System.Windows.Forms.Label lblPathOut;
|
||||
public System.Windows.Forms.Label lblPath;
|
||||
public System.Windows.Forms.TextBox txtPathOut;
|
||||
private System.Windows.Forms.PictureBox pictureBox1;
|
||||
}
|
||||
}
|
||||
66
OpenRA.Editor/MapSelect.cs
Normal file
66
OpenRA.Editor/MapSelect.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Graphics;
|
||||
|
||||
namespace OpenRA.Editor
|
||||
{
|
||||
public partial class MapSelect : Form
|
||||
{
|
||||
public string MapFolderPath;
|
||||
|
||||
public MapSelect()
|
||||
{
|
||||
InitializeComponent();
|
||||
MapIconsList.Images.Add(pictureBox1.Image);
|
||||
}
|
||||
|
||||
void MapSelect_Load(object sender, EventArgs e)
|
||||
{
|
||||
DirectoryInfo directory = new DirectoryInfo(MapFolderPath);
|
||||
DirectoryInfo[] directories = directory.GetDirectories();
|
||||
MapList.Items.Clear();
|
||||
txtPathOut.Text = MapFolderPath;
|
||||
foreach (DirectoryInfo subDirectory in directories)
|
||||
{
|
||||
ListViewItem map1 = new ListViewItem(subDirectory.Name);
|
||||
map1.ImageIndex = 0;
|
||||
MapList.Items.Add(map1);
|
||||
}
|
||||
|
||||
// hack
|
||||
if (txtNew.Text != "unnamed")
|
||||
MapList.Items[0].Selected = true;
|
||||
}
|
||||
|
||||
void MapList_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (MapList.SelectedItems.Count == 1)
|
||||
{
|
||||
txtNew.Text = MapList.SelectedItems[0].Text;
|
||||
var map = new Map(new Folder(Path.Combine(MapFolderPath, MapList.SelectedItems[0].Text), 0));
|
||||
txtTitle.Text = map.Title;
|
||||
txtAuthor.Text = map.Author;
|
||||
txtTheater.Text = map.Theater;
|
||||
txtDesc.Text = map.Description;
|
||||
pbMinimap.Image = null;
|
||||
try
|
||||
{
|
||||
pbMinimap.Image = Minimap.AddStaticResources(map, Minimap.TerrainBitmap(map, true));
|
||||
}
|
||||
catch (Exception ed)
|
||||
{
|
||||
Console.WriteLine("No map preview image found: {0}", ed.ToString());
|
||||
}
|
||||
finally { }
|
||||
}
|
||||
}
|
||||
|
||||
void txtPathOut_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
MapFolderPath = txtPathOut.Text;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
177
OpenRA.Editor/MapSelect.resx
Normal file
177
OpenRA.Editor/MapSelect.resx
Normal file
@@ -0,0 +1,177 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="MapIconsList.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="pictureBox1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAArjSURBVFhHrVcJUFRXFmVpkE0Wg0ZEMoIBl8RodGSMmVES
|
||||
R0NiChVxCyIIAmFfhe6maeh9AZodZHFpUFQWcQmKisiuLKLEKFFEcIuljtZMYmI5Uc/c14EZYyapmpq8
|
||||
qlP/9/+/373v3HPu+19P7/cf+jSlEWHCOEuzZfNn2Yvo3Pj3D/PTjCwYAwtgyeFwFk163Tos2tvtWJZw
|
||||
zeUjmYFP6vL9fhw31vRPI8/9LnmMrtCWZhtPcJ7hbC/W8DwfnS0LR0t5NKoFazHcqsaprE3YGbMQLrYW
|
||||
W/7fBAxogjGEd5wcXuPK4jxa60qD75VrfIbKMrYMD7VlPX/Ul49rp8RoyPbFIaEnhpuU6NRGoVa2HKuX
|
||||
zEj/X8vAVmlIsDY2Nna2sjBd+ee5b7Yq4tfgfm8a7pxNw60OFa6e4uFmhxr/uFSIexfz0VsZh7PaIJzb
|
||||
F42u8hAcV2/ANz3KF8Hub52kucb+Fv+jAccbm5quWOfxYX5y6Mcnq/IDh1oreX/vOcx9drdbjTudUgye
|
||||
Tsb1piT0H4/DACUw0JiEh33ZePhlFi7UxOCLtI1o2x6IW2cUqM/egLtdediV9MnjSTYm60bE+Ys8rMzN
|
||||
zd1c3/vLgVRV3lN1XjkqyzNoNaEUjIvrLXwMtQsw1JqEy/UxuHg0DJcp+KXj8bh0IobOucSGDA8vpqE6
|
||||
+VNINixBU0kQbp5JJ8jxDSXdeyAE5arlAxTZ/BfRra2tS8Tqwh9L9tQhq6gSabm7odLkoP8oF90V/rjR
|
||||
LsRgExc32oS40ZFCiQgw2Mgj+gW42pBI4OPSsUh6Jgn1mX4ojXJH865IXDzCx50uDe6fV+P8oQQ4Tx6r
|
||||
pOATmVteKgdjXu/Mhk1h328rO4TMwn3gp2YhmquEX7gAfYfjcb4qGH0HQ3D5WAiunU7ApfpofH0ymhIS
|
||||
UwkSqQRb6VoYvm6IZvXG7W4VBVbjwQU1/tanIQZkGDqtwOmSjzHXxXaLsZnZpy85QpdAnfunax/mllRD
|
||||
ma2FQJyHxORMJAqzwBVpUJgtRLF8E7bxlqKjzA991QEYaIijgFwMt6VggJK60hCFr46F4sqprbjbLaf6
|
||||
S0icIh1rwy1i3OvNQff+GEgj3r87/c1JLIGfjX1LP/F6KJDlIy1vN4SyQohVRdAU7IVIXQxuSiZ8/OOw
|
||||
JYyP8EiqfV04Lh2JoHIwMSbiwoFgtO1ah97aTSTMKGIjDl/WhONWl5jKlYrbZ9OJGRWVIg/+axf8SK5a
|
||||
8WoC5fPm//l2qqIIOaVVECm3QZG5C7L0HZCklYJLTCQKNUiWFYAnykJYRDRaywNxrTGRyhKNKyciiIEY
|
||||
dFd743z1ZioT6eJkHK41kXDbRFSKbHzTpcJwsxoHc71fTLGzyBix+L/zUFlaWX+VTcFZ4NzSamQXV1Lw
|
||||
EggkeeBRAsnSfKgyy6DKKcNnxEahIgRfHg5B/7EoDDYn4ma7FD0VAThfG4Cemi3EDI90IKWVq3GbHHKz
|
||||
nUpCbrh6QokEr5mPTEw4773MQij9aPZY5fNYrC6hEhRAnrkTjJEkcS5ieWokS/IhUZdCrtlJbGQiIjQQ
|
||||
/YeD0VMVhoTVbmgs8iVBctG11xtdlUHkDGpQpIN7velUAhmG2+W43spclI6K9JWY6TyxlGKOGxWjG53s
|
||||
5HBMBpZ7+iI6UY44vhoiVTH4ohxCLoTyArqu1OlBll6CZHE20mI9EOjuis3L5uFCbTh6D4Wgu8offYeC
|
||||
qSRccgcPD/qyMEiBb55VYahFgSuNckhjlr2YaGMqH2ntOiKmEAQGBgbnNviGPg2LFSM4UoiAUD78ghLo
|
||||
yEVojBhRiQqEx0nAI5sKiBH/z+OgVfuic7c/Lh+NwZndfughDfQdCtL1hKFmEW51ymn1EjpSAh1ytFCL
|
||||
Pl+nhKebY8XLTYn16DWEgzY2ttdzyI6yjB06+uP4acRANokvhzRRjBR5oe4aN4WupeYgNCIWZ2vj0b17
|
||||
I/UKf3Tt34jOis9otTyyILmkORUDTRKyqxj9DSI07Y0k26Yhes38Roo3YVQH7OVhGiGR0K7O0epEqCRB
|
||||
shKwRIQkQrZqMelAIM6ncihII9uQSCXZEi2HSMjDXvVqXKSGdTLbg6z6OVkwGcfLQvHB4jkYbJMS/UL0
|
||||
1aeSM6So1Hg/oljTR93AupEVYSXhGE+soZa8X+cIlgALzFhg5/HJ6YhIzACXVs9EKiHRMmckSfMQGx0G
|
||||
rXIldU4/dJSvJx3EoSDZC7OszHByTxTOfZGEq00y9B3lo70iElamhp4Ujy1eN8wIrEOd0BRW6DpiWEwq
|
||||
giKSdYiIl5IOUskRKh39AmKECZNP7Mg0O6Ci59Pzd4O/NQK7FBvQULyGOmMUpBsX4KqjGTL5qzHQIqJy
|
||||
iNG6Px5dtYlY7jqhmeKxvUE32C7FGKiP58uf5W6v0ekgPkmNrYIMor4YqcoinQBFdGQrl2ZsB4/cwBJR
|
||||
Zml/+k0sxcQnQZzgDWHIIni9NQHSHU5IS15EPSEN11ok6G9UQs1dh/lvv/GdkZHR3NEETOhkIUE7zvb1
|
||||
wRRFwYv0vD3UBTORJCEdSHMhydgFCXVHVnuWEGvZrDewjqmzKbHDNjHmFl5KBlasWokiFwtop5nhyL6p
|
||||
2JO/CN2HBdSgMpHJ88GH82c8s7b4T1vmUPA3CFxCp19QzBPdtpxdRqon2kkDKRSYXeOJcyBUFMI7IJ70
|
||||
kYsEgRLTXGbgrzNnwmWqC2Y4OsLZZjx43El4ggXI1zohy24MAFd4u9tj8YLpmD71DTiMtwGHY1A7ygB7
|
||||
52N29CLULV7qeT+HnFCoPairu87/RC9rTjE8JYJoY/p4lR8lVQAp7Rc+/pHY7OKE61NN8a21MbQpfwC+
|
||||
m4fbQ7MQNdcCfWMMsTPWDi2yyRgyNkDhOGPYGhpeo97jP5oAcwJjYQ4hk3DOyzvwn9v3HtUJjHXAzSFc
|
||||
RHHlCAznIyAsCZa2k56u3xT2gtHPmGHCdXtnHh47mKBqjS1K5Q7ITrCjlf8RqXPM0bDUCr3bp2C9nj70
|
||||
DDinKMYSwmujCbAjY4G9ZrN3tyMLP/D4IT1vP/J21CBeoKaa55MTUhAeK8J7i91v0DMdxqZmgw7Oc74N
|
||||
iFQ8T5YX6ZzisWI9Uiebo8rKCOcsjLAv1Z72BydUxE5ElcTuKf2P9RunEeGzmD8bTIzsI0I7wc7xdgyf
|
||||
NiayWVoueZ1qz7zPT8l5McnBqZieYZsYO/a4zF7yaKWP4HlASMKLj9xX4WrXWzhdMxUFlkaI1tPDAZE9
|
||||
Htc4wWuhOas5Y/oXgUezYDdZdmK2N6zzCfuB1V1GFkulNswT5cFllms73f+QMIWwjCDjGJnUW1rbfu2z
|
||||
wvXJk85pUH5gieNJdugvd8QV7RSc0TjgiMwevkvH3np1xa/+ZplZE9jecNh14UcPmO8VmnLyfzGr/feU
|
||||
mB/dY7VjybItdSZhrb6+fvEYY6PuMWOMn7ZbGeILfQNYmnN+mO1o/OBdCw74HAMsMjR8NjL/r+Yx+p3H
|
||||
XhjKZs93uxMZr4Z/uOb54qWf3bGf4pw3EpC1UPYsS3g0EU9K4uBsI86zYHPOY3MOp4zuRRLyDfT1O941
|
||||
Mrzvb86Bob4h+0r6zcEmdiFICA2vvT55kLFBYOJhnYt9or06TOmCJ7HTbGxgADpndmaJMU29QxAQKvTo
|
||||
vhnHkN1nX12/OlgCNoT3CZsIvgRWc9ao2IT/bTD3+BID7N1/zisBWCKOBB/CagKf8PboJP8CoUmu3yhA
|
||||
ga8AAAAASUVORK5CYII=
|
||||
</value>
|
||||
</data>
|
||||
</root>
|
||||
22
OpenRA.Editor/NewMapDialog.Designer.cs
generated
Normal file → Executable file
22
OpenRA.Editor/NewMapDialog.Designer.cs
generated
Normal file → Executable file
@@ -55,7 +55,7 @@
|
||||
this.button2.Location = new System.Drawing.Point(229, 160);
|
||||
this.button2.Name = "button2";
|
||||
this.button2.Size = new System.Drawing.Size(75, 23);
|
||||
this.button2.TabIndex = 12;
|
||||
this.button2.TabIndex = 7;
|
||||
this.button2.Text = "OK";
|
||||
this.button2.UseVisualStyleBackColor = true;
|
||||
//
|
||||
@@ -65,7 +65,7 @@
|
||||
this.button1.Location = new System.Drawing.Point(310, 160);
|
||||
this.button1.Name = "button1";
|
||||
this.button1.Size = new System.Drawing.Size(75, 23);
|
||||
this.button1.TabIndex = 13;
|
||||
this.button1.TabIndex = 8;
|
||||
this.button1.Text = "Cancel";
|
||||
this.button1.UseVisualStyleBackColor = true;
|
||||
//
|
||||
@@ -106,12 +106,13 @@
|
||||
0});
|
||||
this.cordonBottom.Name = "cordonBottom";
|
||||
this.cordonBottom.Size = new System.Drawing.Size(105, 20);
|
||||
this.cordonBottom.TabIndex = 8;
|
||||
this.cordonBottom.TabIndex = 5;
|
||||
this.cordonBottom.Value = new decimal(new int[] {
|
||||
112,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.cordonBottom.Enter += new System.EventHandler(this.SelectText);
|
||||
//
|
||||
// cordonTop
|
||||
//
|
||||
@@ -129,6 +130,7 @@
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.cordonTop.Enter += new System.EventHandler(this.SelectText);
|
||||
//
|
||||
// cordonRight
|
||||
//
|
||||
@@ -140,12 +142,13 @@
|
||||
0});
|
||||
this.cordonRight.Name = "cordonRight";
|
||||
this.cordonRight.Size = new System.Drawing.Size(105, 20);
|
||||
this.cordonRight.TabIndex = 5;
|
||||
this.cordonRight.TabIndex = 4;
|
||||
this.cordonRight.Value = new decimal(new int[] {
|
||||
112,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.cordonRight.Enter += new System.EventHandler(this.SelectText);
|
||||
//
|
||||
// cordonLeft
|
||||
//
|
||||
@@ -157,12 +160,13 @@
|
||||
0});
|
||||
this.cordonLeft.Name = "cordonLeft";
|
||||
this.cordonLeft.Size = new System.Drawing.Size(105, 20);
|
||||
this.cordonLeft.TabIndex = 7;
|
||||
this.cordonLeft.TabIndex = 2;
|
||||
this.cordonLeft.Value = new decimal(new int[] {
|
||||
16,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.cordonLeft.Enter += new System.EventHandler(this.SelectText);
|
||||
//
|
||||
// height
|
||||
//
|
||||
@@ -179,12 +183,13 @@
|
||||
0});
|
||||
this.height.Name = "height";
|
||||
this.height.Size = new System.Drawing.Size(105, 20);
|
||||
this.height.TabIndex = 6;
|
||||
this.height.TabIndex = 1;
|
||||
this.height.Value = new decimal(new int[] {
|
||||
128,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.height.Enter += new System.EventHandler(this.SelectText);
|
||||
//
|
||||
// width
|
||||
//
|
||||
@@ -201,12 +206,13 @@
|
||||
0});
|
||||
this.width.Name = "width";
|
||||
this.width.Size = new System.Drawing.Size(105, 20);
|
||||
this.width.TabIndex = 4;
|
||||
this.width.TabIndex = 0;
|
||||
this.width.Value = new decimal(new int[] {
|
||||
128,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.width.Enter += new System.EventHandler(this.SelectText);
|
||||
//
|
||||
// label4
|
||||
//
|
||||
@@ -224,7 +230,7 @@
|
||||
this.theater.Location = new System.Drawing.Point(169, 121);
|
||||
this.theater.Name = "theater";
|
||||
this.theater.Size = new System.Drawing.Size(216, 21);
|
||||
this.theater.TabIndex = 15;
|
||||
this.theater.TabIndex = 6;
|
||||
//
|
||||
// NewMapDialog
|
||||
//
|
||||
|
||||
5
OpenRA.Editor/NewMapDialog.cs
Normal file → Executable file
5
OpenRA.Editor/NewMapDialog.cs
Normal file → Executable file
@@ -18,5 +18,10 @@ namespace OpenRA.Editor
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void SelectText(object sender, System.EventArgs e)
|
||||
{
|
||||
(sender as NumericUpDown).Select(0, (sender as NumericUpDown).ToString().Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BIN
OpenRA.Editor/OpenRA.Editor.Icon.ico
Normal file
BIN
OpenRA.Editor/OpenRA.Editor.Icon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
@@ -12,6 +12,7 @@
|
||||
<AssemblyName>OpenRA.Editor</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ApplicationIcon>OpenRA.Editor.Icon.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@@ -23,6 +24,7 @@
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
@@ -31,6 +33,8 @@
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
@@ -44,7 +48,6 @@
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Deployment" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
@@ -57,12 +60,25 @@
|
||||
<Compile Include="Form1.Designer.cs">
|
||||
<DependentUpon>Form1.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="LegacyMapImporter.cs" />
|
||||
<Compile Include="MapSelect.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MapSelect.Designer.cs">
|
||||
<DependentUpon>MapSelect.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="NewMapDialog.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="NewMapDialog.Designer.cs">
|
||||
<DependentUpon>NewMapDialog.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="PaletteBox.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="PaletteBox.Designer.cs">
|
||||
<DependentUpon>PaletteBox.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="PropertiesDialog.cs">
|
||||
<SubType>Form</SubType>
|
||||
@@ -74,9 +90,15 @@
|
||||
<EmbeddedResource Include="Form1.resx">
|
||||
<DependentUpon>Form1.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="MapSelect.resx">
|
||||
<DependentUpon>MapSelect.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="NewMapDialog.resx">
|
||||
<DependentUpon>NewMapDialog.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="PaletteBox.resx">
|
||||
<DependentUpon>PaletteBox.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="PropertiesDialog.resx">
|
||||
<DependentUpon>PropertiesDialog.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
@@ -101,6 +123,7 @@
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
<Compile Include="RenderUtils.cs" />
|
||||
<Compile Include="ResizeDialog.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
@@ -121,7 +144,10 @@
|
||||
<Name>OpenRA.Game</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
<Content Include="OpenRA.Editor.Icon.ico" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
|
||||
165
OpenRA.Editor/PaletteBox.Designer.cs
generated
Normal file
165
OpenRA.Editor/PaletteBox.Designer.cs
generated
Normal file
@@ -0,0 +1,165 @@
|
||||
namespace OpenRA.Editor
|
||||
{
|
||||
partial class PaletteBox
|
||||
{
|
||||
/// <summary>
|
||||
/// Требуется переменная конструктора.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Освободить все используемые ресурсы.
|
||||
/// </summary>
|
||||
/// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Код, автоматически созданный конструктором форм Windows
|
||||
|
||||
/// <summary>
|
||||
/// Обязательный метод для поддержки конструктора - не изменяйте
|
||||
/// содержимое данного метода при помощи редактора кода.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.LayerBox = new System.Windows.Forms.ComboBox();
|
||||
this.tabControl1 = new System.Windows.Forms.TabControl();
|
||||
this.tabPage1 = new System.Windows.Forms.TabPage();
|
||||
this.pbtilePalette = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.tabPage2 = new System.Windows.Forms.TabPage();
|
||||
this.pbactorPalette = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.tabPage3 = new System.Windows.Forms.TabPage();
|
||||
this.pbresourcePalette = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.tabControl1.SuspendLayout();
|
||||
this.tabPage1.SuspendLayout();
|
||||
this.tabPage2.SuspendLayout();
|
||||
this.tabPage3.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// LayerBox
|
||||
//
|
||||
this.LayerBox.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.LayerBox.FormattingEnabled = true;
|
||||
this.LayerBox.Location = new System.Drawing.Point(0, 0);
|
||||
this.LayerBox.Name = "LayerBox";
|
||||
this.LayerBox.Size = new System.Drawing.Size(194, 21);
|
||||
this.LayerBox.TabIndex = 0;
|
||||
//
|
||||
// tabControl1
|
||||
//
|
||||
this.tabControl1.Controls.Add(this.tabPage1);
|
||||
this.tabControl1.Controls.Add(this.tabPage2);
|
||||
this.tabControl1.Controls.Add(this.tabPage3);
|
||||
this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tabControl1.Location = new System.Drawing.Point(0, 21);
|
||||
this.tabControl1.Margin = new System.Windows.Forms.Padding(3, 3, 3, 0);
|
||||
this.tabControl1.Multiline = true;
|
||||
this.tabControl1.Name = "tabControl1";
|
||||
this.tabControl1.SelectedIndex = 0;
|
||||
this.tabControl1.Size = new System.Drawing.Size(194, 357);
|
||||
this.tabControl1.TabIndex = 1;
|
||||
//
|
||||
// tabPage1
|
||||
//
|
||||
this.tabPage1.Controls.Add(this.pbtilePalette);
|
||||
this.tabPage1.Location = new System.Drawing.Point(4, 22);
|
||||
this.tabPage1.Name = "tabPage1";
|
||||
this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tabPage1.Size = new System.Drawing.Size(186, 331);
|
||||
this.tabPage1.TabIndex = 0;
|
||||
this.tabPage1.Text = "Templates";
|
||||
this.tabPage1.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// pbtilePalette
|
||||
//
|
||||
this.pbtilePalette.AutoScroll = true;
|
||||
this.pbtilePalette.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
this.pbtilePalette.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.pbtilePalette.Location = new System.Drawing.Point(3, 3);
|
||||
this.pbtilePalette.Name = "pbtilePalette";
|
||||
this.pbtilePalette.Size = new System.Drawing.Size(180, 325);
|
||||
this.pbtilePalette.TabIndex = 1;
|
||||
//
|
||||
// tabPage2
|
||||
//
|
||||
this.tabPage2.Controls.Add(this.pbactorPalette);
|
||||
this.tabPage2.Location = new System.Drawing.Point(4, 22);
|
||||
this.tabPage2.Name = "tabPage2";
|
||||
this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tabPage2.Size = new System.Drawing.Size(186, 331);
|
||||
this.tabPage2.TabIndex = 1;
|
||||
this.tabPage2.Text = "Actors";
|
||||
this.tabPage2.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// pbactorPalette
|
||||
//
|
||||
this.pbactorPalette.AutoScroll = true;
|
||||
this.pbactorPalette.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
this.pbactorPalette.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.pbactorPalette.Location = new System.Drawing.Point(3, 3);
|
||||
this.pbactorPalette.Name = "pbactorPalette";
|
||||
this.pbactorPalette.Size = new System.Drawing.Size(180, 325);
|
||||
this.pbactorPalette.TabIndex = 2;
|
||||
//
|
||||
// tabPage3
|
||||
//
|
||||
this.tabPage3.Controls.Add(this.pbresourcePalette);
|
||||
this.tabPage3.Location = new System.Drawing.Point(4, 22);
|
||||
this.tabPage3.Name = "tabPage3";
|
||||
this.tabPage3.Size = new System.Drawing.Size(186, 331);
|
||||
this.tabPage3.TabIndex = 2;
|
||||
this.tabPage3.Text = "Resources";
|
||||
this.tabPage3.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// pbresourcePalette
|
||||
//
|
||||
this.pbresourcePalette.AutoScroll = true;
|
||||
this.pbresourcePalette.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
this.pbresourcePalette.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.pbresourcePalette.Location = new System.Drawing.Point(0, 0);
|
||||
this.pbresourcePalette.Name = "pbresourcePalette";
|
||||
this.pbresourcePalette.Size = new System.Drawing.Size(186, 331);
|
||||
this.pbresourcePalette.TabIndex = 3;
|
||||
//
|
||||
// PaletteBox
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(194, 378);
|
||||
this.Controls.Add(this.tabControl1);
|
||||
this.Controls.Add(this.LayerBox);
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "PaletteBox";
|
||||
this.ShowIcon = false;
|
||||
this.ShowInTaskbar = false;
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||
this.Text = "Palette Box";
|
||||
this.TopMost = true;
|
||||
this.tabControl1.ResumeLayout(false);
|
||||
this.tabPage1.ResumeLayout(false);
|
||||
this.tabPage2.ResumeLayout(false);
|
||||
this.tabPage3.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public System.Windows.Forms.ComboBox LayerBox;
|
||||
public System.Windows.Forms.TabControl tabControl1;
|
||||
public System.Windows.Forms.TabPage tabPage1;
|
||||
public System.Windows.Forms.FlowLayoutPanel pbtilePalette;
|
||||
public System.Windows.Forms.TabPage tabPage2;
|
||||
public System.Windows.Forms.FlowLayoutPanel pbactorPalette;
|
||||
public System.Windows.Forms.TabPage tabPage3;
|
||||
public System.Windows.Forms.FlowLayoutPanel pbresourcePalette;
|
||||
|
||||
}
|
||||
}
|
||||
19
OpenRA.Editor/PaletteBox.cs
Normal file
19
OpenRA.Editor/PaletteBox.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace OpenRA.Editor
|
||||
{
|
||||
public partial class PaletteBox : Form
|
||||
{
|
||||
public PaletteBox()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
120
OpenRA.Editor/PaletteBox.resx
Normal file
120
OpenRA.Editor/PaletteBox.resx
Normal file
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@@ -22,6 +22,7 @@ namespace OpenRA.Editor
|
||||
Application.CurrentCulture = CultureInfo.InvariantCulture;
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
|
||||
Application.Run(new Form1(args));
|
||||
}
|
||||
}
|
||||
|
||||
161
OpenRA.Editor/RenderUtils.cs
Normal file
161
OpenRA.Editor/RenderUtils.cs
Normal file
@@ -0,0 +1,161 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Editor
|
||||
{
|
||||
static class RenderUtils
|
||||
{
|
||||
public static ColorPalette MakeSystemPalette(Palette p)
|
||||
{
|
||||
ColorPalette pal;
|
||||
using (var b = new Bitmap(1, 1, PixelFormat.Format8bppIndexed))
|
||||
pal = b.Palette;
|
||||
|
||||
for (var i = 0; i < 256; i++)
|
||||
pal.Entries[i] = p.GetColor(i);
|
||||
return pal;
|
||||
}
|
||||
|
||||
public static Bitmap RenderTemplate(TileSet ts, ushort n, Palette p)
|
||||
{
|
||||
var template = ts.Templates[n];
|
||||
var tile = ts.Tiles[n];
|
||||
|
||||
var bitmap = new Bitmap(ts.TileSize * template.Size.X, ts.TileSize * template.Size.Y,
|
||||
PixelFormat.Format8bppIndexed);
|
||||
|
||||
bitmap.Palette = MakeSystemPalette(p);
|
||||
|
||||
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
|
||||
|
||||
unsafe
|
||||
{
|
||||
byte* q = (byte*)data.Scan0.ToPointer();
|
||||
var stride = data.Stride;
|
||||
|
||||
for (var u = 0; u < template.Size.X; u++)
|
||||
for (var v = 0; v < template.Size.Y; v++)
|
||||
if (tile.TileBitmapBytes[u + v * template.Size.X] != null)
|
||||
{
|
||||
var rawImage = tile.TileBitmapBytes[u + v * template.Size.X];
|
||||
for (var i = 0; i < ts.TileSize; i++)
|
||||
for (var j = 0; j < ts.TileSize; j++)
|
||||
q[(v * ts.TileSize + j) * stride + u * ts.TileSize + i] = rawImage[i + ts.TileSize * j];
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < ts.TileSize; i++)
|
||||
for (var j = 0; j < ts.TileSize; j++)
|
||||
q[(v * ts.TileSize + j) * stride + u * ts.TileSize + i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bitmap.UnlockBits(data);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
static Bitmap RenderShp(ShpReader shp, Palette p)
|
||||
{
|
||||
var frame = shp[0];
|
||||
|
||||
var bitmap = new Bitmap(shp.Width, shp.Height, PixelFormat.Format8bppIndexed);
|
||||
|
||||
bitmap.Palette = MakeSystemPalette(p);
|
||||
|
||||
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
|
||||
|
||||
unsafe
|
||||
{
|
||||
byte* q = (byte*)data.Scan0.ToPointer();
|
||||
var stride2 = data.Stride;
|
||||
|
||||
for (var i = 0; i < shp.Width; i++)
|
||||
for (var j = 0; j < shp.Height; j++)
|
||||
q[j * stride2 + i] = frame.Image[i + shp.Width * j];
|
||||
}
|
||||
|
||||
bitmap.UnlockBits(data);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
public static ActorTemplate RenderActor(ActorInfo info, TileSet tileset, Palette p)
|
||||
{
|
||||
var ri = info.Traits.Get<RenderSimpleInfo>();
|
||||
string image = null;
|
||||
if (ri.OverrideTheater != null)
|
||||
for (int i = 0; i < ri.OverrideTheater.Length; i++)
|
||||
if (ri.OverrideTheater[i] == tileset.Id)
|
||||
image = ri.OverrideImage[i];
|
||||
|
||||
image = image ?? ri.Image ?? info.Name;
|
||||
using (var s = FileSystem.OpenWithExts(image, tileset.Extensions))
|
||||
{
|
||||
var shp = new ShpReader(s);
|
||||
var bitmap = RenderShp(shp, p);
|
||||
|
||||
try
|
||||
{
|
||||
using (var s2 = FileSystem.OpenWithExts(image + "2", tileset.Extensions))
|
||||
{
|
||||
var shp2 = new ShpReader(s2);
|
||||
var roofBitmap = RenderShp(shp2, p);
|
||||
|
||||
using (var g = System.Drawing.Graphics.FromImage(bitmap))
|
||||
g.DrawImage(roofBitmap, 0, 0);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
return new ActorTemplate
|
||||
{
|
||||
Bitmap = bitmap,
|
||||
Info = info,
|
||||
Appearance = info.Traits.GetOrDefault<EditorAppearanceInfo>()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public static ResourceTemplate RenderResourceType(ResourceTypeInfo info, string[] exts, Palette p)
|
||||
{
|
||||
var image = info.SpriteNames[0];
|
||||
using (var s = FileSystem.OpenWithExts(image, exts))
|
||||
{
|
||||
var shp = new ShpReader(s);
|
||||
var frame = shp[shp.ImageCount - 1];
|
||||
|
||||
var bitmap = new Bitmap(shp.Width, shp.Height, PixelFormat.Format8bppIndexed);
|
||||
bitmap.Palette = MakeSystemPalette(p);
|
||||
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
|
||||
|
||||
unsafe
|
||||
{
|
||||
byte* q = (byte*)data.Scan0.ToPointer();
|
||||
var stride = data.Stride;
|
||||
|
||||
for (var i = 0; i < shp.Width; i++)
|
||||
for (var j = 0; j < shp.Height; j++)
|
||||
q[j * stride + i] = frame.Image[i + shp.Width * j];
|
||||
}
|
||||
|
||||
bitmap.UnlockBits(data);
|
||||
return new ResourceTemplate { Bitmap = bitmap, Info = info, Value = shp.ImageCount - 1 };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
252
OpenRA.Editor/Surface.cs
Normal file → Executable file
252
OpenRA.Editor/Surface.cs
Normal file → Executable file
@@ -8,13 +8,14 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Thirdparty;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Editor
|
||||
{
|
||||
@@ -25,12 +26,16 @@ namespace OpenRA.Editor
|
||||
public Palette Palette { get; private set; }
|
||||
int2 Offset;
|
||||
|
||||
float Zoom = 1.0f;
|
||||
|
||||
BrushTemplate Brush;
|
||||
ActorTemplate Actor;
|
||||
ResourceTemplate Resource;
|
||||
WaypointTemplate Waypoint;
|
||||
|
||||
public bool IsPanning;
|
||||
public event Action AfterChange = () => { };
|
||||
public event Action<string> MousePositionChanged = _ => { };
|
||||
|
||||
Dictionary<string, ActorTemplate> ActorTemplates = new Dictionary<string, ActorTemplate>();
|
||||
Dictionary<int, ResourceTemplate> ResourceTemplates = new Dictionary<int, ResourceTemplate>();
|
||||
@@ -41,6 +46,7 @@ namespace OpenRA.Editor
|
||||
TileSet = ts;
|
||||
Palette = p;
|
||||
Brush = null;
|
||||
PlayerPalettes = null;
|
||||
Chunks.Clear();
|
||||
}
|
||||
|
||||
@@ -79,13 +85,45 @@ namespace OpenRA.Editor
|
||||
Offset -= dx;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
|
||||
protected override void OnMouseWheel(MouseEventArgs e)
|
||||
{
|
||||
base.OnMouseWheel(e);
|
||||
|
||||
if (Map == null) return;
|
||||
|
||||
Zoom *= e.Delta > 0 ? 4.0f / 3.0f : .75f;
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
protected override void OnMouseLeave(EventArgs e)
|
||||
{
|
||||
base.OnMouseLeave(e);
|
||||
|
||||
this.Parent.Focus();
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
protected override void OnMouseEnter(EventArgs e)
|
||||
{
|
||||
base.OnMouseLeave(e);
|
||||
|
||||
this.Focus();
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
protected override void OnMouseMove(MouseEventArgs e)
|
||||
{
|
||||
base.OnMouseMove(e);
|
||||
|
||||
if (Map == null) return;
|
||||
|
||||
var oldMousePos = MousePos;
|
||||
MousePos = new int2(e.Location);
|
||||
MousePositionChanged(GetBrushLocation().ToString());
|
||||
|
||||
if (e.Button == MouseButtons.Middle || (e.Button != MouseButtons.None && IsPanning))
|
||||
Scroll(oldMousePos - MousePos);
|
||||
@@ -95,7 +133,7 @@ namespace OpenRA.Editor
|
||||
Erase();
|
||||
|
||||
if (e.Button == MouseButtons.Left)
|
||||
Draw();
|
||||
Draw();
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
@@ -129,13 +167,15 @@ namespace OpenRA.Editor
|
||||
/* todo: optimize */
|
||||
foreach (var ch in Chunks.Values) ch.Dispose();
|
||||
Chunks.Clear();
|
||||
|
||||
AfterChange();
|
||||
}
|
||||
|
||||
int2 FindEdge(int2 p, int2 d, TileReference<ushort, byte> replace)
|
||||
{
|
||||
for (; ; )
|
||||
{
|
||||
var q = p+d;
|
||||
var q = p + d;
|
||||
if (!Map.IsInMap(q)) return p;
|
||||
if (!Map.MapTiles[q.X, q.Y].Equals(replace)) return p;
|
||||
p = q;
|
||||
@@ -167,7 +207,7 @@ namespace OpenRA.Editor
|
||||
{
|
||||
type = Brush.N,
|
||||
index = template.PickAny ? byte.MaxValue : (byte)z,
|
||||
image = template.PickAny ? (byte)((u + pos.X) % 4 + ((v + pos.Y) % 4)*4) : (byte)z,
|
||||
image = template.PickAny ? (byte)((u + pos.X) % 4 + ((v + pos.Y) % 4) * 4) : (byte)z,
|
||||
};
|
||||
|
||||
var ch = new int2((pos.X + u) / ChunkSize, (pos.Y + v) / ChunkSize);
|
||||
@@ -178,6 +218,8 @@ namespace OpenRA.Editor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AfterChange();
|
||||
}
|
||||
|
||||
int wpid;
|
||||
@@ -197,22 +239,33 @@ namespace OpenRA.Editor
|
||||
if (k.Key != null) Map.Waypoints.Remove(k.Key);
|
||||
|
||||
Map.Waypoints.Add(NextWpid(), GetBrushLocation());
|
||||
|
||||
AfterChange();
|
||||
}
|
||||
|
||||
void Erase()
|
||||
{
|
||||
// Crash preventing
|
||||
var BrushLocation = GetBrushLocation();
|
||||
|
||||
if (Map == null || BrushLocation.X >= Map.MapSize.X ||
|
||||
BrushLocation.Y >= Map.MapSize.Y ||
|
||||
BrushLocation.X < 0 ||
|
||||
BrushLocation.Y < 0)
|
||||
return;
|
||||
|
||||
Actor = null;
|
||||
Brush = null;
|
||||
Resource = null;
|
||||
Waypoint = null;
|
||||
|
||||
var key = Map.Actors.FirstOrDefault(a => a.Value.Location == GetBrushLocation());
|
||||
var key = Map.Actors.FirstOrDefault(a => a.Value.Location() == BrushLocation);
|
||||
if (key.Key != null) Map.Actors.Remove(key.Key);
|
||||
|
||||
if (Map.MapResources[GetBrushLocation().X, GetBrushLocation().Y].type != 0)
|
||||
if (Map.MapResources[BrushLocation.X, BrushLocation.Y].type != 0)
|
||||
{
|
||||
Map.MapResources[GetBrushLocation().X, GetBrushLocation().Y] = new TileReference<byte, byte>();
|
||||
var ch = new int2((GetBrushLocation().X) / ChunkSize, (GetBrushLocation().Y) / ChunkSize);
|
||||
Map.MapResources[BrushLocation.X, BrushLocation.Y] = new TileReference<byte, byte>();
|
||||
var ch = new int2((BrushLocation.X) / ChunkSize, (BrushLocation.Y) / ChunkSize);
|
||||
if (Chunks.ContainsKey(ch))
|
||||
{
|
||||
Chunks[ch].Dispose();
|
||||
@@ -220,8 +273,10 @@ namespace OpenRA.Editor
|
||||
}
|
||||
}
|
||||
|
||||
var k = Map.Waypoints.FirstOrDefault(a => a.Value == GetBrushLocation());
|
||||
var k = Map.Waypoints.FirstOrDefault(a => a.Value == BrushLocation);
|
||||
if (k.Key != null) Map.Waypoints.Remove(k.Key);
|
||||
|
||||
AfterChange();
|
||||
}
|
||||
|
||||
void Draw()
|
||||
@@ -230,6 +285,8 @@ namespace OpenRA.Editor
|
||||
if (Actor != null) DrawWithActor();
|
||||
if (Resource != null) DrawWithResource();
|
||||
if (Waypoint != null) DrawWithWaypoint();
|
||||
|
||||
AfterChange();
|
||||
}
|
||||
|
||||
int id;
|
||||
@@ -244,15 +301,21 @@ namespace OpenRA.Editor
|
||||
|
||||
void DrawWithActor()
|
||||
{
|
||||
if (Map.Actors.Any(a => a.Value.Location == GetBrushLocation()))
|
||||
if (Map.Actors.Any(a => a.Value.Location() == GetBrushLocation()))
|
||||
return;
|
||||
|
||||
var owner = "Neutral";
|
||||
var id = NextActorName();
|
||||
Map.Actors[id] = new ActorReference(id,Actor.Info.Name.ToLowerInvariant(), GetBrushLocation(), owner);
|
||||
Map.Actors[id] = new ActorReference(Actor.Info.Name.ToLowerInvariant())
|
||||
{
|
||||
new LocationInit( GetBrushLocation() ),
|
||||
new OwnerInit( owner)
|
||||
};
|
||||
|
||||
AfterChange();
|
||||
}
|
||||
|
||||
Random r = new Random();
|
||||
System.Random r = new System.Random();
|
||||
void DrawWithResource()
|
||||
{
|
||||
Map.MapResources[GetBrushLocation().X, GetBrushLocation().Y]
|
||||
@@ -269,12 +332,16 @@ namespace OpenRA.Editor
|
||||
Chunks[ch].Dispose();
|
||||
Chunks.Remove(ch);
|
||||
}
|
||||
|
||||
AfterChange();
|
||||
}
|
||||
|
||||
protected override void OnMouseDown(MouseEventArgs e)
|
||||
{
|
||||
base.OnMouseDown(e);
|
||||
|
||||
if (Map == null) return;
|
||||
|
||||
if (!IsPanning)
|
||||
{
|
||||
if (e.Button == MouseButtons.Right) Erase();
|
||||
@@ -288,10 +355,11 @@ namespace OpenRA.Editor
|
||||
|
||||
Bitmap RenderChunk(int u, int v)
|
||||
{
|
||||
var bitmap = new Bitmap(ChunkSize * 24, ChunkSize * 24);
|
||||
|
||||
var bitmap = new Bitmap(ChunkSize * TileSet.TileSize, ChunkSize * TileSet.TileSize);
|
||||
bitmap.SetPixel(0, 0, Color.Green);
|
||||
|
||||
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
|
||||
|
||||
unsafe
|
||||
@@ -306,9 +374,9 @@ namespace OpenRA.Editor
|
||||
var tile = TileSet.Tiles[tr.type];
|
||||
var index = (tr.image < tile.TileBitmapBytes.Count) ? tr.image : (byte)0;
|
||||
var rawImage = tile.TileBitmapBytes[index];
|
||||
for (var x = 0; x < 24; x++)
|
||||
for (var y = 0; y < 24; y++)
|
||||
p[ (j * 24 + y) * stride + i * 24 + x ] = Palette.GetColor(rawImage[x + 24 * y]).ToArgb();
|
||||
for (var x = 0; x < TileSet.TileSize; x++)
|
||||
for (var y = 0; y < TileSet.TileSize; y++)
|
||||
p[(j * TileSet.TileSize + y) * stride + i * TileSet.TileSize + x] = Palette.GetColor(rawImage[x + TileSet.TileSize * y]).ToArgb();
|
||||
|
||||
if (Map.MapResources[u * ChunkSize + i, v * ChunkSize + j].type != 0)
|
||||
{
|
||||
@@ -319,12 +387,12 @@ namespace OpenRA.Editor
|
||||
int* q = (int*)srcdata.Scan0.ToPointer();
|
||||
var srcstride = srcdata.Stride >> 2;
|
||||
|
||||
for (var x = 0; x < 24; x++)
|
||||
for (var y = 0; y < 24; y++)
|
||||
for (var x = 0; x < TileSet.TileSize; x++)
|
||||
for (var y = 0; y < TileSet.TileSize; y++)
|
||||
{
|
||||
var c = q[y * srcstride + x];
|
||||
if ((c & 0xff000000) != 0) /* quick & dirty, i cbf doing real alpha */
|
||||
p[(j * 24 + y) * stride + i * 24 + x] = c;
|
||||
p[(j * TileSet.TileSize + y) * stride + i * TileSet.TileSize + x] = c;
|
||||
}
|
||||
|
||||
resourceImage.UnlockBits(srcdata);
|
||||
@@ -338,28 +406,82 @@ namespace OpenRA.Editor
|
||||
|
||||
int2 GetBrushLocation()
|
||||
{
|
||||
var v = MousePos - Offset;
|
||||
return new int2(v.X / 24, v.Y / 24);
|
||||
var vX = (int)Math.Floor((MousePos.X - Offset.X) / Zoom);
|
||||
var vY = (int)Math.Floor((MousePos.Y - Offset.Y) / Zoom);
|
||||
return new int2(vX / TileSet.TileSize, vY / TileSet.TileSize);
|
||||
}
|
||||
|
||||
void DrawActor(System.Drawing.Graphics g, int2 p, ActorTemplate t)
|
||||
void DrawActor(System.Drawing.Graphics g, int2 p, ActorTemplate t, ColorPalette cp)
|
||||
{
|
||||
g.DrawImage(t.Bitmap,
|
||||
((24 * p + Offset
|
||||
- (t.Centered
|
||||
? new int2(t.Bitmap.Width / 2 - 12, t.Bitmap.Height / 2 - 12)
|
||||
: int2.Zero)).ToPoint()));
|
||||
var centered = t.Appearance == null || !t.Appearance.RelativeToTopLeft;
|
||||
|
||||
float OffsetX = centered ? t.Bitmap.Width / 2 - TileSet.TileSize / 2 : 0;
|
||||
float DrawX = TileSet.TileSize * p.X * Zoom + Offset.X - OffsetX;
|
||||
|
||||
float OffsetY = centered ? t.Bitmap.Height / 2 - TileSet.TileSize / 2 : 0;
|
||||
float DrawY = TileSet.TileSize * p.Y * Zoom + Offset.Y - OffsetY;
|
||||
|
||||
float width = t.Bitmap.Width * Zoom;
|
||||
float height = t.Bitmap.Height * Zoom;
|
||||
RectangleF sourceRect = new RectangleF(0, 0, t.Bitmap.Width, t.Bitmap.Height);
|
||||
RectangleF destRect = new RectangleF(DrawX, DrawY, width, height);
|
||||
|
||||
var restorePalette = t.Bitmap.Palette;
|
||||
if (cp != null) t.Bitmap.Palette = cp;
|
||||
g.DrawImage(t.Bitmap, destRect, sourceRect, GraphicsUnit.Pixel);
|
||||
if (cp != null) t.Bitmap.Palette = restorePalette;
|
||||
}
|
||||
|
||||
void DrawImage(System.Drawing.Graphics g, Bitmap bmp, int2 location)
|
||||
{
|
||||
float OffsetX = bmp.Width / 2 - TileSet.TileSize / 2;
|
||||
float DrawX = TileSet.TileSize * location.X * Zoom + Offset.X - OffsetX;
|
||||
|
||||
float OffsetY = bmp.Height / 2 - TileSet.TileSize / 2;
|
||||
float DrawY = TileSet.TileSize * location.Y * Zoom + Offset.Y - OffsetY;
|
||||
|
||||
float width = bmp.Width * Zoom;
|
||||
float height = bmp.Height * Zoom;
|
||||
RectangleF sourceRect = new RectangleF(0, 0, bmp.Width, bmp.Height);
|
||||
RectangleF destRect = new RectangleF(DrawX, DrawY, width, height);
|
||||
g.DrawImage(bmp, destRect, sourceRect, GraphicsUnit.Pixel);
|
||||
}
|
||||
|
||||
void DrawActorBorder(System.Drawing.Graphics g, int2 p, ActorTemplate t)
|
||||
{
|
||||
var origin = (24 * p + Offset
|
||||
- (t.Centered
|
||||
? new int2(t.Bitmap.Width / 2 - 12, t.Bitmap.Height / 2 - 12)
|
||||
: int2.Zero)).ToPoint();
|
||||
var centered = t.Appearance == null || !t.Appearance.RelativeToTopLeft;
|
||||
|
||||
float OffsetX = centered ? t.Bitmap.Width / 2 - TileSet.TileSize / 2 : 0;
|
||||
float DrawX = TileSet.TileSize * p.X * Zoom + Offset.X - OffsetX;
|
||||
|
||||
float OffsetY = centered ? t.Bitmap.Height / 2 - TileSet.TileSize / 2 : 0;
|
||||
float DrawY = TileSet.TileSize * p.Y * Zoom + Offset.Y - OffsetY;
|
||||
|
||||
g.DrawRectangle(CordonPen,
|
||||
origin.X, origin.Y,
|
||||
t.Bitmap.Width, t.Bitmap.Height );
|
||||
DrawX, DrawY,
|
||||
t.Bitmap.Width * Zoom, t.Bitmap.Height * Zoom);
|
||||
}
|
||||
|
||||
ColorPalette GetPaletteForPlayer(string name)
|
||||
{
|
||||
var pr = Map.Players[name];
|
||||
var pcpi = Rules.Info["player"].Traits.Get<PlayerColorPaletteInfo>();
|
||||
var remap = new PlayerColorRemap(pr.Color, pr.Color2, pcpi.PaletteFormat);
|
||||
return RenderUtils.MakeSystemPalette(new Palette(Palette, remap));
|
||||
}
|
||||
|
||||
Cache<string, ColorPalette> PlayerPalettes;
|
||||
|
||||
ColorPalette GetPaletteForActor(ActorReference ar)
|
||||
{
|
||||
if (PlayerPalettes == null)
|
||||
PlayerPalettes = new Cache<string, ColorPalette>(GetPaletteForPlayer);
|
||||
|
||||
var ownerInit = ar.InitDict.GetOrDefault<OwnerInit>();
|
||||
if (ownerInit == null)
|
||||
return null;
|
||||
|
||||
return PlayerPalettes[ownerInit.PlayerName];
|
||||
}
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
@@ -367,49 +489,71 @@ namespace OpenRA.Editor
|
||||
if (Map == null) return;
|
||||
if (TileSet == null) return;
|
||||
|
||||
for( var u = 0; u < Map.MapSize.X; u += ChunkSize )
|
||||
for (var u = 0; u < Map.MapSize.X; u += ChunkSize)
|
||||
for (var v = 0; v < Map.MapSize.Y; v += ChunkSize)
|
||||
{
|
||||
var x = new int2(u/ChunkSize,v/ChunkSize);
|
||||
var x = new int2(u / ChunkSize, v / ChunkSize);
|
||||
if (!Chunks.ContainsKey(x)) Chunks[x] = RenderChunk(u / ChunkSize, v / ChunkSize);
|
||||
e.Graphics.DrawImage(Chunks[x], (24 * ChunkSize * x + Offset).ToPoint());
|
||||
|
||||
Bitmap bmp = Chunks[x];
|
||||
|
||||
float DrawX = TileSet.TileSize * 1f * (float)ChunkSize * (float)x.X * Zoom + Offset.X;
|
||||
float DrawY = TileSet.TileSize * 1f * (float)ChunkSize * (float)x.Y * Zoom + Offset.Y;
|
||||
RectangleF sourceRect = new RectangleF(0, 0, bmp.Width, bmp.Height);
|
||||
RectangleF destRect = new RectangleF(DrawX, DrawY, bmp.Width * Zoom, bmp.Height * Zoom);
|
||||
e.Graphics.DrawImage(bmp, destRect, sourceRect, GraphicsUnit.Pixel);
|
||||
}
|
||||
|
||||
e.Graphics.DrawRectangle(CordonPen,
|
||||
new Rectangle(Map.XOffset * 24 + Offset.X, Map.YOffset * 24 + Offset.Y, Map.Width * 24, Map.Height * 24));
|
||||
Map.XOffset * TileSet.TileSize * Zoom + Offset.X,
|
||||
Map.YOffset * TileSet.TileSize * Zoom + Offset.Y,
|
||||
Map.Width * TileSet.TileSize * Zoom,
|
||||
Map.Height * TileSet.TileSize * Zoom);
|
||||
|
||||
foreach (var ar in Map.Actors)
|
||||
DrawActor(e.Graphics, ar.Value.Location, ActorTemplates[ar.Value.Type]);
|
||||
DrawActor(e.Graphics, ar.Value.Location(), ActorTemplates[ar.Value.Type],
|
||||
GetPaletteForActor(ar.Value));
|
||||
|
||||
foreach (var wp in Map.Waypoints)
|
||||
e.Graphics.DrawRectangle(Pens.LimeGreen, new Rectangle(
|
||||
24 * wp.Value.X + Offset.X + 4,
|
||||
24 * wp.Value.Y + Offset.Y + 4,
|
||||
16, 16));
|
||||
e.Graphics.DrawRectangle(Pens.LimeGreen,
|
||||
TileSet.TileSize * wp.Value.X * Zoom + Offset.X + 4,
|
||||
TileSet.TileSize * wp.Value.Y * Zoom + Offset.Y + 4,
|
||||
(TileSet.TileSize - 8) * Zoom, (TileSet.TileSize - 8) * Zoom);
|
||||
|
||||
if (Brush != null)
|
||||
e.Graphics.DrawImage(Brush.Bitmap,
|
||||
(24 * GetBrushLocation() + Offset).ToPoint());
|
||||
TileSet.TileSize * GetBrushLocation().X * Zoom + Offset.X,
|
||||
TileSet.TileSize * GetBrushLocation().Y * Zoom + Offset.Y,
|
||||
Brush.Bitmap.Width * Zoom,
|
||||
Brush.Bitmap.Height * Zoom);
|
||||
|
||||
if (Actor != null)
|
||||
DrawActor(e.Graphics, GetBrushLocation(), Actor);
|
||||
DrawActor(e.Graphics, GetBrushLocation(), Actor, null); /* todo: include the player
|
||||
* in the brush so we can color new buildings too */
|
||||
|
||||
if (Resource != null)
|
||||
e.Graphics.DrawImage(Resource.Bitmap,
|
||||
(24 * GetBrushLocation() + Offset).ToPoint());
|
||||
DrawImage(e.Graphics, Resource.Bitmap, GetBrushLocation());
|
||||
|
||||
if (Waypoint != null)
|
||||
e.Graphics.DrawRectangle(Pens.LimeGreen, new Rectangle(
|
||||
24 * GetBrushLocation().X + Offset.X + 4,
|
||||
24 * GetBrushLocation().Y + Offset.Y + 4,
|
||||
16, 16));
|
||||
e.Graphics.DrawRectangle(Pens.LimeGreen,
|
||||
TileSet.TileSize * GetBrushLocation().X * Zoom + Offset.X + 4,
|
||||
TileSet.TileSize * GetBrushLocation().Y * Zoom + Offset.Y + 4,
|
||||
(TileSet.TileSize - 8) * Zoom, (TileSet.TileSize - 8) * Zoom);
|
||||
|
||||
if (Brush == null && Actor == null && Resource == null)
|
||||
{
|
||||
var x = Map.Actors.FirstOrDefault(a => a.Value.Location == GetBrushLocation());
|
||||
var x = Map.Actors.FirstOrDefault(a => a.Value.Location() == GetBrushLocation());
|
||||
if (x.Key != null)
|
||||
DrawActorBorder(e.Graphics, x.Value.Location, ActorTemplates[x.Value.Type]);
|
||||
DrawActorBorder(e.Graphics, x.Value.Location(), ActorTemplates[x.Value.Type]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class ActorReferenceExts
|
||||
{
|
||||
public static int2 Location(this ActorReference ar)
|
||||
{
|
||||
return ar.InitDict.Get<LocationInit>().value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Packaging;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class CompressedPackage : IFolder
|
||||
{
|
||||
readonly uint[] hashes;
|
||||
readonly Stream s;
|
||||
readonly ZipPackage pkg;
|
||||
|
||||
public CompressedPackage(string filename)
|
||||
{
|
||||
s = FileSystem.Open(filename);
|
||||
pkg = (ZipPackage)ZipPackage.Open(s, FileMode.Open);
|
||||
hashes = pkg.GetParts()
|
||||
.Select(p => PackageEntry.HashFilename(p.Uri.LocalPath)).ToArray();
|
||||
}
|
||||
|
||||
public Stream GetContent(string filename)
|
||||
{
|
||||
return pkg.GetPart(new Uri(filename)).GetStream(FileMode.Open);
|
||||
}
|
||||
|
||||
public IEnumerable<uint> AllFileHashes() { return hashes; }
|
||||
}
|
||||
}
|
||||
22
OpenRA.FileFormats/Exts.cs
Normal file → Executable file
22
OpenRA.FileFormats/Exts.cs
Normal file → Executable file
@@ -73,5 +73,27 @@ namespace OpenRA
|
||||
{
|
||||
return mi.GetCustomAttributes(typeof(T), true).Length != 0;
|
||||
}
|
||||
|
||||
public static T[] GetCustomAttributes<T>( this MemberInfo mi, bool inherit )
|
||||
where T : class
|
||||
{
|
||||
return (T[])mi.GetCustomAttributes( typeof( T ), inherit );
|
||||
}
|
||||
|
||||
public static T[] GetCustomAttributes<T>( this ParameterInfo mi )
|
||||
where T : class
|
||||
{
|
||||
return (T[])mi.GetCustomAttributes( typeof( T ), true );
|
||||
}
|
||||
|
||||
public static T Clamp<T>(this T val, T min, T max) where T : IComparable<T>
|
||||
{
|
||||
if (val.CompareTo(min) < 0)
|
||||
return min;
|
||||
else if (val.CompareTo(max) > 0)
|
||||
return max;
|
||||
else
|
||||
return val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
172
OpenRA.FileFormats/FieldLoader.cs
Normal file → Executable file
172
OpenRA.FileFormats/FieldLoader.cs
Normal file → Executable file
@@ -13,6 +13,7 @@ using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Globalization;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
@@ -22,19 +23,40 @@ namespace OpenRA.FileFormats
|
||||
{
|
||||
throw new InvalidOperationException("FieldLoader: Cannot parse `{0}` into `{1}.{2}` ".F(s,f,t) );
|
||||
};
|
||||
|
||||
|
||||
public static Action<string,Type> UnknownFieldAction = (s,f) =>
|
||||
{
|
||||
throw new NotImplementedException( "FieldLoader: Missing field `{0}` on `{1}`".F( s, f.Name ) );
|
||||
};
|
||||
|
||||
public static void Load(object self, MiniYaml my) { Load(self, my.Nodes); }
|
||||
|
||||
public static void Load(object self, Dictionary<string, MiniYaml> my)
|
||||
public static void Load( object self, MiniYaml my )
|
||||
{
|
||||
foreach (var x in my)
|
||||
if (!x.Key.StartsWith("-"))
|
||||
LoadField(self, x.Key, x.Value.Value);
|
||||
var loadDict = typeLoadInfo[ self.GetType() ];
|
||||
|
||||
foreach( var kv in loadDict )
|
||||
{
|
||||
object val;
|
||||
if( kv.Value != null )
|
||||
val = kv.Value( kv.Key.Name, kv.Key.FieldType, my );
|
||||
else if( !TryGetValueFromYaml( kv.Key.Name, kv.Key.FieldType, my, out val ) )
|
||||
continue;
|
||||
|
||||
kv.Key.SetValue( self, val );
|
||||
}
|
||||
}
|
||||
|
||||
static bool TryGetValueFromYaml( string fieldName, Type fieldType, MiniYaml yaml, out object ret )
|
||||
{
|
||||
ret = null;
|
||||
var n = yaml.Nodes.Where( x=>x.Key == fieldName ).ToList();
|
||||
if( n.Count == 0 )
|
||||
return false;
|
||||
if( n.Count == 1 && n[ 0 ].Value.Nodes.Count == 0 )
|
||||
{
|
||||
ret = GetValue( fieldName, fieldType, n[ 0 ].Value.Value );
|
||||
return true;
|
||||
}
|
||||
throw new InvalidOperationException( "TryGetValueFromYaml: unable to load field {0} (of type {1})".F( fieldName, fieldType ) );
|
||||
}
|
||||
|
||||
public static T Load<T>(MiniYaml y) where T : new()
|
||||
@@ -43,26 +65,19 @@ namespace OpenRA.FileFormats
|
||||
Load(t, y);
|
||||
return t;
|
||||
}
|
||||
|
||||
public static void LoadFields( object self, Dictionary<string,MiniYaml> my, IEnumerable<string> fields )
|
||||
{
|
||||
foreach (var field in fields)
|
||||
{
|
||||
if (!my.ContainsKey(field)) continue;
|
||||
LoadField(self,field,my[field].Value);
|
||||
}
|
||||
}
|
||||
|
||||
public static void LoadField( object self, string key, string value )
|
||||
{
|
||||
var field = self.GetType().GetField( key.Trim() );
|
||||
|
||||
if( field == null )
|
||||
UnknownFieldAction(key.Trim(), self.GetType());
|
||||
UnknownFieldAction( key.Trim(), self.GetType() );
|
||||
else if( field.HasAttribute<FieldFromYamlKeyAttribute>() )
|
||||
return;
|
||||
else
|
||||
field.SetValue( self, GetValue( field.Name, field.FieldType, value ) );
|
||||
}
|
||||
|
||||
|
||||
public static object GetValue( string field, Type fieldType, string x )
|
||||
{
|
||||
if (x != null) x = x.Trim();
|
||||
@@ -73,7 +88,7 @@ namespace OpenRA.FileFormats
|
||||
return res;
|
||||
return InvalidValueAction(x,fieldType, field);
|
||||
}
|
||||
|
||||
|
||||
else if( fieldType == typeof( ushort ) )
|
||||
{
|
||||
ushort res;
|
||||
@@ -85,31 +100,39 @@ namespace OpenRA.FileFormats
|
||||
else if (fieldType == typeof(float))
|
||||
{
|
||||
float res;
|
||||
if (float.TryParse(x.Replace("%",""), out res))
|
||||
if (float.TryParse(x.Replace("%",""), System.Globalization.NumberStyles.Any, NumberFormatInfo.InvariantInfo, out res))
|
||||
return res * (x.Contains( '%' ) ? 0.01f : 1f);
|
||||
return InvalidValueAction(x,fieldType, field);
|
||||
}
|
||||
|
||||
else if (fieldType == typeof(decimal))
|
||||
{
|
||||
decimal res;
|
||||
if (decimal.TryParse(x.Replace("%",""), System.Globalization.NumberStyles.Any, NumberFormatInfo.InvariantInfo, out res))
|
||||
return res * (x.Contains( '%' ) ? 0.01m : 1m);
|
||||
return InvalidValueAction(x,fieldType, field);
|
||||
}
|
||||
|
||||
else if (fieldType == typeof(string))
|
||||
return x;
|
||||
|
||||
|
||||
else if (fieldType == typeof(Color))
|
||||
{
|
||||
var parts = x.Split(',');
|
||||
if (parts.Length == 3)
|
||||
return Color.FromArgb(int.Parse(parts[0]), int.Parse(parts[1]), int.Parse(parts[2]));
|
||||
return Color.FromArgb(int.Parse(parts[0]).Clamp(0, 255), int.Parse(parts[1]).Clamp(0, 255), int.Parse(parts[2]).Clamp(0, 255));
|
||||
if (parts.Length == 4)
|
||||
return Color.FromArgb(int.Parse(parts[0]), int.Parse(parts[1]), int.Parse(parts[2]), int.Parse(parts[3]));
|
||||
return Color.FromArgb(int.Parse(parts[0]).Clamp(0, 255), int.Parse(parts[1]).Clamp(0, 255), int.Parse(parts[2]).Clamp(0, 255), int.Parse(parts[3]).Clamp(0, 255));
|
||||
return InvalidValueAction(x,fieldType, field);
|
||||
}
|
||||
|
||||
|
||||
else if (fieldType.IsEnum)
|
||||
{
|
||||
if (!Enum.GetNames(fieldType).Select(a => a.ToLower()).Contains(x.ToLower()))
|
||||
return InvalidValueAction(x,fieldType, field);
|
||||
return Enum.Parse(fieldType, x, true);
|
||||
}
|
||||
|
||||
|
||||
else if (fieldType == typeof(bool))
|
||||
return ParseYesNo(x, fieldType, field);
|
||||
|
||||
@@ -130,7 +153,19 @@ namespace OpenRA.FileFormats
|
||||
var parts = x.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
return new int2(int.Parse(parts[0]), int.Parse(parts[1]));
|
||||
}
|
||||
|
||||
else if (fieldType == typeof(float2))
|
||||
{
|
||||
var parts = x.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
float xx = 0;
|
||||
float yy = 0;
|
||||
float res;
|
||||
if (float.TryParse(parts[0].Replace("%",""), out res))
|
||||
xx = res * (parts[0].Contains( '%' ) ? 0.01f : 1f);
|
||||
if (float.TryParse(parts[1].Replace("%",""), out res))
|
||||
yy = res * (parts[1].Contains( '%' ) ? 0.01f : 1f);
|
||||
return new float2(xx,yy);
|
||||
}
|
||||
|
||||
UnknownFieldAction("[Type] {0}".F(x),fieldType);
|
||||
return null;
|
||||
}
|
||||
@@ -144,18 +179,76 @@ namespace OpenRA.FileFormats
|
||||
if( p == "false" ) return false;
|
||||
return InvalidValueAction(p,fieldType, field);
|
||||
}
|
||||
|
||||
static Cache<Type, Dictionary<FieldInfo, Func<string, Type, MiniYaml, object>>> typeLoadInfo = new Cache<Type, Dictionary<FieldInfo, Func<string, Type, MiniYaml, object>>>( GetTypeLoadInfo );
|
||||
|
||||
static Dictionary<FieldInfo, Func<string, Type, MiniYaml, object>> GetTypeLoadInfo( Type type )
|
||||
{
|
||||
var ret = new Dictionary<FieldInfo, Func<string, Type, MiniYaml, object>>();
|
||||
|
||||
foreach( var ff in type.GetFields() )
|
||||
{
|
||||
var field = ff;
|
||||
var load = field.GetCustomAttributes<LoadAttribute>( false );
|
||||
var loadUsing = field.GetCustomAttributes<LoadUsingAttribute>( false );
|
||||
var fromYamlKey = field.GetCustomAttributes<FieldFromYamlKeyAttribute>( false );
|
||||
if( loadUsing.Length != 0 )
|
||||
ret[ field ] = ( _1, fieldType, yaml ) => loadUsing[ 0 ].LoaderFunc( field )( yaml );
|
||||
else if( fromYamlKey.Length != 0 )
|
||||
ret[ field ] = ( f, ft, yaml ) => GetValue( f, ft, yaml.Value );
|
||||
else if( load.Length != 0 )
|
||||
ret[ field ] = null;
|
||||
}
|
||||
|
||||
if( ret.Count == 0 )
|
||||
foreach( var f in type.GetFields() )
|
||||
ret.Add( f, null );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
[AttributeUsage( AttributeTargets.Field )]
|
||||
public class LoadAttribute : Attribute { }
|
||||
|
||||
[AttributeUsage( AttributeTargets.Field )]
|
||||
public class LoadUsingAttribute : Attribute
|
||||
{
|
||||
Func<MiniYaml, object> loaderFuncCache;
|
||||
public readonly string Loader;
|
||||
|
||||
public LoadUsingAttribute( string loader )
|
||||
{
|
||||
Loader = loader;
|
||||
}
|
||||
|
||||
internal Func<MiniYaml, object> LoaderFunc( FieldInfo field )
|
||||
{
|
||||
const BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
|
||||
if( loaderFuncCache == null )
|
||||
loaderFuncCache = (Func<MiniYaml, object>)Delegate.CreateDelegate( typeof( Func<MiniYaml, object> ), field.DeclaringType.GetMethod( Loader, bf ) );
|
||||
return loaderFuncCache;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class FieldSaver
|
||||
{
|
||||
public static MiniYaml Save(object o)
|
||||
{
|
||||
return new MiniYaml(null, o.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance)
|
||||
.ToDictionary(
|
||||
f => f.Name,
|
||||
f => new MiniYaml(FormatValue(o, f))));
|
||||
var nodes = new List<MiniYamlNode>();
|
||||
string root = null;
|
||||
|
||||
foreach( var f in o.GetType().GetFields( BindingFlags.Public | BindingFlags.Instance ) )
|
||||
{
|
||||
if( f.HasAttribute<FieldFromYamlKeyAttribute>() )
|
||||
root = FormatValue( o, f );
|
||||
else
|
||||
nodes.Add( new MiniYamlNode( f.Name, FormatValue( o, f ) ) );
|
||||
}
|
||||
|
||||
return new MiniYaml( root, nodes );
|
||||
}
|
||||
|
||||
|
||||
public static MiniYaml SaveDifferences(object o, object from)
|
||||
{
|
||||
if (o.GetType() != from.GetType())
|
||||
@@ -163,10 +256,10 @@ namespace OpenRA.FileFormats
|
||||
|
||||
var fields = o.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance)
|
||||
.Where(f => FormatValue(o,f) != FormatValue(from,f));
|
||||
|
||||
return new MiniYaml(null, fields.ToDictionary(
|
||||
f => f.Name,
|
||||
f => new MiniYaml(FormatValue(o, f))));
|
||||
|
||||
return new MiniYaml( null, fields.Select( f => new MiniYamlNode(
|
||||
f.Name,
|
||||
FormatValue( o, f ) ) ).ToList() );
|
||||
}
|
||||
|
||||
public static string FormatValue(object o, FieldInfo f)
|
||||
@@ -179,12 +272,17 @@ namespace OpenRA.FileFormats
|
||||
if (f.FieldType == typeof(Color))
|
||||
{
|
||||
var c = (Color)v;
|
||||
return "{0},{1},{2},{3}".F(c.A,c.R,c.G,c.B);
|
||||
return "{0},{1},{2},{3}".F(((int)c.A).Clamp(0, 255),
|
||||
((int)c.R).Clamp(0, 255),
|
||||
((int)c.G).Clamp(0, 255),
|
||||
((int)c.B).Clamp(0, 255));
|
||||
}
|
||||
|
||||
|
||||
return f.FieldType.IsArray
|
||||
? string.Join(",", ((Array)v).OfType<object>().Select(a => a.ToString()).ToArray())
|
||||
: v.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public class FieldFromYamlKeyAttribute : Attribute { }
|
||||
}
|
||||
|
||||
@@ -76,6 +76,46 @@ namespace OpenRA.FileFormats
|
||||
return (short)current;
|
||||
}
|
||||
|
||||
public static byte[] LoadSound(byte[] raw, ref int index)
|
||||
{
|
||||
var br = new BinaryReader(new MemoryStream(raw));
|
||||
var dataSize = raw.Length;
|
||||
var outputSize = raw.Length * 4;
|
||||
|
||||
var output = new byte[outputSize];
|
||||
var offset = 0;
|
||||
var currentSample = 0;
|
||||
|
||||
while (dataSize-- > 0)
|
||||
{
|
||||
var b = br.ReadByte();
|
||||
|
||||
var t = DecodeSample(b, ref index, ref currentSample);
|
||||
output[offset++] = (byte)t;
|
||||
output[offset++] = (byte)(t >> 8);
|
||||
|
||||
t = DecodeSample((byte)(b >> 4), ref index, ref currentSample);
|
||||
output[offset++] = (byte)t;
|
||||
output[offset++] = (byte)(t >> 8);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
public static float SoundLength(Stream s)
|
||||
{
|
||||
var br = new BinaryReader(s);
|
||||
var sampleRate = br.ReadUInt16();
|
||||
/*var dataSize = */ br.ReadInt32();
|
||||
var outputSize = br.ReadInt32();
|
||||
var flags = (SoundFlags) br.ReadByte();
|
||||
|
||||
var samples = outputSize;
|
||||
if (0 != (flags & SoundFlags.Stereo)) samples /= 2;
|
||||
if (0 != (flags & SoundFlags._16Bit)) samples /= 2;
|
||||
return samples / sampleRate;
|
||||
}
|
||||
|
||||
public static byte[] LoadSound(Stream s)
|
||||
{
|
||||
var br = new BinaryReader(s);
|
||||
|
||||
274
OpenRA.FileFormats/FileFormats/Blast.cs
Normal file
274
OpenRA.FileFormats/FileFormats/Blast.cs
Normal file
@@ -0,0 +1,274 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*
|
||||
* This file is based on the blast routines (version 1.1 by Mark Adler)
|
||||
* included in zlib/contrib
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public static class Blast
|
||||
{
|
||||
public static readonly int MAXBITS = 13; // maximum code length
|
||||
public static readonly int MAXWIN = 4096; // maximum window size
|
||||
|
||||
static byte[] litlen = new byte[] {
|
||||
11, 124, 8, 7, 28, 7, 188, 13, 76, 4,
|
||||
10, 8, 12, 10, 12, 10, 8, 23, 8, 9,
|
||||
7, 6, 7, 8, 7, 6, 55, 8, 23, 24,
|
||||
12, 11, 7, 9, 11, 12, 6, 7, 22, 5,
|
||||
7, 24, 6, 11, 9, 6, 7, 22, 7, 11,
|
||||
38, 7, 9, 8, 25, 11, 8, 11, 9, 12,
|
||||
8, 12, 5, 38, 5, 38, 5, 11, 7, 5,
|
||||
6, 21, 6, 10, 53, 8, 7, 24, 10, 27,
|
||||
44, 253, 253, 253, 252, 252, 252, 13, 12, 45,
|
||||
12, 45, 12, 61, 12, 45, 44, 173
|
||||
};
|
||||
|
||||
// bit lengths of length codes 0..15
|
||||
static byte[] lenlen = new byte[] { 2, 35, 36, 53, 38, 23 };
|
||||
|
||||
// bit lengths of distance codes 0..63
|
||||
static byte[] distlen = new byte[] { 2, 20, 53, 230, 247, 151, 248 };
|
||||
|
||||
// base for length codes
|
||||
static short[] lengthbase = new short[] {
|
||||
3, 2, 4, 5, 6, 7, 8, 9, 10, 12,
|
||||
16, 24, 40, 72, 136, 264
|
||||
};
|
||||
|
||||
// extra bits for length codes
|
||||
static byte[] extra = new byte[] {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 2,
|
||||
3, 4, 5, 6, 7, 8
|
||||
};
|
||||
|
||||
static Huffman litcode = new Huffman(litlen, litlen.Length, 256);
|
||||
static Huffman lencode = new Huffman(lenlen, lenlen.Length, 16);
|
||||
static Huffman distcode = new Huffman(distlen, distlen.Length, 64);
|
||||
|
||||
// Decode PKWare Compression Library stream.
|
||||
public static byte[] Decompress(byte[] src)
|
||||
{
|
||||
BitReader br = new BitReader(src);
|
||||
|
||||
// Are literals coded?
|
||||
int coded = br.ReadBits(8);
|
||||
|
||||
if (coded < 0 || coded > 1)
|
||||
throw new NotImplementedException("Invalid datastream");
|
||||
bool EncodedLiterals = (coded == 1);
|
||||
|
||||
// log2(dictionary size) - 6
|
||||
int dict = br.ReadBits(8);
|
||||
if (dict < 4 || dict > 6)
|
||||
throw new InvalidDataException("Invalid dictionary size");
|
||||
|
||||
// output state
|
||||
ushort next = 0; // index of next write location in out[]
|
||||
bool first = true; // true to check distances (for first 4K)
|
||||
byte[] outBuffer = new byte[MAXWIN]; // output buffer and sliding window
|
||||
var ms = new MemoryStream();
|
||||
|
||||
// decode literals and length/distance pairs
|
||||
do
|
||||
{
|
||||
// length/distance pair
|
||||
if (br.ReadBits(1) == 1)
|
||||
{
|
||||
// Length
|
||||
int symbol = Decode(lencode, br);
|
||||
int len = lengthbase[symbol] + br.ReadBits(extra[symbol]);
|
||||
if (len == 519) // Magic number for "done"
|
||||
{
|
||||
for (int i = 0; i < next; i++)
|
||||
ms.WriteByte(outBuffer[i]);
|
||||
break;
|
||||
}
|
||||
|
||||
// Distance
|
||||
symbol = len == 2 ? 2 : dict;
|
||||
int dist = Decode(distcode, br) << symbol;
|
||||
dist += br.ReadBits(symbol);
|
||||
dist++;
|
||||
|
||||
if (first && dist > next)
|
||||
throw new InvalidDataException("Attempt to jump before data");
|
||||
|
||||
// copy length bytes from distance bytes back
|
||||
do
|
||||
{
|
||||
int dest = next;
|
||||
int source = dest - dist;
|
||||
|
||||
int copy = MAXWIN;
|
||||
if (next < dist)
|
||||
{
|
||||
source += copy;
|
||||
copy = dist;
|
||||
}
|
||||
|
||||
copy -= next;
|
||||
if (copy > len)
|
||||
copy = len;
|
||||
|
||||
len -= copy;
|
||||
next += (ushort)copy;
|
||||
Array.Copy(outBuffer, source, outBuffer, dest, copy);
|
||||
|
||||
// Flush window to outstream
|
||||
if (next == MAXWIN)
|
||||
{
|
||||
for (int i = 0; i < next; i++)
|
||||
ms.WriteByte(outBuffer[i]);
|
||||
next = 0;
|
||||
first = false;
|
||||
}
|
||||
} while (len != 0);
|
||||
}
|
||||
else // literal value
|
||||
{
|
||||
int symbol = EncodedLiterals ? Decode(litcode, br) : br.ReadBits(8);
|
||||
outBuffer[next++] = (byte)symbol;
|
||||
if (next == MAXWIN)
|
||||
{
|
||||
for (int i = 0; i < next; i++)
|
||||
ms.WriteByte(outBuffer[i]);
|
||||
next = 0;
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
} while (true);
|
||||
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
// Decode a code using huffman table h.
|
||||
private static int Decode(Huffman h, BitReader br)
|
||||
{
|
||||
int code = 0; // len bits being decoded
|
||||
int first = 0; // first code of length len
|
||||
int index = 0; // index of first code of length len in symbol table
|
||||
short next = 1;
|
||||
while (true)
|
||||
{
|
||||
code |= br.ReadBits(1) ^ 1; // invert code
|
||||
int count = h.Count[next++];
|
||||
if (code < first + count)
|
||||
return h.Symbol[index + (code - first)];
|
||||
|
||||
index += count;
|
||||
first += count;
|
||||
first <<= 1;
|
||||
code <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class BitReader
|
||||
{
|
||||
readonly byte[] src;
|
||||
int offset = 0;
|
||||
int bitBuffer = 0;
|
||||
int bitCount = 0;
|
||||
|
||||
public BitReader(byte[] src)
|
||||
{
|
||||
this.src = src;
|
||||
}
|
||||
|
||||
public int ReadBits(int count)
|
||||
{
|
||||
int ret = 0;
|
||||
int filled = 0;
|
||||
while (filled < count)
|
||||
{
|
||||
if (bitCount == 0)
|
||||
{
|
||||
bitBuffer = src[offset++];
|
||||
bitCount = 8;
|
||||
}
|
||||
|
||||
ret |= (bitBuffer & 1) << filled;
|
||||
bitBuffer >>= 1;
|
||||
bitCount--;
|
||||
filled++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a list of repeated code lengths rep[0..n-1], where each byte is a
|
||||
* count (high four bits + 1) and a code length (low four bits), generate the
|
||||
* list of code lengths. This compaction reduces the size of the object code.
|
||||
* Then given the list of code lengths length[0..n-1] representing a canonical
|
||||
* Huffman code for n symbols, construct the tables required to decode those
|
||||
* codes. Those tables are the number of codes of each length, and the symbols
|
||||
* sorted by length, retaining their original order within each length.
|
||||
*/
|
||||
class Huffman
|
||||
{
|
||||
public short[] Count; // number of symbols of each length
|
||||
public short[] Symbol; // canonically ordered symbols
|
||||
|
||||
public Huffman(byte[] rep, int n, short SymbolCount)
|
||||
{
|
||||
short[] length = new short[256]; // code lengths
|
||||
int s = 0; // current symbol
|
||||
|
||||
// convert compact repeat counts into symbol bit length list
|
||||
foreach (byte code in rep)
|
||||
{
|
||||
int num = (code >> 4) + 1; // Number of codes (top four bits plus 1)
|
||||
byte len = (byte)(code & 15); // Code length (low four bits)
|
||||
do
|
||||
{
|
||||
length[s++] = len;
|
||||
} while (--num > 0);
|
||||
}
|
||||
n = s;
|
||||
|
||||
// count number of codes of each length
|
||||
Count = new short[Blast.MAXBITS + 1];
|
||||
for (int i = 0; i < n; i++)
|
||||
Count[length[i]]++;
|
||||
|
||||
// no codes!
|
||||
if (Count[0] == n)
|
||||
return;
|
||||
|
||||
// check for an over-subscribed or incomplete set of lengths
|
||||
int left = 1; // one possible code of zero length
|
||||
for (int len = 1; len <= Blast.MAXBITS; len++)
|
||||
{
|
||||
left <<= 1;
|
||||
// one more bit, double codes left
|
||||
left -= Count[len];
|
||||
// deduct count from possible codes
|
||||
if (left < 0)
|
||||
throw new InvalidDataException ("over subscribed code set");
|
||||
}
|
||||
|
||||
// generate offsets into symbol table for each length for sorting
|
||||
short[] offs = new short[Blast.MAXBITS + 1];
|
||||
for (int len = 1; len < Blast.MAXBITS; len++)
|
||||
offs[len + 1] = (short)(offs[len] + Count[len]);
|
||||
|
||||
// put symbols in table sorted by length, by symbol order within each length
|
||||
Symbol = new short[SymbolCount];
|
||||
for (short i = 0; i < n; i++)
|
||||
if (length[i] != 0)
|
||||
Symbol[offs[length[i]]++] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
@@ -33,19 +34,22 @@ namespace OpenRA.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
static int order = 0;
|
||||
|
||||
static IFolder OpenPackage(string filename)
|
||||
{
|
||||
if (filename.EndsWith(".mix"))
|
||||
return new Package(filename);
|
||||
else if (filename.EndsWith(".zip"))
|
||||
return new CompressedPackage(filename);
|
||||
if (filename.EndsWith(".mix", StringComparison.InvariantCultureIgnoreCase))
|
||||
return new MixFile(filename, order++);
|
||||
else if (filename.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase))
|
||||
return new ZipFile(filename, order++);
|
||||
else if (filename.EndsWith(".Z", StringComparison.InvariantCultureIgnoreCase))
|
||||
return new InstallShieldPackage(filename, order++);
|
||||
else
|
||||
return new Folder(filename);
|
||||
return new Folder(filename, order++);
|
||||
}
|
||||
|
||||
public static void Mount(string name)
|
||||
{
|
||||
name = name.ToLowerInvariant();
|
||||
var optional = name.StartsWith("~");
|
||||
if (optional) name = name.Substring(1);
|
||||
|
||||
@@ -64,14 +68,33 @@ namespace OpenRA.FileFormats
|
||||
allFiles = new Cache<uint, List<IFolder>>( _ => new List<IFolder>() );
|
||||
}
|
||||
|
||||
public static bool Unmount(IFolder mount)
|
||||
{
|
||||
return (mountedFolders.RemoveAll(f => f == mount) > 0);
|
||||
}
|
||||
|
||||
public static void Mount(IFolder mount)
|
||||
{
|
||||
if (!mountedFolders.Contains(mount)) mountedFolders.Add(mount);
|
||||
}
|
||||
|
||||
public static void LoadFromManifest( Manifest manifest )
|
||||
{
|
||||
UnmountAll();
|
||||
foreach (var dir in manifest.Folders) Mount(dir);
|
||||
foreach (var pkg in manifest.Packages) Mount(pkg);
|
||||
}
|
||||
|
||||
static Stream GetFromCache( Cache<uint, List<IFolder>> index, string filename )
|
||||
{
|
||||
foreach( var folder in index[ PackageEntry.HashFilename( filename ) ] )
|
||||
{
|
||||
Stream s = folder.GetContent(filename);
|
||||
if( s != null )
|
||||
return s;
|
||||
}
|
||||
var folder = index[PackageEntry.HashFilename(filename)]
|
||||
.Where(x => x.Exists(filename))
|
||||
.OrderBy(x => x.Priority)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (folder != null)
|
||||
return folder.GetContent(filename);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -84,12 +107,13 @@ namespace OpenRA.FileFormats
|
||||
return ret;
|
||||
}
|
||||
|
||||
foreach( IFolder folder in mountedFolders )
|
||||
{
|
||||
Stream s = folder.GetContent(filename);
|
||||
if( s != null )
|
||||
return s;
|
||||
}
|
||||
var folder = mountedFolders
|
||||
.Where(x => x.Exists(filename))
|
||||
.OrderByDescending(x => x.Priority)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (folder != null)
|
||||
return folder.GetContent(filename);
|
||||
|
||||
throw new FileNotFoundException( string.Format( "File not found: {0}", filename ), filename );
|
||||
}
|
||||
@@ -109,11 +133,8 @@ namespace OpenRA.FileFormats
|
||||
foreach( var ext in exts )
|
||||
{
|
||||
foreach( IFolder folder in mountedFolders )
|
||||
{
|
||||
Stream s = folder.GetContent( filename + ext );
|
||||
if( s != null )
|
||||
return s;
|
||||
}
|
||||
if (folder.Exists(filename + ext))
|
||||
return folder.GetContent( filename + ext );
|
||||
}
|
||||
|
||||
throw new FileNotFoundException( string.Format( "File not found: {0}", filename ), filename );
|
||||
@@ -122,15 +143,8 @@ namespace OpenRA.FileFormats
|
||||
public static bool Exists(string filename)
|
||||
{
|
||||
foreach (var folder in mountedFolders)
|
||||
{
|
||||
var s = folder.GetContent(filename);
|
||||
if (s != null)
|
||||
{
|
||||
s.Dispose();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (folder.Exists(filename))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,9 @@ namespace OpenRA.FileFormats
|
||||
{
|
||||
readonly string path;
|
||||
|
||||
public Folder(string path) { this.path = path; }
|
||||
int priority;
|
||||
|
||||
public Folder(string path, int priority) { this.path = path; this.priority = priority; }
|
||||
|
||||
public Stream GetContent(string filename)
|
||||
{
|
||||
@@ -28,7 +30,18 @@ namespace OpenRA.FileFormats
|
||||
public IEnumerable<uint> AllFileHashes()
|
||||
{
|
||||
foreach( var filename in Directory.GetFiles( path, "*", SearchOption.TopDirectoryOnly ) )
|
||||
yield return PackageEntry.HashFilename( filename );
|
||||
yield return PackageEntry.HashFilename( Path.GetFileName(filename) );
|
||||
}
|
||||
|
||||
public bool Exists(string filename)
|
||||
{
|
||||
return File.Exists(Path.Combine(path,filename));
|
||||
}
|
||||
|
||||
|
||||
public int Priority
|
||||
{
|
||||
get { return priority; }
|
||||
}
|
||||
}
|
||||
}
|
||||
121
OpenRA.FileFormats/Filesystem/InstallShieldPackage.cs
Normal file
121
OpenRA.FileFormats/Filesystem/InstallShieldPackage.cs
Normal file
@@ -0,0 +1,121 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class InstallShieldPackage : IFolder
|
||||
{
|
||||
readonly Dictionary<uint, PackageEntry> index = new Dictionary<uint, PackageEntry>();
|
||||
readonly Stream s;
|
||||
readonly long dataStart = 255;
|
||||
int priority;
|
||||
|
||||
public InstallShieldPackage(string filename, int priority)
|
||||
{
|
||||
this.priority = priority;
|
||||
s = FileSystem.Open(filename);
|
||||
|
||||
// Parse package header
|
||||
BinaryReader reader = new BinaryReader(s);
|
||||
uint signature = reader.ReadUInt32();
|
||||
if (signature != 0x8C655D13)
|
||||
throw new InvalidDataException("Not an Installshield package");
|
||||
|
||||
reader.ReadBytes(8);
|
||||
/*var FileCount = */reader.ReadUInt16();
|
||||
reader.ReadBytes(4);
|
||||
/*var ArchiveSize = */reader.ReadUInt32();
|
||||
reader.ReadBytes(19);
|
||||
var TOCAddress = reader.ReadInt32();
|
||||
reader.ReadBytes(4);
|
||||
var DirCount = reader.ReadUInt16();
|
||||
|
||||
// Parse the directory list
|
||||
s.Seek(TOCAddress, SeekOrigin.Begin);
|
||||
BinaryReader TOCreader = new BinaryReader(s);
|
||||
for (var i = 0; i < DirCount; i++)
|
||||
ParseDirectory(TOCreader);
|
||||
}
|
||||
|
||||
void ParseDirectory(BinaryReader reader)
|
||||
{
|
||||
// Parse directory header
|
||||
var FileCount = reader.ReadUInt16();
|
||||
var ChunkSize = reader.ReadUInt16();
|
||||
var NameLength = reader.ReadUInt16();
|
||||
reader.ReadChars(NameLength); //var DirName = new String(reader.ReadChars(NameLength));
|
||||
|
||||
// Skip to the end of the chunk
|
||||
reader.ReadBytes(ChunkSize - NameLength - 6);
|
||||
|
||||
// Parse files
|
||||
for (var i = 0; i < FileCount; i++)
|
||||
ParseFile(reader);
|
||||
}
|
||||
|
||||
uint AccumulatedData = 0;
|
||||
void ParseFile(BinaryReader reader)
|
||||
{
|
||||
reader.ReadBytes(7);
|
||||
var CompressedSize = reader.ReadUInt32();
|
||||
reader.ReadBytes(12);
|
||||
var ChunkSize = reader.ReadUInt16();
|
||||
reader.ReadBytes(4);
|
||||
var NameLength = reader.ReadByte();
|
||||
var FileName = new String(reader.ReadChars(NameLength));
|
||||
|
||||
var hash = PackageEntry.HashFilename(FileName);
|
||||
index.Add(hash, new PackageEntry(hash,AccumulatedData, CompressedSize));
|
||||
AccumulatedData += CompressedSize;
|
||||
|
||||
// Skip to the end of the chunk
|
||||
reader.ReadBytes(ChunkSize - NameLength - 30);
|
||||
}
|
||||
|
||||
public Stream GetContent(uint hash)
|
||||
{
|
||||
PackageEntry e;
|
||||
if (!index.TryGetValue(hash, out e))
|
||||
return null;
|
||||
|
||||
s.Seek( dataStart + e.Offset, SeekOrigin.Begin );
|
||||
byte[] data = new byte[ e.Length ];
|
||||
s.Read( data, 0, (int)e.Length );
|
||||
|
||||
return new MemoryStream(Blast.Decompress(data));
|
||||
}
|
||||
|
||||
public Stream GetContent(string filename)
|
||||
{
|
||||
return GetContent(PackageEntry.HashFilename(filename));
|
||||
}
|
||||
|
||||
public IEnumerable<uint> AllFileHashes()
|
||||
{
|
||||
return index.Keys;
|
||||
}
|
||||
|
||||
public bool Exists(string filename)
|
||||
{
|
||||
return index.ContainsKey(PackageEntry.HashFilename(filename));
|
||||
}
|
||||
|
||||
|
||||
public int Priority
|
||||
{
|
||||
get { return 2000 + priority; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,18 +18,22 @@ namespace OpenRA.FileFormats
|
||||
public interface IFolder
|
||||
{
|
||||
Stream GetContent(string filename);
|
||||
bool Exists(string filename);
|
||||
IEnumerable<uint> AllFileHashes();
|
||||
int Priority { get; }
|
||||
}
|
||||
|
||||
public class Package : IFolder
|
||||
public class MixFile : IFolder
|
||||
{
|
||||
readonly Dictionary<uint, PackageEntry> index;
|
||||
readonly bool isRmix, isEncrypted;
|
||||
readonly long dataStart;
|
||||
readonly Stream s;
|
||||
int priority;
|
||||
|
||||
public Package(string filename)
|
||||
public MixFile(string filename, int priority)
|
||||
{
|
||||
this.priority = priority;
|
||||
s = FileSystem.Open(filename);
|
||||
|
||||
BinaryReader reader = new BinaryReader(s);
|
||||
@@ -68,7 +72,7 @@ namespace OpenRA.FileFormats
|
||||
BinaryReader reader2 = new BinaryReader(ms);
|
||||
|
||||
ushort numFiles = reader2.ReadUInt16();
|
||||
uint datasize = reader2.ReadUInt32();
|
||||
reader2.ReadUInt32(); /*datasize*/
|
||||
|
||||
s.Position = headerStart;
|
||||
reader = new BinaryReader(s);
|
||||
@@ -143,6 +147,17 @@ namespace OpenRA.FileFormats
|
||||
{
|
||||
return index.Keys;
|
||||
}
|
||||
|
||||
public bool Exists(string filename)
|
||||
{
|
||||
return index.ContainsKey(PackageEntry.HashFilename(filename));
|
||||
}
|
||||
|
||||
|
||||
public int Priority
|
||||
{
|
||||
get { return 1000 + priority; }
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
52
OpenRA.FileFormats/Filesystem/ZipFile.cs
Normal file
52
OpenRA.FileFormats/Filesystem/ZipFile.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using ICSharpCode.SharpZipLib.Zip;
|
||||
using SZipFile = ICSharpCode.SharpZipLib.Zip.ZipFile;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class ZipFile : IFolder
|
||||
{
|
||||
readonly SZipFile pkg;
|
||||
int priority;
|
||||
|
||||
public ZipFile(string filename, int priority)
|
||||
{
|
||||
this.priority = priority;
|
||||
pkg = new SZipFile(File.OpenRead(filename));
|
||||
}
|
||||
|
||||
public Stream GetContent(string filename)
|
||||
{
|
||||
return pkg.GetInputStream(pkg.GetEntry(filename));
|
||||
}
|
||||
|
||||
public IEnumerable<uint> AllFileHashes()
|
||||
{
|
||||
foreach(ZipEntry entry in pkg)
|
||||
yield return PackageEntry.HashFilename(entry.Name);
|
||||
}
|
||||
|
||||
public bool Exists(string filename)
|
||||
{
|
||||
return pkg.GetEntry(filename) != null;
|
||||
}
|
||||
|
||||
public int Priority
|
||||
{
|
||||
get { return 500 + priority; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,14 +32,13 @@ namespace OpenRA.FileFormats.Graphics
|
||||
IVertexBuffer<Vertex> CreateVertexBuffer( int length );
|
||||
IIndexBuffer CreateIndexBuffer( int length );
|
||||
ITexture CreateTexture( Bitmap bitmap );
|
||||
IShader CreateShader( Stream stream );
|
||||
ITexture CreateTexture();
|
||||
IShader CreateShader( string name );
|
||||
|
||||
Size WindowSize { get; }
|
||||
|
||||
void Begin();
|
||||
void End();
|
||||
void Clear( Color color );
|
||||
void Present();
|
||||
void Present( IInputHandler inputHandler );
|
||||
|
||||
void DrawIndexedPrimitives( PrimitiveType type, Range<int> vertexRange, Range<int> indexRange );
|
||||
void DrawIndexedPrimitives( PrimitiveType type, int vertexPool, int numPrimitives );
|
||||
@@ -51,13 +50,13 @@ namespace OpenRA.FileFormats.Graphics
|
||||
public interface IVertexBuffer<T>
|
||||
{
|
||||
void Bind();
|
||||
void SetData( T[] vertices );
|
||||
void SetData( T[] vertices, int length );
|
||||
}
|
||||
|
||||
public interface IIndexBuffer
|
||||
{
|
||||
void Bind();
|
||||
void SetData( ushort[] indices );
|
||||
void SetData( ushort[] indices, int length );
|
||||
}
|
||||
|
||||
public interface IShader
|
||||
@@ -70,14 +69,9 @@ namespace OpenRA.FileFormats.Graphics
|
||||
|
||||
public interface ITexture
|
||||
{
|
||||
void SetData( Bitmap bitmap );
|
||||
}
|
||||
|
||||
public interface IFont
|
||||
{
|
||||
void DrawText( string text, int2 pos, Color c );
|
||||
|
||||
int2 Measure( string text );
|
||||
void SetData(Bitmap bitmap);
|
||||
void SetData(uint[,] colors);
|
||||
void SetData(byte[] colors, int width, int height);
|
||||
}
|
||||
|
||||
public enum PrimitiveType
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#region Copyright & License Information
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
@@ -9,16 +9,33 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public interface IInputHandler
|
||||
{
|
||||
void ModifierKeys( Modifiers mods );
|
||||
void OnKeyInput( KeyInput input );
|
||||
void OnMouseInput( MouseInput input );
|
||||
}
|
||||
|
||||
public struct MouseInput
|
||||
{
|
||||
public MouseInputEvent Event;
|
||||
public int2 Location;
|
||||
public MouseButton Button;
|
||||
public int2 Location;
|
||||
public Modifiers Modifiers;
|
||||
|
||||
public MouseInput( MouseInputEvent ev, MouseButton button, int2 location, Modifiers mods )
|
||||
{
|
||||
this.Event = ev;
|
||||
this.Button = button;
|
||||
this.Location = location;
|
||||
this.Modifiers = mods;
|
||||
}
|
||||
}
|
||||
|
||||
public enum MouseInputEvent { Down, Move, Up };
|
||||
@@ -41,8 +58,10 @@ namespace OpenRA
|
||||
Ctrl = (int)Keys.Control,
|
||||
}
|
||||
|
||||
public enum KeyInputEvent { Down, Up };
|
||||
public struct KeyInput
|
||||
{
|
||||
public KeyInputEvent Event;
|
||||
public char KeyChar;
|
||||
public string KeyName;
|
||||
public Modifiers Modifiers;
|
||||
294
OpenRA.FileFormats/Graphics/VqaReader.cs
Normal file
294
OpenRA.FileFormats/Graphics/VqaReader.cs
Normal file
@@ -0,0 +1,294 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class VqaReader
|
||||
{
|
||||
public readonly ushort Frames;
|
||||
public readonly byte Framerate;
|
||||
public readonly ushort Width;
|
||||
public readonly ushort Height;
|
||||
|
||||
Stream stream;
|
||||
int currentFrame;
|
||||
ushort numColors;
|
||||
ushort blockWidth;
|
||||
ushort blockHeight;
|
||||
byte cbParts;
|
||||
int2 blocks;
|
||||
UInt32[] offsets;
|
||||
uint[] palette;
|
||||
|
||||
// Stores a list of subpixels, referenced by the VPTZ chunk
|
||||
byte[] cbf;
|
||||
byte[] cbp;
|
||||
int cbChunk = 0;
|
||||
int cbOffset = 0;
|
||||
|
||||
// Top half contains block info, bottom half contains references to cbf array
|
||||
byte[] origData;
|
||||
|
||||
// Final frame output
|
||||
uint[,] frameData;
|
||||
byte[] audioData; // audio for this frame: 22050Hz 16bit mono pcm, uncompressed.
|
||||
|
||||
public byte[] AudioData { get { return audioData; } }
|
||||
public int CurrentFrame { get { return currentFrame; } }
|
||||
|
||||
public VqaReader( Stream stream )
|
||||
{
|
||||
this.stream = stream;
|
||||
BinaryReader reader = new BinaryReader( stream );
|
||||
|
||||
// Decode FORM chunk
|
||||
if (new String(reader.ReadChars(4)) != "FORM")
|
||||
throw new InvalidDataException("Invalid vqa (invalid FORM section)");
|
||||
/*var length = */ reader.ReadUInt32();
|
||||
|
||||
if (new String(reader.ReadChars(8)) != "WVQAVQHD")
|
||||
throw new InvalidDataException("Invalid vqa (not WVQAVQHD)");
|
||||
/* var length = */reader.ReadUInt32();
|
||||
|
||||
/*var version = */reader.ReadUInt16();
|
||||
/*var flags = */reader.ReadUInt16();
|
||||
Frames = reader.ReadUInt16();
|
||||
Width = reader.ReadUInt16();
|
||||
Height = reader.ReadUInt16();
|
||||
|
||||
blockWidth = reader.ReadByte();
|
||||
blockHeight = reader.ReadByte();
|
||||
Framerate = reader.ReadByte();
|
||||
cbParts = reader.ReadByte();
|
||||
blocks = new int2(Width / blockWidth, Height / blockHeight);
|
||||
|
||||
numColors = reader.ReadUInt16();
|
||||
/*var maxBlocks = */reader.ReadUInt16();
|
||||
/*var unknown1 = */reader.ReadUInt16();
|
||||
/*var unknown2 = */reader.ReadUInt32();
|
||||
|
||||
// Audio
|
||||
/*var freq = */reader.ReadUInt16();
|
||||
/*var channels = */reader.ReadByte();
|
||||
/*var bits = */reader.ReadByte();
|
||||
/*var unknown3 = */reader.ReadChars(14);
|
||||
|
||||
|
||||
var frameSize = NextPowerOf2(Math.Max(Width,Height));
|
||||
cbf = new byte[Width*Height];
|
||||
cbp = new byte[Width*Height];
|
||||
palette = new uint[numColors];
|
||||
origData = new byte[2*blocks.X*blocks.Y];
|
||||
frameData = new uint[frameSize,frameSize];
|
||||
|
||||
var type = new String(reader.ReadChars(4));
|
||||
if (type != "FINF")
|
||||
{
|
||||
reader.ReadBytes(27);
|
||||
type = new String(reader.ReadChars(4));
|
||||
}
|
||||
|
||||
/*var length = */reader.ReadUInt16();
|
||||
/*var unknown4 = */reader.ReadUInt16();
|
||||
|
||||
// Frame offsets
|
||||
offsets = new UInt32[Frames];
|
||||
for (int i = 0; i < Frames; i++)
|
||||
{
|
||||
offsets[i] = reader.ReadUInt32();
|
||||
if (offsets[i] > 0x40000000) offsets[i] -= 0x40000000;
|
||||
offsets[i] <<= 1;
|
||||
}
|
||||
|
||||
CollectAudioData();
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
currentFrame = cbOffset = cbChunk = 0;
|
||||
LoadFrame();
|
||||
}
|
||||
|
||||
void CollectAudioData()
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
var adpcmIndex = 0;
|
||||
|
||||
bool compressed = false;
|
||||
for (var i = 0; i < Frames; i++)
|
||||
{
|
||||
stream.Seek(offsets[i], SeekOrigin.Begin);
|
||||
BinaryReader reader = new BinaryReader(stream);
|
||||
var end = (i < Frames - 1) ? offsets[i + 1] : stream.Length;
|
||||
|
||||
while (reader.BaseStream.Position < end)
|
||||
{
|
||||
var type = new String(reader.ReadChars(4));
|
||||
var length = int2.Swap(reader.ReadUInt32());
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case "SND0":
|
||||
case "SND2":
|
||||
var rawAudio = reader.ReadBytes((int)length);
|
||||
ms.Write(rawAudio);
|
||||
compressed = (type == "SND2");
|
||||
break;
|
||||
default:
|
||||
reader.ReadBytes((int)length);
|
||||
break;
|
||||
}
|
||||
|
||||
if (reader.PeekChar() == 0) reader.ReadByte();
|
||||
}
|
||||
}
|
||||
|
||||
audioData = (compressed) ? AudLoader.LoadSound(ms.ToArray(), ref adpcmIndex) : ms.ToArray();
|
||||
}
|
||||
|
||||
public void AdvanceFrame()
|
||||
{
|
||||
currentFrame++;
|
||||
LoadFrame();
|
||||
}
|
||||
|
||||
void LoadFrame()
|
||||
{
|
||||
if (currentFrame >= Frames)
|
||||
return;
|
||||
|
||||
// Seek to the start of the frame
|
||||
stream.Seek(offsets[currentFrame], SeekOrigin.Begin);
|
||||
BinaryReader reader = new BinaryReader(stream);
|
||||
var end = (currentFrame < Frames - 1) ? offsets[currentFrame+1] : stream.Length;
|
||||
|
||||
while(reader.BaseStream.Position < end)
|
||||
{
|
||||
var type = new String(reader.ReadChars(4));
|
||||
var length = int2.Swap(reader.ReadUInt32());
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case "VQFR":
|
||||
DecodeVQFR(reader);
|
||||
break;
|
||||
default:
|
||||
// Don't parse sound here.
|
||||
reader.ReadBytes((int)length);
|
||||
break;
|
||||
}
|
||||
|
||||
// Chunks are aligned on even bytes; advance by a byte if the next one is null
|
||||
if (reader.PeekChar() == 0) reader.ReadByte();
|
||||
}
|
||||
}
|
||||
|
||||
// VQA Frame
|
||||
public void DecodeVQFR(BinaryReader reader)
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
// Chunks are aligned on even bytes; may be padded with a single null
|
||||
if (reader.PeekChar() == 0) reader.ReadByte();
|
||||
var type = new String(reader.ReadChars(4));
|
||||
int subchunkLength = (int)int2.Swap(reader.ReadUInt32());
|
||||
|
||||
switch(type)
|
||||
{
|
||||
// Full frame-modifier
|
||||
case "CBFZ":
|
||||
Format80.DecodeInto( reader.ReadBytes(subchunkLength), cbf );
|
||||
break;
|
||||
case "CBF0":
|
||||
cbf = reader.ReadBytes(subchunkLength);
|
||||
break;
|
||||
|
||||
// frame-modifier chunk
|
||||
case "CBP0":
|
||||
case "CBPZ":
|
||||
// Partial buffer is full; dump and recreate
|
||||
if (cbChunk == cbParts)
|
||||
{
|
||||
if (type == "CBP0")
|
||||
cbf = (byte[])cbp.Clone();
|
||||
else
|
||||
Format80.DecodeInto( cbp, cbf );
|
||||
|
||||
cbOffset = cbChunk = 0;
|
||||
}
|
||||
|
||||
var bytes = reader.ReadBytes(subchunkLength);
|
||||
bytes.CopyTo(cbp,cbOffset);
|
||||
cbOffset += subchunkLength;
|
||||
cbChunk++;
|
||||
break;
|
||||
|
||||
// Palette
|
||||
case "CPL0":
|
||||
for (int i = 0; i < numColors; i++)
|
||||
{
|
||||
byte r = (byte)(reader.ReadByte() << 2);
|
||||
byte g = (byte)(reader.ReadByte() << 2);
|
||||
byte b = (byte)(reader.ReadByte() << 2);
|
||||
palette[i] = (uint)((255 << 24) | (r << 16) | (g << 8) | b);
|
||||
}
|
||||
break;
|
||||
|
||||
// Frame data
|
||||
case "VPTZ":
|
||||
Format80.DecodeInto( reader.ReadBytes(subchunkLength), origData );
|
||||
// This is the last subchunk
|
||||
return;
|
||||
default:
|
||||
throw new InvalidDataException("Unknown sub-chunk {0}".F(type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int cachedFrame = -1;
|
||||
public uint[,] FrameData { get
|
||||
{
|
||||
if (cachedFrame != currentFrame)
|
||||
{
|
||||
cachedFrame = currentFrame;
|
||||
for (var y = 0; y < blocks.Y; y++)
|
||||
for (var x = 0; x < blocks.X; x++)
|
||||
{
|
||||
var px = origData[x + y*blocks.X];
|
||||
var mod = origData[x + (y + blocks.Y)*blocks.X];
|
||||
for (var j = 0; j < blockHeight; j++)
|
||||
for (var i = 0; i < blockWidth; i++)
|
||||
{
|
||||
var cbfi = (mod*256 + px)*8 + j*blockWidth + i;
|
||||
byte color = (mod == 0x0f) ? px : cbf[cbfi];
|
||||
frameData[y*blockHeight + j, x*blockWidth + i] = palette[color];
|
||||
}
|
||||
}
|
||||
}
|
||||
return frameData;
|
||||
}}
|
||||
|
||||
int NextPowerOf2(int v)
|
||||
{
|
||||
--v;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
++v;
|
||||
return v;
|
||||
}
|
||||
}
|
||||
}
|
||||
66
OpenRA.FileFormats/Manifest.cs
Normal file
66
OpenRA.FileFormats/Manifest.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
/* describes what is to be loaded in order to run a set of mods */
|
||||
|
||||
public class Manifest
|
||||
{
|
||||
public readonly string[]
|
||||
Mods, Folders, Packages, Rules, ServerTraits,
|
||||
Sequences, Cursors, Chrome, Assemblies, ChromeLayout,
|
||||
Weapons, Voices, Music, Movies, TileSets;
|
||||
public readonly string ShellmapUid, LoadScreen;
|
||||
public readonly int TileSize = 24;
|
||||
|
||||
public Manifest(string[] mods)
|
||||
{
|
||||
Mods = mods;
|
||||
var yaml = mods
|
||||
.Select(m => MiniYaml.FromFile("mods/" + m + "/mod.yaml"))
|
||||
.Aggregate(MiniYaml.Merge);
|
||||
|
||||
// Todo: Use fieldloader
|
||||
Folders = YamlList(yaml, "Folders");
|
||||
Packages = YamlList(yaml, "Packages");
|
||||
Rules = YamlList(yaml, "Rules");
|
||||
ServerTraits = YamlList(yaml, "ServerTraits");
|
||||
Sequences = YamlList(yaml, "Sequences");
|
||||
Cursors = YamlList(yaml, "Cursors");
|
||||
Chrome = YamlList(yaml, "Chrome");
|
||||
Assemblies = YamlList(yaml, "Assemblies");
|
||||
ChromeLayout = YamlList(yaml, "ChromeLayout");
|
||||
Weapons = YamlList(yaml, "Weapons");
|
||||
Voices = YamlList(yaml, "Voices");
|
||||
Music = YamlList(yaml, "Music");
|
||||
Movies = YamlList(yaml, "Movies");
|
||||
TileSets = YamlList(yaml, "TileSets");
|
||||
|
||||
ShellmapUid = yaml.First( x => x.Key == "ShellmapUid" ).Value.Value;
|
||||
LoadScreen = yaml.First( x => x.Key == "LoadScreen" ).Value.Value;
|
||||
|
||||
if (yaml.FirstOrDefault( x => x.Key == "TileSize" ) != null)
|
||||
TileSize = int.Parse(yaml.First( x => x.Key == "TileSize" ).Value.Value);
|
||||
}
|
||||
|
||||
static string[] YamlList(List<MiniYamlNode> ys, string key)
|
||||
{
|
||||
var y = ys.FirstOrDefault( x => x.Key == key );
|
||||
if( y == null )
|
||||
return new string[ 0 ];
|
||||
|
||||
return y.Value.NodesDict.Keys.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class ActorReference
|
||||
{
|
||||
public readonly string Id;
|
||||
public readonly string Type;
|
||||
public readonly int2 Location;
|
||||
public readonly string Owner;
|
||||
|
||||
public ActorReference(MiniYaml my)
|
||||
{
|
||||
FieldLoader.Load(this, my);
|
||||
}
|
||||
|
||||
// Legacy construtor for old format maps
|
||||
public ActorReference(string id, string type, int2 location, string owner )
|
||||
{
|
||||
Id = id;
|
||||
Type = type;
|
||||
Location = location;
|
||||
Owner = owner;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,44 +17,46 @@ namespace OpenRA.FileFormats
|
||||
{
|
||||
public class MapStub
|
||||
{
|
||||
public IFolder Package;
|
||||
public IFolder Container { get; protected set; }
|
||||
|
||||
// Yaml map data
|
||||
public string Uid;
|
||||
public bool Selectable;
|
||||
public string Uid { get; protected set; }
|
||||
[FieldLoader.Load] public bool Selectable;
|
||||
|
||||
public string Title;
|
||||
public string Description;
|
||||
public string Author;
|
||||
public int PlayerCount;
|
||||
public string Tileset;
|
||||
[FieldLoader.Load] public string Title;
|
||||
[FieldLoader.Load] public string Description;
|
||||
[FieldLoader.Load] public string Author;
|
||||
[FieldLoader.Load] public int PlayerCount;
|
||||
[FieldLoader.Load] public string Tileset;
|
||||
|
||||
[FieldLoader.LoadUsing( "LoadWaypoints" )]
|
||||
public Dictionary<string, int2> Waypoints = new Dictionary<string, int2>();
|
||||
public IEnumerable<int2> SpawnPoints { get { return Waypoints.Select(kv => kv.Value); } }
|
||||
|
||||
public int2 TopLeft;
|
||||
public int2 BottomRight;
|
||||
[FieldLoader.Load] public int2 TopLeft;
|
||||
[FieldLoader.Load] public int2 BottomRight;
|
||||
public int Width { get { return BottomRight.X - TopLeft.X; } }
|
||||
public int Height { get { return BottomRight.Y - TopLeft.Y; } }
|
||||
public Map Map { get { return new Map(Package); }}
|
||||
|
||||
static List<string> Fields = new List<string>() {
|
||||
"Selectable", "Title", "Description", "Author", "PlayerCount", "Tileset", "TopLeft", "BottomRight"
|
||||
};
|
||||
|
||||
public MapStub(IFolder package)
|
||||
|
||||
public MapStub() {} // Hack for the editor - not used for anything important
|
||||
public MapStub(IFolder container)
|
||||
{
|
||||
Package = package;
|
||||
var yaml = MiniYaml.FromStream(Package.GetContent("map.yaml"));
|
||||
FieldLoader.LoadFields(this, yaml, Fields);
|
||||
Container = container;
|
||||
var yaml = MiniYaml.FromStream(Container.GetContent("map.yaml"));
|
||||
FieldLoader.Load( this, new MiniYaml( null, yaml ) );
|
||||
|
||||
// Waypoints
|
||||
foreach (var wp in yaml["Waypoints"].Nodes)
|
||||
{
|
||||
string[] loc = wp.Value.Value.Split(',');
|
||||
Waypoints.Add(wp.Key, new int2(int.Parse(loc[0]), int.Parse(loc[1])));
|
||||
}
|
||||
Uid = Container.GetContent("map.uid").ReadAllText();
|
||||
}
|
||||
|
||||
Uid = Package.GetContent("map.uid").ReadAllText();
|
||||
static object LoadWaypoints( MiniYaml y )
|
||||
{
|
||||
var ret = new Dictionary<string, int2>();
|
||||
foreach( var wp in y.NodesDict[ "Waypoints" ].NodesDict )
|
||||
{
|
||||
string[] loc = wp.Value.Value.Split( ',' );
|
||||
ret.Add( wp.Key, new int2( int.Parse( loc[ 0 ] ), int.Parse( loc[ 1 ] ) ) );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,14 +14,26 @@ namespace OpenRA.FileFormats
|
||||
{
|
||||
public class PlayerReference
|
||||
{
|
||||
public readonly string Name;
|
||||
public readonly string Palette;
|
||||
public readonly string Race;
|
||||
public readonly bool OwnsWorld = false;
|
||||
public readonly bool NonCombatant = false;
|
||||
public readonly Color Color = Color.FromArgb(238,238,238);
|
||||
public readonly Color Color2 = Color.FromArgb(44,28,24);
|
||||
|
||||
public string Name;
|
||||
public string Palette;
|
||||
public bool OwnsWorld = false;
|
||||
public bool NonCombatant = false;
|
||||
public bool Playable = false;
|
||||
public bool DefaultStartingUnits = false;
|
||||
public bool AllowBots = true;
|
||||
|
||||
public bool LockRace = false;
|
||||
public string Race;
|
||||
|
||||
public bool LockColor = false;
|
||||
public Color Color = Color.FromArgb(238,238,238);
|
||||
public Color Color2 = Color.FromArgb(44,28,24);
|
||||
|
||||
public int InitialCash = 0;
|
||||
public string[] Allies = {};
|
||||
public string[] Enemies = {};
|
||||
|
||||
public PlayerReference() {}
|
||||
public PlayerReference(MiniYaml my)
|
||||
{
|
||||
FieldLoader.Load(this, my);
|
||||
|
||||
@@ -17,15 +17,15 @@ namespace OpenRA.FileFormats
|
||||
{
|
||||
public readonly List<byte[]> TileBitmapBytes = new List<byte[]>();
|
||||
|
||||
public Terrain( Stream stream )
|
||||
public Terrain( Stream stream, int size )
|
||||
{
|
||||
// Try loading as a cnc .tem
|
||||
BinaryReader reader = new BinaryReader( stream );
|
||||
int Width = reader.ReadUInt16();
|
||||
int Height = reader.ReadUInt16();
|
||||
|
||||
if( Width != 24 || Height != 24 )
|
||||
throw new InvalidDataException( string.Format( "{0}x{1}", Width, Height ) );
|
||||
|
||||
if( Width != size || Height != size )
|
||||
throw new InvalidDataException( "{0}x{1} != {2}x{2}".F(Width, Height, size ) );
|
||||
|
||||
/*NumTiles = */reader.ReadUInt16();
|
||||
/*Zero1 = */reader.ReadUInt16();
|
||||
@@ -46,9 +46,7 @@ namespace OpenRA.FileFormats
|
||||
reader = new BinaryReader( stream );
|
||||
Width = reader.ReadUInt16();
|
||||
Height = reader.ReadUInt16();
|
||||
if( Width != 24 || Height != 24 )
|
||||
throw new InvalidDataException( string.Format( "{0}x{1}", Width, Height ) );
|
||||
|
||||
|
||||
/*NumTiles = */reader.ReadUInt16();
|
||||
reader.ReadUInt16();
|
||||
/*XDim = */reader.ReadUInt16();
|
||||
@@ -67,8 +65,8 @@ namespace OpenRA.FileFormats
|
||||
{
|
||||
if (b != 255)
|
||||
{
|
||||
stream.Position = ImgStart + b * 24 * 24;
|
||||
TileBitmapBytes.Add(new BinaryReader(stream).ReadBytes(24 * 24));
|
||||
stream.Position = ImgStart + b * size * size;
|
||||
TileBitmapBytes.Add(new BinaryReader(stream).ReadBytes(size * size));
|
||||
}
|
||||
else
|
||||
TileBitmapBytes.Add(null);
|
||||
|
||||
@@ -31,38 +31,39 @@ namespace OpenRA.FileFormats
|
||||
|
||||
public class TileTemplate
|
||||
{
|
||||
public ushort Id;
|
||||
public string Image;
|
||||
public int2 Size;
|
||||
public bool PickAny;
|
||||
[FieldLoader.Load] public ushort Id;
|
||||
[FieldLoader.Load] public string Image;
|
||||
[FieldLoader.Load] public int2 Size;
|
||||
[FieldLoader.Load] public bool PickAny;
|
||||
|
||||
[FieldLoader.LoadUsing( "LoadTiles" )]
|
||||
public Dictionary<byte, string> Tiles = new Dictionary<byte, string>();
|
||||
|
||||
static List<string> fields = new List<string>() {"Id", "Image", "Size", "PickAny"};
|
||||
|
||||
public TileTemplate() {}
|
||||
public TileTemplate(MiniYaml my)
|
||||
{
|
||||
FieldLoader.LoadFields(this, my.Nodes, fields);
|
||||
FieldLoader.Load( this, my );
|
||||
}
|
||||
|
||||
Tiles = my.Nodes["Tiles"].Nodes.ToDictionary(
|
||||
static object LoadTiles( MiniYaml y )
|
||||
{
|
||||
return y.NodesDict["Tiles"].NodesDict.ToDictionary(
|
||||
t => byte.Parse(t.Key),
|
||||
t => t.Value.Value);
|
||||
t => t.Value.Value );
|
||||
}
|
||||
|
||||
public MiniYaml Save()
|
||||
{
|
||||
var root = new Dictionary<string, MiniYaml>();
|
||||
foreach (var field in fields)
|
||||
var root = new List<MiniYamlNode>();
|
||||
foreach (var field in new string[] {"Id", "Image", "Size", "PickAny"})
|
||||
{
|
||||
FieldInfo f = this.GetType().GetField(field);
|
||||
if (f.GetValue(this) == null) continue;
|
||||
root.Add(field, new MiniYaml(FieldSaver.FormatValue(this, f), null));
|
||||
root.Add( new MiniYamlNode( field, FieldSaver.FormatValue( this, f ) ) );
|
||||
}
|
||||
|
||||
root.Add("Tiles",
|
||||
new MiniYaml(null, Tiles.ToDictionary(
|
||||
p => p.Key.ToString(),
|
||||
p => new MiniYaml(p.Value))));
|
||||
root.Add( new MiniYamlNode( "Tiles", null,
|
||||
Tiles.Select( x => new MiniYamlNode( x.Key.ToString(), x.Value ) ).ToList() ) );
|
||||
|
||||
return new MiniYaml(null, root);
|
||||
}
|
||||
@@ -73,26 +74,27 @@ namespace OpenRA.FileFormats
|
||||
public string Name;
|
||||
public string Id;
|
||||
public string Palette;
|
||||
public int TileSize = 24;
|
||||
public string[] Extensions;
|
||||
public Dictionary<string, TerrainTypeInfo> Terrain = new Dictionary<string, TerrainTypeInfo>();
|
||||
public Dictionary<ushort, Terrain> Tiles = new Dictionary<ushort, Terrain>();
|
||||
public Dictionary<ushort, TileTemplate> Templates = new Dictionary<ushort, TileTemplate>();
|
||||
static List<string> fields = new List<string>() {"Name", "Id", "Palette", "Extensions"};
|
||||
static List<string> fields = new List<string>() {"Name", "TileSize", "Id", "Palette", "Extensions"};
|
||||
|
||||
public TileSet() {}
|
||||
public TileSet( string filepath )
|
||||
{
|
||||
var yaml = MiniYaml.FromFile(filepath);
|
||||
var yaml = MiniYaml.DictFromFile( filepath );
|
||||
|
||||
// General info
|
||||
FieldLoader.Load(this, yaml["General"]);
|
||||
|
||||
// TerrainTypes
|
||||
Terrain = yaml["Terrain"].Nodes.Values
|
||||
Terrain = yaml["Terrain"].NodesDict.Values
|
||||
.Select(y => new TerrainTypeInfo(y)).ToDictionary(t => t.Type);
|
||||
|
||||
// Templates
|
||||
Templates = yaml["Templates"].Nodes.Values
|
||||
Templates = yaml["Templates"].NodesDict.Values
|
||||
.Select(y => new TileTemplate(y)).ToDictionary(t => t.Id);
|
||||
}
|
||||
|
||||
@@ -102,38 +104,31 @@ namespace OpenRA.FileFormats
|
||||
using( Stream s = FileSystem.OpenWithExts(t.Value.Image, Extensions) )
|
||||
{
|
||||
if( !Tiles.ContainsKey( t.Key ) )
|
||||
Tiles.Add( t.Key, new Terrain( s ) );
|
||||
Tiles.Add( t.Key, new Terrain( s, TileSize ) );
|
||||
}
|
||||
}
|
||||
|
||||
public void Save(string filepath)
|
||||
{
|
||||
var root = new Dictionary<string, MiniYaml>();
|
||||
var root = new List<MiniYamlNode>();
|
||||
var gen = new List<MiniYamlNode>();
|
||||
foreach (var field in fields)
|
||||
{
|
||||
FieldInfo f = this.GetType().GetField(field);
|
||||
if (f.GetValue(this) == null) continue;
|
||||
root.Add(field, new MiniYaml(FieldSaver.FormatValue(this, f), null));
|
||||
gen.Add( new MiniYamlNode( field, FieldSaver.FormatValue( this, f ) ) );
|
||||
}
|
||||
|
||||
var gen = new Dictionary<string, MiniYaml>();
|
||||
foreach (var field in fields)
|
||||
{
|
||||
FieldInfo f = this.GetType().GetField(field);
|
||||
if (f.GetValue(this) == null) continue;
|
||||
gen.Add(field, new MiniYaml(FieldSaver.FormatValue(this, f), null));
|
||||
}
|
||||
root.Add("General", new MiniYaml(null, gen));
|
||||
|
||||
root.Add("Terrain",
|
||||
new MiniYaml(null, Terrain.ToDictionary(
|
||||
t => "TerrainType@{0}".F(t.Value.Type),
|
||||
t => t.Value.Save())));
|
||||
|
||||
root.Add("Templates",
|
||||
new MiniYaml(null, Templates.ToDictionary(
|
||||
t => "Template@{0}".F(t.Value.Id),
|
||||
t => t.Value.Save())));
|
||||
root.Add( new MiniYamlNode( "General", null, gen ) );
|
||||
|
||||
root.Add( new MiniYamlNode( "Terrain", null,
|
||||
Terrain.Select( t => new MiniYamlNode(
|
||||
"TerrainType@{0}".F( t.Value.Type ),
|
||||
t.Value.Save() ) ).ToList() ) );
|
||||
|
||||
root.Add( new MiniYamlNode( "Templates", null,
|
||||
Templates.Select( t => new MiniYamlNode(
|
||||
"Template@{0}".F( t.Value.Id ),
|
||||
t.Value.Save() ) ).ToList() ) );
|
||||
root.WriteToFile(filepath);
|
||||
}
|
||||
|
||||
@@ -143,7 +138,7 @@ namespace OpenRA.FileFormats
|
||||
if( Tiles.TryGetValue( r.type, out tile ) )
|
||||
return tile.TileBitmapBytes[ r.image ];
|
||||
|
||||
byte[] missingTile = new byte[ 24 * 24 ];
|
||||
byte[] missingTile = new byte[ TileSize * TileSize ];
|
||||
for( int i = 0 ; i < missingTile.Length ; i++ )
|
||||
missingTile[ i ] = 0x36;
|
||||
|
||||
|
||||
@@ -15,38 +15,80 @@ using System.Linq;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
using MiniYamlNodes = Dictionary<string, MiniYaml>;
|
||||
using MiniYamlNodes = List<MiniYamlNode>;
|
||||
|
||||
public class MiniYamlNode
|
||||
{
|
||||
public struct SourceLocation
|
||||
{
|
||||
public string Filename; public int Line;
|
||||
}
|
||||
|
||||
public SourceLocation Location;
|
||||
public string Key;
|
||||
public MiniYaml Value;
|
||||
|
||||
public MiniYamlNode( string k, MiniYaml v )
|
||||
{
|
||||
Key = k;
|
||||
Value = v;
|
||||
}
|
||||
|
||||
public MiniYamlNode( string k, MiniYaml v, SourceLocation loc )
|
||||
: this( k, v )
|
||||
{
|
||||
Location = loc;
|
||||
}
|
||||
|
||||
public MiniYamlNode( string k, string v )
|
||||
: this( k, v, null )
|
||||
{
|
||||
}
|
||||
public MiniYamlNode( string k, string v, List<MiniYamlNode> n )
|
||||
: this( k, new MiniYaml( v, n ) )
|
||||
{
|
||||
}
|
||||
|
||||
public MiniYamlNode( string k, string v, List<MiniYamlNode> n, SourceLocation loc )
|
||||
: this( k, new MiniYaml( v, n ), loc )
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class MiniYaml
|
||||
{
|
||||
public string Value;
|
||||
public Dictionary<string, MiniYaml> Nodes = new Dictionary<string,MiniYaml>();
|
||||
public List<MiniYamlNode> Nodes;
|
||||
|
||||
public MiniYaml( string value ) : this( value, new Dictionary<string, MiniYaml>() ) { }
|
||||
public Dictionary<string, MiniYaml> NodesDict { get { return Nodes.ToDictionary( x => x.Key, x => x.Value ); } }
|
||||
|
||||
public MiniYaml( string value, Dictionary<string, MiniYaml> nodes )
|
||||
public MiniYaml( string value ) : this( value, null ) { }
|
||||
|
||||
public MiniYaml( string value, List<MiniYamlNode> nodes )
|
||||
{
|
||||
Value = value;
|
||||
Nodes = nodes;
|
||||
Nodes = nodes ?? new List<MiniYamlNode>();
|
||||
}
|
||||
|
||||
public static MiniYaml FromDictionary<K,V>(Dictionary<K,V>dict)
|
||||
{
|
||||
return new MiniYaml( null, dict.ToDictionary( x=>x.Key.ToString(), x=>new MiniYaml(x.Value.ToString())));
|
||||
}
|
||||
|
||||
public static MiniYaml FromList<T>(List<T>list)
|
||||
{
|
||||
return new MiniYaml( null, list.ToDictionary( x=>x.ToString(), x=>new MiniYaml(null)));
|
||||
}
|
||||
|
||||
static Dictionary<string, MiniYaml> FromLines(string[] lines)
|
||||
{
|
||||
var levels = new List<Dictionary<string, MiniYaml>>();
|
||||
levels.Add(new Dictionary<string, MiniYaml>());
|
||||
|
||||
public static MiniYaml FromDictionary<K, V>( Dictionary<K, V> dict )
|
||||
{
|
||||
return new MiniYaml( null, dict.Select( x => new MiniYamlNode( x.Key.ToString(), new MiniYaml( x.Value.ToString() ) ) ).ToList() );
|
||||
}
|
||||
|
||||
public static MiniYaml FromList<T>( List<T> list )
|
||||
{
|
||||
return new MiniYaml( null, list.Select( x => new MiniYamlNode( x.ToString(), new MiniYaml( null ) ) ).ToList() );
|
||||
}
|
||||
|
||||
static List<MiniYamlNode> FromLines(string[] lines, string filename)
|
||||
{
|
||||
var levels = new List<List<MiniYamlNode>>();
|
||||
levels.Add(new List<MiniYamlNode>());
|
||||
|
||||
var lineNo = 0;
|
||||
foreach (var line in lines)
|
||||
{
|
||||
++lineNo;
|
||||
var t = line.TrimStart(' ', '\t');
|
||||
if (t.Length == 0 || t[0] == '#')
|
||||
continue;
|
||||
@@ -57,28 +99,28 @@ namespace OpenRA.FileFormats
|
||||
while (levels.Count > level + 1)
|
||||
levels.RemoveAt(levels.Count - 1);
|
||||
|
||||
var colon = t.IndexOf(':');
|
||||
var d = new Dictionary<string, MiniYaml>();
|
||||
try
|
||||
{
|
||||
if (colon == -1)
|
||||
levels[level].Add(t.Trim(), new MiniYaml(null, d));
|
||||
else
|
||||
{
|
||||
var value = t.Substring(colon + 1).Trim();
|
||||
if (value.Length == 0)
|
||||
value = null;
|
||||
levels[level].Add(t.Substring(0, colon).Trim(), new MiniYaml(value, d));
|
||||
}
|
||||
}
|
||||
catch (ArgumentException) { throw new InvalidDataException("Duplicate Identifier:`{0}`".F(t)); }
|
||||
var d = new List<MiniYamlNode>();
|
||||
var rhs = SplitAtColon( ref t );
|
||||
levels[ level ].Add( new MiniYamlNode( t, rhs, d, new MiniYamlNode.SourceLocation { Filename = filename, Line = lineNo } ) );
|
||||
|
||||
levels.Add(d);
|
||||
}
|
||||
return levels[0];
|
||||
return levels[ 0 ];
|
||||
}
|
||||
|
||||
public static Dictionary<string, MiniYaml> FromFileInPackage( string path )
|
||||
static string SplitAtColon( ref string t )
|
||||
{
|
||||
var colon = t.IndexOf(':');
|
||||
if( colon == -1 )
|
||||
return null;
|
||||
var ret = t.Substring( colon + 1 ).Trim();
|
||||
if( ret.Length == 0 )
|
||||
ret = null;
|
||||
t = t.Substring( 0, colon ).Trim();
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static List<MiniYamlNode> FromFileInPackage( string path )
|
||||
{
|
||||
StreamReader reader = new StreamReader( FileSystem.Open(path) );
|
||||
List<string> lines = new List<string>();
|
||||
@@ -87,54 +129,67 @@ namespace OpenRA.FileFormats
|
||||
lines.Add(reader.ReadLine());
|
||||
reader.Close();
|
||||
|
||||
return FromLines(lines.ToArray());
|
||||
}
|
||||
|
||||
public static Dictionary<string, MiniYaml> FromFile( string path )
|
||||
{
|
||||
return FromLines(File.ReadAllLines( path ));
|
||||
return FromLines(lines.ToArray(), path);
|
||||
}
|
||||
|
||||
public static Dictionary<string, MiniYaml> FromStream(Stream s)
|
||||
public static Dictionary<string, MiniYaml> DictFromFile( string path )
|
||||
{
|
||||
return FromFile( path ).ToDictionary( x => x.Key, x => x.Value );
|
||||
}
|
||||
|
||||
public static Dictionary<string, MiniYaml> DictFromStream( Stream stream )
|
||||
{
|
||||
return FromStream( stream ).ToDictionary( x => x.Key, x => x.Value );
|
||||
}
|
||||
|
||||
public static List<MiniYamlNode> FromFile( string path )
|
||||
{
|
||||
return FromLines(File.ReadAllLines( path ), path);
|
||||
}
|
||||
|
||||
public static List<MiniYamlNode> FromStream(Stream s)
|
||||
{
|
||||
using (var reader = new StreamReader(s))
|
||||
return FromString(reader.ReadToEnd());
|
||||
}
|
||||
|
||||
public static Dictionary<string, MiniYaml> FromString(string text)
|
||||
public static List<MiniYamlNode> FromString(string text)
|
||||
{
|
||||
return FromLines(text.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries));
|
||||
return FromLines(text.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries), "<no filename available>");
|
||||
}
|
||||
|
||||
public static Dictionary<string, MiniYaml> Merge( Dictionary<string, MiniYaml> a, Dictionary<string, MiniYaml> b )
|
||||
public static List<MiniYamlNode> Merge( List<MiniYamlNode> a, List<MiniYamlNode> b )
|
||||
{
|
||||
if( a.Count == 0 )
|
||||
return b;
|
||||
if( b.Count == 0 )
|
||||
return a;
|
||||
|
||||
var ret = new Dictionary<string, MiniYaml>();
|
||||
var ret = new List<MiniYamlNode>();
|
||||
|
||||
var keys = a.Keys.Union( b.Keys ).ToList();
|
||||
var aDict = a.ToDictionary( x => x.Key );
|
||||
var bDict = b.ToDictionary( x => x.Key );
|
||||
var keys = aDict.Keys.Union( bDict.Keys ).ToList();
|
||||
|
||||
var noInherit = keys.Where( x => x.Length > 0 && x[ 0 ] == '-' ).Select( x => x.Substring( 1 ) ).ToList();
|
||||
|
||||
foreach( var key in keys )
|
||||
{
|
||||
MiniYaml aa, bb;
|
||||
a.TryGetValue( key, out aa );
|
||||
b.TryGetValue( key, out bb );
|
||||
MiniYamlNode aa, bb;
|
||||
aDict.TryGetValue( key, out aa );
|
||||
bDict.TryGetValue( key, out bb );
|
||||
|
||||
// if( key.Length > 0 && key[ 0 ] == '-' )
|
||||
// continue;
|
||||
// else
|
||||
if( noInherit.Contains( key ) )
|
||||
{
|
||||
if( aa != null )
|
||||
ret.Add( key, aa );
|
||||
ret.Add( aa );
|
||||
}
|
||||
else
|
||||
ret.Add( key, Merge( aa, bb ) );
|
||||
{
|
||||
var loc = aa == null ? default( MiniYamlNode.SourceLocation ) : aa.Location;
|
||||
var merged = ( aa == null || bb == null ) ? aa ?? bb : new MiniYamlNode( key, Merge( aa.Value, bb.Value ), loc );
|
||||
ret.Add( merged );
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
39
OpenRA.FileFormats/Mod.cs
Normal file
39
OpenRA.FileFormats/Mod.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class Mod
|
||||
{
|
||||
public string Title;
|
||||
public string Description;
|
||||
public string Version;
|
||||
public string Author;
|
||||
public string[] RequiresMods;
|
||||
public bool Standalone = false;
|
||||
|
||||
public static readonly Dictionary<string, Mod> AllMods = ValidateMods(Directory.GetDirectories("mods").Select(x => x.Substring(5)).ToArray());
|
||||
|
||||
public static Dictionary<string, Mod> ValidateMods(string[] mods)
|
||||
{
|
||||
var ret = new Dictionary<string, Mod>();
|
||||
foreach (var m in mods)
|
||||
{
|
||||
if (!File.Exists("mods" + Path.DirectorySeparatorChar + m + Path.DirectorySeparatorChar + "mod.yaml"))
|
||||
continue;
|
||||
|
||||
var yaml = new MiniYaml(null, MiniYaml.FromFile("mods" + Path.DirectorySeparatorChar + m + Path.DirectorySeparatorChar + "mod.yaml"));
|
||||
if (!yaml.NodesDict.ContainsKey("Metadata"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ret.Add(m, FieldLoader.Load<Mod>(yaml.NodesDict["Metadata"]));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
@@ -45,6 +45,7 @@
|
||||
</Reference>
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Tao.Sdl, Version=1.2.13.0, Culture=neutral, PublicKeyToken=9c7a200e36c0094e">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
@@ -53,31 +54,31 @@
|
||||
<Reference Include="WindowsBase">
|
||||
<RequiredTargetFramework>3.0</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\thirdparty\ICSharpCode.SharpZipLib.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Evaluator.cs" />
|
||||
<Compile Include="Exts.cs" />
|
||||
<Compile Include="FieldLoader.cs" />
|
||||
<Compile Include="FileSystem.cs" />
|
||||
<Compile Include="Folder.cs" />
|
||||
<Compile Include="Graphics\IGraphicsDevice.cs" />
|
||||
<Compile Include="Graphics\IInputHandler.cs" />
|
||||
<Compile Include="Graphics\Vertex.cs" />
|
||||
<Compile Include="Manifest.cs" />
|
||||
<Compile Include="MiniYaml.cs" />
|
||||
<Compile Include="Mod.cs" />
|
||||
<Compile Include="PackageEntry.cs" />
|
||||
<Compile Include="Package.cs" />
|
||||
<Compile Include="PackageWriter.cs" />
|
||||
<Compile Include="Palette.cs" />
|
||||
<Compile Include="PlayerColorRemap.cs" />
|
||||
<Compile Include="Primitives\DisposableAction.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Thirdparty\Random.cs" />
|
||||
<Compile Include="Session.cs" />
|
||||
<Compile Include="Support\Log.cs" />
|
||||
<Compile Include="Support\Stopwatch.cs" />
|
||||
<Compile Include="Support\Timer.cs" />
|
||||
<Compile Include="TypeDictionary.cs" />
|
||||
<Compile Include="Map\ActorReference.cs" />
|
||||
<Compile Include="Map\Map.cs" />
|
||||
<Compile Include="Map\TileReference.cs" />
|
||||
<Compile Include="Map\Terrain.cs" />
|
||||
<Compile Include="Primitives\Cache.cs" />
|
||||
@@ -100,7 +101,14 @@
|
||||
<Compile Include="Map\MapStub.cs" />
|
||||
<Compile Include="Map\SmudgeReference.cs" />
|
||||
<Compile Include="Map\PlayerReference.cs" />
|
||||
<Compile Include="CompressedPackage.cs" />
|
||||
<Compile Include="Graphics\VqaReader.cs" />
|
||||
<Compile Include="Filesystem\MixFile.cs" />
|
||||
<Compile Include="Filesystem\FileSystem.cs" />
|
||||
<Compile Include="Filesystem\Folder.cs" />
|
||||
<Compile Include="Filesystem\PackageWriter.cs" />
|
||||
<Compile Include="Filesystem\InstallShieldPackage.cs" />
|
||||
<Compile Include="FileFormats\Blast.cs" />
|
||||
<Compile Include="Filesystem\ZipFile.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
@@ -110,4 +118,7 @@
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
<ItemGroup>
|
||||
<Folder Include="Filesystem\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -8,7 +8,6 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
|
||||
@@ -16,15 +15,31 @@ namespace OpenRA.FileFormats
|
||||
{
|
||||
public class Palette
|
||||
{
|
||||
List<Color> colors = new List<Color>();
|
||||
|
||||
uint[] colors;
|
||||
public Color GetColor(int index)
|
||||
{
|
||||
return colors[index];
|
||||
return Color.FromArgb((int)colors[index]);
|
||||
}
|
||||
|
||||
public void SetColor(int index, Color color)
|
||||
{
|
||||
colors[index] = (uint)color.ToArgb();
|
||||
}
|
||||
|
||||
public void SetColor(int index, uint color)
|
||||
{
|
||||
colors[index] = (uint)color;
|
||||
}
|
||||
|
||||
public uint[] Values
|
||||
{
|
||||
get { return colors; }
|
||||
}
|
||||
|
||||
public Palette(Stream s, bool remapTransparent)
|
||||
{
|
||||
colors = new uint[256];
|
||||
|
||||
using (BinaryReader reader = new BinaryReader(s))
|
||||
{
|
||||
for (int i = 0; i < 256; i++)
|
||||
@@ -32,24 +47,29 @@ namespace OpenRA.FileFormats
|
||||
byte r = (byte)(reader.ReadByte() << 2);
|
||||
byte g = (byte)(reader.ReadByte() << 2);
|
||||
byte b = (byte)(reader.ReadByte() << 2);
|
||||
|
||||
colors.Add(Color.FromArgb(r, g, b));
|
||||
colors[i] = (uint)((255 << 24) | (r << 16) | (g << 8) | b);
|
||||
}
|
||||
}
|
||||
|
||||
colors[0] = Color.FromArgb(0, 0, 0, 0);
|
||||
|
||||
colors[0] = 0;
|
||||
if (remapTransparent)
|
||||
{
|
||||
colors[3] = Color.FromArgb(178, 0, 0, 0);
|
||||
colors[4] = Color.FromArgb(140, 0, 0, 0);
|
||||
colors[1] = 178u << 24; // Hack for d2k; may have side effects
|
||||
colors[3] = 178u << 24;
|
||||
colors[4] = 140u << 24;
|
||||
}
|
||||
}
|
||||
|
||||
public Palette(Palette p, IPaletteRemap r)
|
||||
{
|
||||
for (int i = 0; i < 256; i++)
|
||||
colors.Add(r.GetRemappedColor(p.GetColor(i), i));
|
||||
colors = new uint[256];
|
||||
for(int i = 0; i < 256; i++)
|
||||
colors[i] = (uint)r.GetRemappedColor(Color.FromArgb((int)p.colors[i]),i).ToArgb();
|
||||
}
|
||||
|
||||
public Palette(Palette p)
|
||||
{
|
||||
colors = (uint[])p.colors.Clone();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
38
OpenRA.FileFormats/PlayerColorRemap.cs
Normal file → Executable file
38
OpenRA.FileFormats/PlayerColorRemap.cs
Normal file → Executable file
@@ -15,15 +15,16 @@ using System.Linq;
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
// TODO: ship this out of here.
|
||||
public enum PaletteFormat { ra, cnc, d2k }
|
||||
|
||||
public class PlayerColorRemap : IPaletteRemap
|
||||
{
|
||||
Dictionary<int, Color> remapColors;
|
||||
|
||||
public PlayerColorRemap(Color c1, Color c2, bool useSplitRamp)
|
||||
public PlayerColorRemap(Color c1, Color c2, PaletteFormat fmt)
|
||||
{
|
||||
var baseIndex = useSplitRamp ? 0xb0 : 80;
|
||||
var ramp = useSplitRamp
|
||||
var baseIndex = (fmt == PaletteFormat.cnc) ? 0xb0 : (fmt == PaletteFormat.d2k) ? 240 : 80;
|
||||
var ramp = (fmt == PaletteFormat.cnc)
|
||||
? new[] { 0, 2, 4, 6, 8, 10, 13, 15, 1, 3, 5, 7, 9, 11, 12, 14 }
|
||||
: new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
|
||||
|
||||
@@ -31,7 +32,7 @@ namespace OpenRA.FileFormats
|
||||
.ToDictionary(u => u.First, u => u.Second);
|
||||
}
|
||||
|
||||
static Color ColorLerp(float t, Color c1, Color c2)
|
||||
public static Color ColorLerp(float t, Color c1, Color c2)
|
||||
{
|
||||
return Color.FromArgb(255,
|
||||
(int)(t * c2.R + (1 - t) * c1.R),
|
||||
@@ -45,5 +46,34 @@ namespace OpenRA.FileFormats
|
||||
return remapColors.TryGetValue(index, out c)
|
||||
? c : original;
|
||||
}
|
||||
|
||||
// hk is hue in the range [0,1] instead of [0,360]
|
||||
public static Color ColorFromHSL(float hk, float s, float l)
|
||||
{
|
||||
// Convert from HSL to RGB
|
||||
var q = (l < 0.5f) ? l * (1 + s) : l + s - (l * s);
|
||||
var p = 2 * l - q;
|
||||
|
||||
float[] trgb = { hk + 1 / 3.0f,
|
||||
hk,
|
||||
hk - 1/3.0f };
|
||||
float[] rgb = { 0, 0, 0 };
|
||||
|
||||
for (int k = 0; k < 3; k++)
|
||||
{
|
||||
while (trgb[k] < 0) trgb[k] += 1.0f;
|
||||
while (trgb[k] > 1) trgb[k] -= 1.0f;
|
||||
}
|
||||
|
||||
for (int k = 0; k < 3; k++)
|
||||
{
|
||||
if (trgb[k] < 1 / 6.0f) { rgb[k] = (p + ((q - p) * 6 * trgb[k])); }
|
||||
else if (trgb[k] >= 1 / 6.0f && trgb[k] < 0.5) { rgb[k] = q; }
|
||||
else if (trgb[k] >= 0.5f && trgb[k] < 2.0f / 3) { rgb[k] = (p + ((q - p) * 6 * (2.0f / 3 - trgb[k]))); }
|
||||
else { rgb[k] = p; }
|
||||
}
|
||||
|
||||
return Color.FromArgb((int)(rgb[0] * 255), (int)(rgb[1] * 255), (int)(rgb[2] * 255));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +56,11 @@ namespace OpenRA.FileFormats
|
||||
public static U AsSecond(Pair<T, U> p) { return p.Second; }
|
||||
|
||||
public Pair<U, T> Swap() { return Pair.New(Second, First); }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "({0},{1})".F(First, Second);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Pair
|
||||
|
||||
@@ -62,7 +62,8 @@ namespace OpenRA
|
||||
Constrain(Y, min.Y, max.Y));
|
||||
}
|
||||
|
||||
public static float2 operator *(float a, float2 b) { return new float2(a * b.X, a * b.Y); }
|
||||
public static float2 operator *(float a, float2 b) { return new float2(a * b.X, a * b.Y); }
|
||||
public static float2 operator *(float2 b, float a) { return new float2(a * b.X, a * b.Y); }
|
||||
public static float2 operator *( float2 a, float2 b ) { return new float2( a.X * b.X, a.Y * b.Y ); }
|
||||
public static float2 operator /( float2 a, float2 b ) { return new float2( a.X / b.X, a.Y / b.Y ); }
|
||||
|
||||
|
||||
@@ -25,6 +25,9 @@ namespace OpenRA
|
||||
public static int2 operator -(int2 a, int2 b) { return new int2(a.X - b.X, a.Y - b.Y); }
|
||||
public static int2 operator *(int a, int2 b) { return new int2(a * b.X, a * b.Y); }
|
||||
public static int2 operator *(int2 b, int a) { return new int2(a * b.X, a * b.Y); }
|
||||
public static int2 operator /(int2 a, int b) { return new int2(a.X / b, a.Y / b); }
|
||||
|
||||
public static int2 operator -(int2 a) { return new int2(-a.X, -a.Y); }
|
||||
|
||||
public static bool operator ==(int2 me, int2 other) { return (me.X == other.X && me.Y == other.Y); }
|
||||
public static bool operator !=(int2 me, int2 other) { return !(me == other); }
|
||||
@@ -53,5 +56,21 @@ namespace OpenRA
|
||||
public float2 ToFloat2() { return new float2(X, Y); }
|
||||
|
||||
public override string ToString() { return string.Format("{0},{1}", X, Y); }
|
||||
|
||||
// Change endianness of a uint32
|
||||
public static uint Swap(uint orig)
|
||||
{
|
||||
return (uint)((orig & 0xff000000) >> 24) | ((orig & 0x00ff0000) >> 8) | ((orig & 0x0000ff00) << 8) | ((orig & 0x000000ff) << 24);
|
||||
}
|
||||
|
||||
public static int Lerp( int a, int b, int mul, int div )
|
||||
{
|
||||
return a + ( b - a ) * mul / div;
|
||||
}
|
||||
|
||||
public static int2 Lerp( int2 a, int2 b, int mul, int div )
|
||||
{
|
||||
return a + ( b - a ) * mul / div;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
// todo: ship most of this back to the Game assembly;
|
||||
// it was only in FileFormats due to the original server model,
|
||||
// in a sep. process.
|
||||
|
||||
public class Session
|
||||
{
|
||||
public List<Client> Clients = new List<Client>();
|
||||
public Global GlobalSettings = new Global();
|
||||
|
||||
public enum ClientState
|
||||
{
|
||||
NotReady,
|
||||
Ready
|
||||
}
|
||||
|
||||
public class Client
|
||||
{
|
||||
public int Index;
|
||||
public System.Drawing.Color Color1;
|
||||
public System.Drawing.Color Color2;
|
||||
public string Country;
|
||||
public int SpawnPoint;
|
||||
public string Name;
|
||||
public ClientState State;
|
||||
public int Team;
|
||||
}
|
||||
|
||||
public class Global
|
||||
{
|
||||
public string Map;
|
||||
public string[] Mods = { "ra" }; // mod names
|
||||
public int OrderLatency = 3;
|
||||
public int RandomSeed = 0;
|
||||
public bool LockTeams = false; // don't allow team changes after game start.
|
||||
}
|
||||
}
|
||||
|
||||
public class Manifest
|
||||
{
|
||||
public readonly string[]
|
||||
Folders, Packages, Rules,
|
||||
Sequences, Chrome, Assemblies, ChromeLayout,
|
||||
Weapons, Voices, Music, TileSets;
|
||||
|
||||
public readonly string ShellmapUid;
|
||||
|
||||
public Manifest(string[] mods)
|
||||
{
|
||||
var yaml = mods
|
||||
.Select(m => MiniYaml.FromFile("mods/" + m + "/mod.yaml"))
|
||||
.Aggregate(MiniYaml.Merge);
|
||||
|
||||
Folders = YamlList(yaml, "Folders");
|
||||
Packages = YamlList(yaml, "Packages");
|
||||
Rules = YamlList(yaml, "Rules");
|
||||
Sequences = YamlList(yaml, "Sequences");
|
||||
Chrome = YamlList(yaml, "Chrome");
|
||||
Assemblies = YamlList(yaml, "Assemblies");
|
||||
ChromeLayout = YamlList(yaml, "ChromeLayout");
|
||||
Weapons = YamlList(yaml, "Weapons");
|
||||
Voices = YamlList(yaml, "Voices");
|
||||
Music = YamlList(yaml, "Music");
|
||||
TileSets = YamlList(yaml, "TileSets");
|
||||
|
||||
ShellmapUid = yaml["ShellmapUid"].Value;
|
||||
}
|
||||
|
||||
static string[] YamlList(Dictionary<string, MiniYaml> ys, string key)
|
||||
{
|
||||
return ys.ContainsKey(key) ? ys[key].Nodes.Keys.ToArray() : new string[] { };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,10 +19,8 @@ namespace OpenRA
|
||||
{
|
||||
public struct ChannelInfo
|
||||
{
|
||||
public bool Upload;
|
||||
public string Filename;
|
||||
public StreamWriter Writer;
|
||||
public bool Diff;
|
||||
}
|
||||
|
||||
public static class Log
|
||||
@@ -41,7 +39,7 @@ namespace OpenRA
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddChannel(string channelName, string filename, bool upload, bool diff)
|
||||
public static void AddChannel(string channelName, string filename)
|
||||
{
|
||||
if (channels.ContainsKey(channelName)) return;
|
||||
|
||||
@@ -52,7 +50,7 @@ namespace OpenRA
|
||||
{
|
||||
StreamWriter writer = File.CreateText(LogPathPrefix + filename);
|
||||
writer.AutoFlush = true;
|
||||
channels.Add(channelName, new ChannelInfo() { Upload = upload, Filename = filename, Writer = writer, Diff = diff });
|
||||
channels.Add(channelName, new ChannelInfo() { Filename = filename, Writer = writer });
|
||||
return;
|
||||
}
|
||||
catch (IOException) { filename = f + ".{0}".F(++i); }
|
||||
@@ -60,7 +58,7 @@ namespace OpenRA
|
||||
//if no logs exist, just make it
|
||||
StreamWriter w = File.CreateText(LogPathPrefix + filename);
|
||||
w.AutoFlush = true;
|
||||
channels.Add(channelName, new ChannelInfo() { Upload = upload, Filename = filename, Writer = w, Diff = diff });
|
||||
channels.Add(channelName, new ChannelInfo() { Filename = filename, Writer = w });
|
||||
|
||||
}
|
||||
|
||||
@@ -72,35 +70,5 @@ namespace OpenRA
|
||||
|
||||
info.Writer.WriteLine(format, args);
|
||||
}
|
||||
|
||||
public static void Upload(int gameId)
|
||||
{
|
||||
foreach (var kvp in channels.Where(x => x.Value.Upload))
|
||||
{
|
||||
kvp.Value.Writer.Close();
|
||||
var logfile = File.OpenRead(Log.LogPathPrefix + kvp.Value.Filename);
|
||||
byte[] fileContents = logfile.ReadAllBytes();
|
||||
var ms = new MemoryStream();
|
||||
|
||||
using (var gzip = new GZipStream(ms, CompressionMode.Compress, true))
|
||||
gzip.Write(fileContents, 0, fileContents.Length);
|
||||
|
||||
ms.Position = 0;
|
||||
byte[] buffer = ms.ReadAllBytes();
|
||||
|
||||
WebRequest request = WebRequest.Create("http://open-ra.org/logs/upload.php");
|
||||
request.ContentType = "application/x-gzip";
|
||||
request.ContentLength = buffer.Length;
|
||||
request.Method = "POST";
|
||||
request.Headers.Add("Game-ID", gameId.ToString());
|
||||
request.Headers.Add("Channel", kvp.Key);
|
||||
// request.Headers.Add("Diff", kvp.Value.Diff ? "1" : "0");
|
||||
|
||||
using (var requestStream = request.GetRequestStream())
|
||||
requestStream.Write(buffer, 0, buffer.Length);
|
||||
|
||||
//var response = (HttpWebResponse)request.GetResponse();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
5
OpenRA.FileFormats/Thirdparty/Random.cs
vendored
5
OpenRA.FileFormats/Thirdparty/Random.cs
vendored
@@ -18,6 +18,8 @@ namespace OpenRA.Thirdparty
|
||||
{
|
||||
uint[] mt = new uint[624];
|
||||
int index = 0;
|
||||
|
||||
public int Last;
|
||||
|
||||
public Random() : this(Environment.TickCount) { }
|
||||
|
||||
@@ -39,7 +41,8 @@ namespace OpenRA.Thirdparty
|
||||
y ^= y >> 18;
|
||||
|
||||
index = (index + 1) % 624;
|
||||
return (int)(y % int.MaxValue);
|
||||
Last = (int)(y % int.MaxValue);
|
||||
return Last;
|
||||
}
|
||||
|
||||
public int Next(int low, int high) { return low + Next() % (high - low); }
|
||||
|
||||
@@ -9,12 +9,13 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class TypeDictionary
|
||||
public class TypeDictionary : IEnumerable
|
||||
{
|
||||
Dictionary<Type, object> dataSingular = new Dictionary<Type, object>();
|
||||
Dictionary<Type, List<object>> dataMultiple = new Dictionary<Type, List<object>>();
|
||||
@@ -85,13 +86,13 @@ namespace OpenRA.FileFormats
|
||||
return new T[ 0 ];
|
||||
}
|
||||
|
||||
public IEnumerator<object> GetEnumerator()
|
||||
public IEnumerator GetEnumerator()
|
||||
{
|
||||
return WithInterface<object>().GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
static class TypeExts
|
||||
public static class TypeExts
|
||||
{
|
||||
public static IEnumerable<Type> BaseTypes( this Type t )
|
||||
{
|
||||
|
||||
@@ -6,44 +6,42 @@
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.Traits;
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Support;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Traits.Activities;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public class Actor
|
||||
{
|
||||
[Sync]
|
||||
public readonly TypeDictionary traits = new TypeDictionary();
|
||||
public readonly ActorInfo Info;
|
||||
|
||||
public readonly World World;
|
||||
public readonly uint ActorID;
|
||||
|
||||
public int2 Location { get { return traits.Get<IOccupySpace>().TopLeft; } }
|
||||
public int2 Location { get { return Trait<IOccupySpace>().TopLeft; } }
|
||||
public float2 CenterLocation { get { return Trait<IHasLocation>().PxPosition; } }
|
||||
[Sync]
|
||||
public Player Owner;
|
||||
[Sync]
|
||||
public int Health;
|
||||
|
||||
IActivity currentActivity;
|
||||
public Group Group;
|
||||
|
||||
public Actor(World world, string name, int2 location, Player owner)
|
||||
public Group Group;
|
||||
|
||||
internal Actor(World world, string name, TypeDictionary initDict )
|
||||
{
|
||||
World = world;
|
||||
ActorID = world.NextAID();
|
||||
Owner = owner;
|
||||
var init = new ActorInitializer( this, initDict );
|
||||
|
||||
var init = new ActorInitializer( this, location );
|
||||
World = world;
|
||||
ActorID = world.NextAID();
|
||||
if( initDict.Contains<OwnerInit>() )
|
||||
Owner = init.Get<OwnerInit,Player>();
|
||||
|
||||
if (name != null)
|
||||
{
|
||||
@@ -51,15 +49,10 @@ namespace OpenRA
|
||||
throw new NotImplementedException("No rules definition for unit {0}".F(name.ToLowerInvariant()));
|
||||
|
||||
Info = Rules.Info[name.ToLowerInvariant()];
|
||||
Health = this.GetMaxHP();
|
||||
|
||||
foreach (var trait in Info.TraitsInConstructOrder())
|
||||
traits.Add(trait.Create(init));
|
||||
AddTrait(trait.Create(init));
|
||||
}
|
||||
|
||||
if( CenterLocation == float2.Zero && traits.Contains<IOccupySpace>() )
|
||||
CenterLocation = Traits.Util.CenterOfCell(Location);
|
||||
|
||||
Size = Lazy.New(() =>
|
||||
{
|
||||
var si = Info.Traits.GetOrDefault<SelectableInfo>();
|
||||
@@ -67,31 +60,19 @@ namespace OpenRA
|
||||
return new float2(si.Bounds[0], si.Bounds[1]);
|
||||
|
||||
// auto size from render
|
||||
var firstSprite = traits.WithInterface<IRender>().SelectMany(x => x.Render(this)).FirstOrDefault();
|
||||
if (firstSprite.Sprite == null) return float2.Zero;
|
||||
return firstSprite.Sprite.size;
|
||||
var firstSprite = TraitsImplementing<IRender>().SelectMany(x => x.Render(this)).FirstOrDefault();
|
||||
if (firstSprite.Sprite == null) return float2.Zero;
|
||||
return firstSprite.Sprite.size * firstSprite.Scale;
|
||||
});
|
||||
}
|
||||
|
||||
public void Tick()
|
||||
{
|
||||
var wasIdle = currentActivity is Idle;
|
||||
while (currentActivity != null)
|
||||
{
|
||||
var a = currentActivity;
|
||||
currentActivity = a.Tick(this) ?? new Idle();
|
||||
{
|
||||
if (currentActivity == null)
|
||||
foreach (var ni in TraitsImplementing<INotifyIdle>())
|
||||
ni.TickIdle(this);
|
||||
|
||||
if (a == currentActivity) break;
|
||||
|
||||
if (currentActivity is Idle)
|
||||
{
|
||||
if (!wasIdle)
|
||||
foreach (var ni in traits.WithInterface<INotifyIdle>())
|
||||
ni.Idle(this);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
currentActivity = Util.RunActivity( this, currentActivity );
|
||||
}
|
||||
|
||||
public bool IsIdle
|
||||
@@ -99,40 +80,26 @@ namespace OpenRA
|
||||
get { return currentActivity == null || currentActivity is Idle; }
|
||||
}
|
||||
|
||||
public float2 CenterLocation;
|
||||
|
||||
OpenRA.FileFormats.Lazy<float2> Size;
|
||||
|
||||
public IEnumerable<Renderable> Render()
|
||||
{
|
||||
var mods = traits.WithInterface<IRenderModifier>();
|
||||
var sprites = traits.WithInterface<IRender>().SelectMany(x => x.Render(this));
|
||||
var mods = TraitsImplementing<IRenderModifier>();
|
||||
var sprites = TraitsImplementing<IRender>().SelectMany(x => x.Render(this));
|
||||
return mods.Aggregate(sprites, (m, p) => p.ModifyRender(this, m));
|
||||
}
|
||||
|
||||
public Order Order( int2 xy, MouseInput mi )
|
||||
{
|
||||
if (Owner != World.LocalPlayer)
|
||||
return null;
|
||||
|
||||
if (!World.Map.IsInMap(xy.X, xy.Y))
|
||||
return null;
|
||||
|
||||
var underCursor = World.FindUnitsAtMouse(mi.Location)
|
||||
.Where(a => a.Info.Traits.Contains<SelectableInfo>())
|
||||
.OrderByDescending(a => a.Info.Traits.Get<SelectableInfo>().Priority)
|
||||
.FirstOrDefault();
|
||||
|
||||
return traits.WithInterface<IIssueOrder>()
|
||||
.Select( x => x.IssueOrder( this, xy, mi, underCursor ) )
|
||||
.FirstOrDefault( x => x != null );
|
||||
}
|
||||
|
||||
public RectangleF GetBounds(bool useAltitude)
|
||||
{
|
||||
var si = Info.Traits.GetOrDefault<SelectableInfo>();
|
||||
|
||||
var size = Size.Value;
|
||||
var size = Size.Value;
|
||||
|
||||
/* apply scaling */
|
||||
var scale = this.TraitOrDefault<Scale>();
|
||||
if (scale != null && scale.Info.Value != 1)
|
||||
size = size*scale.Info.Value;
|
||||
|
||||
var loc = CenterLocation - 0.5f * size;
|
||||
|
||||
if (si != null && si.Bounds != null && si.Bounds.Length > 2)
|
||||
@@ -140,87 +107,28 @@ namespace OpenRA
|
||||
|
||||
if (useAltitude)
|
||||
{
|
||||
var unit = traits.GetOrDefault<Unit>();
|
||||
if (unit != null) loc -= new float2(0, unit.Altitude);
|
||||
var move = TraitOrDefault<IMove>();
|
||||
if (move != null) loc -= new float2(0, move.Altitude);
|
||||
}
|
||||
|
||||
return new RectangleF(loc.X, loc.Y, size.X, size.Y);
|
||||
}
|
||||
|
||||
public bool IsDead { get { return Health <= 0; } }
|
||||
public bool IsInWorld { get; set; }
|
||||
public bool RemoveOnDeath = true;
|
||||
|
||||
public DamageState GetDamageState()
|
||||
{
|
||||
if (Health <= 0)
|
||||
return DamageState.Dead;
|
||||
|
||||
if (Health < this.GetMaxHP() * World.Defaults.ConditionYellow)
|
||||
return DamageState.Half;
|
||||
|
||||
return DamageState.Normal;
|
||||
}
|
||||
|
||||
public void InflictDamage(Actor attacker, int damage, WarheadInfo warhead)
|
||||
{
|
||||
if (IsDead) return; /* overkill! don't count extra hits as more kills! */
|
||||
|
||||
var oldState = GetDamageState();
|
||||
|
||||
/* apply the damage modifiers, if we have any. */
|
||||
var modifier = (float)traits.WithInterface<IDamageModifier>()
|
||||
.Select(t => t.GetDamageModifier(warhead)).Product();
|
||||
|
||||
damage = (int)(damage * modifier);
|
||||
|
||||
Health -= damage;
|
||||
if (Health <= 0)
|
||||
{
|
||||
Health = 0;
|
||||
|
||||
attacker.Owner.Kills++;
|
||||
Owner.Deaths++;
|
||||
|
||||
if (RemoveOnDeath)
|
||||
World.AddFrameEndTask(w => w.Remove(this));
|
||||
public bool IsInWorld { get; internal set; }
|
||||
|
||||
Log.Write("debug", "{0} #{1} killed by {2} #{3}", Info.Name, ActorID, attacker.Info.Name, attacker.ActorID);
|
||||
}
|
||||
|
||||
var maxHP = this.GetMaxHP();
|
||||
|
||||
if (Health > maxHP) Health = maxHP;
|
||||
|
||||
// Log.Write("debug", "InflictDamage: {0} #{1} -> {2} #{3} raw={4} adj={5} hp={6} mod={7}",
|
||||
// attacker.Info.Name, attacker.ActorID, Info.Name, ActorID, rawDamage, damage, Health, modifier);
|
||||
|
||||
var newState = GetDamageState();
|
||||
|
||||
foreach (var nd in traits.WithInterface<INotifyDamage>())
|
||||
nd.Damaged(this, new AttackInfo
|
||||
{
|
||||
Attacker = attacker,
|
||||
Damage = damage,
|
||||
DamageState = newState,
|
||||
DamageStateChanged = newState != oldState,
|
||||
Warhead = warhead
|
||||
});
|
||||
public void QueueActivity( bool queued, IActivity nextActivity )
|
||||
{
|
||||
if( !queued )
|
||||
CancelActivity();
|
||||
QueueActivity( nextActivity );
|
||||
}
|
||||
|
||||
public void QueueActivity( IActivity nextActivity )
|
||||
{
|
||||
if( currentActivity == null )
|
||||
{
|
||||
currentActivity = nextActivity;
|
||||
return;
|
||||
}
|
||||
var act = currentActivity;
|
||||
while( act.NextActivity != null )
|
||||
{
|
||||
act = act.NextActivity;
|
||||
}
|
||||
act.NextActivity = nextActivity;
|
||||
else
|
||||
currentActivity.Queue( nextActivity );
|
||||
}
|
||||
|
||||
public void CancelActivity()
|
||||
@@ -245,18 +153,49 @@ namespace OpenRA
|
||||
var o = obj as Actor;
|
||||
return ( o != null && o.ActorID == ActorID );
|
||||
}
|
||||
}
|
||||
|
||||
public class ActorInitializer
|
||||
{
|
||||
public readonly Actor self;
|
||||
public World world { get { return self.World; } }
|
||||
public readonly int2 location;
|
||||
|
||||
public ActorInitializer( Actor actor, int2 location )
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
this.self = actor;
|
||||
this.location = location;
|
||||
return "{0} {1}{2}".F( Info.Name, ActorID, IsInWorld ? "" : " (not in world)" );
|
||||
}
|
||||
|
||||
public T Trait<T>()
|
||||
{
|
||||
return World.traitDict.Get<T>( this );
|
||||
}
|
||||
}
|
||||
|
||||
public T TraitOrDefault<T>()
|
||||
{
|
||||
return World.traitDict.GetOrDefault<T>( this );
|
||||
}
|
||||
|
||||
public IEnumerable<T> TraitsImplementing<T>()
|
||||
{
|
||||
return World.traitDict.WithInterface<T>( this );
|
||||
}
|
||||
|
||||
public bool HasTrait<T>()
|
||||
{
|
||||
return World.traitDict.Contains<T>( this );
|
||||
}
|
||||
|
||||
public void AddTrait( object trait )
|
||||
{
|
||||
World.traitDict.AddTrait( this, trait );
|
||||
}
|
||||
|
||||
public bool Destroyed { get; private set; }
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
World.AddFrameEndTask( w =>
|
||||
{
|
||||
if (Destroyed) return;
|
||||
|
||||
World.Remove( this );
|
||||
World.traitDict.RemoveActor( this );
|
||||
Destroyed = true;
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
134
OpenRA.Game/ActorInitializer.cs
Executable file
134
OpenRA.Game/ActorInitializer.cs
Executable file
@@ -0,0 +1,134 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public class ActorInitializer
|
||||
{
|
||||
public readonly Actor self;
|
||||
public World world { get { return self.World; } }
|
||||
internal TypeDictionary dict;
|
||||
|
||||
public ActorInitializer( Actor actor, TypeDictionary dict )
|
||||
{
|
||||
this.self = actor;
|
||||
this.dict = dict;
|
||||
}
|
||||
|
||||
public T Get<T>()
|
||||
where T : IActorInit
|
||||
{
|
||||
return dict.Get<T>();
|
||||
}
|
||||
|
||||
public U Get<T,U>()
|
||||
where T : IActorInit<U>
|
||||
{
|
||||
return dict.Get<T>().Value( world );
|
||||
}
|
||||
|
||||
public bool Contains<T>()
|
||||
where T : IActorInit
|
||||
{
|
||||
return dict.Contains<T>();
|
||||
}
|
||||
}
|
||||
|
||||
public interface IActorInit {}
|
||||
|
||||
public interface IActorInit<T> : IActorInit
|
||||
{
|
||||
T Value( World world );
|
||||
}
|
||||
|
||||
public class FacingInit : IActorInit<int>
|
||||
{
|
||||
[FieldFromYamlKey]
|
||||
public readonly int value = 128;
|
||||
|
||||
public FacingInit() { }
|
||||
|
||||
public FacingInit( int init )
|
||||
{
|
||||
value = init;
|
||||
}
|
||||
|
||||
public int Value( World world )
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public class AltitudeInit : IActorInit<int>
|
||||
{
|
||||
[FieldFromYamlKey]
|
||||
public readonly int value = 0;
|
||||
|
||||
public AltitudeInit() { }
|
||||
|
||||
public AltitudeInit( int init )
|
||||
{
|
||||
value = init;
|
||||
}
|
||||
|
||||
public int Value( World world )
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public class LocationInit : IActorInit<int2>
|
||||
{
|
||||
[FieldFromYamlKey]
|
||||
public readonly int2 value = int2.Zero;
|
||||
|
||||
public LocationInit() { }
|
||||
|
||||
public LocationInit( int2 init )
|
||||
{
|
||||
value = init;
|
||||
}
|
||||
|
||||
public int2 Value( World world )
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public class OwnerInit : IActorInit<Player>
|
||||
{
|
||||
[FieldFromYamlKey]
|
||||
public readonly string PlayerName = "Neutral";
|
||||
Player player;
|
||||
|
||||
public OwnerInit() { }
|
||||
|
||||
public OwnerInit( string playerName )
|
||||
{
|
||||
this.PlayerName = playerName;
|
||||
}
|
||||
|
||||
public OwnerInit( Player player )
|
||||
{
|
||||
this.player = player;
|
||||
this.PlayerName = player.InternalName;
|
||||
}
|
||||
|
||||
public Player Value( World world )
|
||||
{
|
||||
if( player != null )
|
||||
return player;
|
||||
return world.players.Values.First( x => x.InternalName == PlayerName );
|
||||
}
|
||||
}
|
||||
}
|
||||
57
OpenRA.Game/ActorReference.cs
Executable file
57
OpenRA.Game/ActorReference.cs
Executable file
@@ -0,0 +1,57 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class ActorReference : IEnumerable
|
||||
{
|
||||
public readonly string Type;
|
||||
public readonly TypeDictionary InitDict;
|
||||
|
||||
public ActorReference( string type ) : this( type, new Dictionary<string, MiniYaml>() ) { }
|
||||
|
||||
public ActorReference( string type, Dictionary<string, MiniYaml> inits )
|
||||
{
|
||||
if (Rules.Info != null && !Rules.Info.ContainsKey(type))
|
||||
throw new InvalidDataException("Unknown actor: `{0}'".F(type));
|
||||
|
||||
Type = type;
|
||||
InitDict = new TypeDictionary();
|
||||
foreach( var i in inits )
|
||||
InitDict.Add( LoadInit( i.Key, i.Value ) );
|
||||
}
|
||||
|
||||
static IActorInit LoadInit(string traitName, MiniYaml my)
|
||||
{
|
||||
var info = Game.CreateObject<IActorInit>(traitName + "Init");
|
||||
FieldLoader.Load(info, my);
|
||||
return info;
|
||||
}
|
||||
|
||||
public MiniYaml Save()
|
||||
{
|
||||
var ret = new MiniYaml( Type );
|
||||
foreach( var init in InitDict )
|
||||
{
|
||||
var initName = init.GetType().Name;
|
||||
ret.Nodes.Add( new MiniYamlNode( initName.Substring( 0, initName.Length - 4 ), FieldSaver.Save( init ) ) );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// for initialization syntax
|
||||
public void Add( object o ) { InitDict.Add( o ); }
|
||||
public IEnumerator GetEnumerator() { return InitDict.GetEnumerator(); }
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
class Chrome : IHandleInput
|
||||
{
|
||||
public readonly Renderer renderer;
|
||||
public readonly LineRenderer lineRenderer;
|
||||
|
||||
SpriteRenderer rgbaRenderer { get { return renderer.RgbaSpriteRenderer; } }
|
||||
SpriteRenderer shpRenderer { get { return renderer.WorldSpriteRenderer; } }
|
||||
|
||||
public Chrome(Renderer r, Manifest m)
|
||||
{
|
||||
this.renderer = r;
|
||||
lineRenderer = new LineRenderer(renderer);
|
||||
|
||||
var widgetYaml = m.ChromeLayout.Select(a => MiniYaml.FromFile(a)).Aggregate(MiniYaml.Merge);
|
||||
|
||||
if (rootWidget == null)
|
||||
{
|
||||
rootWidget = WidgetLoader.LoadWidget( widgetYaml.FirstOrDefault() );
|
||||
rootWidget.Initialize();
|
||||
rootWidget.InitDelegates();
|
||||
}
|
||||
}
|
||||
|
||||
public static Widget rootWidget = null;
|
||||
|
||||
public void Tick(World world)
|
||||
{
|
||||
rootWidget.Tick(world);
|
||||
|
||||
if (!world.GameHasStarted) return;
|
||||
if (world.LocalPlayer == null) return;
|
||||
++ticksSinceLastMove;
|
||||
}
|
||||
|
||||
public void Draw(World world) { rootWidget.Draw(world); shpRenderer.Flush(); rgbaRenderer.Flush(); lineRenderer.Flush(); }
|
||||
|
||||
public int ticksSinceLastMove = 0;
|
||||
public int2 lastMousePos;
|
||||
public bool HandleInput(World world, MouseInput mi)
|
||||
{
|
||||
if (Widget.SelectedWidget != null && Widget.SelectedWidget.HandleMouseInputOuter(mi))
|
||||
return true;
|
||||
|
||||
if (rootWidget.HandleMouseInputOuter(mi))
|
||||
return true;
|
||||
|
||||
if (mi.Event == MouseInputEvent.Move)
|
||||
{
|
||||
lastMousePos = mi.Location;
|
||||
ticksSinceLastMove = 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public bool HandleKeyPress(KeyInput e)
|
||||
{
|
||||
if (Widget.SelectedWidget != null)
|
||||
return Widget.SelectedWidget.HandleKeyPressOuter(e);
|
||||
|
||||
if (rootWidget.HandleKeyPressOuter(e))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool HitTest(int2 mousePos)
|
||||
{
|
||||
if (Widget.SelectedWidget != null)
|
||||
return true;
|
||||
|
||||
return rootWidget.HitTest(mousePos);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Orders;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public class Controller : IHandleInput
|
||||
{
|
||||
public IOrderGenerator orderGenerator = new UnitOrderGenerator();
|
||||
public Selection selection = new Selection();
|
||||
|
||||
public void CancelInputMode() { orderGenerator = new UnitOrderGenerator(); }
|
||||
|
||||
public bool ToggleInputMode<T>() where T : IOrderGenerator, new()
|
||||
{
|
||||
if (orderGenerator is T)
|
||||
{
|
||||
CancelInputMode();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
orderGenerator = new T();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyOrders(World world, float2 xy, MouseInput mi)
|
||||
{
|
||||
if (orderGenerator == null) return;
|
||||
|
||||
var orders = orderGenerator.Order(world, xy.ToInt2(), mi).ToArray();
|
||||
Game.orderManager.IssueOrders( orders );
|
||||
|
||||
var voicedActor = orders.Select(o => o.Subject)
|
||||
.FirstOrDefault(a => a.Owner == world.LocalPlayer && a.HasVoice());
|
||||
|
||||
var isMove = orders.Any(o => o.OrderString == "Move");
|
||||
var isAttack = orders.Any( o => o.OrderString == "Attack" );
|
||||
|
||||
if (voicedActor != null)
|
||||
{
|
||||
if(voicedActor.traits.GetOrDefault<IMove>().CanEnterCell(xy.ToInt2()))
|
||||
Sound.PlayVoice(isAttack ? "Attack" : "Move", voicedActor);
|
||||
|
||||
if (isMove)
|
||||
world.Add(new Effects.MoveFlash(world, Game.CellSize * xy));
|
||||
}
|
||||
}
|
||||
|
||||
float2 dragStart, dragEnd;
|
||||
public bool HandleInput(World world, MouseInput mi)
|
||||
{
|
||||
var xy = Game.viewport.ViewToWorld(mi);
|
||||
|
||||
if (mi.Button == MouseButton.Left && mi.Event == MouseInputEvent.Down)
|
||||
{
|
||||
dragStart = dragEnd = xy;
|
||||
ApplyOrders(world, xy, mi);
|
||||
}
|
||||
|
||||
if (mi.Button == MouseButton.Left && mi.Event == MouseInputEvent.Move)
|
||||
dragEnd = xy;
|
||||
|
||||
if (mi.Button == MouseButton.Left && mi.Event == MouseInputEvent.Up)
|
||||
{
|
||||
if (orderGenerator is UnitOrderGenerator)
|
||||
{
|
||||
var newSelection = world.SelectActorsInBox(Game.CellSize * dragStart, Game.CellSize * xy);
|
||||
selection.Combine(world, newSelection, mi.Modifiers.HasModifier(Modifiers.Shift), dragStart == xy);
|
||||
}
|
||||
|
||||
dragStart = dragEnd = xy;
|
||||
}
|
||||
|
||||
if (mi.Button == MouseButton.None && mi.Event == MouseInputEvent.Move)
|
||||
dragStart = dragEnd = xy;
|
||||
|
||||
if (mi.Button == MouseButton.Right && mi.Event == MouseInputEvent.Down)
|
||||
ApplyOrders(world, xy, mi);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public Pair<float2, float2>? SelectionBox
|
||||
{
|
||||
get
|
||||
{
|
||||
if (dragStart == dragEnd) return null;
|
||||
return Pair.New(Game.CellSize * dragStart, Game.CellSize * dragEnd);
|
||||
}
|
||||
}
|
||||
|
||||
public float2 MousePosition { get { return dragEnd; } }
|
||||
Modifiers modifiers;
|
||||
|
||||
public string ChooseCursor( World world )
|
||||
{
|
||||
int sync = world.SyncHash();
|
||||
|
||||
try
|
||||
{
|
||||
if (!world.GameHasStarted)
|
||||
return "default";
|
||||
|
||||
var mi = new MouseInput
|
||||
{
|
||||
Location = ( Game.CellSize * MousePosition - Game.viewport.Location ).ToInt2(),
|
||||
Button = MouseButton.Right,
|
||||
Modifiers = modifiers
|
||||
};
|
||||
|
||||
return orderGenerator.GetCursor( world, MousePosition.ToInt2(), mi );
|
||||
}
|
||||
finally
|
||||
{
|
||||
if( sync != world.SyncHash() )
|
||||
throw new InvalidOperationException( "Desync in Controller.ChooseCursor" );
|
||||
}
|
||||
}
|
||||
|
||||
public void SetModifiers(Modifiers mods) { modifiers = mods; }
|
||||
public Modifiers GetModifiers() { return modifiers; }
|
||||
|
||||
public void GotoNextBase()
|
||||
{
|
||||
var bases = Game.world.Queries.OwnedBy[Game.world.LocalPlayer].WithTrait<BaseBuilding>().ToArray();
|
||||
if (!bases.Any()) return;
|
||||
|
||||
var next = bases
|
||||
.Select( b => b.Actor )
|
||||
.SkipWhile(b => Game.controller.selection.Actors.Contains(b))
|
||||
.Skip(1)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (next == null)
|
||||
next = bases.Select(b => b.Actor).First();
|
||||
|
||||
Game.controller.selection.Combine(Game.world, new Actor[] { next }, false, true);
|
||||
Game.viewport.Center(Game.controller.selection.Actors);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,10 +17,12 @@ namespace OpenRA
|
||||
CursorSequence sequence;
|
||||
public Cursor(string cursor)
|
||||
{
|
||||
sequence = SequenceProvider.GetCursorSequence(cursor);
|
||||
sequence = CursorProvider.GetCursorSequence(cursor);
|
||||
}
|
||||
|
||||
public void Draw(WorldRenderer wr, int frame, float2 pos)
|
||||
{
|
||||
sequence.GetSprite(frame).DrawAt(wr, pos - sequence.Hotspot, sequence.Palette);
|
||||
}
|
||||
|
||||
public Sprite GetSprite(int frame) { return sequence.GetSprite(frame); }
|
||||
public int2 GetHotspot() { return sequence.Hotspot; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,12 +28,15 @@ namespace OpenRA.Effects
|
||||
|
||||
public void Tick( World world )
|
||||
{
|
||||
if (--remainingTicks == 0)
|
||||
if (--remainingTicks == 0 || !target.IsInWorld)
|
||||
world.AddFrameEndTask(w => w.Remove(this));
|
||||
}
|
||||
|
||||
public IEnumerable<Renderable> Render()
|
||||
{
|
||||
if (!target.IsInWorld)
|
||||
yield break;
|
||||
|
||||
if (remainingTicks % 2 == 0)
|
||||
foreach (var r in target.Render())
|
||||
yield return r.WithPalette("highlight");
|
||||
|
||||
@@ -14,11 +14,20 @@ using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Effects
|
||||
{
|
||||
class MoveFlash : IEffect
|
||||
public class MoveFlash : IEffect
|
||||
{
|
||||
Animation anim = new Animation("moveflsh");
|
||||
float2 pos;
|
||||
|
||||
|
||||
public MoveFlash( World world, int2 cell )
|
||||
{
|
||||
this.pos = Game.CellSize * (cell + new float2(0.5f, 0.5f));
|
||||
anim.PlayThen( "idle",
|
||||
() => world.AddFrameEndTask(
|
||||
w => w.Remove( this ) ) );
|
||||
}
|
||||
|
||||
public MoveFlash( World world, float2 pos )
|
||||
{
|
||||
this.pos = pos;
|
||||
@@ -31,7 +40,7 @@ namespace OpenRA.Effects
|
||||
|
||||
public IEnumerable<Renderable> Render()
|
||||
{
|
||||
yield return new Renderable(anim.Image, pos - .5f * anim.Image.size, "shadow");
|
||||
yield return new Renderable(anim.Image, pos - .5f * anim.Image.size, "shadow", (int)pos.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
30
OpenRA.Game/Exts.cs
Normal file → Executable file
30
OpenRA.Game/Exts.cs
Normal file → Executable file
@@ -12,7 +12,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Support;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
@@ -34,24 +33,17 @@ namespace OpenRA
|
||||
return xs.Aggregate(1f, (a, x) => a * x);
|
||||
}
|
||||
|
||||
public static int GetMaxHP(this Actor self)
|
||||
{
|
||||
var oai = self.Info.Traits.GetOrDefault<OwnedActorInfo>();
|
||||
if (oai == null) return 0;
|
||||
return oai.HP;
|
||||
}
|
||||
|
||||
public static V GetOrAdd<K, V>( this Dictionary<K, V> d, K k )
|
||||
public static V GetOrAdd<K, V>(this Dictionary<K, V> d, K k)
|
||||
where V : new()
|
||||
{
|
||||
return d.GetOrAdd( k, _ => new V() );
|
||||
return d.GetOrAdd(k, _ => new V());
|
||||
}
|
||||
|
||||
public static V GetOrAdd<K, V>( this Dictionary<K, V> d, K k, Func<K, V> createFn )
|
||||
public static V GetOrAdd<K, V>(this Dictionary<K, V> d, K k, Func<K, V> createFn)
|
||||
{
|
||||
V ret;
|
||||
if( !d.TryGetValue( k, out ret ) )
|
||||
d.Add( k, ret = createFn( k ) );
|
||||
if (!d.TryGetValue(k, out ret))
|
||||
d.Add(k, ret = createFn(k));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -61,18 +53,18 @@ namespace OpenRA
|
||||
return xs[r.Next(xs.Length)];
|
||||
}
|
||||
|
||||
public static void DoTimed<T>( this IEnumerable<T> e, Action<T> a, string text, double time )
|
||||
public static void DoTimed<T>(this IEnumerable<T> e, Action<T> a, string text, double time)
|
||||
{
|
||||
var sw = new Stopwatch();
|
||||
|
||||
e.Do( x =>
|
||||
e.Do(x =>
|
||||
{
|
||||
var t = sw.ElapsedTime();
|
||||
a( x );
|
||||
a(x);
|
||||
var dt = sw.ElapsedTime() - t;
|
||||
if( dt > time )
|
||||
Log.Write("perf", text, x, dt * 1000);
|
||||
} );
|
||||
if (dt > time)
|
||||
Log.Write("perf", text, x, dt * 1000, Game.LocalTick);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
772
OpenRA.Game/Game.cs
Normal file → Executable file
772
OpenRA.Game/Game.cs
Normal file → Executable file
@@ -6,170 +6,62 @@
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.FileFormats.Graphics;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Network;
|
||||
using OpenRA.Server;
|
||||
using OpenRA.Support;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
using Timer = OpenRA.Support.Timer;
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Windows.Forms;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Network;
|
||||
using OpenRA.Server;
|
||||
using OpenRA.Support;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
using XRandom = OpenRA.Thirdparty.Random;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public static class Game
|
||||
{
|
||||
public static readonly int CellSize = 24;
|
||||
public static int CellSize { get { return modData.Manifest.TileSize; } }
|
||||
|
||||
public static World world;
|
||||
internal static Viewport viewport;
|
||||
public static Controller controller;
|
||||
internal static Chrome chrome;
|
||||
internal static UserSettings Settings;
|
||||
public static ModData modData;
|
||||
private static WorldRenderer worldRenderer;
|
||||
|
||||
public static Viewport viewport;
|
||||
public static Settings Settings;
|
||||
|
||||
internal static OrderManager orderManager;
|
||||
|
||||
public static bool skipMakeAnims = true;
|
||||
static Server.Server server;
|
||||
|
||||
public static XRandom CosmeticRandom = new XRandom(); // not synced
|
||||
|
||||
internal static Renderer renderer;
|
||||
static int2 clientSize;
|
||||
static string mapName;
|
||||
public static Session LobbyInfo = new Session();
|
||||
static bool packageChangePending;
|
||||
static bool mapChangePending;
|
||||
static Pair<Assembly, string>[] ModAssemblies;
|
||||
|
||||
static internal bool scrollUp = false;
|
||||
static internal bool scrollDown = false;
|
||||
static internal bool scrollLeft = false;
|
||||
static internal bool scrollRight = false;
|
||||
|
||||
static void LoadModPackages(Manifest manifest)
|
||||
{
|
||||
FileSystem.UnmountAll();
|
||||
Timer.Time("reset: {0}");
|
||||
|
||||
foreach (var dir in manifest.Folders) FileSystem.Mount(dir);
|
||||
foreach (var pkg in manifest.Packages) FileSystem.Mount(pkg);
|
||||
|
||||
Timer.Time("mount temporary packages: {0}");
|
||||
}
|
||||
|
||||
public static void LoadModAssemblies(Manifest m)
|
||||
{
|
||||
// All the core namespaces
|
||||
var asms = typeof(Game).Assembly.GetNamespaces()
|
||||
.Select(c => Pair.New(typeof(Game).Assembly, c))
|
||||
.ToList();
|
||||
|
||||
// Namespaces from each mod assembly
|
||||
foreach (var a in m.Assemblies)
|
||||
{
|
||||
var asm = Assembly.LoadFile(Path.GetFullPath(a));
|
||||
asms.AddRange(asm.GetNamespaces().Select(ns => Pair.New(asm, ns)));
|
||||
}
|
||||
|
||||
ModAssemblies = asms.ToArray();
|
||||
}
|
||||
|
||||
public static T CreateObject<T>(string classname)
|
||||
{
|
||||
foreach (var mod in ModAssemblies)
|
||||
{
|
||||
var fullTypeName = mod.Second + "." + classname;
|
||||
var obj = mod.First.CreateInstance(fullTypeName);
|
||||
if (obj != null)
|
||||
return (T)obj;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("Cannot locate type: {0}".F(classname));
|
||||
}
|
||||
|
||||
public static Dictionary<string, MapStub> AvailableMaps;
|
||||
|
||||
// TODO: Do this nicer
|
||||
static Dictionary<string, MapStub> FindMaps(string[] mods)
|
||||
{
|
||||
var paths = new[] { "maps/" }.Concat(mods.Select(m => "mods/" + m + "/maps/"))
|
||||
.Where(p => Directory.Exists(p))
|
||||
.SelectMany(p => Directory.GetDirectories(p)).ToList();
|
||||
|
||||
return paths.Select(p => new MapStub(new Folder(p))).ToDictionary(m => m.Uid);
|
||||
}
|
||||
|
||||
static void ChangeMods()
|
||||
{
|
||||
Timer.Time("----ChangeMods");
|
||||
var manifest = new Manifest(LobbyInfo.GlobalSettings.Mods);
|
||||
Timer.Time("manifest: {0}");
|
||||
LoadModAssemblies(manifest);
|
||||
SheetBuilder.Initialize(renderer);
|
||||
LoadModPackages(manifest);
|
||||
Timer.Time("load assemblies, packages: {0}");
|
||||
packageChangePending = false;
|
||||
}
|
||||
|
||||
static void LoadMap(string mapName)
|
||||
{
|
||||
Timer.Time("----LoadMap");
|
||||
SheetBuilder.Initialize(renderer);
|
||||
var manifest = new Manifest(LobbyInfo.GlobalSettings.Mods);
|
||||
Timer.Time("manifest: {0}");
|
||||
|
||||
if (!Game.AvailableMaps.ContainsKey(mapName))
|
||||
throw new InvalidDataException("Cannot find map with Uid {0}".F(mapName));
|
||||
|
||||
var map = new Map(Game.AvailableMaps[mapName].Package);
|
||||
|
||||
viewport = new Viewport(clientSize, map.TopLeft, map.BottomRight, renderer);
|
||||
world = null; // trying to access the old world will NRE, rather than silently doing it wrong.
|
||||
ChromeProvider.Initialize(manifest.Chrome);
|
||||
Timer.Time("viewport, ChromeProvider: {0}");
|
||||
world = new World(manifest, map);
|
||||
Timer.Time("world: {0}");
|
||||
|
||||
SequenceProvider.Initialize(manifest.Sequences);
|
||||
Timer.Time("ChromeProv, SeqProv: {0}");
|
||||
|
||||
chrome = new Chrome(renderer, manifest);
|
||||
Timer.Time("chrome: {0}");
|
||||
|
||||
Timer.Time("----end LoadMap");
|
||||
Debug("Map change {0} -> {1}".F(Game.mapName, mapName));
|
||||
}
|
||||
|
||||
public static void MoveViewport(int2 loc)
|
||||
public static Renderer Renderer;
|
||||
public static bool HasInputFocus = false;
|
||||
|
||||
public static void MoveViewport(float2 loc)
|
||||
{
|
||||
viewport.Center(loc);
|
||||
}
|
||||
|
||||
internal static string CurrentHost = "";
|
||||
internal static int CurrentPort = 0;
|
||||
|
||||
internal static void JoinServer(string host, int port)
|
||||
public static void JoinServer(string host, int port)
|
||||
{
|
||||
if (orderManager != null) orderManager.Dispose();
|
||||
|
||||
CurrentHost = host;
|
||||
CurrentPort = port;
|
||||
var replayFilename = ChooseReplayFilename();
|
||||
string path = Path.Combine( Game.SupportDir, "Replays" );
|
||||
if( !Directory.Exists( path ) ) Directory.CreateDirectory( path );
|
||||
var replayFile = File.Create( Path.Combine( path, replayFilename ) );
|
||||
|
||||
orderManager = new OrderManager(new NetworkConnection(host, port), ChooseReplayFilename());
|
||||
orderManager = new OrderManager( host, port, new ReplayRecorderConnection( new NetworkConnection( host, port ), replayFile ) );
|
||||
lastConnectionState = ConnectionState.PreConnecting;
|
||||
ConnectionStateChanged(orderManager);
|
||||
}
|
||||
|
||||
static string ChooseReplayFilename()
|
||||
@@ -180,145 +72,35 @@ namespace OpenRA
|
||||
static void JoinLocal()
|
||||
{
|
||||
if (orderManager != null) orderManager.Dispose();
|
||||
orderManager = new OrderManager(new EchoConnection());
|
||||
}
|
||||
|
||||
static int lastTime = Environment.TickCount;
|
||||
|
||||
static void ResetTimer()
|
||||
{
|
||||
lastTime = Environment.TickCount;
|
||||
orderManager = new OrderManager("<no server>", -1, new EchoConnection());
|
||||
lastConnectionState = ConnectionState.PreConnecting;
|
||||
ConnectionStateChanged( orderManager );
|
||||
}
|
||||
|
||||
internal static int RenderFrame = 0;
|
||||
internal static int LocalTick = 0;
|
||||
internal static int LocalTick { get { return orderManager.LocalFrameNumber; } }
|
||||
const int NetTickScale = 3; // 120ms net tick for 40ms local tick
|
||||
|
||||
static Queue<Pair<int, string>> syncReports = new Queue<Pair<int, string>>();
|
||||
const int numSyncReports = 5;
|
||||
public static event Action<OrderManager> ConnectionStateChanged = _ => { };
|
||||
static ConnectionState lastConnectionState = ConnectionState.PreConnecting;
|
||||
public static int LocalClientId { get { return orderManager.Connection.LocalClientId; } }
|
||||
|
||||
internal static void UpdateSyncReport()
|
||||
static void Tick( OrderManager orderManager, Viewport viewPort )
|
||||
{
|
||||
if (!Settings.RecordSyncReports)
|
||||
return;
|
||||
|
||||
while (syncReports.Count >= numSyncReports) syncReports.Dequeue();
|
||||
syncReports.Enqueue(Pair.New(orderManager.FrameNumber, GenerateSyncReport()));
|
||||
}
|
||||
|
||||
static string GenerateSyncReport()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("Actors:");
|
||||
foreach (var a in world.Actors)
|
||||
sb.AppendLine("\t {0} {1} {2} ({3})".F(
|
||||
a.ActorID,
|
||||
a.Info.Name,
|
||||
(a.Owner == null) ? "null" : a.Owner.InternalName,
|
||||
Sync.CalculateSyncHash(a)));
|
||||
|
||||
sb.AppendLine("Tick Actors:");
|
||||
foreach (var a in world.Queries.WithTraitMultiple<object>())
|
||||
if (orderManager.Connection.ConnectionState != lastConnectionState)
|
||||
{
|
||||
var sync = Sync.CalculateSyncHash(a.Trait);
|
||||
if (sync != 0)
|
||||
sb.AppendLine("\t {0} {1} {2} {3} ({4})".F(
|
||||
a.Actor.ActorID,
|
||||
a.Actor.Info.Name,
|
||||
(a.Actor.Owner == null) ? "null" : a.Actor.Owner.InternalName,
|
||||
a.Trait.GetType().Name,
|
||||
sync));
|
||||
lastConnectionState = orderManager.Connection.ConnectionState;
|
||||
ConnectionStateChanged( orderManager );
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
internal static void DumpSyncReport(int frame)
|
||||
{
|
||||
var f = syncReports.FirstOrDefault(a => a.First == frame);
|
||||
if (f == null)
|
||||
{
|
||||
Log.Write("sync", "No sync report available!");
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Write("sync", "Sync for net frame {0} -------------", f.First);
|
||||
Log.Write("sync", "{0}", f.Second);
|
||||
}
|
||||
|
||||
public static event Action ConnectionStateChanged = () => { };
|
||||
static ConnectionState lastConnectionState = ConnectionState.PreConnecting;
|
||||
|
||||
static void Tick()
|
||||
{
|
||||
if (packageChangePending)
|
||||
{
|
||||
// TODO: Only do this on mod change
|
||||
Timer.Time("----begin maplist");
|
||||
AvailableMaps = FindMaps(LobbyInfo.GlobalSettings.Mods);
|
||||
Timer.Time("maplist: {0}");
|
||||
ChangeMods();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mapChangePending)
|
||||
{
|
||||
mapName = LobbyInfo.GlobalSettings.Map;
|
||||
mapChangePending = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (orderManager.Connection.ConnectionState != lastConnectionState)
|
||||
{
|
||||
lastConnectionState = orderManager.Connection.ConnectionState;
|
||||
ConnectionStateChanged();
|
||||
}
|
||||
|
||||
int t = Environment.TickCount;
|
||||
int dt = t - lastTime;
|
||||
if (dt >= Settings.Timestep)
|
||||
{
|
||||
using (new PerfSample("tick_time"))
|
||||
{
|
||||
lastTime += Settings.Timestep;
|
||||
chrome.Tick(world);
|
||||
|
||||
orderManager.TickImmediate(world);
|
||||
|
||||
var isNetTick = LocalTick % NetTickScale == 0;
|
||||
|
||||
if (!isNetTick || orderManager.IsReadyForNextFrame)
|
||||
{
|
||||
++LocalTick;
|
||||
|
||||
if (isNetTick) orderManager.Tick(world);
|
||||
|
||||
controller.orderGenerator.Tick(world);
|
||||
controller.selection.Tick(world);
|
||||
|
||||
world.Tick();
|
||||
|
||||
PerfHistory.Tick();
|
||||
}
|
||||
else
|
||||
if (orderManager.FrameNumber == 0)
|
||||
lastTime = Environment.TickCount;
|
||||
}
|
||||
}
|
||||
|
||||
if (scrollUp == true)
|
||||
viewport.Scroll(new float2(0, -10));
|
||||
if (scrollRight == true)
|
||||
viewport.Scroll(new float2(10, 0));
|
||||
if (scrollDown == true)
|
||||
viewport.Scroll(new float2(0, 10));
|
||||
if (scrollLeft == true)
|
||||
viewport.Scroll(new float2(-10, 0));
|
||||
Tick( orderManager );
|
||||
if( orderManager.world != worldRenderer.world )
|
||||
Tick( worldRenderer.world.orderManager );
|
||||
|
||||
using (new PerfSample("render"))
|
||||
{
|
||||
++RenderFrame;
|
||||
viewport.DrawRegions(world);
|
||||
viewport.DrawRegions(worldRenderer, new DefaultInputHandler( orderManager.world ));
|
||||
Sound.SetListenerPosition(viewport.Location + .5f * new float2(viewport.Width, viewport.Height));
|
||||
}
|
||||
|
||||
@@ -330,273 +112,130 @@ namespace OpenRA
|
||||
MasterServerQuery.Tick();
|
||||
}
|
||||
|
||||
internal static event Action LobbyInfoChanged = () => { };
|
||||
|
||||
internal static void SyncLobbyInfo(string data)
|
||||
private static void Tick( OrderManager orderManager )
|
||||
{
|
||||
var oldLobbyInfo = LobbyInfo;
|
||||
|
||||
var session = new Session();
|
||||
session.GlobalSettings.Mods = Settings.InitialMods;
|
||||
|
||||
var ys = MiniYaml.FromString(data);
|
||||
foreach (var y in ys)
|
||||
{
|
||||
if (y.Key == "GlobalSettings")
|
||||
int t = Environment.TickCount;
|
||||
int dt = t - orderManager.LastTickTime;
|
||||
if (dt >= Settings.Game.Timestep)
|
||||
using( new PerfSample( "tick_time" ) )
|
||||
{
|
||||
FieldLoader.Load(session.GlobalSettings, y.Value);
|
||||
continue;
|
||||
orderManager.LastTickTime += Settings.Game.Timestep;
|
||||
Widget.DoTick();
|
||||
var world = orderManager.world;
|
||||
if( orderManager.GameStarted && world.LocalPlayer != null )
|
||||
++Viewport.TicksSinceLastMove;
|
||||
Sound.Tick();
|
||||
Sync.CheckSyncUnchanged( world, () => { orderManager.TickImmediate(); } );
|
||||
|
||||
var isNetTick = LocalTick % NetTickScale == 0;
|
||||
|
||||
if( !isNetTick || orderManager.IsReadyForNextFrame )
|
||||
{
|
||||
++orderManager.LocalFrameNumber;
|
||||
|
||||
Log.Write( "debug", "--Tick: {0} ({1})", LocalTick, isNetTick ? "net" : "local" );
|
||||
|
||||
if( isNetTick ) orderManager.Tick();
|
||||
|
||||
Sync.CheckSyncUnchanged(world, () =>
|
||||
{
|
||||
world.OrderGenerator.Tick(world);
|
||||
world.Selection.Tick(world);
|
||||
});
|
||||
|
||||
world.Tick();
|
||||
|
||||
PerfHistory.Tick();
|
||||
}
|
||||
else
|
||||
if( orderManager.NetFrameNumber == 0 )
|
||||
orderManager.LastTickTime = Environment.TickCount;
|
||||
}
|
||||
}
|
||||
|
||||
int index;
|
||||
if (!int.TryParse(y.Key, out index))
|
||||
continue; // not a player.
|
||||
|
||||
var client = new Session.Client();
|
||||
FieldLoader.Load(client, y.Value);
|
||||
session.Clients.Add(client);
|
||||
}
|
||||
|
||||
LobbyInfo = session;
|
||||
|
||||
if (!world.GameHasStarted)
|
||||
world.SharedRandom = new OpenRA.Thirdparty.Random(LobbyInfo.GlobalSettings.RandomSeed);
|
||||
|
||||
if (orderManager.Connection.ConnectionState == ConnectionState.Connected)
|
||||
world.SetLocalPlayer(orderManager.Connection.LocalClientId);
|
||||
|
||||
if (orderManager.FramesAhead != LobbyInfo.GlobalSettings.OrderLatency
|
||||
&& !orderManager.GameStarted)
|
||||
{
|
||||
orderManager.FramesAhead = LobbyInfo.GlobalSettings.OrderLatency;
|
||||
Debug("Order lag is now {0} frames.".F(LobbyInfo.GlobalSettings.OrderLatency));
|
||||
}
|
||||
|
||||
if (mapName != LobbyInfo.GlobalSettings.Map)
|
||||
mapChangePending = true;
|
||||
|
||||
if (string.Join(",", oldLobbyInfo.GlobalSettings.Mods)
|
||||
!= string.Join(",", LobbyInfo.GlobalSettings.Mods))
|
||||
{
|
||||
Debug("Mods list changed, reloading: {0}".F(string.Join(",", LobbyInfo.GlobalSettings.Mods)));
|
||||
packageChangePending = true;
|
||||
}
|
||||
public static event Action LobbyInfoChanged = () => { };
|
||||
public static event Action ConnectedToLobby = () => { };
|
||||
|
||||
internal static void SyncLobbyInfo()
|
||||
{
|
||||
LobbyInfoChanged();
|
||||
}
|
||||
|
||||
public static void IssueOrder(Order o) { orderManager.IssueOrder(o); } /* avoid exposing the OM to mod code */
|
||||
|
||||
static void LoadShellMap(string map)
|
||||
public static event Action<World> AfterGameStart = _ => {};
|
||||
public static event Action BeforeGameStart = () => {};
|
||||
internal static void StartGame(string mapUID)
|
||||
{
|
||||
LoadMap(map);
|
||||
world.Queries = new World.AllQueries(world);
|
||||
BeforeGameStart();
|
||||
|
||||
var map = modData.PrepareMap(mapUID);
|
||||
viewport = new Viewport(new int2(Renderer.Resolution), map.TopLeft, map.BottomRight, Renderer);
|
||||
orderManager.world = new World(modData.Manifest, map, orderManager);
|
||||
worldRenderer = new WorldRenderer(orderManager.world);
|
||||
|
||||
foreach (var gs in world.WorldActor.traits.WithInterface<IGameStarted>())
|
||||
gs.GameStarted(world);
|
||||
orderManager.StartGame();
|
||||
}
|
||||
|
||||
public static event Action OnGameStart = () => { };
|
||||
internal static void StartGame()
|
||||
{
|
||||
LoadMap(LobbyInfo.GlobalSettings.Map);
|
||||
if (orderManager.GameStarted) return;
|
||||
Widget.SelectedWidget = null;
|
||||
|
||||
world.Queries = new World.AllQueries(world);
|
||||
Widget.SelectedWidget = null;
|
||||
|
||||
foreach (var gs in world.WorldActor.traits.WithInterface<IGameStarted>())
|
||||
gs.GameStarted(world);
|
||||
|
||||
viewport.GoToStartLocation(world.LocalPlayer);
|
||||
orderManager.StartGame();
|
||||
OnGameStart();
|
||||
orderManager.LocalFrameNumber = 0;
|
||||
orderManager.StartGame();
|
||||
worldRenderer.RefreshPalette();
|
||||
AfterGameStart( orderManager.world );
|
||||
}
|
||||
|
||||
public static Stance ChooseInitialStance(Player p, Player q)
|
||||
{
|
||||
if (p == q) return Stance.Ally;
|
||||
|
||||
// Hack: All map players are neutral wrt everyone else
|
||||
if (p.Index < 0 || q.Index < 0) return Stance.Neutral;
|
||||
|
||||
var pc = GetClientForPlayer(p);
|
||||
var qc = GetClientForPlayer(q);
|
||||
|
||||
return pc.Team != 0 && pc.Team == qc.Team
|
||||
? Stance.Ally : Stance.Enemy;
|
||||
}
|
||||
|
||||
static Session.Client GetClientForPlayer(Player p)
|
||||
{
|
||||
return LobbyInfo.Clients.Single(c => c.Index == p.Index);
|
||||
}
|
||||
|
||||
static int2 lastPos;
|
||||
public static void DispatchMouseInput(MouseInputEvent ev, MouseEventArgs e, Modifiers modifierKeys)
|
||||
{
|
||||
int sync = world.SyncHash();
|
||||
var initialWorld = world;
|
||||
|
||||
if (ev == MouseInputEvent.Down)
|
||||
lastPos = new int2(e.Location);
|
||||
|
||||
if (ev == MouseInputEvent.Move &&
|
||||
(e.Button == MouseButtons.Middle ||
|
||||
e.Button == (MouseButtons.Left | MouseButtons.Right)))
|
||||
{
|
||||
var p = new int2(e.Location);
|
||||
viewport.Scroll(lastPos - p);
|
||||
lastPos = p;
|
||||
}
|
||||
|
||||
viewport.DispatchMouseInput(world,
|
||||
new MouseInput
|
||||
{
|
||||
Button = (MouseButton)(int)e.Button,
|
||||
Event = ev,
|
||||
Location = new int2(e.Location),
|
||||
Modifiers = modifierKeys,
|
||||
});
|
||||
|
||||
if (sync != world.SyncHash() && world == initialWorld)
|
||||
throw new InvalidOperationException("Desync in DispatchMouseInput");
|
||||
}
|
||||
|
||||
internal static bool IsHost
|
||||
public static bool IsHost
|
||||
{
|
||||
get { return orderManager.Connection.LocalClientId == 0; }
|
||||
}
|
||||
|
||||
internal static Session.Client LocalClient
|
||||
static Modifiers modifiers;
|
||||
public static Modifiers GetModifierKeys() { return modifiers; }
|
||||
internal static void HandleModifierKeys(Modifiers mods) { modifiers = mods; }
|
||||
|
||||
internal static void Initialize(Arguments args)
|
||||
{
|
||||
get { return LobbyInfo.Clients.FirstOrDefault(c => c.Index == orderManager.Connection.LocalClientId); }
|
||||
}
|
||||
AppDomain.CurrentDomain.AssemblyResolve += FileSystem.ResolveAssembly;
|
||||
|
||||
public static void HandleKeyDown(KeyInput e)
|
||||
{
|
||||
int sync = world.SyncHash();
|
||||
|
||||
if (chrome.HandleKeyPress(e))
|
||||
return;
|
||||
var defaultSupport = Environment.GetFolderPath(Environment.SpecialFolder.Personal)
|
||||
+ Path.DirectorySeparatorChar + "OpenRA";
|
||||
|
||||
switch (e.KeyName)
|
||||
{
|
||||
case "up": scrollUp = true; break;
|
||||
case "down": scrollDown = true; break;
|
||||
case "left": scrollLeft = true; break;
|
||||
case "right": scrollRight = true; break;
|
||||
}
|
||||
SupportDir = args.GetValue("SupportDir", defaultSupport);
|
||||
Settings = new Settings(SupportDir + "settings.yaml", args);
|
||||
|
||||
if (e.KeyName.Length == 1 && char.IsDigit(e.KeyName[0]))
|
||||
Game.controller.selection.DoControlGroup(world, e.KeyName[0] - '0', e.Modifiers);
|
||||
Settings.Save();
|
||||
|
||||
Log.LogPath = SupportDir + "Logs" + Path.DirectorySeparatorChar;
|
||||
Log.AddChannel("perf", "perf.log");
|
||||
Log.AddChannel("debug", "debug.log");
|
||||
Log.AddChannel("sync", "syncreport.log");
|
||||
|
||||
FileSystem.Mount("."); // Needed to access shaders
|
||||
Renderer.Initialize( Game.Settings.Graphics.Mode );
|
||||
Renderer.SheetSize = Settings.Game.SheetSize;
|
||||
Renderer = new Renderer();
|
||||
|
||||
if (e.KeyChar == 08)
|
||||
Game.controller.GotoNextBase();
|
||||
|
||||
if (sync != Game.world.SyncHash())
|
||||
throw new InvalidOperationException("Desync in OnKeyPress");
|
||||
}
|
||||
|
||||
public static void HandleKeyUp(KeyInput e)
|
||||
{
|
||||
switch (e.KeyName)
|
||||
{
|
||||
case "up": scrollUp = false; break;
|
||||
case "down": scrollDown = false; break;
|
||||
case "left": scrollLeft = false; break;
|
||||
case "right": scrollRight = false; break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void HandleArrowKeyScroll(String k, Boolean pressed)
|
||||
{
|
||||
if (k == "up")
|
||||
{
|
||||
scrollUp = pressed;
|
||||
}
|
||||
if (k == "left")
|
||||
{
|
||||
scrollLeft = pressed;
|
||||
}
|
||||
if (k == "down")
|
||||
{
|
||||
scrollDown = pressed;
|
||||
}
|
||||
if (k == "right")
|
||||
{
|
||||
scrollRight = pressed;
|
||||
}
|
||||
}
|
||||
|
||||
public static void HandleModifierKeys(Modifiers mods)
|
||||
{
|
||||
controller.SetModifiers(mods);
|
||||
}
|
||||
|
||||
static Size GetResolution(Settings settings, WindowMode windowmode)
|
||||
{
|
||||
var desktopResolution = Screen.PrimaryScreen.Bounds.Size;
|
||||
var customSize = (windowmode == WindowMode.Windowed) ? Settings.WindowedSize : Settings.FullscreenSize;
|
||||
|
||||
if (customSize.X > 0 && customSize.Y > 0)
|
||||
{
|
||||
desktopResolution.Width = customSize.X;
|
||||
desktopResolution.Height = customSize.Y;
|
||||
}
|
||||
return new Size(
|
||||
desktopResolution.Width,
|
||||
desktopResolution.Height);
|
||||
}
|
||||
|
||||
internal static void Initialize(Settings settings)
|
||||
{
|
||||
AppDomain.CurrentDomain.AssemblyResolve += FileSystem.ResolveAssembly;
|
||||
|
||||
var defaultSupport = Environment.GetFolderPath(Environment.SpecialFolder.Personal)
|
||||
+ Path.DirectorySeparatorChar + "OpenRA";
|
||||
|
||||
SupportDir = settings.GetValue("SupportDir", defaultSupport);
|
||||
Settings = new UserSettings(settings);
|
||||
|
||||
Log.LogPath = SupportDir + "Logs" + Path.DirectorySeparatorChar;
|
||||
Log.AddChannel("perf", "perf.log", false, false);
|
||||
Log.AddChannel("debug", "debug.log", false, false);
|
||||
Log.AddChannel("sync", "syncreport.log", true, true);
|
||||
|
||||
LobbyInfo.GlobalSettings.Mods = Settings.InitialMods;
|
||||
|
||||
// Load the default mod to access required files
|
||||
LoadModPackages(new Manifest(LobbyInfo.GlobalSettings.Mods));
|
||||
|
||||
Renderer.SheetSize = Settings.SheetSize;
|
||||
|
||||
var resolution = GetResolution(settings, Game.Settings.WindowMode);
|
||||
renderer = new Renderer(resolution, Game.Settings.WindowMode);
|
||||
resolution = renderer.Resolution;
|
||||
|
||||
controller = new Controller();
|
||||
clientSize = new int2(resolution);
|
||||
|
||||
Console.WriteLine("Available mods:");
|
||||
foreach(var mod in Mod.AllMods)
|
||||
Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Title, mod.Value.Version);
|
||||
|
||||
// Discard any invalid mods
|
||||
var mods = Settings.Game.Mods.Where( m => Mod.AllMods.ContainsKey( m ) ).ToArray();
|
||||
Console.WriteLine("Loading mods: {0}",string.Join(",",mods));
|
||||
|
||||
modData = new ModData( mods );
|
||||
Sound.Initialize();
|
||||
PerfHistory.items["render"].hasNormalTick = false;
|
||||
PerfHistory.items["batches"].hasNormalTick = false;
|
||||
PerfHistory.items["text"].hasNormalTick = false;
|
||||
PerfHistory.items["cursor"].hasNormalTick = false;
|
||||
AvailableMaps = FindMaps(LobbyInfo.GlobalSettings.Mods);
|
||||
|
||||
ChangeMods();
|
||||
|
||||
JoinLocal();
|
||||
StartGame(modData.Manifest.ShellmapUid);
|
||||
|
||||
if (Settings.Replay != null)
|
||||
orderManager = new OrderManager(new ReplayConnection(Settings.Replay));
|
||||
else
|
||||
JoinLocal();
|
||||
|
||||
LoadShellMap(new Manifest(LobbyInfo.GlobalSettings.Mods).ShellmapUid);
|
||||
|
||||
ResetTimer();
|
||||
// TODO: unhardcode this
|
||||
modData.WidgetLoader.LoadWidget( new Dictionary<string,object>(), Widget.RootWidget, "PERF_BG" );
|
||||
Widget.OpenWindow("MAINMENU_BG");
|
||||
|
||||
Game.orderManager.LastTickTime = Environment.TickCount;
|
||||
}
|
||||
|
||||
static bool quit;
|
||||
@@ -604,83 +243,90 @@ namespace OpenRA
|
||||
{
|
||||
while (!quit)
|
||||
{
|
||||
Tick();
|
||||
Tick( orderManager, viewport );
|
||||
Application.DoEvents();
|
||||
}
|
||||
}
|
||||
|
||||
public static void Exit() { quit = true; }
|
||||
|
||||
public static void Exit() { quit = true; }
|
||||
|
||||
public static Action<Color,string,string> AddChatLine = (c,n,s) => {};
|
||||
|
||||
public static void Debug(string s)
|
||||
{
|
||||
AddChatLine(Color.White, "Debug", s);
|
||||
public static void Debug(string s, params object[] args)
|
||||
{
|
||||
AddChatLine(Color.White, "Debug", String.Format(s,args));
|
||||
}
|
||||
|
||||
public static void Disconnect()
|
||||
{
|
||||
var shellmap = new Manifest(LobbyInfo.GlobalSettings.Mods).ShellmapUid;
|
||||
LobbyInfo = new Session();
|
||||
LobbyInfo.GlobalSettings.Mods = Settings.InitialMods;
|
||||
if (IsHost && server != null)
|
||||
server.Shutdown();
|
||||
|
||||
orderManager.Dispose();
|
||||
var shellmap = modData.Manifest.ShellmapUid;
|
||||
JoinLocal();
|
||||
LoadShellMap(shellmap);
|
||||
StartGame(shellmap);
|
||||
|
||||
Chrome.rootWidget.CloseWindow();
|
||||
Chrome.rootWidget.OpenWindow("MAINMENU_BG");
|
||||
}
|
||||
|
||||
static string baseSupportDir = null;
|
||||
public static string SupportDir
|
||||
{
|
||||
set {
|
||||
var dir = value;
|
||||
|
||||
// Expand paths relative to the personal directory
|
||||
if (dir.ElementAt(0) == '~')
|
||||
dir = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + dir.Substring(1);
|
||||
|
||||
if (!Directory.Exists(dir))
|
||||
Directory.CreateDirectory(dir);
|
||||
|
||||
baseSupportDir = dir + Path.DirectorySeparatorChar;
|
||||
}
|
||||
get {return baseSupportDir;}
|
||||
}
|
||||
|
||||
|
||||
internal static int GetGameId()
|
||||
{
|
||||
try
|
||||
{
|
||||
string s = File.ReadAllText(SupportDir + "currentgameid");
|
||||
return int.Parse(s);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
Widget.CloseWindow();
|
||||
Widget.OpenWindow("MAINMENU_BG");
|
||||
}
|
||||
|
||||
internal static void SetGameId(int id)
|
||||
static string baseSupportDir = null;
|
||||
public static string SupportDir
|
||||
{
|
||||
var file = File.CreateText(SupportDir + "currentgameid");
|
||||
file.Write(id);
|
||||
file.Flush();
|
||||
file.Close();
|
||||
set
|
||||
{
|
||||
var dir = value;
|
||||
|
||||
// Expand paths relative to the personal directory
|
||||
if (dir.ElementAt(0) == '~')
|
||||
dir = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + dir.Substring(1);
|
||||
|
||||
if (!Directory.Exists(dir))
|
||||
Directory.CreateDirectory(dir);
|
||||
|
||||
baseSupportDir = dir + Path.DirectorySeparatorChar;
|
||||
}
|
||||
get { return baseSupportDir; }
|
||||
}
|
||||
|
||||
public static void InitializeEngineWithMods(string[] mods)
|
||||
public static T CreateObject<T>( string name )
|
||||
{
|
||||
AppDomain.CurrentDomain.AssemblyResolve += FileSystem.ResolveAssembly;
|
||||
var manifest = new Manifest(mods);
|
||||
LoadModAssemblies(manifest);
|
||||
return modData.ObjectCreator.CreateObject<T>( name );
|
||||
}
|
||||
|
||||
FileSystem.UnmountAll();
|
||||
foreach (var folder in manifest.Folders) FileSystem.Mount(folder);
|
||||
foreach (var pkg in manifest.Packages) FileSystem.Mount(pkg);
|
||||
public static void RejoinLobby(World world)
|
||||
{
|
||||
var map = orderManager.LobbyInfo.GlobalSettings.Map;
|
||||
var host = orderManager.Host;
|
||||
var port = orderManager.Port;
|
||||
var isHost = Game.IsHost;
|
||||
|
||||
Rules.LoadRules(manifest, new Map());
|
||||
Disconnect();
|
||||
ConnectedToLobby += () =>
|
||||
{
|
||||
if (world.LocalPlayer != null)
|
||||
{
|
||||
/* Try to get back the old slot */
|
||||
Game.orderManager.IssueOrder(Order.Command("race " + world.LocalPlayer.Country.Race));
|
||||
Game.orderManager.IssueOrder(Order.Command("slot " + world.LobbyInfo.ClientWithIndex(world.LocalPlayer.ClientIndex).Slot));
|
||||
}else /* a spectator */
|
||||
{
|
||||
Game.orderManager.IssueOrder(Order.Command("spectator"));
|
||||
}
|
||||
|
||||
ConnectedToLobby = null;
|
||||
};
|
||||
if (isHost)
|
||||
CreateAndJoinServer( Settings, map );
|
||||
else
|
||||
JoinServer(host, port);
|
||||
}
|
||||
|
||||
public static void CreateAndJoinServer(Settings settings, string map)
|
||||
{
|
||||
server = new Server.Server(modData, settings, map);
|
||||
JoinServer(IPAddress.Loopback.ToString(), settings.Server.ListenPort);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,32 +14,27 @@ using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.GameRules
|
||||
namespace OpenRA
|
||||
{
|
||||
public class ActorInfo
|
||||
{
|
||||
public readonly string Name;
|
||||
public readonly string Category;
|
||||
public readonly TypeDictionary Traits = new TypeDictionary();
|
||||
|
||||
public ActorInfo( string name, MiniYaml node, Dictionary<string, MiniYaml> allUnits )
|
||||
{
|
||||
var mergedNode = MergeWithParent( node, allUnits ).Nodes;
|
||||
var mergedNode = MergeWithParent( node, allUnits ).NodesDict;
|
||||
|
||||
Name = name;
|
||||
MiniYaml categoryNode;
|
||||
if( mergedNode.TryGetValue( "Category", out categoryNode ) )
|
||||
Category = categoryNode.Value;
|
||||
|
||||
foreach( var t in mergedNode )
|
||||
if( t.Key != "Inherits" && t.Key != "Category" && !t.Key.StartsWith("-") )
|
||||
if( t.Key != "Inherits" && !t.Key.StartsWith("-") )
|
||||
Traits.Add( LoadTraitInfo( t.Key.Split('@')[0], t.Value ) );
|
||||
}
|
||||
|
||||
static MiniYaml GetParent( MiniYaml node, Dictionary<string, MiniYaml> allUnits )
|
||||
{
|
||||
MiniYaml inherits;
|
||||
node.Nodes.TryGetValue( "Inherits", out inherits );
|
||||
node.NodesDict.TryGetValue( "Inherits", out inherits );
|
||||
if( inherits == null || string.IsNullOrEmpty( inherits.Value ) )
|
||||
return null;
|
||||
|
||||
@@ -71,21 +66,21 @@ namespace OpenRA.GameRules
|
||||
var ret = new List<ITraitInfo>();
|
||||
var t = Traits.WithInterface<ITraitInfo>().ToList();
|
||||
int index = 0;
|
||||
while( t.Count != 0 )
|
||||
while (t.Count != 0)
|
||||
{
|
||||
if( index >= t.Count )
|
||||
throw new InvalidOperationException( "Trait prerequisites not satisfied (or prerequisite loop) Actor={0} Unresolved={1}".F(
|
||||
Name, string.Join( ",", t.Select( x => x.GetType().Name ).ToArray())));
|
||||
|
||||
var prereqs = PrerequisitesOf( t[ index ] );
|
||||
if( prereqs.Count == 0 || prereqs.All( n => ret.Any( x => x.GetType() == n || x.GetType().IsSubclassOf( n ) ) ) )
|
||||
var prereqs = PrerequisitesOf(t[index]);
|
||||
var unsatisfied = prereqs.Where(n => !ret.Any(x => x.GetType() == n || x.GetType().IsSubclassOf(n)));
|
||||
if (!unsatisfied.Any())
|
||||
{
|
||||
ret.Add( t[ index ] );
|
||||
t.RemoveAt( index );
|
||||
ret.Add(t[index]);
|
||||
t.RemoveAt(index);
|
||||
index = 0;
|
||||
}
|
||||
else
|
||||
++index;
|
||||
else if (++index >= t.Count)
|
||||
throw new InvalidOperationException("Trait prerequisites not satisfied (or prerequisite loop) Actor={0} Unresolved={1} Missing={2}".F(
|
||||
Name,
|
||||
string.Join(",", t.Select(x => x.GetType().Name).ToArray()),
|
||||
string.Join(",", unsatisfied.Select(x => x.Name).ToArray())));
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -13,38 +13,22 @@ using OpenRA.FileFormats;
|
||||
namespace OpenRA.GameRules
|
||||
{
|
||||
public class MusicInfo
|
||||
{
|
||||
public readonly MusicPool Pool;
|
||||
public readonly string[] Music = { };
|
||||
{
|
||||
public readonly string Filename = null;
|
||||
public readonly string Title = null;
|
||||
public readonly int Length = 0; // seconds
|
||||
public readonly bool Exists = false;
|
||||
|
||||
public MusicInfo( MiniYaml y )
|
||||
public MusicInfo( string key, MiniYaml value )
|
||||
{
|
||||
FieldLoader.Load(this, y);
|
||||
Pool = new MusicPool(Music);
|
||||
Filename = key+".aud";
|
||||
Title = value.Value;
|
||||
|
||||
if (!FileSystem.Exists(Filename))
|
||||
return;
|
||||
|
||||
Exists = true;
|
||||
Length = (int)AudLoader.SoundLength(FileSystem.Open(Filename));
|
||||
}
|
||||
}
|
||||
|
||||
public class MusicPool
|
||||
{
|
||||
readonly string[] clips;
|
||||
int playing = 0;
|
||||
|
||||
public MusicPool(params string[] clips)
|
||||
{
|
||||
this.clips = clips;
|
||||
}
|
||||
|
||||
public string GetNext()
|
||||
{
|
||||
playing = (playing + 1) % clips.Length;
|
||||
return clips[playing];
|
||||
}
|
||||
public string GetPrev()
|
||||
{
|
||||
playing = (playing + clips.Length - 1) % clips.Length;
|
||||
return clips[playing];
|
||||
}
|
||||
public string GetCurrent(){ return clips[playing];}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,20 +18,21 @@ namespace OpenRA
|
||||
{
|
||||
public static class Rules
|
||||
{
|
||||
public static TechTree TechTree;
|
||||
|
||||
public static Dictionary<string, ActorInfo> Info;
|
||||
public static Dictionary<string, WeaponInfo> Weapons;
|
||||
public static Dictionary<string, VoiceInfo> Voices;
|
||||
public static Dictionary<string, MusicInfo> Music;
|
||||
public static Dictionary<string, string> Movies;
|
||||
public static Dictionary<string, TileSet> TileSets;
|
||||
|
||||
public static void LoadRules(Manifest m, Map map)
|
||||
{
|
||||
// Added support to extend the list of rules (add it to m.LocalRules)
|
||||
Info = LoadYamlRules(m.Rules, map.Rules, (k, y) => new ActorInfo(k.Key.ToLowerInvariant(), k.Value, y));
|
||||
Weapons = LoadYamlRules(m.Weapons, map.Weapons, (k, _) => new WeaponInfo(k.Key.ToLowerInvariant(), k.Value));
|
||||
Voices = LoadYamlRules(m.Voices, map.Voices, (k, _) => new VoiceInfo(k.Value));
|
||||
Music = LoadYamlRules(m.Music, map.Music, (k, _) => new MusicInfo(k.Value));
|
||||
Music = LoadYamlRules(m.Music, new List<MiniYamlNode>(), (k, _) => new MusicInfo(k.Key, k.Value));
|
||||
Movies = LoadYamlRules(m.Movies, new List<MiniYamlNode>(), (k, v) => k.Value.Value);
|
||||
|
||||
TileSets = new Dictionary<string, TileSet>();
|
||||
foreach (var file in m.TileSets)
|
||||
@@ -39,19 +40,13 @@ namespace OpenRA
|
||||
var t = new TileSet(file);
|
||||
TileSets.Add(t.Id,t);
|
||||
}
|
||||
|
||||
TechTree = new TechTree();
|
||||
}
|
||||
|
||||
static Dictionary<string, T> LoadYamlRules<T>(string[] files, Dictionary<string,MiniYaml>dict, Func<KeyValuePair<string, MiniYaml>, Dictionary<string, MiniYaml>, T> f)
|
||||
static Dictionary<string, T> LoadYamlRules<T>(string[] files, List<MiniYamlNode> dict, Func<MiniYamlNode, Dictionary<string, MiniYaml>, T> f)
|
||||
{
|
||||
var y = files.Select(a => MiniYaml.FromFile(a)).Aggregate(dict,MiniYaml.Merge);
|
||||
return y.ToDictionary(kv => kv.Key.ToLowerInvariant(), kv => f(kv, y));
|
||||
}
|
||||
|
||||
public static IEnumerable<string> Categories()
|
||||
{
|
||||
return Info.Values.Select( x => x.Category ).Distinct().Where( g => g != null ).ToList();
|
||||
var yy = y.ToDictionary( x => x.Key, x => x.Value );
|
||||
return y.ToDictionary(kv => kv.Key.ToLowerInvariant(), kv => f(kv, yy));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
160
OpenRA.Game/GameRules/Settings.cs
Executable file
160
OpenRA.Game/GameRules/Settings.cs
Executable file
@@ -0,0 +1,160 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.FileFormats.Graphics;
|
||||
using OpenRA.Server;
|
||||
|
||||
namespace OpenRA.GameRules
|
||||
{
|
||||
public class ServerSettings
|
||||
{
|
||||
public string Name = "OpenRA Game";
|
||||
public int ListenPort = 1234;
|
||||
public int ExternalPort = 1234;
|
||||
public bool AdvertiseOnline = true;
|
||||
public string MasterServer = "http://master.open-ra.org/";
|
||||
public bool AllowCheats = false;
|
||||
}
|
||||
|
||||
public class DebugSettings
|
||||
{
|
||||
public bool BotDebug = false;
|
||||
public bool PerfGraph = false;
|
||||
public bool RecordSyncReports = true;
|
||||
public float LongTickThreshold = 0.001f;
|
||||
}
|
||||
|
||||
public class GraphicSettings
|
||||
{
|
||||
public string Renderer = "Gl";
|
||||
public WindowMode Mode = WindowMode.PseudoFullscreen;
|
||||
public int2 FullscreenSize = new int2(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
|
||||
public int2 WindowedSize = new int2(1024, 768);
|
||||
public readonly int2 MinResolution = new int2(800, 600);
|
||||
}
|
||||
|
||||
public class SoundSettings
|
||||
{
|
||||
public float SoundVolume = 0.5f;
|
||||
public float MusicVolume = 0.5f;
|
||||
public float VideoVolume = 0.5f;
|
||||
public bool Shuffle = false;
|
||||
public bool Repeat = false;
|
||||
}
|
||||
|
||||
public class PlayerSettings
|
||||
{
|
||||
public string Name = "Newbie";
|
||||
public Color Color1 = Color.FromArgb(255,160,238);
|
||||
public Color Color2 = Color.FromArgb(68,0,56);
|
||||
public string LastServer = "localhost:1234";
|
||||
}
|
||||
|
||||
public class GameSettings
|
||||
{
|
||||
public string[] Mods = { "ra" };
|
||||
public bool MatchTimer = true;
|
||||
|
||||
// Chat settings
|
||||
public bool TeamChatToggle = false;
|
||||
|
||||
// Behaviour settings
|
||||
public bool ViewportEdgeScroll = true;
|
||||
public bool InverseDragScroll = false;
|
||||
public float ViewportEdgeScrollStep = 10f;
|
||||
|
||||
// Internal game settings
|
||||
public int Timestep = 40;
|
||||
public int SheetSize = 2048;
|
||||
}
|
||||
|
||||
public class Settings
|
||||
{
|
||||
string SettingsFile;
|
||||
|
||||
public PlayerSettings Player = new PlayerSettings();
|
||||
public GameSettings Game = new GameSettings();
|
||||
public SoundSettings Sound = new SoundSettings();
|
||||
public GraphicSettings Graphics = new GraphicSettings();
|
||||
public ServerSettings Server = new ServerSettings();
|
||||
public DebugSettings Debug = new DebugSettings();
|
||||
|
||||
Dictionary<string, object> Sections;
|
||||
public Settings(string file, Arguments args)
|
||||
{
|
||||
SettingsFile = file;
|
||||
Sections = new Dictionary<string, object>()
|
||||
{
|
||||
{"Player", Player},
|
||||
{"Game", Game},
|
||||
{"Sound", Sound},
|
||||
{"Graphics", Graphics},
|
||||
{"Server", Server},
|
||||
{"Debug", Debug}
|
||||
};
|
||||
|
||||
// Override fieldloader to ignore invalid entries
|
||||
var err1 = FieldLoader.UnknownFieldAction;
|
||||
var err2 = FieldLoader.InvalidValueAction;
|
||||
|
||||
FieldLoader.UnknownFieldAction = (s,f) =>
|
||||
{
|
||||
Console.WriteLine( "Ignoring unknown field `{0}` on `{1}`".F( s, f.Name ) );
|
||||
};
|
||||
|
||||
if (File.Exists(SettingsFile))
|
||||
{
|
||||
Console.WriteLine("Loading settings file {0}",SettingsFile);
|
||||
var yaml = MiniYaml.DictFromFile(SettingsFile);
|
||||
|
||||
foreach (var kv in Sections)
|
||||
if (yaml.ContainsKey(kv.Key))
|
||||
LoadSectionYaml(yaml[kv.Key], kv.Value);
|
||||
}
|
||||
|
||||
// Override with commandline args
|
||||
foreach (var kv in Sections)
|
||||
foreach (var f in kv.Value.GetType().GetFields())
|
||||
if (args.Contains(kv.Key+"."+f.Name))
|
||||
FieldLoader.LoadField( kv.Value, f.Name, args.GetValue(kv.Key+"."+f.Name, "") );
|
||||
|
||||
FieldLoader.UnknownFieldAction = err1;
|
||||
FieldLoader.InvalidValueAction = err2;
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
var root = new List<MiniYamlNode>();
|
||||
foreach( var kv in Sections )
|
||||
root.Add( new MiniYamlNode( kv.Key, FieldSaver.SaveDifferences(kv.Value, Activator.CreateInstance(kv.Value.GetType())) ) );
|
||||
|
||||
root.WriteToFile(SettingsFile);
|
||||
}
|
||||
|
||||
void LoadSectionYaml(MiniYaml yaml, object section)
|
||||
{
|
||||
object defaults = Activator.CreateInstance(section.GetType());
|
||||
FieldLoader.InvalidValueAction = (s,t,f) =>
|
||||
{
|
||||
object ret = defaults.GetType().GetField(f).GetValue(defaults);
|
||||
System.Console.WriteLine("FieldLoader: Cannot parse `{0}` into `{2}:{1}`; substituting default `{3}`".F(s,t.Name,f,ret) );
|
||||
return ret;
|
||||
};
|
||||
|
||||
FieldLoader.Load(section, yaml);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.GameRules
|
||||
{
|
||||
public class TechTree
|
||||
{
|
||||
readonly Cache<string, List<ActorInfo>> producesIndex = new Cache<string, List<ActorInfo>>(x => new List<ActorInfo>());
|
||||
|
||||
public TechTree()
|
||||
{
|
||||
foreach( var info in Rules.Info.Values )
|
||||
{
|
||||
var pi = info.Traits.GetOrDefault<ProductionInfo>();
|
||||
if (pi != null)
|
||||
foreach( var p in pi.Produces )
|
||||
producesIndex[ p ].Add( info );
|
||||
}
|
||||
}
|
||||
|
||||
public Cache<string, List<Actor>> GatherBuildings( Player player )
|
||||
{
|
||||
var ret = new Cache<string, List<Actor>>( x => new List<Actor>() );
|
||||
if (player == null)
|
||||
return ret;
|
||||
|
||||
foreach( var b in player.World.Queries.OwnedBy[player].Where( x=>x.Info.Traits.Contains<BuildingInfo>() ) )
|
||||
{
|
||||
ret[ b.Info.Name ].Add( b );
|
||||
var buildable = b.Info.Traits.GetOrDefault<BuildableInfo>();
|
||||
if( buildable != null )
|
||||
foreach( var alt in buildable.AlternateName )
|
||||
ret[ alt ].Add( b );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool CanBuild( ActorInfo info, Player player, Cache<string, List<Actor>> playerBuildings )
|
||||
{
|
||||
if (player == null)
|
||||
return false;
|
||||
|
||||
var bi = info.Traits.GetOrDefault<BuildableInfo>();
|
||||
if( bi == null ) return false;
|
||||
|
||||
if( !bi.Owner.Contains( player.Country.Race ) )
|
||||
return false;
|
||||
|
||||
foreach( var p in bi.Prerequisites )
|
||||
if( playerBuildings[ p ].Count == 0 )
|
||||
return false;
|
||||
|
||||
if( producesIndex[ info.Category ].All( x => playerBuildings[ x.Name ].Count == 0 ) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public IEnumerable<string> BuildableItems( Player player, params string[] categories )
|
||||
{
|
||||
if (player == null)
|
||||
yield break;
|
||||
|
||||
var playerBuildings = GatherBuildings( player );
|
||||
foreach (var unit in AllBuildables(categories))
|
||||
if( CanBuild( unit, player, playerBuildings ) )
|
||||
yield return unit.Name;
|
||||
}
|
||||
|
||||
public IEnumerable<ActorInfo> AllBuildables(params string[] categories)
|
||||
{
|
||||
return Rules.Info.Values
|
||||
.Where( x => x.Name[ 0 ] != '^' )
|
||||
.Where( x => categories.Contains( x.Category ) )
|
||||
.Where( x => x.Traits.Contains<BuildableInfo>() );
|
||||
}
|
||||
|
||||
public IEnumerable<ActorInfo> UnitBuiltAt( ActorInfo info )
|
||||
{
|
||||
var builtAt = info.Traits.Get<BuildableInfo>().BuiltAt;
|
||||
if( builtAt.Length != 0 )
|
||||
return builtAt.Select( x => Rules.Info[ x.ToLowerInvariant() ] );
|
||||
else
|
||||
return producesIndex[ info.Category ];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.FileFormats.Graphics;
|
||||
|
||||
namespace OpenRA.GameRules
|
||||
{
|
||||
public class UserSettings
|
||||
{
|
||||
// Debug settings
|
||||
public bool UnitDebug = false;
|
||||
public bool PathDebug = false;
|
||||
public bool PerfDebug = false;
|
||||
public bool IndexDebug = false;
|
||||
public bool RecordSyncReports = true;
|
||||
public bool ShowGameTimer = true;
|
||||
|
||||
// Window settings
|
||||
public WindowMode WindowMode = WindowMode.PseudoFullscreen;
|
||||
public int2 FullscreenSize = new int2(Screen.PrimaryScreen.Bounds.Width,Screen.PrimaryScreen.Bounds.Height);
|
||||
public int2 WindowedSize = new int2(1024,768);
|
||||
public readonly static int2 MinResolution = new int2(800, 600);
|
||||
|
||||
//Sound Settings
|
||||
public float SoundVolume = 0.5f;
|
||||
public float MusicVolume = 0.5f;
|
||||
public bool MusicPlayer = false;
|
||||
|
||||
// Internal game settings
|
||||
public int Timestep = 40;
|
||||
public int SheetSize = 2048;
|
||||
|
||||
// External game settings
|
||||
public string LastServer = "localhost:1234";
|
||||
public string Replay = null;
|
||||
public string PlayerName = "Newbie";
|
||||
public Color PlayerColor1 = Color.FromArgb(255,160,238);
|
||||
public Color PlayerColor2 = Color.FromArgb(68,0,56);
|
||||
|
||||
public string[] InitialMods = { "ra" };
|
||||
|
||||
// Server settings
|
||||
public string LastServerTitle = "OpenRA Game";
|
||||
public int ListenPort = 1234;
|
||||
public int ExternalPort = 1234;
|
||||
public bool AdvertiseOnline = true;
|
||||
public string MasterServer = "http://open-ra.org/master/";
|
||||
|
||||
string SettingsFile;
|
||||
UserSettings defaults;
|
||||
|
||||
public UserSettings() {}
|
||||
public UserSettings(Settings args)
|
||||
{
|
||||
defaults = new UserSettings();
|
||||
SettingsFile = Game.SupportDir + "settings.yaml";
|
||||
|
||||
// Override settings loading to not crash
|
||||
var err1 = FieldLoader.UnknownFieldAction;
|
||||
var err2 = FieldLoader.InvalidValueAction;
|
||||
|
||||
FieldLoader.InvalidValueAction = (s,t,f) =>
|
||||
{
|
||||
object ret = defaults.GetType().GetField(f).GetValue(defaults);
|
||||
System.Console.WriteLine("FieldLoader: Cannot parse `{0}` into `{2}:{1}`; substituting default `{3}`".F(s,t.Name,f,ret) );
|
||||
return ret;
|
||||
};
|
||||
|
||||
FieldLoader.UnknownFieldAction = (s,f) =>
|
||||
{
|
||||
System.Console.WriteLine( "Ignoring unknown field `{0}` on `{1}`".F( s, f.Name ) );
|
||||
};
|
||||
|
||||
if (File.Exists(SettingsFile))
|
||||
{
|
||||
System.Console.WriteLine("Loading settings file {0}",SettingsFile);
|
||||
var yaml = MiniYaml.FromFile(SettingsFile);
|
||||
FieldLoader.Load(this, yaml["Settings"]);
|
||||
}
|
||||
|
||||
foreach (var f in this.GetType().GetFields())
|
||||
if (args.Contains(f.Name))
|
||||
OpenRA.FileFormats.FieldLoader.LoadField( this, f.Name, args.GetValue(f.Name, "") );
|
||||
|
||||
FieldLoader.UnknownFieldAction = err1;
|
||||
FieldLoader.InvalidValueAction = err2;
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
Dictionary<string, MiniYaml> root = new Dictionary<string, MiniYaml>();
|
||||
root.Add("Settings", FieldSaver.SaveDifferences(this, defaults));
|
||||
root.WriteToFile(SettingsFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,35 +9,43 @@
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using System;
|
||||
|
||||
namespace OpenRA.GameRules
|
||||
{
|
||||
public class VoiceInfo
|
||||
{
|
||||
public readonly string[] SovietVariants = { ".aud" };
|
||||
public readonly string[] AlliedVariants = { ".aud" };
|
||||
public readonly string[] Select = { };
|
||||
public readonly string[] Move = { };
|
||||
public readonly string[] Attack = null;
|
||||
public readonly string[] Die = { };
|
||||
public readonly string[] Lost = { };
|
||||
public readonly Dictionary<string,string[]> Variants;
|
||||
public readonly Dictionary<string,string[]> Voices;
|
||||
public readonly string DefaultVariant = ".aud" ;
|
||||
[FieldLoader.Load] public readonly string[] DisableVariants = { };
|
||||
|
||||
public readonly Lazy<Dictionary<string, VoicePool>> Pools;
|
||||
static Dictionary<string, string[]> Load( MiniYaml y, string name )
|
||||
{
|
||||
return y.NodesDict.ContainsKey( name )
|
||||
? y.NodesDict[ name ].NodesDict.ToDictionary(
|
||||
a => a.Key,
|
||||
a => (string[])FieldLoader.GetValue( "(value)", typeof( string[] ), a.Value.Value ) )
|
||||
: new Dictionary<string, string[]>();
|
||||
}
|
||||
|
||||
public readonly OpenRA.FileFormats.Lazy<Dictionary<string, VoicePool>> Pools;
|
||||
|
||||
public VoiceInfo( MiniYaml y )
|
||||
{
|
||||
FieldLoader.Load(this, y);
|
||||
FieldLoader.Load( this, y );
|
||||
Variants = Load(y, "Variants");
|
||||
Voices = Load(y, "Voices");
|
||||
|
||||
if (!Voices.ContainsKey("Attack"))
|
||||
Voices.Add("Attack", Voices["Move"]);
|
||||
|
||||
Pools = Lazy.New(() =>
|
||||
new Dictionary<string, VoicePool>
|
||||
{
|
||||
{ "Select", new VoicePool(Select) },
|
||||
{ "Move", new VoicePool(Move) },
|
||||
{ "Attack", new VoicePool( Attack ?? Move ) },
|
||||
{ "Die", new VoicePool(Die) },
|
||||
{ "Lost", new VoicePool(Lost) },
|
||||
});
|
||||
if (!Voices.ContainsKey("AttackMove"))
|
||||
Voices.Add("AttackMove", Voices["Move"]);
|
||||
|
||||
Pools = Lazy.New(() => Voices.ToDictionary( a => a.Key, a => new VoicePool(a.Value) ));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,36 +11,56 @@
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.Effects;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Traits;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.GameRules
|
||||
{
|
||||
public class WarheadInfo
|
||||
{
|
||||
public readonly int Spread = 1; // distance (in pixels) from the explosion center at which damage is 1/2.
|
||||
public readonly float[] Verses = { 1, 1, 1, 1, 1 }; // damage vs each armortype
|
||||
public readonly bool Ore = false; // can this damage ore?
|
||||
public readonly string Explosion = null; // explosion effect to use
|
||||
public readonly string WaterExplosion = null; // explosion effect on hitting water (usually a splash)
|
||||
public readonly string SmudgeType = null; // type of smudge to apply
|
||||
public readonly int[] Size = { 0, 0 }; // size of the explosion. provide 2 values for a ring effect (outer/inner)
|
||||
public readonly int InfDeath = 0; // infantry death animation to use
|
||||
public readonly string ImpactSound = null; // sound to play on impact
|
||||
public readonly string WaterImpactSound = null; // sound to play on impact with water
|
||||
public readonly int Damage = 0; // how much (raw) damage to deal
|
||||
public readonly int Delay = 0; // delay in ticks before dealing the damage. 0=instant (old model)
|
||||
public readonly DamageModel DamageModel = DamageModel.Normal; // which damage model to use
|
||||
[FieldLoader.Load] public readonly int Spread = 1; // distance (in pixels) from the explosion center at which damage is 1/2.
|
||||
[FieldLoader.LoadUsing( "LoadVersus" )]
|
||||
public readonly Dictionary<string, float> Versus; // damage vs each armortype
|
||||
[FieldLoader.Load] public readonly bool Ore = false; // can this damage ore?
|
||||
[FieldLoader.Load] public readonly string Explosion = null; // explosion effect to use
|
||||
[FieldLoader.Load] public readonly string WaterExplosion = null; // explosion effect on hitting water (usually a splash)
|
||||
[FieldLoader.Load] public readonly string SmudgeType = null; // type of smudge to apply
|
||||
[FieldLoader.Load] public readonly int[] Size = { 0, 0 }; // size of the explosion. provide 2 values for a ring effect (outer/inner)
|
||||
[FieldLoader.Load] public readonly int InfDeath = 0; // infantry death animation to use
|
||||
[FieldLoader.Load] public readonly string ImpactSound = null; // sound to play on impact
|
||||
[FieldLoader.Load] public readonly string WaterImpactSound = null; // sound to play on impact with water
|
||||
[FieldLoader.Load] public readonly int Damage = 0; // how much (raw) damage to deal
|
||||
[FieldLoader.Load] public readonly int Delay = 0; // delay in ticks before dealing the damage. 0=instant (old model)
|
||||
[FieldLoader.Load] public readonly DamageModel DamageModel = DamageModel.Normal; // which damage model to use
|
||||
[FieldLoader.Load] public readonly bool PreventProne = false; // whether we should prevent prone response in infantry.
|
||||
|
||||
public float EffectivenessAgainst(ArmorType at) { return Verses[(int)at]; }
|
||||
}
|
||||
public float EffectivenessAgainst(Actor self)
|
||||
{
|
||||
var health = self.Info.Traits.GetOrDefault<HealthInfo>();
|
||||
if (health == null) return 0f;
|
||||
var armor = self.Info.Traits.GetOrDefault<ArmorInfo>();
|
||||
if (armor == null || armor.Type == null) return 1;
|
||||
|
||||
float versus;
|
||||
return Versus.TryGetValue(armor.Type, out versus) ? versus : 1;
|
||||
}
|
||||
|
||||
public enum ArmorType
|
||||
{
|
||||
none = 0,
|
||||
wood = 1,
|
||||
light = 2,
|
||||
heavy = 3,
|
||||
concrete = 4,
|
||||
public WarheadInfo( MiniYaml yaml )
|
||||
{
|
||||
FieldLoader.Load( this, yaml );
|
||||
}
|
||||
|
||||
static object LoadVersus( MiniYaml y )
|
||||
{
|
||||
return y.NodesDict.ContainsKey( "Versus" )
|
||||
? y.NodesDict[ "Versus" ].NodesDict.ToDictionary(
|
||||
a => a.Key,
|
||||
a => (float)FieldLoader.GetValue( "(value)", typeof( float ), a.Value.Value ) )
|
||||
: new Dictionary<string, float>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public enum DamageModel
|
||||
{
|
||||
@@ -55,58 +75,52 @@ namespace OpenRA.GameRules
|
||||
public int2 src;
|
||||
public int srcAltitude;
|
||||
public int facing;
|
||||
public Actor target;
|
||||
public Target target;
|
||||
public int2 dest;
|
||||
public int destAltitude;
|
||||
public float firepowerModifier = 1.0f;
|
||||
}
|
||||
|
||||
public interface IProjectileInfo { IEffect Create(ProjectileArgs args); }
|
||||
|
||||
public class WeaponInfo
|
||||
{
|
||||
public readonly float Range = 0;
|
||||
public readonly string Report = null;
|
||||
public readonly int ROF = 1;
|
||||
public readonly int Burst = 1;
|
||||
public readonly bool Charges = false;
|
||||
public readonly bool Underwater = false;
|
||||
public readonly string[] ValidTargets = { "Ground" };
|
||||
public readonly int BurstDelay = 5;
|
||||
[FieldLoader.Load] public readonly float Range = 0;
|
||||
[FieldLoader.Load] public readonly string Report = null;
|
||||
[FieldLoader.Load] public readonly int ROF = 1;
|
||||
[FieldLoader.Load] public readonly int Burst = 1;
|
||||
[FieldLoader.Load] public readonly bool Charges = false;
|
||||
[FieldLoader.Load] public readonly bool Underwater = false;
|
||||
[FieldLoader.Load] public readonly string[] ValidTargets = { "Ground" };
|
||||
[FieldLoader.Load] public readonly int BurstDelay = 5;
|
||||
[FieldLoader.Load] public readonly float MinRange = 0;
|
||||
|
||||
public IProjectileInfo Projectile;
|
||||
public List<WarheadInfo> Warheads = new List<WarheadInfo>();
|
||||
[FieldLoader.LoadUsing( "LoadProjectile" )] public IProjectileInfo Projectile;
|
||||
[FieldLoader.LoadUsing( "LoadWarheads" )] public List<WarheadInfo> Warheads;
|
||||
|
||||
public WeaponInfo(string name, MiniYaml content)
|
||||
{
|
||||
foreach (var kv in content.Nodes)
|
||||
{
|
||||
var key = kv.Key.Split('@')[0];
|
||||
switch (key)
|
||||
{
|
||||
case "Range": FieldLoader.LoadField(this, "Range", content.Nodes["Range"].Value); break;
|
||||
case "ROF": FieldLoader.LoadField(this, "ROF", content.Nodes["ROF"].Value); break;
|
||||
case "Report": FieldLoader.LoadField(this, "Report", content.Nodes["Report"].Value); break;
|
||||
case "Burst": FieldLoader.LoadField(this, "Burst", content.Nodes["Burst"].Value); break;
|
||||
case "Charges": FieldLoader.LoadField(this, "Charges", content.Nodes["Charges"].Value); break;
|
||||
case "ValidTargets": FieldLoader.LoadField(this, "ValidTargets", content.Nodes["ValidTargets"].Value); break;
|
||||
case "Underwater": FieldLoader.LoadField(this, "Underwater", content.Nodes["Underwater"].Value); break;
|
||||
case "BurstDelay": FieldLoader.LoadField(this, "BurstDelay", content.Nodes["BurstDelay"].Value); break;
|
||||
FieldLoader.Load( this, content );
|
||||
}
|
||||
|
||||
case "Warhead":
|
||||
{
|
||||
var warhead = new WarheadInfo();
|
||||
FieldLoader.Load(warhead, kv.Value);
|
||||
Warheads.Add(warhead);
|
||||
} break;
|
||||
static object LoadProjectile( MiniYaml yaml )
|
||||
{
|
||||
MiniYaml proj;
|
||||
if( !yaml.NodesDict.TryGetValue( "Projectile", out proj ) )
|
||||
return null;
|
||||
var ret = Game.CreateObject<IProjectileInfo>( proj.Value + "Info" );
|
||||
FieldLoader.Load( ret, proj );
|
||||
return ret;
|
||||
}
|
||||
|
||||
// in this case, it's an implementation of IProjectileInfo
|
||||
default:
|
||||
{
|
||||
Projectile = Game.CreateObject<IProjectileInfo>(key + "Info");
|
||||
FieldLoader.Load(Projectile, kv.Value);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
static object LoadWarheads( MiniYaml yaml )
|
||||
{
|
||||
var ret = new List<WarheadInfo>();
|
||||
foreach( var w in yaml.Nodes )
|
||||
if( w.Key.Split( '@' )[ 0 ] == "Warhead" )
|
||||
ret.Add( new WarheadInfo( w.Value ) );
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
static class ChromeProvider
|
||||
public static class ChromeProvider
|
||||
{
|
||||
static Dictionary<string, Dictionary<string, MappedImage>> collections;
|
||||
static Dictionary<string, Sheet> cachedSheets;
|
||||
@@ -52,7 +52,7 @@ namespace OpenRA.Graphics
|
||||
collections.Add(elementName, images);
|
||||
}
|
||||
|
||||
public static Sprite GetImage(Renderer renderer, string collection, string image)
|
||||
public static Sprite GetImage(string collection, string image)
|
||||
{
|
||||
// Cached sprite
|
||||
if (cachedSprites.ContainsKey(collection) && cachedSprites[collection].ContainsKey(image))
|
||||
@@ -72,14 +72,14 @@ namespace OpenRA.Graphics
|
||||
sheet = cachedSheets[mi.Src];
|
||||
else
|
||||
{
|
||||
sheet = new Sheet(renderer, mi.Src);
|
||||
sheet = new Sheet(mi.Src);
|
||||
cachedSheets.Add(mi.Src, sheet);
|
||||
}
|
||||
|
||||
// Cache the sprite
|
||||
if (!cachedSprites.ContainsKey(collection))
|
||||
cachedSprites.Add(collection, new Dictionary<string, Sprite>());
|
||||
cachedSprites[collection].Add(image, mi.GetImage(renderer, sheet));
|
||||
cachedSprites[collection].Add(image, mi.GetImage(sheet));
|
||||
|
||||
return cachedSprites[collection][image];
|
||||
}
|
||||
|
||||
67
OpenRA.Game/Graphics/CursorProvider.cs
Normal file
67
OpenRA.Game/Graphics/CursorProvider.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
public static class CursorProvider
|
||||
{
|
||||
static Dictionary<string, CursorSequence> cursors;
|
||||
|
||||
public static void Initialize(string[] sequenceFiles)
|
||||
{
|
||||
cursors = new Dictionary<string, CursorSequence>();
|
||||
|
||||
foreach (var f in sequenceFiles)
|
||||
LoadSequenceSource(f);
|
||||
}
|
||||
|
||||
static void LoadSequenceSource(string filename)
|
||||
{
|
||||
XmlDocument document = new XmlDocument();
|
||||
document.Load(FileSystem.Open(filename));
|
||||
|
||||
foreach (XmlElement eCursor in document.SelectNodes("/sequences/cursor"))
|
||||
LoadSequencesForCursor(eCursor);
|
||||
}
|
||||
|
||||
static void LoadSequencesForCursor(XmlElement eCursor)
|
||||
{
|
||||
Game.modData.LoadScreen.Display();
|
||||
string cursorSrc = eCursor.GetAttribute("src");
|
||||
string palette = eCursor.GetAttribute("palette");
|
||||
|
||||
foreach (XmlElement eSequence in eCursor.SelectNodes("./sequence"))
|
||||
cursors.Add(eSequence.GetAttribute("name"), new CursorSequence(cursorSrc, palette, eSequence));
|
||||
|
||||
}
|
||||
|
||||
public static bool HasCursorSequence(string cursor)
|
||||
{
|
||||
return cursors.ContainsKey(cursor);
|
||||
}
|
||||
|
||||
public static CursorSequence GetCursorSequence(string cursor)
|
||||
{
|
||||
try { return cursors[cursor]; }
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Cursor does not have a sequence `{0}`".F(cursor));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,21 +15,23 @@ namespace OpenRA.Graphics
|
||||
public class CursorSequence
|
||||
{
|
||||
readonly int start, length;
|
||||
readonly string palette;
|
||||
|
||||
public int Start { get { return start; } }
|
||||
public int End { get { return start + length; } }
|
||||
public int Length { get { return length; } }
|
||||
|
||||
public string Palette { get { return palette; } }
|
||||
public readonly int2 Hotspot;
|
||||
|
||||
Sprite[] sprites;
|
||||
|
||||
public CursorSequence(string cursorSrc, XmlElement e)
|
||||
public CursorSequence(string cursorSrc, string palette, XmlElement e)
|
||||
{
|
||||
sprites = CursorSheetBuilder.LoadAllSprites(cursorSrc);
|
||||
sprites = Game.modData.CursorSheetBuilder.LoadAllSprites(cursorSrc);
|
||||
|
||||
start = int.Parse(e.GetAttribute("start"));
|
||||
|
||||
this.palette = palette;
|
||||
|
||||
if (e.GetAttribute("length") == "*" || e.GetAttribute("end") == "*")
|
||||
length = sprites.Length - start;
|
||||
else if (e.HasAttribute("length"))
|
||||
|
||||
@@ -14,25 +14,32 @@ using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
static class CursorSheetBuilder
|
||||
public class CursorSheetBuilder
|
||||
{
|
||||
static Cache<string, Sprite[]> cursors = new Cache<string, Sprite[]>(LoadCursors);
|
||||
static readonly string[] exts = { ".shp" };
|
||||
ModData modData;
|
||||
Cache<string, Sprite[]> cursors;
|
||||
readonly string[] exts = { ".shp" };
|
||||
|
||||
static Sprite[] LoadCursors(string filename)
|
||||
public CursorSheetBuilder( ModData modData )
|
||||
{
|
||||
this.modData = modData;
|
||||
this.cursors = new Cache<string, Sprite[]>( LoadCursors );
|
||||
}
|
||||
|
||||
Sprite[] LoadCursors(string filename)
|
||||
{
|
||||
try
|
||||
{
|
||||
var shp = new Dune2ShpReader(FileSystem.OpenWithExts(filename, exts));
|
||||
return shp.Select(a => SheetBuilder.SharedInstance.Add(a.Image, a.Size)).ToArray();
|
||||
return shp.Select(a => modData.SheetBuilder.Add(a.Image, a.Size)).ToArray();
|
||||
}
|
||||
catch (IndexOutOfRangeException) // This will occur when loading a custom (RA-format) .shp
|
||||
{
|
||||
var shp = new ShpReader(FileSystem.OpenWithExts(filename, exts));
|
||||
return shp.Select(a => SheetBuilder.SharedInstance.Add(a.Image, shp.Size)).ToArray();
|
||||
return shp.Select(a => modData.SheetBuilder.Add(a.Image, shp.Size)).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public static Sprite[] LoadAllSprites(string filename) { return cursors[filename]; }
|
||||
public Sprite[] LoadAllSprites(string filename) { return cursors[filename]; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,78 +10,70 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.FileFormats.Graphics;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
class HardwarePalette : Sheet
|
||||
class HardwarePalette
|
||||
{
|
||||
public const int MaxPalettes = 64;
|
||||
int allocated = 0;
|
||||
|
||||
// We need to store the Palettes themselves for the remap palettes to work
|
||||
// We should probably try to fix this somehow
|
||||
static Dictionary<string, Palette> palettes;
|
||||
static Dictionary<string, int> indices;
|
||||
public HardwarePalette(Renderer renderer, Map map)
|
||||
: base(renderer,new Size(256, MaxPalettes))
|
||||
ITexture texture;
|
||||
Dictionary<string, Palette> palettes;
|
||||
Dictionary<string, int> indices;
|
||||
|
||||
public HardwarePalette(Map map)
|
||||
{
|
||||
palettes = new Dictionary<string, Palette>();
|
||||
indices = new Dictionary<string, int>();
|
||||
texture = Game.Renderer.Device.CreateTexture();
|
||||
}
|
||||
|
||||
public Palette GetPalette(string name)
|
||||
{
|
||||
try { return palettes[name]; }
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Palette `{0}` does not exist".F(name));
|
||||
}
|
||||
Palette ret;
|
||||
if (!palettes.TryGetValue(name,out ret))
|
||||
throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
|
||||
return ret;
|
||||
}
|
||||
|
||||
public int GetPaletteIndex(string name)
|
||||
{
|
||||
try { return indices[name]; }
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Palette `{0}` does not exist".F(name));
|
||||
}
|
||||
int ret;
|
||||
if (!indices.TryGetValue(name,out ret))
|
||||
throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
|
||||
return ret;
|
||||
}
|
||||
|
||||
public int AddPalette(string name, Palette p)
|
||||
public void AddPalette(string name, Palette p)
|
||||
{
|
||||
palettes.Add(name, p);
|
||||
indices.Add(name, allocated);
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
this[new Point(i, allocated)] = p.GetColor(i);
|
||||
}
|
||||
return allocated++;
|
||||
}
|
||||
|
||||
public void UpdatePalette(string name, Palette p)
|
||||
{
|
||||
palettes[name] = p;
|
||||
var j = indices[name];
|
||||
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
this[new Point(i, j)] = p.GetColor(i);
|
||||
}
|
||||
indices.Add(name, allocated++);
|
||||
}
|
||||
|
||||
public void Update(IEnumerable<IPaletteModifier> paletteMods)
|
||||
{
|
||||
var b = new Bitmap(Bitmap);
|
||||
var copy = palettes.ToDictionary(p => p.Key, p => new Palette(p.Value));
|
||||
|
||||
foreach (var mod in paletteMods)
|
||||
mod.AdjustPalette(b);
|
||||
|
||||
Texture.SetData(b);
|
||||
Game.renderer.PaletteTexture = Texture;
|
||||
mod.AdjustPalette(copy);
|
||||
|
||||
var data = new uint[MaxPalettes,256];
|
||||
foreach (var pal in copy)
|
||||
{
|
||||
var j = indices[pal.Key];
|
||||
var c = pal.Value.Values;
|
||||
for (var i = 0; i < 256; i++)
|
||||
data[j,i] = c[i];
|
||||
}
|
||||
|
||||
// Doesn't work
|
||||
texture.SetData(data);
|
||||
Game.Renderer.PaletteTexture = texture;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,45 +13,46 @@ using OpenRA.FileFormats.Graphics;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
class LineRenderer
|
||||
public class LineRenderer : Renderer.IBatchRenderer
|
||||
{
|
||||
Renderer renderer;
|
||||
IVertexBuffer<Vertex> vertexBuffer;
|
||||
IIndexBuffer indexBuffer; /* kindof a waste of space, but the GPU likes indexing, oh well */
|
||||
|
||||
const int linesPerBatch = 1024;
|
||||
|
||||
Vertex[] vertices = new Vertex[ 2 * linesPerBatch ];
|
||||
ushort[] indices = new ushort[ 2 * linesPerBatch ];
|
||||
int lines = 0;
|
||||
Vertex[] vertices = new Vertex[ Renderer.TempBufferSize ];
|
||||
ushort[] indices = new ushort[ Renderer.TempBufferSize ];
|
||||
int nv = 0, ni = 0;
|
||||
|
||||
public LineRenderer( Renderer renderer )
|
||||
{
|
||||
this.renderer = renderer;
|
||||
vertexBuffer = renderer.Device.CreateVertexBuffer(vertices.Length );
|
||||
indexBuffer = renderer.Device.CreateIndexBuffer( indices.Length );
|
||||
}
|
||||
|
||||
public void Flush()
|
||||
{
|
||||
if( lines > 0 )
|
||||
if( ni > 0 )
|
||||
{
|
||||
renderer.LineShader.Render( () =>
|
||||
{
|
||||
vertexBuffer.SetData( vertices );
|
||||
indexBuffer.SetData( indices );
|
||||
renderer.DrawBatch( vertexBuffer, indexBuffer,
|
||||
var vb = renderer.GetTempVertexBuffer();
|
||||
var ib = renderer.GetTempIndexBuffer();
|
||||
vb.SetData( vertices, nv );
|
||||
ib.SetData( indices, ni );
|
||||
renderer.DrawBatch( vb, ib,
|
||||
nv, ni / 2, PrimitiveType.LineList );
|
||||
} );
|
||||
|
||||
nv = 0; ni = 0;
|
||||
lines = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawLine( float2 start, float2 end, Color startColor, Color endColor )
|
||||
{
|
||||
Renderer.CurrentBatchRenderer = this;
|
||||
|
||||
if( ni + 2 > Renderer.TempBufferSize )
|
||||
Flush();
|
||||
if( nv + 2 > Renderer.TempBufferSize )
|
||||
Flush();
|
||||
|
||||
indices[ ni++ ] = (ushort)nv;
|
||||
|
||||
vertices[ nv++ ] = new Vertex( start,
|
||||
@@ -63,9 +64,6 @@ namespace OpenRA.Graphics
|
||||
vertices[ nv++ ] = new Vertex( end,
|
||||
new float2( endColor.R / 255.0f, endColor.G / 255.0f ),
|
||||
new float2( endColor.B / 255.0f, endColor.A / 255.0f ) );
|
||||
|
||||
if( ++lines >= linesPerBatch )
|
||||
Flush();
|
||||
}
|
||||
|
||||
public void FillRect( RectangleF r, Color color )
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace OpenRA.Graphics
|
||||
int.Parse(e.GetAttribute("height")));
|
||||
}
|
||||
|
||||
public Sprite GetImage(Renderer r, Sheet s)
|
||||
public Sprite GetImage(Sheet s)
|
||||
{
|
||||
return new Sprite(s, rect, TextureChannel.Alpha);
|
||||
}
|
||||
|
||||
@@ -14,171 +14,60 @@ using System.Drawing.Imaging;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Traits;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
class Minimap
|
||||
{
|
||||
readonly World world;
|
||||
Sheet sheet;
|
||||
SpriteRenderer rgbaRenderer;
|
||||
Sprite sprite;
|
||||
Bitmap terrain, customLayer;
|
||||
Rectangle bounds;
|
||||
|
||||
const int alpha = 230;
|
||||
|
||||
public Minimap(World world, Renderer r)
|
||||
public class Minimap
|
||||
{
|
||||
public static Bitmap TerrainBitmap(Map map)
|
||||
{
|
||||
this.world = world;
|
||||
sheet = new Sheet(r, new Size(world.Map.MapSize.X, world.Map.MapSize.Y));
|
||||
rgbaRenderer = r.RgbaSpriteRenderer;
|
||||
var size = Math.Max(world.Map.Width, world.Map.Height);
|
||||
var dw = (size - world.Map.Width) / 2;
|
||||
var dh = (size - world.Map.Height) / 2;
|
||||
|
||||
bounds = new Rectangle(world.Map.TopLeft.X - dw, world.Map.TopLeft.Y - dh, size, size);
|
||||
|
||||
sprite = new Sprite(sheet, bounds, TextureChannel.Alpha);
|
||||
|
||||
shroudColor = Color.FromArgb(alpha, Color.Black);
|
||||
}
|
||||
|
||||
public static Rectangle MakeMinimapBounds(Map m)
|
||||
{
|
||||
var size = Math.Max(m.Width, m.Height);
|
||||
var dw = (size - m.Width) / 2;
|
||||
var dh = (size - m.Height) / 2;
|
||||
|
||||
return new Rectangle(m.TopLeft.X - dw, m.TopLeft.Y - dh, size, size);
|
||||
return TerrainBitmap(map, false);
|
||||
}
|
||||
|
||||
static Color shroudColor;
|
||||
|
||||
public void InvalidateCustom() { customLayer = null; }
|
||||
|
||||
public static Bitmap RenderTerrainBitmap(Map map, TileSet tileset)
|
||||
public static Bitmap TerrainBitmap(Map map, bool actualSize)
|
||||
{
|
||||
var terrain = new Bitmap(map.MapSize.X, map.MapSize.Y);
|
||||
var tileset = Rules.TileSets[map.Tileset];
|
||||
var width = map.Width;
|
||||
var height = map.Height;
|
||||
|
||||
if (!actualSize)
|
||||
{
|
||||
width = height = Util.NextPowerOf2(Math.Max(map.Width, map.Height));
|
||||
}
|
||||
|
||||
Bitmap terrain = new Bitmap(width, height);
|
||||
|
||||
var bitmapData = terrain.LockBits(new Rectangle(0, 0, terrain.Width, terrain.Height),
|
||||
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||
|
||||
unsafe
|
||||
{
|
||||
int* c = (int*)bitmapData.Scan0;
|
||||
|
||||
for (var x = 0; x < map.MapSize.X; x++)
|
||||
for (var y = 0; y < map.MapSize.Y; y++)
|
||||
for (var x = 0; x < map.Width; x++)
|
||||
for (var y = 0; y < map.Height; y++)
|
||||
{
|
||||
var type = tileset.GetTerrainType(map.MapTiles[x, y]);
|
||||
*(c + (y * bitmapData.Stride >> 2) + x) = map.IsInMap(x, y)
|
||||
? Color.FromArgb(alpha, tileset.Terrain[type].Color).ToArgb()
|
||||
: shroudColor.ToArgb();
|
||||
var mapX = x + map.TopLeft.X;
|
||||
var mapY = y + map.TopLeft.Y;
|
||||
var type = tileset.GetTerrainType(map.MapTiles[mapX, mapY]);
|
||||
if (!tileset.Terrain.ContainsKey(type))
|
||||
throw new InvalidDataException("Tileset {0} lacks terraintype {1}".F(tileset.Id, type));
|
||||
|
||||
*(c + (y * bitmapData.Stride >> 2) + x) = tileset.Terrain[type].Color.ToArgb();
|
||||
}
|
||||
}
|
||||
terrain.UnlockBits(bitmapData);
|
||||
return terrain;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (terrain == null)
|
||||
terrain = RenderTerrainBitmap(world.Map, world.TileSet);
|
||||
|
||||
// Custom terrain layer
|
||||
if (customLayer == null)
|
||||
{
|
||||
customLayer = new Bitmap(terrain);
|
||||
for (var x = world.Map.TopLeft.X; x < world.Map.BottomRight.X; x++)
|
||||
for (var y = world.Map.TopLeft.Y; y < world.Map.BottomRight.Y; y++)
|
||||
{
|
||||
var customTerrain = world.WorldActor.traits.WithInterface<ITerrainTypeModifier>()
|
||||
.Select( t => t.GetTerrainType(new int2(x,y)) )
|
||||
.FirstOrDefault( t => t != null );
|
||||
if (customTerrain == null) continue;
|
||||
customLayer.SetPixel(x, y, Color.FromArgb(alpha, world.TileSet.Terrain[customTerrain].Color));
|
||||
}
|
||||
}
|
||||
|
||||
if (!world.GameHasStarted || !world.Queries.OwnedBy[world.LocalPlayer].WithTrait<ProvidesRadar>().Any())
|
||||
return;
|
||||
|
||||
var bitmap = new Bitmap(customLayer);
|
||||
var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||
|
||||
unsafe
|
||||
{
|
||||
int* c = (int*)bitmapData.Scan0;
|
||||
|
||||
foreach (var a in world.Queries.WithTrait<Unit>().Where(a => a.Actor.Owner != null && a.Actor.IsVisible()))
|
||||
*(c + (a.Actor.Location.Y * bitmapData.Stride >> 2) + a.Actor.Location.X) =
|
||||
Color.FromArgb(alpha, a.Actor.Owner.Color).ToArgb();
|
||||
|
||||
for (var x = world.Map.TopLeft.X; x < world.Map.BottomRight.X; x++)
|
||||
for (var y = world.Map.TopLeft.Y; y < world.Map.BottomRight.Y; y++)
|
||||
{
|
||||
if (!world.LocalPlayer.Shroud.DisplayOnRadar(x, y))
|
||||
{
|
||||
*(c + (y * bitmapData.Stride >> 2) + x) = shroudColor.ToArgb();
|
||||
continue;
|
||||
}
|
||||
var b = world.WorldActor.traits.Get<BuildingInfluence>().GetBuildingAt(new int2(x, y));
|
||||
|
||||
if (b != null)
|
||||
*(c + (y * bitmapData.Stride >> 2) + x) = Color.FromArgb(alpha, b.Owner.Color).ToArgb();
|
||||
}
|
||||
}
|
||||
|
||||
bitmap.UnlockBits(bitmapData);
|
||||
sheet.Texture.SetData(bitmap);
|
||||
}
|
||||
|
||||
public void Draw(RectangleF rect)
|
||||
{
|
||||
rgbaRenderer.DrawSprite(sprite,
|
||||
new float2(rect.X, rect.Y), "chrome", new float2(rect.Width, rect.Height));
|
||||
rgbaRenderer.Flush();
|
||||
}
|
||||
|
||||
int2 CellToMinimapPixel(RectangleF viewRect, int2 p)
|
||||
{
|
||||
var fx = (float)(p.X - bounds.X) / bounds.Width;
|
||||
var fy = (float)(p.Y - bounds.Y) / bounds.Height;
|
||||
|
||||
return new int2(
|
||||
(int)(viewRect.Width * fx + viewRect.Left),
|
||||
(int)(viewRect.Height * fy + viewRect.Top));
|
||||
}
|
||||
|
||||
public int2 MinimapPixelToCell(RectangleF viewRect, int2 p)
|
||||
{
|
||||
var fx = (float)(p.X - viewRect.Left) / viewRect.Width;
|
||||
var fy = (float)(p.Y - viewRect.Top) / viewRect.Height;
|
||||
|
||||
return new int2(
|
||||
(int)(bounds.Width * fx + bounds.Left),
|
||||
(int)(bounds.Height * fy + bounds.Top));
|
||||
}
|
||||
|
||||
|
||||
static int NextPowerOf2(int v)
|
||||
// Add the static resources defined in the map; if the map lives
|
||||
// in a world use AddCustomTerrain instead
|
||||
public static Bitmap AddStaticResources(Map map, Bitmap terrainBitmap)
|
||||
{
|
||||
--v;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
++v;
|
||||
return v;
|
||||
}
|
||||
|
||||
public static Bitmap RenderMapPreview(MapStub stub)
|
||||
{
|
||||
Map map = stub.Map;
|
||||
Bitmap terrain = new Bitmap(terrainBitmap);
|
||||
var tileset = Rules.TileSets[map.Tileset];
|
||||
var size = NextPowerOf2(Math.Max(map.Width, map.Height));
|
||||
Bitmap terrain = new Bitmap(size, size);
|
||||
|
||||
|
||||
var bitmapData = terrain.LockBits(new Rectangle(0, 0, terrain.Width, terrain.Height),
|
||||
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||
|
||||
@@ -190,22 +79,118 @@ namespace OpenRA.Graphics
|
||||
for (var y = 0; y < map.Height; y++)
|
||||
{
|
||||
var mapX = x + map.TopLeft.X;
|
||||
var mapY = y + map.TopLeft.Y;
|
||||
var type = tileset.GetTerrainType(map.MapTiles[mapX, mapY]);
|
||||
string res = null;
|
||||
if (map.MapResources[mapX, mapY].type != 0)
|
||||
res = Rules.Info["world"].Traits.WithInterface<ResourceTypeInfo>()
|
||||
var mapY = y + map.TopLeft.Y;
|
||||
if (map.MapResources[mapX, mapY].type == 0)
|
||||
continue;
|
||||
|
||||
var res = Rules.Info["world"].Traits.WithInterface<ResourceTypeInfo>()
|
||||
.Where(t => t.ResourceType == map.MapResources[mapX, mapY].type)
|
||||
.Select(t => t.TerrainType).FirstOrDefault();
|
||||
if (res != null)
|
||||
type = res;
|
||||
if (res == null)
|
||||
continue;
|
||||
|
||||
*(c + (y * bitmapData.Stride >> 2) + x) = tileset.Terrain[type].Color.ToArgb();
|
||||
*(c + (y * bitmapData.Stride >> 2) + x) = tileset.Terrain[res].Color.ToArgb();
|
||||
}
|
||||
}
|
||||
terrain.UnlockBits(bitmapData);
|
||||
|
||||
return terrain;
|
||||
}
|
||||
|
||||
public static Bitmap CustomTerrainBitmap(World world)
|
||||
{
|
||||
var map = world.Map;
|
||||
var size = Util.NextPowerOf2(Math.Max(map.Width, map.Height));
|
||||
Bitmap bitmap = new Bitmap(size, size);
|
||||
var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||
|
||||
unsafe
|
||||
{
|
||||
int* c = (int*)bitmapData.Scan0;
|
||||
|
||||
for (var x = 0; x < map.Width; x++)
|
||||
for (var y = 0; y < map.Height; y++)
|
||||
{
|
||||
var mapX = x + map.TopLeft.X;
|
||||
var mapY = y + map.TopLeft.Y;
|
||||
var custom = map.CustomTerrain[mapX,mapY];
|
||||
if (custom == null)
|
||||
continue;
|
||||
*(c + (y * bitmapData.Stride >> 2) + x) = world.TileSet.Terrain[custom].Color.ToArgb();
|
||||
}
|
||||
}
|
||||
bitmap.UnlockBits(bitmapData);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
public static Bitmap ActorsBitmap(World world)
|
||||
{
|
||||
var map = world.Map;
|
||||
var size = Util.NextPowerOf2(Math.Max(map.Width, map.Height));
|
||||
Bitmap bitmap = new Bitmap(size, size);
|
||||
var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||
|
||||
unsafe
|
||||
{
|
||||
int* c = (int*)bitmapData.Scan0;
|
||||
|
||||
var player = world.LocalPlayer;
|
||||
|
||||
foreach (var t in world.Queries.WithTraitMultiple<IRadarSignature>())
|
||||
{
|
||||
if (!t.Actor.IsVisible(player))
|
||||
continue;
|
||||
|
||||
var color = t.Trait.RadarSignatureColor(t.Actor);
|
||||
foreach (var cell in t.Trait.RadarSignatureCells(t.Actor))
|
||||
if (world.Map.IsInMap(cell))
|
||||
*(c + ((cell.Y - world.Map.TopLeft.Y) * bitmapData.Stride >> 2) + cell.X - world.Map.TopLeft.X) = color.ToArgb();
|
||||
}
|
||||
}
|
||||
|
||||
bitmap.UnlockBits(bitmapData);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
public static Bitmap ShroudBitmap(World world)
|
||||
{
|
||||
var map = world.Map;
|
||||
var size = Util.NextPowerOf2(Math.Max(map.Width, map.Height));
|
||||
Bitmap bitmap = new Bitmap(size, size);
|
||||
var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||
|
||||
var shroud = Color.Black.ToArgb();
|
||||
var fog = Color.FromArgb(128, Color.Black).ToArgb();
|
||||
|
||||
var playerShroud = world.LocalPlayer.Shroud;
|
||||
|
||||
unsafe
|
||||
{
|
||||
int* c = (int*)bitmapData.Scan0;
|
||||
|
||||
for (var x = 0; x < map.Width; x++)
|
||||
for (var y = 0; y < map.Height; y++)
|
||||
{
|
||||
var mapX = x + map.TopLeft.X;
|
||||
var mapY = y + map.TopLeft.Y;
|
||||
if (!playerShroud.IsExplored(mapX, mapY))
|
||||
*(c + (y * bitmapData.Stride >> 2) + x) = shroud;
|
||||
else if (!playerShroud.IsVisible(mapX,mapY))
|
||||
*(c + (y * bitmapData.Stride >> 2) + x) = fog;
|
||||
}
|
||||
}
|
||||
|
||||
bitmap.UnlockBits(bitmapData);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
public static Bitmap RenderMapPreview(Map map)
|
||||
{
|
||||
Bitmap terrain = TerrainBitmap(map);
|
||||
return AddStaticResources(map, terrain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,71 +9,73 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Windows.Forms;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.FileFormats.Graphics;
|
||||
using OpenRA.Support;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
internal class Renderer
|
||||
public class Renderer
|
||||
{
|
||||
internal static int SheetSize;
|
||||
|
||||
readonly IGraphicsDevice device;
|
||||
|
||||
public IShader SpriteShader { get; private set; } /* note: shared shader params */
|
||||
public IShader LineShader { get; private set; }
|
||||
public IShader RgbaSpriteShader { get; private set; }
|
||||
public IShader WorldSpriteShader { get; private set; }
|
||||
internal IShader SpriteShader { get; private set; } /* note: shared shader params */
|
||||
internal IShader LineShader { get; private set; }
|
||||
internal IShader RgbaSpriteShader { get; private set; }
|
||||
internal IShader WorldSpriteShader { get; private set; }
|
||||
|
||||
public SpriteRenderer SpriteRenderer { get; private set; }
|
||||
public SpriteRenderer RgbaSpriteRenderer { get; private set; }
|
||||
public SpriteRenderer WorldSpriteRenderer { get; private set; }
|
||||
public LineRenderer LineRenderer { get; private set; }
|
||||
|
||||
public ITexture PaletteTexture;
|
||||
|
||||
public readonly SpriteFont RegularFont, BoldFont, TitleFont;
|
||||
|
||||
public Size Resolution { get { return device.WindowSize; } }
|
||||
internal const int TempBufferSize = 8192;
|
||||
const int TempBufferCount = 8;
|
||||
|
||||
public Renderer(Size resolution, OpenRA.FileFormats.Graphics.WindowMode windowMode)
|
||||
Queue<IVertexBuffer<Vertex>> tempBuffersV = new Queue<IVertexBuffer<Vertex>>();
|
||||
Queue<IIndexBuffer> tempBuffersI = new Queue<IIndexBuffer>();
|
||||
|
||||
public Renderer()
|
||||
{
|
||||
device = CreateDevice( Assembly.LoadFile( Path.GetFullPath( "OpenRA.Gl.dll" ) ), resolution.Width, resolution.Height, windowMode, false );
|
||||
|
||||
SpriteShader = device.CreateShader(FileSystem.Open("shaders/world-shp.fx"));
|
||||
LineShader = device.CreateShader(FileSystem.Open("shaders/line.fx"));
|
||||
RgbaSpriteShader = device.CreateShader(FileSystem.Open("shaders/chrome-rgba.fx"));
|
||||
WorldSpriteShader = device.CreateShader(FileSystem.Open("shaders/chrome-shp.fx"));
|
||||
SpriteShader = device.CreateShader("world-shp");
|
||||
LineShader = device.CreateShader("world-line");
|
||||
RgbaSpriteShader = device.CreateShader("chrome-rgba");
|
||||
WorldSpriteShader = device.CreateShader("chrome-shp");
|
||||
|
||||
SpriteRenderer = new SpriteRenderer( this, SpriteShader );
|
||||
RgbaSpriteRenderer = new SpriteRenderer( this, RgbaSpriteShader );
|
||||
WorldSpriteRenderer = new SpriteRenderer( this, WorldSpriteShader );
|
||||
LineRenderer = new LineRenderer(this);
|
||||
|
||||
RegularFont = new SpriteFont(this, "FreeSans.ttf", 14);
|
||||
BoldFont = new SpriteFont(this, "FreeSansBold.ttf", 14);
|
||||
TitleFont = new SpriteFont(this, "titles.ttf", 48);
|
||||
}
|
||||
RegularFont = new SpriteFont("FreeSans.ttf", 14);
|
||||
BoldFont = new SpriteFont("FreeSansBold.ttf", 14);
|
||||
TitleFont = new SpriteFont("titles.ttf", 48);
|
||||
|
||||
IGraphicsDevice CreateDevice( Assembly rendererDll, int width, int height, WindowMode window, bool vsync )
|
||||
{
|
||||
foreach( RendererAttribute r in rendererDll.GetCustomAttributes( typeof( RendererAttribute ), false ) )
|
||||
for( int i = 0 ; i < TempBufferCount ; i++ )
|
||||
{
|
||||
return (IGraphicsDevice)r.Type.GetConstructor( new Type[] { typeof( int ), typeof( int ), typeof( WindowMode ), typeof( bool ) } )
|
||||
.Invoke( new object[] { width, height, window, vsync } );
|
||||
tempBuffersV.Enqueue( device.CreateVertexBuffer( TempBufferSize ) );
|
||||
tempBuffersI.Enqueue( device.CreateIndexBuffer( TempBufferSize ) );
|
||||
}
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IGraphicsDevice Device { get { return device; } }
|
||||
internal IGraphicsDevice Device { get { return device; } }
|
||||
|
||||
public void BeginFrame(float2 r1, float2 r2, float2 scroll)
|
||||
public void BeginFrame(float2 scroll)
|
||||
{
|
||||
device.Begin();
|
||||
device.Clear(Color.Black);
|
||||
|
||||
float2 r1 = new float2(2f/Resolution.Width, -2f/Resolution.Height);
|
||||
float2 r2 = new float2(-1, 1);
|
||||
|
||||
SetShaderParams( SpriteShader, r1, r2, scroll );
|
||||
SetShaderParams( LineShader, r1, r2, scroll );
|
||||
SetShaderParams( RgbaSpriteShader, r1, r2, scroll );
|
||||
@@ -83,16 +85,16 @@ namespace OpenRA.Graphics
|
||||
private void SetShaderParams( IShader s, float2 r1, float2 r2, float2 scroll )
|
||||
{
|
||||
s.SetValue( "Palette", PaletteTexture );
|
||||
s.SetValue( "Scroll", scroll.X, scroll.Y );
|
||||
s.SetValue( "Scroll", (int) scroll.X, (int) scroll.Y );
|
||||
s.SetValue( "r1", r1.X, r1.Y );
|
||||
s.SetValue( "r2", r2.X, r2.Y );
|
||||
s.Commit();
|
||||
}
|
||||
|
||||
public void EndFrame()
|
||||
public void EndFrame( IInputHandler inputHandler )
|
||||
{
|
||||
device.End();
|
||||
device.Present();
|
||||
Flush();
|
||||
device.Present( inputHandler );
|
||||
}
|
||||
|
||||
public void DrawBatch<T>(IVertexBuffer<T> vertices, IIndexBuffer indices,
|
||||
@@ -118,5 +120,89 @@ namespace OpenRA.Graphics
|
||||
|
||||
PerfHistory.Increment("batches", 1);
|
||||
}
|
||||
|
||||
public void Flush()
|
||||
{
|
||||
CurrentBatchRenderer = null;
|
||||
}
|
||||
|
||||
static IGraphicsDevice device;
|
||||
|
||||
public static Size Resolution { get { return device.WindowSize; } }
|
||||
|
||||
internal static void Initialize( OpenRA.FileFormats.Graphics.WindowMode windowMode )
|
||||
{
|
||||
var resolution = GetResolution( windowMode );
|
||||
device = CreateDevice( Assembly.LoadFile( Path.GetFullPath( "OpenRA.Renderer.{0}.dll".F(Game.Settings.Graphics.Renderer) ) ), resolution.Width, resolution.Height, windowMode, false );
|
||||
}
|
||||
|
||||
static Size GetResolution(WindowMode windowmode)
|
||||
{
|
||||
var desktopResolution = Screen.PrimaryScreen.Bounds.Size;
|
||||
var customSize = (windowmode == WindowMode.Windowed) ? Game.Settings.Graphics.WindowedSize : Game.Settings.Graphics.FullscreenSize;
|
||||
|
||||
if (customSize.X > 0 && customSize.Y > 0)
|
||||
{
|
||||
desktopResolution.Width = customSize.X;
|
||||
desktopResolution.Height = customSize.Y;
|
||||
}
|
||||
return new Size(
|
||||
desktopResolution.Width,
|
||||
desktopResolution.Height);
|
||||
}
|
||||
|
||||
static IGraphicsDevice CreateDevice( Assembly rendererDll, int width, int height, WindowMode window, bool vsync )
|
||||
{
|
||||
foreach( RendererAttribute r in rendererDll.GetCustomAttributes( typeof( RendererAttribute ), false ) )
|
||||
{
|
||||
return (IGraphicsDevice)r.Type.GetConstructor( new Type[] { typeof( int ), typeof( int ), typeof( WindowMode ), typeof( bool ) } )
|
||||
.Invoke( new object[] { width, height, window, vsync } );
|
||||
}
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal IVertexBuffer<Vertex> GetTempVertexBuffer()
|
||||
{
|
||||
var ret = tempBuffersV.Dequeue();
|
||||
tempBuffersV.Enqueue( ret );
|
||||
return ret;
|
||||
}
|
||||
|
||||
internal IIndexBuffer GetTempIndexBuffer()
|
||||
{
|
||||
var ret = tempBuffersI.Dequeue();
|
||||
tempBuffersI.Enqueue( ret );
|
||||
return ret;
|
||||
}
|
||||
|
||||
public interface IBatchRenderer
|
||||
{
|
||||
void Flush();
|
||||
}
|
||||
|
||||
static IBatchRenderer currentBatchRenderer;
|
||||
public static IBatchRenderer CurrentBatchRenderer
|
||||
{
|
||||
get { return currentBatchRenderer; }
|
||||
set
|
||||
{
|
||||
if( currentBatchRenderer == value ) return;
|
||||
if( currentBatchRenderer != null )
|
||||
currentBatchRenderer.Flush();
|
||||
currentBatchRenderer = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void EnableScissor(int left, int top, int width, int height)
|
||||
{
|
||||
Flush();
|
||||
Device.EnableScissor( left, top, width, height );
|
||||
}
|
||||
|
||||
public void DisableScissor()
|
||||
{
|
||||
Flush();
|
||||
Device.DisableScissor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#endregion
|
||||
|
||||
using System.Xml;
|
||||
using OpenRA.FileFormats;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
@@ -24,34 +26,55 @@ namespace OpenRA.Graphics
|
||||
public int Facings { get { return facings; } }
|
||||
public int Tick { get { return tick; } }
|
||||
|
||||
public Sequence(string unit, XmlElement e)
|
||||
string srcOverride;
|
||||
public Sequence(string unit, string name, MiniYaml info)
|
||||
{
|
||||
string srcOverride = e.GetAttribute("src");
|
||||
Name = e.GetAttribute("name");
|
||||
|
||||
srcOverride = info.Value;
|
||||
Name = name;
|
||||
var d = info.NodesDict;
|
||||
|
||||
sprites = SpriteSheetBuilder.LoadAllSprites(string.IsNullOrEmpty(srcOverride) ? unit : srcOverride );
|
||||
start = int.Parse(e.GetAttribute("start"));
|
||||
start = int.Parse(d["Start"].Value);
|
||||
|
||||
if (e.GetAttribute("length") == "*" || e.GetAttribute("end") == "*")
|
||||
length = sprites.Length - Start;
|
||||
else if (e.HasAttribute("length"))
|
||||
length = int.Parse(e.GetAttribute("length"));
|
||||
else if (e.HasAttribute("end"))
|
||||
length = int.Parse(e.GetAttribute("end")) - int.Parse(e.GetAttribute("start"));
|
||||
else
|
||||
if (!d.ContainsKey("Length"))
|
||||
length = 1;
|
||||
else if (d["Length"].Value == "*")
|
||||
length = sprites.Length - Start;
|
||||
else
|
||||
length = int.Parse(d["Length"].Value);
|
||||
|
||||
if( e.HasAttribute( "facings" ) )
|
||||
facings = int.Parse( e.GetAttribute( "facings" ) );
|
||||
|
||||
if(d.ContainsKey("Facings"))
|
||||
facings = int.Parse(d["Facings"].Value);
|
||||
else
|
||||
facings = 1;
|
||||
|
||||
if (e.HasAttribute("tick"))
|
||||
tick = int.Parse(e.GetAttribute("tick"));
|
||||
if(d.ContainsKey("Tick"))
|
||||
tick = int.Parse(d["Tick"].Value);
|
||||
else
|
||||
tick = 40;
|
||||
}
|
||||
|
||||
|
||||
public MiniYaml Save()
|
||||
{
|
||||
var root = new List<MiniYamlNode>();
|
||||
|
||||
root.Add(new MiniYamlNode("Start", start.ToString()));
|
||||
|
||||
if (length > 1 && (start != 0 || length != sprites.Length - start))
|
||||
root.Add(new MiniYamlNode("Length", length.ToString()));
|
||||
else if (length > 1 && length == sprites.Length - start)
|
||||
root.Add(new MiniYamlNode("Length", "*"));
|
||||
|
||||
if (facings > 1)
|
||||
root.Add(new MiniYamlNode("Facings", facings.ToString()));
|
||||
|
||||
if (tick != 40)
|
||||
root.Add(new MiniYamlNode("Tick", tick.ToString()));
|
||||
|
||||
return new MiniYaml(srcOverride, root);
|
||||
}
|
||||
|
||||
public Sprite GetSprite( int frame )
|
||||
{
|
||||
return GetSprite( frame, 0 );
|
||||
|
||||
@@ -20,50 +20,37 @@ namespace OpenRA.Graphics
|
||||
public static class SequenceProvider
|
||||
{
|
||||
static Dictionary<string, Dictionary<string, Sequence>> units;
|
||||
static Dictionary<string, CursorSequence> cursors;
|
||||
|
||||
public static void Initialize(string[] sequenceFiles)
|
||||
public static void Initialize(string[] sequenceFiles, List<MiniYamlNode> sequenceNodes)
|
||||
{
|
||||
units = new Dictionary<string, Dictionary<string, Sequence>>();
|
||||
cursors = new Dictionary<string, CursorSequence>();
|
||||
|
||||
foreach (var f in sequenceFiles)
|
||||
LoadSequenceSource(f);
|
||||
if (sequenceFiles.Length == 0)
|
||||
return;
|
||||
|
||||
var sequences = sequenceFiles.Select(s => MiniYaml.FromFile(s)).Aggregate(sequenceNodes, MiniYaml.Merge);
|
||||
|
||||
foreach (var s in sequences)
|
||||
LoadSequencesForUnit(s.Key, s.Value);
|
||||
}
|
||||
|
||||
static void LoadSequenceSource(string filename)
|
||||
static void LoadSequencesForUnit(string unit, MiniYaml sequences)
|
||||
{
|
||||
XmlDocument document = new XmlDocument();
|
||||
document.Load(FileSystem.Open(filename));
|
||||
|
||||
foreach (XmlElement eUnit in document.SelectNodes("/sequences/unit"))
|
||||
LoadSequencesForUnit(eUnit);
|
||||
|
||||
foreach (XmlElement eCursor in document.SelectNodes("/sequences/cursor"))
|
||||
LoadSequencesForCursor(eCursor);
|
||||
}
|
||||
|
||||
static void LoadSequencesForCursor(XmlElement eCursor)
|
||||
{
|
||||
string cursorSrc = eCursor.GetAttribute("src");
|
||||
|
||||
foreach (XmlElement eSequence in eCursor.SelectNodes("./sequence"))
|
||||
cursors.Add(eSequence.GetAttribute("name"), new CursorSequence(cursorSrc, eSequence));
|
||||
|
||||
}
|
||||
|
||||
static void LoadSequencesForUnit(XmlElement eUnit)
|
||||
{
|
||||
string unitName = eUnit.GetAttribute("name");
|
||||
Game.modData.LoadScreen.Display();
|
||||
try {
|
||||
var sequences = eUnit.SelectNodes("./sequence").OfType<XmlElement>()
|
||||
.Select(e => new Sequence(unitName, e))
|
||||
.ToDictionary(s => s.Name);
|
||||
|
||||
units.Add(unitName, sequences);
|
||||
var seq = sequences.NodesDict.ToDictionary(x => x.Key, x => new Sequence(unit,x.Key,x.Value));
|
||||
units.Add(unit, seq);
|
||||
} catch (FileNotFoundException) {} // Do nothing; we can crash later if we actually wanted art
|
||||
}
|
||||
|
||||
public static MiniYaml SaveSequencesForUnit(string unitname)
|
||||
{
|
||||
var ret = new List<MiniYamlNode>();
|
||||
foreach (var s in units[unitname])
|
||||
ret.Add(new MiniYamlNode(s.Key, s.Value.Save()));
|
||||
|
||||
return new MiniYaml(null, ret);
|
||||
}
|
||||
|
||||
public static Sequence GetSequence(string unitName, string sequenceName)
|
||||
{
|
||||
try { return units[unitName][sequenceName]; }
|
||||
@@ -78,15 +65,5 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
return units[unit].ContainsKey(seq);
|
||||
}
|
||||
|
||||
public static CursorSequence GetCursorSequence(string cursor)
|
||||
{
|
||||
try { return cursors[cursor]; }
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Cursor does not have a sequence `{0}`".F(cursor));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,21 +16,21 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
public class Sheet
|
||||
{
|
||||
readonly Renderer renderer;
|
||||
protected readonly Bitmap bitmap;
|
||||
Bitmap bitmap;
|
||||
ITexture texture;
|
||||
bool dirty;
|
||||
byte[] data;
|
||||
public readonly Size Size;
|
||||
|
||||
internal Sheet(Renderer renderer, Size size)
|
||||
public Sheet(Size size)
|
||||
{
|
||||
this.renderer = renderer;
|
||||
this.bitmap = new Bitmap(size.Width, size.Height);
|
||||
Size = size;
|
||||
}
|
||||
|
||||
internal Sheet(Renderer renderer, string filename)
|
||||
public Sheet(string filename)
|
||||
{
|
||||
this.renderer = renderer;
|
||||
this.bitmap = (Bitmap)Image.FromStream(FileSystem.Open(filename));
|
||||
bitmap = (Bitmap)Image.FromStream(FileSystem.Open(filename));
|
||||
Size = bitmap.Size;
|
||||
}
|
||||
|
||||
public ITexture Texture
|
||||
@@ -38,28 +38,30 @@ namespace OpenRA.Graphics
|
||||
get
|
||||
{
|
||||
if (texture == null)
|
||||
texture = renderer.Device.CreateTexture(bitmap);
|
||||
{
|
||||
texture = Game.Renderer.Device.CreateTexture();
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
if (dirty)
|
||||
{
|
||||
texture.SetData(bitmap);
|
||||
dirty = false;
|
||||
if (data != null)
|
||||
{
|
||||
texture.SetData(data, Size.Width, Size.Height);
|
||||
dirty = false;
|
||||
}
|
||||
else if (bitmap != null)
|
||||
{
|
||||
texture.SetData(bitmap);
|
||||
dirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
return texture;
|
||||
}
|
||||
}
|
||||
|
||||
public Size Size { get { return bitmap.Size; } }
|
||||
|
||||
protected Color this[Point p]
|
||||
{
|
||||
get { return bitmap.GetPixel(p.X, p.Y); }
|
||||
set { bitmap.SetPixel(p.X, p.Y, value); }
|
||||
}
|
||||
|
||||
public Bitmap Bitmap { get { return bitmap; } } // for perf
|
||||
|
||||
public byte[] Data { get { if (data == null) data = new byte[4 * Size.Width * Size.Height]; return data; } }
|
||||
public void MakeDirty() { dirty = true; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,15 +14,8 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
public class SheetBuilder
|
||||
{
|
||||
public static SheetBuilder SharedInstance;
|
||||
internal static void Initialize(Renderer r)
|
||||
internal SheetBuilder(TextureChannel ch)
|
||||
{
|
||||
SharedInstance = new SheetBuilder(r, TextureChannel.Red);
|
||||
}
|
||||
|
||||
internal SheetBuilder(Renderer r, TextureChannel ch)
|
||||
{
|
||||
renderer = r;
|
||||
current = null;
|
||||
rowHeight = 0;
|
||||
channel = null;
|
||||
@@ -45,9 +38,8 @@ namespace OpenRA.Graphics
|
||||
return Add(data, size);
|
||||
}
|
||||
|
||||
Sheet NewSheet() { return new Sheet( renderer, new Size( Renderer.SheetSize, Renderer.SheetSize ) ); }
|
||||
|
||||
Renderer renderer;
|
||||
Sheet NewSheet() { return new Sheet(new Size( Renderer.SheetSize, Renderer.SheetSize ) ); }
|
||||
|
||||
Sheet current = null;
|
||||
int rowHeight = 0;
|
||||
Point p;
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace OpenRA.Graphics
|
||||
|
||||
readonly float2[] uvhax;
|
||||
|
||||
internal Sprite(Sheet sheet, Rectangle bounds, TextureChannel channel)
|
||||
public Sprite(Sheet sheet, Rectangle bounds, TextureChannel channel)
|
||||
{
|
||||
this.bounds = bounds;
|
||||
this.sheet = sheet;
|
||||
@@ -49,6 +49,26 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
return uvhax[ k ];
|
||||
}
|
||||
|
||||
public void DrawAt( WorldRenderer wr, float2 location, string palette )
|
||||
{
|
||||
Game.Renderer.SpriteRenderer.DrawSprite( this, location, wr, palette, this.size );
|
||||
}
|
||||
|
||||
public void DrawAt( float2 location, int paletteIndex )
|
||||
{
|
||||
Game.Renderer.SpriteRenderer.DrawSprite( this, location, paletteIndex, this.size );
|
||||
}
|
||||
|
||||
public void DrawAt(float2 location, int paletteIndex, float scale)
|
||||
{
|
||||
Game.Renderer.SpriteRenderer.DrawSprite(this, location, paletteIndex, this.size * scale);
|
||||
}
|
||||
|
||||
public void DrawAt( float2 location, int paletteIndex, float2 size )
|
||||
{
|
||||
Game.Renderer.SpriteRenderer.DrawSprite( this, location, paletteIndex, size );
|
||||
}
|
||||
}
|
||||
|
||||
public enum TextureChannel
|
||||
|
||||
@@ -17,14 +17,12 @@ using Tao.FreeType;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
class SpriteFont
|
||||
public class SpriteFont
|
||||
{
|
||||
Renderer renderer;
|
||||
int size;
|
||||
|
||||
public SpriteFont(Renderer r, string name, int size)
|
||||
public SpriteFont(string name, int size)
|
||||
{
|
||||
this.renderer = r;
|
||||
this.size = size;
|
||||
|
||||
if (0 != FT.FT_New_Face(library, name, 0, out face))
|
||||
@@ -34,7 +32,7 @@ namespace OpenRA.Graphics
|
||||
glyphs = new Cache<Pair<char, Color>, GlyphInfo>(CreateGlyph);
|
||||
|
||||
// setup a 1-channel SheetBuilder for our private use
|
||||
if (builder == null) builder = new SheetBuilder(r, TextureChannel.Alpha);
|
||||
if (builder == null) builder = new SheetBuilder(TextureChannel.Alpha);
|
||||
|
||||
PrecacheColor(Color.White);
|
||||
PrecacheColor(Color.Red);
|
||||
@@ -63,15 +61,12 @@ namespace OpenRA.Graphics
|
||||
}
|
||||
|
||||
var g = glyphs[Pair.New(s, c)];
|
||||
renderer.RgbaSpriteRenderer.DrawSprite(g.Sprite,
|
||||
Game.Renderer.RgbaSpriteRenderer.DrawSprite(g.Sprite,
|
||||
new float2(
|
||||
(int)Math.Round(p.X + g.Offset.X, 0),
|
||||
p.Y + g.Offset.Y),
|
||||
"chrome");
|
||||
p.Y + g.Offset.Y));
|
||||
p.X += g.Advance;
|
||||
}
|
||||
|
||||
// r.Flush();
|
||||
}
|
||||
|
||||
public int2 Measure(string text)
|
||||
@@ -85,30 +80,40 @@ namespace OpenRA.Graphics
|
||||
GlyphInfo CreateGlyph(Pair<char,Color> c)
|
||||
{
|
||||
var index = FT.FT_Get_Char_Index(face, (uint)c.First);
|
||||
FT.FT_Load_Glyph(face, index, FT.FT_LOAD_RENDER);
|
||||
if (0 != FT.FT_Load_Glyph(face, index, FT.FT_LOAD_RENDER))
|
||||
throw new InvalidOperationException( "FT_Load_Glyph failed." );
|
||||
|
||||
var _face = (FT_FaceRec)Marshal.PtrToStructure(face, typeof(FT_FaceRec));
|
||||
var _glyph = (FT_GlyphSlotRec)Marshal.PtrToStructure(_face.glyph, typeof(FT_GlyphSlotRec));
|
||||
|
||||
var s = builder.Allocate(new Size(_glyph.metrics.width >> 6, _glyph.metrics.height >> 6));
|
||||
var s = builder.Allocate(
|
||||
new Size(_glyph.metrics.width.ToInt32() >> 6,
|
||||
_glyph.metrics.height.ToInt32() >> 6));
|
||||
|
||||
var g = new GlyphInfo
|
||||
{
|
||||
Sprite = s,
|
||||
Advance = _glyph.metrics.horiAdvance / 64f,
|
||||
Advance = _glyph.metrics.horiAdvance.ToInt32() / 64f,
|
||||
Offset = { X = _glyph.bitmap_left, Y = -_glyph.bitmap_top }
|
||||
};
|
||||
|
||||
unsafe
|
||||
{
|
||||
var p = (byte*)_glyph.bitmap.buffer;
|
||||
var dest = s.sheet.Data;
|
||||
var destStride = s.sheet.Size.Width * 4;
|
||||
|
||||
for (var j = 0; j < s.size.Y; j++)
|
||||
{
|
||||
for (var i = 0; i < s.size.X; i++)
|
||||
if (p[i] != 0)
|
||||
s.sheet.Bitmap.SetPixel(i + s.bounds.Left, j + s.bounds.Top,
|
||||
Color.FromArgb(p[i], c.Second.R, c.Second.G, c.Second.B));
|
||||
{
|
||||
var q = destStride * (j + s.bounds.Top) + 4 * (i + s.bounds.Left);
|
||||
dest[q] = c.Second.B;
|
||||
dest[q + 1] = c.Second.G;
|
||||
dest[q + 2] = c.Second.R;
|
||||
dest[q + 3] = p[i];
|
||||
}
|
||||
|
||||
p += _glyph.bitmap.pitch;
|
||||
}
|
||||
|
||||
@@ -12,28 +12,20 @@ using OpenRA.FileFormats.Graphics;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
class SpriteRenderer
|
||||
public class SpriteRenderer : Renderer.IBatchRenderer
|
||||
{
|
||||
IVertexBuffer<Vertex> vertexBuffer;
|
||||
IIndexBuffer indexBuffer;
|
||||
Renderer renderer;
|
||||
IShader shader;
|
||||
|
||||
const int spritesPerBatch = 1024;
|
||||
|
||||
Vertex[] vertices = new Vertex[4 * spritesPerBatch];
|
||||
ushort[] indices = new ushort[6 * spritesPerBatch];
|
||||
Vertex[] vertices = new Vertex[Renderer.TempBufferSize];
|
||||
ushort[] indices = new ushort[Renderer.TempBufferSize];
|
||||
Sheet currentSheet = null;
|
||||
int sprites = 0;
|
||||
int nv = 0, ni = 0;
|
||||
|
||||
public SpriteRenderer(Renderer renderer, IShader shader)
|
||||
{
|
||||
this.renderer = renderer;
|
||||
this.shader = shader;
|
||||
|
||||
vertexBuffer = renderer.Device.CreateVertexBuffer( vertices.Length );
|
||||
indexBuffer = renderer.Device.CreateIndexBuffer( indices.Length );
|
||||
}
|
||||
|
||||
public SpriteRenderer(Renderer renderer)
|
||||
@@ -41,14 +33,16 @@ namespace OpenRA.Graphics
|
||||
|
||||
public void Flush()
|
||||
{
|
||||
if (sprites > 0)
|
||||
if (ni > 0)
|
||||
{
|
||||
shader.SetValue( "DiffuseTexture", currentSheet.Texture );
|
||||
shader.Render(() =>
|
||||
{
|
||||
vertexBuffer.SetData(vertices);
|
||||
indexBuffer.SetData(indices);
|
||||
renderer.DrawBatch(vertexBuffer, indexBuffer,
|
||||
var vb = renderer.GetTempVertexBuffer();
|
||||
var ib = renderer.GetTempIndexBuffer();
|
||||
vb.SetData(vertices, nv);
|
||||
ib.SetData(indices, ni);
|
||||
renderer.DrawBatch(vb, ib,
|
||||
new Range<int>(0, nv),
|
||||
new Range<int>(0, ni),
|
||||
PrimitiveType.TriangleList,
|
||||
@@ -57,25 +51,46 @@ namespace OpenRA.Graphics
|
||||
|
||||
nv = 0; ni = 0;
|
||||
currentSheet = null;
|
||||
sprites = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawSprite(Sprite s, float2 location, string palette)
|
||||
|
||||
public void DrawSprite(Sprite s, float2 location, WorldRenderer wr, string palette)
|
||||
{
|
||||
DrawSprite(s, location, palette, s.size);
|
||||
DrawSprite(s, location, wr.GetPaletteIndex(palette), s.size);
|
||||
}
|
||||
|
||||
public void DrawSprite(Sprite s, float2 location, string palette, float2 size)
|
||||
|
||||
public void DrawSprite(Sprite s, float2 location, WorldRenderer wr, string palette, float2 size)
|
||||
{
|
||||
DrawSprite(s, location, wr.GetPaletteIndex(palette), size);
|
||||
}
|
||||
|
||||
public void DrawSprite(Sprite s, float2 location, int paletteIndex, float2 size)
|
||||
{
|
||||
Renderer.CurrentBatchRenderer = this;
|
||||
|
||||
if (s.sheet != currentSheet)
|
||||
Flush();
|
||||
|
||||
currentSheet = s.sheet;
|
||||
Util.FastCreateQuad(vertices, indices, location.ToInt2(), s, Game.world.WorldRenderer.GetPaletteIndex(palette), nv, ni, size);
|
||||
nv += 4; ni += 6;
|
||||
if (++sprites >= spritesPerBatch)
|
||||
if( nv + 4 > Renderer.TempBufferSize )
|
||||
Flush();
|
||||
if( ni + 6 > Renderer.TempBufferSize )
|
||||
Flush();
|
||||
|
||||
currentSheet = s.sheet;
|
||||
Util.FastCreateQuad(vertices, indices, location.ToInt2(), s, paletteIndex, nv, ni, size);
|
||||
nv += 4; ni += 6;
|
||||
}
|
||||
|
||||
|
||||
// For RGBASpriteRenderer, which doesn't use palettes
|
||||
public void DrawSprite(Sprite s, float2 location)
|
||||
{
|
||||
DrawSprite(s, location, 0, s.size);
|
||||
}
|
||||
|
||||
public void DrawSprite(Sprite s, float2 location, float2 size)
|
||||
{
|
||||
DrawSprite(s, location, 0, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,11 +13,10 @@ using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
static class SpriteSheetBuilder
|
||||
public static class SpriteSheetBuilder
|
||||
{
|
||||
public static void Initialize( TileSet tileset )
|
||||
{
|
||||
/* .tem: hack to allow incomplete theaters (interior) to work, falling back to temperate for the missing art */
|
||||
exts = tileset.Extensions;
|
||||
sprites = new Cache<string, Sprite[]>( LoadSprites );
|
||||
}
|
||||
@@ -28,7 +27,7 @@ namespace OpenRA.Graphics
|
||||
static Sprite[] LoadSprites(string filename)
|
||||
{
|
||||
var shp = new ShpReader(FileSystem.OpenWithExts(filename, exts));
|
||||
return shp.Select(a => SheetBuilder.SharedInstance.Add(a.Image, shp.Size)).ToArray();
|
||||
return shp.Select(a => Game.modData.SheetBuilder.Add(a.Image, shp.Size)).ToArray();
|
||||
}
|
||||
|
||||
public static Sprite[] LoadAllSprites(string filename) { return sprites[filename]; }
|
||||
|
||||
@@ -23,19 +23,16 @@ namespace OpenRA.Graphics
|
||||
Sheet terrainSheet;
|
||||
|
||||
World world;
|
||||
Renderer renderer;
|
||||
Map map;
|
||||
|
||||
public TerrainRenderer(World world, Renderer renderer, WorldRenderer wr)
|
||||
public TerrainRenderer(World world, WorldRenderer wr)
|
||||
{
|
||||
this.world = world;
|
||||
this.renderer = renderer;
|
||||
this.map = world.Map;
|
||||
|
||||
Size tileSize = new Size( Game.CellSize, Game.CellSize );
|
||||
|
||||
var tileMapping = new Cache<TileReference<ushort,byte>, Sprite>(
|
||||
x => SheetBuilder.SharedInstance.Add(world.TileSet.GetBytes(x), tileSize));
|
||||
x => Game.modData.SheetBuilder.Add(world.TileSet.GetBytes(x), tileSize));
|
||||
|
||||
Vertex[] vertices = new Vertex[4 * map.Height * map.Width];
|
||||
ushort[] indices = new ushort[6 * map.Height * map.Width];
|
||||
@@ -49,7 +46,7 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
Sprite tile = tileMapping[map.MapTiles[i, j]];
|
||||
// TODO: The zero below should explicitly refer to the terrain palette, but this code is called
|
||||
// before the palettes are created
|
||||
// before the palettes are created. Therefore assumes that "terrain" is the first palette to be defined
|
||||
Util.FastCreateQuad(vertices, indices, Game.CellSize * new float2(i, j), tile, 0, nv, ni, tile.size);
|
||||
nv += 4;
|
||||
ni += 6;
|
||||
@@ -58,21 +55,21 @@ namespace OpenRA.Graphics
|
||||
throw new InvalidOperationException("Terrain sprites span multiple sheets");
|
||||
}
|
||||
|
||||
vertexBuffer = renderer.Device.CreateVertexBuffer( vertices.Length );
|
||||
vertexBuffer.SetData( vertices );
|
||||
vertexBuffer = Game.Renderer.Device.CreateVertexBuffer( vertices.Length );
|
||||
vertexBuffer.SetData( vertices, nv );
|
||||
|
||||
indexBuffer = renderer.Device.CreateIndexBuffer( indices.Length );
|
||||
indexBuffer.SetData( indices );
|
||||
indexBuffer = Game.Renderer.Device.CreateIndexBuffer( indices.Length );
|
||||
indexBuffer.SetData( indices, ni );
|
||||
}
|
||||
|
||||
public void Draw( Viewport viewport )
|
||||
public void Draw( WorldRenderer wr, Viewport viewport )
|
||||
{
|
||||
int indicesPerRow = map.Width * 6;
|
||||
int verticesPerRow = map.Width * 4;
|
||||
|
||||
int visibleRows = (int)(viewport.Height / 24.0f + 2);
|
||||
int visibleRows = (int)(viewport.Height * 1f / Game.CellSize + 2);
|
||||
|
||||
int firstRow = (int)((viewport.Location.Y) / 24.0f - map.YOffset);
|
||||
int firstRow = (int)(viewport.Location.Y * 1f / Game.CellSize - map.YOffset);
|
||||
int lastRow = firstRow + visibleRows;
|
||||
|
||||
if (lastRow < 0 || firstRow > map.Height)
|
||||
@@ -93,15 +90,15 @@ namespace OpenRA.Graphics
|
||||
|
||||
if( lastRow < firstRow ) lastRow = firstRow;
|
||||
|
||||
renderer.SpriteShader.SetValue( "DiffuseTexture", terrainSheet.Texture );
|
||||
renderer.SpriteShader.Render(() =>
|
||||
renderer.DrawBatch(vertexBuffer, indexBuffer,
|
||||
Game.Renderer.SpriteShader.SetValue( "DiffuseTexture", terrainSheet.Texture );
|
||||
Game.Renderer.SpriteShader.Render(() =>
|
||||
Game.Renderer.DrawBatch(vertexBuffer, indexBuffer,
|
||||
new Range<int>(verticesPerRow * firstRow, verticesPerRow * lastRow),
|
||||
new Range<int>(indicesPerRow * firstRow, indicesPerRow * lastRow),
|
||||
PrimitiveType.TriangleList, renderer.SpriteShader));
|
||||
PrimitiveType.TriangleList, Game.Renderer.SpriteShader));
|
||||
|
||||
foreach (var r in world.WorldActor.traits.WithInterface<IRenderOverlay>())
|
||||
r.Render();
|
||||
foreach (var r in world.WorldActor.TraitsImplementing<IRenderOverlay>())
|
||||
r.Render( wr );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,42 +65,23 @@ namespace OpenRA.Graphics
|
||||
|
||||
public static void FastCopyIntoChannel(Sprite dest, byte[] src)
|
||||
{
|
||||
var bitmap = dest.sheet.Bitmap;
|
||||
BitmapData bits = null;
|
||||
uint[] channelMasks = { 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 };
|
||||
int[] shifts = { 16, 8, 0, 24 };
|
||||
var masks = new int[] { 2, 1, 0, 3 }; // hack, our channel order is nuts.
|
||||
var data = dest.sheet.Data;
|
||||
var srcStride = dest.bounds.Width;
|
||||
var destStride = dest.sheet.Size.Width * 4;
|
||||
var destOffset = destStride * dest.bounds.Top + dest.bounds.Left * 4 + masks[(int)dest.channel];
|
||||
var destSkip = destStride - 4 * srcStride;
|
||||
var height = dest.bounds.Height;
|
||||
|
||||
uint mask = channelMasks[(int)dest.channel];
|
||||
int shift = shifts[(int)dest.channel];
|
||||
|
||||
try
|
||||
var srcOffset = 0;
|
||||
for (var j = 0; j < height; j++)
|
||||
{
|
||||
bits = bitmap.LockBits(dest.bounds, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||
|
||||
int width = dest.bounds.Width;
|
||||
int height = dest.bounds.Height;
|
||||
|
||||
unsafe
|
||||
for (int i = 0; i < srcStride; i++, srcOffset++)
|
||||
{
|
||||
fixed (byte* srcbase = &src[0])
|
||||
{
|
||||
byte* s = srcbase;
|
||||
uint* t = (uint*)bits.Scan0.ToPointer();
|
||||
int stride = bits.Stride >> 2;
|
||||
|
||||
for (int j = 0; j < height; j++)
|
||||
{
|
||||
uint* p = t;
|
||||
for (int i = 0; i < width; i++, p++)
|
||||
*p = (*p & ~mask) | ((mask & ((uint)*s++) << shift));
|
||||
t += stride;
|
||||
}
|
||||
}
|
||||
data[destOffset] = src[srcOffset];
|
||||
destOffset += 4;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
bitmap.UnlockBits(bits);
|
||||
destOffset += destSkip;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,10 +93,30 @@ namespace OpenRA.Graphics
|
||||
LerpChannel(t, a.G, b.G),
|
||||
LerpChannel(t, a.B, b.B));
|
||||
}
|
||||
|
||||
public static int LerpARGBColor(float t, int c1, int c2)
|
||||
{
|
||||
int a = LerpChannel(t, (c1 >> 24) & 255, (c2 >> 24) & 255);
|
||||
int r = LerpChannel(t, (c1 >> 16) & 255, (c2 >> 16) & 255);
|
||||
int g = LerpChannel(t, (c1 >> 8) & 255, (c2 >> 8) & 255);
|
||||
int b = LerpChannel(t, c1 & 255, c2 & 255);
|
||||
return (a << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
|
||||
public static int LerpChannel(float t, int a, int b)
|
||||
{
|
||||
return (int)((1 - t) * a + t * b);
|
||||
}
|
||||
|
||||
public static int NextPowerOf2(int v)
|
||||
{
|
||||
--v;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
++v;
|
||||
return v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
157
OpenRA.Game/Graphics/Viewport.cs
Normal file → Executable file
157
OpenRA.Game/Graphics/Viewport.cs
Normal file → Executable file
@@ -11,75 +11,103 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.Support;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
interface IHandleInput
|
||||
public class Viewport
|
||||
{
|
||||
bool HandleInput(World world, MouseInput mi);
|
||||
}
|
||||
|
||||
class Viewport
|
||||
{
|
||||
readonly float2 screenSize;
|
||||
float2 scrollPosition;
|
||||
readonly int2 screenSize;
|
||||
int2 scrollPosition;
|
||||
readonly Renderer renderer;
|
||||
readonly int2 mapStart;
|
||||
readonly int2 mapEnd;
|
||||
|
||||
public float2 Location { get { return scrollPosition; } }
|
||||
|
||||
public int Width { get { return (int)screenSize.X; } }
|
||||
public int Height { get { return (int)screenSize.Y; } }
|
||||
public int Width { get { return screenSize.X; } }
|
||||
public int Height { get { return screenSize.Y; } }
|
||||
|
||||
SpriteRenderer cursorRenderer;
|
||||
int2 mousePos;
|
||||
float cursorFrame = 0f;
|
||||
|
||||
public static int TicksSinceLastMove = 0;
|
||||
public static int2 LastMousePos;
|
||||
|
||||
public void Scroll(float2 delta)
|
||||
{
|
||||
scrollPosition = scrollPosition + delta;
|
||||
this.Scroll(delta, false);
|
||||
}
|
||||
|
||||
public void Scroll(float2 delta, bool ignoreBorders)
|
||||
{
|
||||
var d = delta.ToInt2();
|
||||
var newScrollPosition = scrollPosition + d;
|
||||
|
||||
if(!ignoreBorders)
|
||||
newScrollPosition = this.NormalizeScrollPosition(newScrollPosition);
|
||||
|
||||
scrollPosition = newScrollPosition;
|
||||
}
|
||||
|
||||
private int2 NormalizeScrollPosition(int2 newScrollPosition)
|
||||
{
|
||||
var topLeftBorder = Game.CellSize* mapStart;
|
||||
var bottomRightBorder = Game.CellSize* mapEnd;
|
||||
|
||||
if(newScrollPosition.Y < topLeftBorder.Y - screenSize.Y/2)
|
||||
newScrollPosition.Y = topLeftBorder.Y - screenSize.Y/2;
|
||||
if(newScrollPosition.X < topLeftBorder.X - screenSize.X/2)
|
||||
newScrollPosition.X = topLeftBorder.X - screenSize.X/2;
|
||||
if(newScrollPosition.Y > bottomRightBorder.Y - screenSize.Y/2)
|
||||
newScrollPosition.Y = bottomRightBorder.Y - screenSize.Y/2;
|
||||
if(newScrollPosition.X > bottomRightBorder.X - screenSize.X/2)
|
||||
newScrollPosition.X = bottomRightBorder.X - screenSize.X/2;
|
||||
|
||||
return newScrollPosition;
|
||||
}
|
||||
|
||||
public ScrollDirection GetBlockedDirections()
|
||||
{
|
||||
int2 topLeftBorder = (Game.CellSize* mapStart);
|
||||
int2 bottomRightBorder = (Game.CellSize* mapEnd);
|
||||
|
||||
ScrollDirection blockedDirections = ScrollDirection.None;
|
||||
|
||||
if(scrollPosition.Y <= topLeftBorder.Y - screenSize.Y/2)
|
||||
blockedDirections = blockedDirections.Set(ScrollDirection.Up, true);
|
||||
if(scrollPosition.X <= topLeftBorder.X - screenSize.X/2)
|
||||
blockedDirections = blockedDirections.Set(ScrollDirection.Left, true);
|
||||
if(scrollPosition.Y >= bottomRightBorder.Y - screenSize.Y/2)
|
||||
blockedDirections = blockedDirections.Set(ScrollDirection.Down, true);
|
||||
if(scrollPosition.X >= bottomRightBorder.X - screenSize.X/2)
|
||||
blockedDirections = blockedDirections.Set(ScrollDirection.Right, true);
|
||||
|
||||
return blockedDirections;
|
||||
}
|
||||
|
||||
public IEnumerable<IHandleInput> regions { get { return new IHandleInput[] { Game.chrome, Game.controller }; } }
|
||||
|
||||
public Viewport(float2 screenSize, int2 mapStart, int2 mapEnd, Renderer renderer)
|
||||
public Viewport(int2 screenSize, int2 mapStart, int2 mapEnd, Renderer renderer)
|
||||
{
|
||||
this.screenSize = screenSize;
|
||||
this.renderer = renderer;
|
||||
cursorRenderer = renderer.SpriteRenderer;
|
||||
this.mapStart = mapStart;
|
||||
this.mapEnd = mapEnd;
|
||||
|
||||
this.scrollPosition = Game.CellSize* mapStart;
|
||||
}
|
||||
|
||||
public void DrawRegions( World world )
|
||||
public void DrawRegions( WorldRenderer wr, IInputHandler inputHandler )
|
||||
{
|
||||
Timer.Time( "DrawRegions start" );
|
||||
renderer.BeginFrame(scrollPosition);
|
||||
wr.Draw();
|
||||
|
||||
world.WorldRenderer.palette.Update(
|
||||
world.WorldActor.traits.WithInterface<IPaletteModifier>());
|
||||
Widget.DoDraw( wr );
|
||||
|
||||
float2 r1 = new float2(2, -2) / screenSize;
|
||||
float2 r2 = new float2(-1, 1);
|
||||
|
||||
renderer.BeginFrame(r1, r2, scrollPosition.ToInt2());
|
||||
world.WorldRenderer.Draw();
|
||||
Timer.Time( "worldRenderer: {0}" );
|
||||
|
||||
Game.chrome.Draw(world);
|
||||
Timer.Time( "widgets: {0}" );
|
||||
|
||||
var cursorName = Game.chrome.HitTest(mousePos) ? "default" : Game.controller.ChooseCursor( world );
|
||||
var cursorName = Widget.RootWidget.GetCursorOuter(Viewport.LastMousePos) ?? "default";
|
||||
var c = new Cursor(cursorName);
|
||||
cursorRenderer.DrawSprite(c.GetSprite((int)cursorFrame), mousePos + Location - c.GetHotspot(), "cursor");
|
||||
Timer.Time( "cursors: {0}" );
|
||||
c.Draw(wr, (int)cursorFrame, Viewport.LastMousePos + Location);
|
||||
|
||||
renderer.RgbaSpriteRenderer.Flush();
|
||||
renderer.SpriteRenderer.Flush();
|
||||
renderer.WorldSpriteRenderer.Flush();
|
||||
|
||||
renderer.EndFrame();
|
||||
Timer.Time( "endFrame: {0}" );
|
||||
renderer.EndFrame( inputHandler );
|
||||
}
|
||||
|
||||
public void Tick()
|
||||
@@ -87,31 +115,18 @@ namespace OpenRA.Graphics
|
||||
cursorFrame += 0.5f;
|
||||
}
|
||||
|
||||
IHandleInput dragRegion = null;
|
||||
public void DispatchMouseInput(World world, MouseInput mi)
|
||||
public float2 ViewToWorld(int2 loc)
|
||||
{
|
||||
if (mi.Event == MouseInputEvent.Move)
|
||||
mousePos = mi.Location;
|
||||
|
||||
if (dragRegion != null) {
|
||||
dragRegion.HandleInput( world, mi );
|
||||
if (mi.Event == MouseInputEvent.Up) dragRegion = null;
|
||||
return;
|
||||
}
|
||||
|
||||
dragRegion = regions.FirstOrDefault(r => r.HandleInput(world, mi));
|
||||
if (mi.Event != MouseInputEvent.Down)
|
||||
dragRegion = null;
|
||||
return (1f / Game.CellSize) * (loc.ToFloat2() + Location);
|
||||
}
|
||||
|
||||
public float2 ViewToWorld(MouseInput mi)
|
||||
{
|
||||
return (1 / 24.0f) * (new float2(mi.Location.X, mi.Location.Y) + Location);
|
||||
return ViewToWorld(mi.Location);
|
||||
}
|
||||
|
||||
public void Center(int2 loc)
|
||||
public void Center(float2 loc)
|
||||
{
|
||||
scrollPosition = (Game.CellSize*loc - .5f * new float2(Width, Height)).ToInt2();
|
||||
scrollPosition = this.NormalizeScrollPosition((Game.CellSize*loc - screenSize / 2).ToInt2());
|
||||
}
|
||||
|
||||
public void Center(IEnumerable<Actor> actors)
|
||||
@@ -122,20 +137,24 @@ namespace OpenRA.Graphics
|
||||
.Select(a => a.CenterLocation)
|
||||
.Aggregate((a, b) => a + b);
|
||||
|
||||
scrollPosition = (avgPos - .5f * new float2(Width, Height)).ToInt2();
|
||||
scrollPosition = this.NormalizeScrollPosition((avgPos.ToInt2() - screenSize / 2));
|
||||
}
|
||||
|
||||
public void GoToStartLocation( Player player )
|
||||
public Rectangle ShroudBounds( World world )
|
||||
{
|
||||
Center( player.World.Queries.OwnedBy[ player ].WithTrait<Selectable>().Select( a => a.Actor ) );
|
||||
var localPlayer = world.LocalPlayer;
|
||||
if( localPlayer == null ) return world.Map.Bounds;
|
||||
if( localPlayer.Shroud.Disabled ) return world.Map.Bounds;
|
||||
if( !localPlayer.Shroud.Bounds.HasValue ) return world.Map.Bounds;
|
||||
return Rectangle.Intersect( localPlayer.Shroud.Bounds.Value, world.Map.Bounds );
|
||||
}
|
||||
|
||||
public Rectangle? ShroudBounds()
|
||||
|
||||
public Rectangle ViewBounds()
|
||||
{
|
||||
var localPlayer = Game.world.LocalPlayer;
|
||||
if (localPlayer == null) return null;
|
||||
if (localPlayer.Shroud.Disabled) return null;
|
||||
return localPlayer.Shroud.Bounds;
|
||||
int2 boundary = new int2(1,1); // Add a curtain of cells around the viewport to account for rounding errors
|
||||
var tl = ViewToWorld(int2.Zero).ToInt2() - boundary;
|
||||
var br = ViewToWorld(new int2(Width, Height)).ToInt2() + boundary;
|
||||
return Rectangle.FromLTRB(tl.X, tl.Y, br.X, br.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,68 +19,32 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
public class WorldRenderer
|
||||
{
|
||||
readonly World world;
|
||||
public readonly World world;
|
||||
internal readonly TerrainRenderer terrainRenderer;
|
||||
internal readonly SpriteRenderer spriteRenderer;
|
||||
internal readonly LineRenderer lineRenderer;
|
||||
internal readonly UiOverlay uiOverlay;
|
||||
internal readonly Renderer renderer;
|
||||
public readonly UiOverlay uiOverlay;
|
||||
internal readonly HardwarePalette palette;
|
||||
|
||||
internal WorldRenderer(World world, Renderer renderer)
|
||||
internal WorldRenderer(World world)
|
||||
{
|
||||
this.world = world;
|
||||
this.renderer = renderer;
|
||||
|
||||
terrainRenderer = new TerrainRenderer(world, renderer, this);
|
||||
spriteRenderer = renderer.SpriteRenderer;
|
||||
lineRenderer = new LineRenderer(renderer);
|
||||
uiOverlay = new UiOverlay(spriteRenderer);
|
||||
palette = new HardwarePalette(renderer, world.Map);
|
||||
}
|
||||
|
||||
public void DrawLine(float2 start, float2 end, Color startColor, Color endColor)
|
||||
{
|
||||
lineRenderer.DrawLine(start,end,startColor,endColor);
|
||||
}
|
||||
|
||||
public int GetPaletteIndex(string name)
|
||||
{
|
||||
return palette.GetPaletteIndex(name);
|
||||
}
|
||||
terrainRenderer = new TerrainRenderer(world, this);
|
||||
uiOverlay = new UiOverlay();
|
||||
palette = new HardwarePalette(world.Map);
|
||||
|
||||
public Palette GetPalette(string name)
|
||||
{
|
||||
return palette.GetPalette(name);
|
||||
foreach( var pal in world.traitDict.ActorsWithTraitMultiple<IPalette>( world ) )
|
||||
pal.Trait.InitPalette( this );
|
||||
}
|
||||
|
||||
public void AddPalette(string name, Palette pal)
|
||||
{
|
||||
System.Console.WriteLine("Registering Palette "+name);
|
||||
|
||||
palette.AddPalette(name, pal);
|
||||
}
|
||||
public int GetPaletteIndex(string name) { return palette.GetPaletteIndex(name); }
|
||||
public Palette GetPalette(string name) { return palette.GetPalette(name); }
|
||||
public void AddPalette(string name, Palette pal) { palette.AddPalette(name, pal); }
|
||||
|
||||
public void UpdatePalette(string name, Palette pal)
|
||||
{
|
||||
palette.UpdatePalette(name, pal);
|
||||
}
|
||||
|
||||
void DrawSpriteList(IEnumerable<Renderable> images)
|
||||
{
|
||||
foreach (var image in images)
|
||||
spriteRenderer.DrawSprite(image.Sprite, image.Pos, image.Palette);
|
||||
}
|
||||
|
||||
class SpriteComparer : IComparer<Renderable>
|
||||
{
|
||||
public int Compare(Renderable x, Renderable y)
|
||||
{
|
||||
var result = x.ZOffset.CompareTo(y.ZOffset);
|
||||
if (result == 0)
|
||||
result = x.Pos.Y.CompareTo(y.Pos.Y);
|
||||
|
||||
return result;
|
||||
return (x.Z + x.ZOffset).CompareTo(y.Z + y.ZOffset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,8 +70,7 @@ namespace OpenRA.Graphics
|
||||
return new Rectangle(0, 0, Game.viewport.Width, Game.viewport.Height);
|
||||
}
|
||||
|
||||
Renderable[] worldSprites = { };
|
||||
public void Tick()
|
||||
IEnumerable<Renderable> SpritesToRender()
|
||||
{
|
||||
var bounds = GetBoundsRect();
|
||||
var comparer = new SpriteComparer();
|
||||
@@ -123,38 +86,37 @@ namespace OpenRA.Graphics
|
||||
|
||||
var effects = world.Effects.SelectMany(e => e.Render());
|
||||
|
||||
worldSprites = renderables.Concat(effects).ToArray();
|
||||
return renderables.Concat(effects);
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
RefreshPalette();
|
||||
var bounds = GetBoundsRect();
|
||||
renderer.Device.EnableScissor(bounds.Left, bounds.Top, bounds.Width, bounds.Height);
|
||||
Game.Renderer.EnableScissor(bounds.Left, bounds.Top, bounds.Width, bounds.Height);
|
||||
|
||||
terrainRenderer.Draw(Game.viewport);
|
||||
terrainRenderer.Draw(this, Game.viewport);
|
||||
|
||||
DrawSpriteList(worldSprites);
|
||||
uiOverlay.Draw(world);
|
||||
spriteRenderer.Flush();
|
||||
DrawBandBox();
|
||||
if (world.OrderGenerator != null)
|
||||
world.OrderGenerator.RenderBeforeWorld(this, world);
|
||||
|
||||
foreach (var image in SpritesToRender() )
|
||||
image.Sprite.DrawAt(image.Pos, this.GetPaletteIndex(image.Palette), image.Scale);
|
||||
uiOverlay.Draw(this, world);
|
||||
|
||||
if (Game.controller.orderGenerator != null)
|
||||
Game.controller.orderGenerator.Render(world);
|
||||
// added for contrails
|
||||
foreach (var a in world.Actors)
|
||||
if (!a.Destroyed)
|
||||
foreach (var t in a.TraitsImplementing<IPostRender>())
|
||||
t.RenderAfterWorld(this, a);
|
||||
|
||||
if (world.OrderGenerator != null)
|
||||
world.OrderGenerator.RenderAfterWorld(this, world);
|
||||
|
||||
if (world.LocalPlayer != null)
|
||||
world.LocalPlayer.Shroud.Draw(spriteRenderer);
|
||||
world.LocalPlayer.Shroud.Draw( this );
|
||||
|
||||
spriteRenderer.Flush();
|
||||
|
||||
renderer.Device.DisableScissor();
|
||||
|
||||
if (Game.Settings.IndexDebug)
|
||||
{
|
||||
bounds.Offset((int)Game.viewport.Location.X, (int)Game.viewport.Location.Y);
|
||||
DrawBins(bounds);
|
||||
}
|
||||
|
||||
lineRenderer.Flush();
|
||||
Game.Renderer.DisableScissor();
|
||||
}
|
||||
|
||||
void DrawBox(RectangleF r, Color color)
|
||||
@@ -162,10 +124,10 @@ namespace OpenRA.Graphics
|
||||
var a = new float2(r.Left, r.Top);
|
||||
var b = new float2(r.Right - a.X, 0);
|
||||
var c = new float2(0, r.Bottom - a.Y);
|
||||
lineRenderer.DrawLine(a, a + b, color, color);
|
||||
lineRenderer.DrawLine(a + b, a + b + c, color, color);
|
||||
lineRenderer.DrawLine(a + b + c, a + c, color, color);
|
||||
lineRenderer.DrawLine(a, a + c, color, color);
|
||||
Game.Renderer.LineRenderer.DrawLine(a, a + b, color, color);
|
||||
Game.Renderer.LineRenderer.DrawLine(a + b, a + b + c, color, color);
|
||||
Game.Renderer.LineRenderer.DrawLine(a + b + c, a + c, color, color);
|
||||
Game.Renderer.LineRenderer.DrawLine(a, a + c, color, color);
|
||||
}
|
||||
|
||||
void DrawBins(RectangleF bounds)
|
||||
@@ -177,30 +139,12 @@ namespace OpenRA.Graphics
|
||||
for (var j = 0; j < world.Map.MapSize.Y;
|
||||
j += world.WorldActor.Info.Traits.Get<SpatialBinsInfo>().BinSize)
|
||||
{
|
||||
lineRenderer.DrawLine(new float2(0, j * 24), new float2(world.Map.MapSize.X * 24, j * 24), Color.Black, Color.Black);
|
||||
lineRenderer.DrawLine(new float2(j * 24, 0), new float2(j * 24, world.Map.MapSize.Y * 24), Color.Black, Color.Black);
|
||||
Game.Renderer.LineRenderer.DrawLine(new float2(0, j * Game.CellSize), new float2(world.Map.MapSize.X * Game.CellSize, j * Game.CellSize), Color.Black, Color.Black);
|
||||
Game.Renderer.LineRenderer.DrawLine(new float2(j * Game.CellSize, 0), new float2(j * Game.CellSize, world.Map.MapSize.Y * Game.CellSize), Color.Black, Color.Black);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawBandBox()
|
||||
{
|
||||
var selbox = Game.controller.SelectionBox;
|
||||
if (selbox == null) return;
|
||||
|
||||
var a = selbox.Value.First;
|
||||
var b = new float2(selbox.Value.Second.X - a.X, 0);
|
||||
var c = new float2(0, selbox.Value.Second.Y - a.Y);
|
||||
|
||||
lineRenderer.DrawLine(a, a + b, Color.White, Color.White);
|
||||
lineRenderer.DrawLine(a + b, a + b + c, Color.White, Color.White);
|
||||
lineRenderer.DrawLine(a + b + c, a + c, Color.White, Color.White);
|
||||
lineRenderer.DrawLine(a, a + c, Color.White, Color.White);
|
||||
|
||||
foreach (var u in world.SelectActorsInBox(selbox.Value.First, selbox.Value.Second))
|
||||
DrawSelectionBox(u, Color.Yellow, false);
|
||||
}
|
||||
|
||||
public void DrawSelectionBox(Actor selectedUnit, Color c, bool drawHealthBar)
|
||||
public void DrawSelectionBox(Actor selectedUnit, Color c)
|
||||
{
|
||||
var bounds = selectedUnit.GetBounds(true);
|
||||
|
||||
@@ -209,145 +153,16 @@ namespace OpenRA.Graphics
|
||||
var xY = new float2(bounds.Left, bounds.Bottom);
|
||||
var XY = new float2(bounds.Right, bounds.Bottom);
|
||||
|
||||
lineRenderer.DrawLine(xy, xy + new float2(4, 0), c, c);
|
||||
lineRenderer.DrawLine(xy, xy + new float2(0, 4), c, c);
|
||||
lineRenderer.DrawLine(Xy, Xy + new float2(-4, 0), c, c);
|
||||
lineRenderer.DrawLine(Xy, Xy + new float2(0, 4), c, c);
|
||||
Game.Renderer.LineRenderer.DrawLine(xy, xy + new float2(4, 0), c, c);
|
||||
Game.Renderer.LineRenderer.DrawLine(xy, xy + new float2(0, 4), c, c);
|
||||
Game.Renderer.LineRenderer.DrawLine(Xy, Xy + new float2(-4, 0), c, c);
|
||||
Game.Renderer.LineRenderer.DrawLine(Xy, Xy + new float2(0, 4), c, c);
|
||||
|
||||
lineRenderer.DrawLine(xY, xY + new float2(4, 0), c, c);
|
||||
lineRenderer.DrawLine(xY, xY + new float2(0, -4), c, c);
|
||||
lineRenderer.DrawLine(XY, XY + new float2(-4, 0), c, c);
|
||||
lineRenderer.DrawLine(XY, XY + new float2(0, -4), c, c);
|
||||
|
||||
if (drawHealthBar)
|
||||
{
|
||||
DrawHealthBar(selectedUnit, xy, Xy);
|
||||
DrawControlGroup(selectedUnit, xy);
|
||||
|
||||
// Only display pips and tags to the owner
|
||||
if (selectedUnit.Owner == world.LocalPlayer)
|
||||
{
|
||||
DrawPips(selectedUnit, xY);
|
||||
DrawTags(selectedUnit, new float2(.5f * (bounds.Left + bounds.Right ), xy.Y));
|
||||
Game.Renderer.LineRenderer.DrawLine(xY, xY + new float2(4, 0), c, c);
|
||||
Game.Renderer.LineRenderer.DrawLine(xY, xY + new float2(0, -4), c, c);
|
||||
Game.Renderer.LineRenderer.DrawLine(XY, XY + new float2(-4, 0), c, c);
|
||||
Game.Renderer.LineRenderer.DrawLine(XY, XY + new float2(0, -4), c, c);
|
||||
}
|
||||
}
|
||||
|
||||
if (Game.Settings.PathDebug)
|
||||
DrawUnitPath(selectedUnit);
|
||||
}
|
||||
|
||||
void DrawUnitPath(Actor selectedUnit)
|
||||
{
|
||||
var mobile = selectedUnit.traits.WithInterface<IMove>().FirstOrDefault();
|
||||
if (mobile != null)
|
||||
{
|
||||
var path = mobile.GetCurrentPath(selectedUnit);
|
||||
var start = selectedUnit.CenterLocation;
|
||||
|
||||
var c = Color.Green;
|
||||
|
||||
foreach (var step in path)
|
||||
{
|
||||
lineRenderer.DrawLine(step + new float2(-1, -1), step + new float2(-1, 1), c, c);
|
||||
lineRenderer.DrawLine(step + new float2(-1, 1), step + new float2(1, 1), c, c);
|
||||
lineRenderer.DrawLine(step + new float2(1, 1), step + new float2(1, -1), c, c);
|
||||
lineRenderer.DrawLine(step + new float2(1, -1), step + new float2(-1, -1), c, c);
|
||||
lineRenderer.DrawLine(start, step, c, c);
|
||||
start = step;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawHealthBar(Actor selectedUnit, float2 xy, float2 Xy)
|
||||
{
|
||||
var c = Color.Gray;
|
||||
lineRenderer.DrawLine(xy + new float2(0, -2), xy + new float2(0, -4), c, c);
|
||||
lineRenderer.DrawLine(Xy + new float2(0, -2), Xy + new float2(0, -4), c, c);
|
||||
|
||||
var healthAmount = (float)selectedUnit.Health / selectedUnit.Info.Traits.Get<OwnedActorInfo>().HP;
|
||||
var healthColor = (healthAmount < selectedUnit.World.Defaults.ConditionRed) ? Color.Red
|
||||
: (healthAmount < selectedUnit.World.Defaults.ConditionYellow) ? Color.Yellow
|
||||
: Color.LimeGreen;
|
||||
|
||||
var healthColor2 = Color.FromArgb(
|
||||
255,
|
||||
healthColor.R / 2,
|
||||
healthColor.G / 2,
|
||||
healthColor.B / 2);
|
||||
|
||||
var z = float2.Lerp(xy, Xy, healthAmount);
|
||||
|
||||
lineRenderer.DrawLine(z + new float2(0, -4), Xy + new float2(0, -4), c, c);
|
||||
lineRenderer.DrawLine(z + new float2(0, -2), Xy + new float2(0, -2), c, c);
|
||||
|
||||
lineRenderer.DrawLine(xy + new float2(0, -3), z + new float2(0, -3), healthColor, healthColor);
|
||||
lineRenderer.DrawLine(xy + new float2(0, -2), z + new float2(0, -2), healthColor2, healthColor2);
|
||||
lineRenderer.DrawLine(xy + new float2(0, -4), z + new float2(0, -4), healthColor2, healthColor2);
|
||||
}
|
||||
|
||||
// depends on the order of pips in TraitsInterfaces.cs!
|
||||
static readonly string[] pipStrings = { "pip-empty", "pip-green", "pip-yellow", "pip-red", "pip-gray" };
|
||||
static readonly string[] tagStrings = { "", "tag-fake", "tag-primary" };
|
||||
|
||||
void DrawControlGroup(Actor selectedUnit, float2 basePosition)
|
||||
{
|
||||
var group = Game.controller.selection.GetControlGroupForActor(selectedUnit);
|
||||
if (group == null) return;
|
||||
|
||||
var pipImages = new Animation("pips");
|
||||
pipImages.PlayFetchIndex("groups", () => (int)group);
|
||||
pipImages.Tick();
|
||||
spriteRenderer.DrawSprite(pipImages.Image, basePosition + new float2(-8, 1), "chrome");
|
||||
}
|
||||
|
||||
void DrawPips(Actor selectedUnit, float2 basePosition)
|
||||
{
|
||||
// If a mod wants to implement a unit with multiple pip sources, then they are placed on multiple rows
|
||||
var pipxyBase = basePosition + new float2(-12, -7); // Correct for the offset in the shp file
|
||||
var pipxyOffset = new float2(0, 0); // Correct for offset due to multiple columns/rows
|
||||
|
||||
foreach (var pips in selectedUnit.traits.WithInterface<IPips>())
|
||||
{
|
||||
foreach (var pip in pips.GetPips(selectedUnit))
|
||||
{
|
||||
if (pipxyOffset.X+5 > selectedUnit.GetBounds(false).Width)
|
||||
{
|
||||
pipxyOffset.X = 0;
|
||||
pipxyOffset.Y -= 4;
|
||||
}
|
||||
var pipImages = new Animation("pips");
|
||||
pipImages.PlayRepeating(pipStrings[(int)pip]);
|
||||
spriteRenderer.DrawSprite(pipImages.Image, pipxyBase + pipxyOffset, "chrome");
|
||||
pipxyOffset += new float2(4, 0);
|
||||
}
|
||||
// Increment row
|
||||
pipxyOffset.X = 0;
|
||||
pipxyOffset.Y -= 5;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawTags(Actor selectedUnit, float2 basePosition)
|
||||
{
|
||||
// If a mod wants to implement a unit with multiple tags, then they are placed on multiple rows
|
||||
var tagxyBase = basePosition + new float2(-16, 2); // Correct for the offset in the shp file
|
||||
var tagxyOffset = new float2(0, 0); // Correct for offset due to multiple rows
|
||||
|
||||
foreach (var tags in selectedUnit.traits.WithInterface<ITags>())
|
||||
{
|
||||
foreach (var tag in tags.GetTags())
|
||||
{
|
||||
if (tag == TagType.None)
|
||||
continue;
|
||||
|
||||
var tagImages = new Animation("pips");
|
||||
tagImages.PlayRepeating(tagStrings[(int)tag]);
|
||||
spriteRenderer.DrawSprite(tagImages.Image, tagxyBase + tagxyOffset, "chrome");
|
||||
|
||||
// Increment row
|
||||
tagxyOffset.Y += 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawLocus(Color c, int2[] cells)
|
||||
{
|
||||
@@ -355,16 +170,16 @@ namespace OpenRA.Graphics
|
||||
foreach (var t in dict.Keys)
|
||||
{
|
||||
if (!dict.ContainsKey(t + new int2(-1, 0)))
|
||||
lineRenderer.DrawLine(Game.CellSize * t, Game.CellSize * (t + new int2(0, 1)),
|
||||
Game.Renderer.LineRenderer.DrawLine(Game.CellSize * t, Game.CellSize * (t + new int2(0, 1)),
|
||||
c, c);
|
||||
if (!dict.ContainsKey(t + new int2(1, 0)))
|
||||
lineRenderer.DrawLine(Game.CellSize * (t + new int2(1, 0)), Game.CellSize * (t + new int2(1, 1)),
|
||||
Game.Renderer.LineRenderer.DrawLine(Game.CellSize * (t + new int2(1, 0)), Game.CellSize * (t + new int2(1, 1)),
|
||||
c, c);
|
||||
if (!dict.ContainsKey(t + new int2(0, -1)))
|
||||
lineRenderer.DrawLine(Game.CellSize * t, Game.CellSize * (t + new int2(1, 0)),
|
||||
Game.Renderer.LineRenderer.DrawLine(Game.CellSize * t, Game.CellSize * (t + new int2(1, 0)),
|
||||
c, c);
|
||||
if (!dict.ContainsKey(t + new int2(0, 1)))
|
||||
lineRenderer.DrawLine(Game.CellSize * (t + new int2(0, 1)), Game.CellSize * (t + new int2(1, 1)),
|
||||
Game.Renderer.LineRenderer.DrawLine(Game.CellSize * (t + new int2(0, 1)), Game.CellSize * (t + new int2(1, 1)),
|
||||
c, c);
|
||||
}
|
||||
}
|
||||
@@ -374,10 +189,15 @@ namespace OpenRA.Graphics
|
||||
var prev = location + Game.CellSize * range * float2.FromAngle(0);
|
||||
for (var i = 1; i <= 32; i++)
|
||||
{
|
||||
var pos = location + Game.CellSize * range * float2.FromAngle((float)(Math.PI * i) / 8);
|
||||
lineRenderer.DrawLine(prev, pos, c, c);
|
||||
var pos = location + Game.CellSize * range * float2.FromAngle((float)(Math.PI * i) / 16);
|
||||
Game.Renderer.LineRenderer.DrawLine(prev, pos, c, c);
|
||||
prev = pos;
|
||||
}
|
||||
}
|
||||
|
||||
public void RefreshPalette()
|
||||
{
|
||||
palette.Update( world.WorldActor.TraitsImplementing<IPaletteModifier>() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
52
OpenRA.Game/InputHandler.cs
Executable file
52
OpenRA.Game/InputHandler.cs
Executable file
@@ -0,0 +1,52 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using OpenRA.Widgets;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public class NullInputHandler : IInputHandler
|
||||
{
|
||||
// ignore all input
|
||||
public void ModifierKeys( Modifiers mods ) { }
|
||||
public void OnKeyInput( KeyInput input ) { }
|
||||
public void OnMouseInput( MouseInput input ) { }
|
||||
}
|
||||
|
||||
public class DefaultInputHandler : IInputHandler
|
||||
{
|
||||
readonly World world;
|
||||
public DefaultInputHandler( World world )
|
||||
{
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
public void ModifierKeys( Modifiers mods )
|
||||
{
|
||||
Game.HandleModifierKeys( mods );
|
||||
}
|
||||
|
||||
public void OnKeyInput( KeyInput input )
|
||||
{
|
||||
Sync.CheckSyncUnchanged( world, () =>
|
||||
{
|
||||
Widget.HandleKeyPress( input );
|
||||
} );
|
||||
}
|
||||
|
||||
public void OnMouseInput( MouseInput input )
|
||||
{
|
||||
Sync.CheckSyncUnchanged( world, () =>
|
||||
{
|
||||
Widget.HandleInput( input );
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,68 +15,63 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
namespace OpenRA
|
||||
{
|
||||
public class Map
|
||||
public class Map : MapStub
|
||||
{
|
||||
public IFolder Package;
|
||||
public string Uid;
|
||||
|
||||
// Yaml map data
|
||||
public bool Selectable = true;
|
||||
public int MapFormat;
|
||||
public string Title;
|
||||
public string Description;
|
||||
public string Author;
|
||||
public int PlayerCount;
|
||||
public string Tileset;
|
||||
[FieldLoader.Load] public int MapFormat;
|
||||
|
||||
public Dictionary<string, PlayerReference> Players = new Dictionary<string, PlayerReference>();
|
||||
public Dictionary<string, ActorReference> Actors = new Dictionary<string, ActorReference>();
|
||||
public List<SmudgeReference> Smudges = new List<SmudgeReference>();
|
||||
public Dictionary<string, int2> Waypoints = new Dictionary<string, int2>();
|
||||
|
||||
// Rules overrides
|
||||
public Dictionary<string, MiniYaml> Rules = new Dictionary<string, MiniYaml>();
|
||||
public Dictionary<string, MiniYaml> Weapons = new Dictionary<string, MiniYaml>();
|
||||
public Dictionary<string, MiniYaml> Voices = new Dictionary<string, MiniYaml>();
|
||||
public Dictionary<string, MiniYaml> Music = new Dictionary<string, MiniYaml>();
|
||||
public Dictionary<string, MiniYaml> Terrain = new Dictionary<string, MiniYaml>();
|
||||
|
||||
|
||||
// Rules overrides
|
||||
public List<MiniYamlNode> Rules = new List<MiniYamlNode>();
|
||||
|
||||
// Sequences overrides
|
||||
public List<MiniYamlNode> Sequences = new List<MiniYamlNode>();
|
||||
|
||||
// Weapon overrides
|
||||
public List<MiniYamlNode> Weapons = new List<MiniYamlNode>();
|
||||
|
||||
// Voices overrides
|
||||
public List<MiniYamlNode> Voices = new List<MiniYamlNode>();
|
||||
|
||||
// Binary map data
|
||||
public byte TileFormat = 1;
|
||||
public int2 MapSize;
|
||||
[FieldLoader.Load] public int2 MapSize;
|
||||
|
||||
public int2 TopLeft;
|
||||
public int2 BottomRight;
|
||||
|
||||
public TileReference<ushort, byte>[,] MapTiles;
|
||||
public TileReference<byte, byte>[,] MapResources;
|
||||
|
||||
public string [,] CustomTerrain;
|
||||
|
||||
// Temporary compat hacks
|
||||
public int XOffset { get { return TopLeft.X; } }
|
||||
public int YOffset { get { return TopLeft.Y; } }
|
||||
public int Width { get { return BottomRight.X - TopLeft.X; } }
|
||||
public int Height { get { return BottomRight.Y - TopLeft.Y; } }
|
||||
public string Theater { get { return Tileset; } }
|
||||
public IEnumerable<int2> SpawnPoints { get { return Waypoints.Select(kv => kv.Value); } }
|
||||
public Rectangle Bounds { get { return Rectangle.FromLTRB(TopLeft.X, TopLeft.Y, BottomRight.X, BottomRight.Y); } }
|
||||
|
||||
static List<string> SimpleFields = new List<string>() {
|
||||
"Selectable", "MapFormat", "Title", "Description", "Author", "PlayerCount", "Tileset", "MapSize", "TopLeft", "BottomRight"
|
||||
};
|
||||
|
||||
public Map()
|
||||
{
|
||||
// Do nothing; not a valid map (editor hack)
|
||||
}
|
||||
|
||||
public Map(string tileset)
|
||||
{
|
||||
MapSize = new int2(1, 1);
|
||||
Tileset = tileset;
|
||||
MapResources = new TileReference<byte, byte>[1, 1];
|
||||
MapTiles = new TileReference<ushort, byte>[1, 1]
|
||||
{ { new TileReference<ushort, byte> {
|
||||
type = (ushort)0xffffu,
|
||||
image = (byte)0xffu,
|
||||
index = (byte)0xffu } } };
|
||||
|
||||
var tile = OpenRA.Rules.TileSets[Tileset].Templates.First();
|
||||
MapTiles = new TileReference<ushort, byte>[1, 1]
|
||||
{ { new TileReference<ushort, byte> {
|
||||
type = tile.Key,
|
||||
image = (byte)(tile.Value.PickAny ? 0xffu : 0),
|
||||
index = (byte)(tile.Value.PickAny ? 0xffu : 0) } } };
|
||||
|
||||
PlayerCount = 0;
|
||||
TopLeft = new int2(0, 0);
|
||||
@@ -87,58 +82,102 @@ namespace OpenRA.FileFormats
|
||||
Author = "Your name here";
|
||||
}
|
||||
|
||||
public Map(IFolder package)
|
||||
class Format2ActorReference
|
||||
{
|
||||
Package = package;
|
||||
var yaml = MiniYaml.FromStream(Package.GetContent("map.yaml"));
|
||||
public string Id = null;
|
||||
public string Type = null;
|
||||
public int2 Location = int2.Zero;
|
||||
public string Owner = null;
|
||||
}
|
||||
|
||||
public Map(MapStub stub) : this(stub.Container) {}
|
||||
public Map(IFolder package)
|
||||
: base(package)
|
||||
{
|
||||
var yaml = new MiniYaml( null, MiniYaml.FromStream( Container.GetContent( "map.yaml" ) ) );
|
||||
|
||||
// 'Simple' metadata
|
||||
FieldLoader.LoadFields(this, yaml, SimpleFields);
|
||||
FieldLoader.Load( this, yaml );
|
||||
|
||||
// Waypoints
|
||||
foreach (var wp in yaml["Waypoints"].Nodes)
|
||||
|
||||
// Players & Actors -- this has changed several times.
|
||||
// - Be backwards compatible wherever possible.
|
||||
// - Loading a map then saving it out upgrades to latest.
|
||||
// Minimum criteria for dropping a format:
|
||||
// - There are no maps of this format left in tree
|
||||
|
||||
switch (MapFormat)
|
||||
{
|
||||
string[] loc = wp.Value.Value.Split(',');
|
||||
Waypoints.Add(wp.Key, new int2(int.Parse(loc[0]), int.Parse(loc[1])));
|
||||
}
|
||||
|
||||
// Players
|
||||
if (MapFormat == 1)
|
||||
{
|
||||
Players.Add("Neutral", new PlayerReference("Neutral", "allies", true, true));
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var kv in yaml["Players"].Nodes)
|
||||
{
|
||||
var player = new PlayerReference(kv.Value);
|
||||
Players.Add(player.Name, player);
|
||||
}
|
||||
}
|
||||
|
||||
// Actors
|
||||
if (MapFormat == 1)
|
||||
{
|
||||
int actors = 0;
|
||||
foreach (var kv in yaml["Actors"].Nodes)
|
||||
{
|
||||
string[] vals = kv.Value.Value.Split(' ');
|
||||
string[] loc = vals[2].Split(',');
|
||||
var a = new ActorReference("Actor"+actors++, vals[0], new int2(int.Parse(loc[0]), int.Parse(loc[1])), "Neutral");
|
||||
Actors.Add(a.Id, a);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var kv in yaml["Actors"].Nodes)
|
||||
{
|
||||
var a = new ActorReference(kv.Value);
|
||||
Actors.Add(a.Id, a);
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
Players.Add("Neutral", new PlayerReference("Neutral", "allies", true, true));
|
||||
|
||||
int actors = 0;
|
||||
foreach (var kv in yaml.NodesDict["Actors"].NodesDict)
|
||||
{
|
||||
string[] vals = kv.Value.Value.Split(' ');
|
||||
string[] loc = vals[2].Split(',');
|
||||
Actors.Add("Actor" + actors++, new ActorReference(vals[0])
|
||||
{
|
||||
new LocationInit( new int2( int.Parse( loc[ 0 ] ), int.Parse( loc[ 1 ] ) ) ),
|
||||
new OwnerInit( "Neutral" ),
|
||||
});
|
||||
}
|
||||
} break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
foreach (var kv in yaml.NodesDict["Players"].NodesDict)
|
||||
{
|
||||
var player = new PlayerReference(kv.Value);
|
||||
Players.Add(player.Name, player);
|
||||
}
|
||||
|
||||
foreach (var kv in yaml.NodesDict["Actors"].NodesDict)
|
||||
{
|
||||
var oldActorReference = FieldLoader.Load<Format2ActorReference>(kv.Value);
|
||||
Actors.Add(oldActorReference.Id, new ActorReference(oldActorReference.Type)
|
||||
{
|
||||
new LocationInit( oldActorReference.Location ),
|
||||
new OwnerInit( oldActorReference.Owner )
|
||||
});
|
||||
}
|
||||
} break;
|
||||
|
||||
case 3:
|
||||
{
|
||||
foreach (var kv in yaml.NodesDict["Players"].NodesDict)
|
||||
{
|
||||
var player = new PlayerReference(kv.Value);
|
||||
Players.Add(player.Name, player);
|
||||
}
|
||||
|
||||
foreach (var kv in yaml.NodesDict["Actors"].NodesDict)
|
||||
Actors.Add(kv.Key, new ActorReference(kv.Value.Value, kv.Value.NodesDict));
|
||||
} break;
|
||||
|
||||
default:
|
||||
throw new InvalidDataException("Map format {0} is not supported.".F(MapFormat));
|
||||
}
|
||||
|
||||
/* hack: make some slots. */
|
||||
if (!Players.Any(p => p.Value.Playable))
|
||||
{
|
||||
for (int index = 0; index < Waypoints.Count; index++)
|
||||
{
|
||||
var p = new PlayerReference
|
||||
{
|
||||
Name = "Multi{0}".F(index),
|
||||
Race = "Random",
|
||||
Playable = true,
|
||||
DefaultStartingUnits = true
|
||||
};
|
||||
Players.Add(p.Name, p);
|
||||
}
|
||||
}
|
||||
|
||||
// Smudges
|
||||
foreach (var kv in yaml["Smudges"].Nodes)
|
||||
foreach (var kv in yaml.NodesDict["Smudges"].NodesDict)
|
||||
{
|
||||
string[] vals = kv.Key.Split(' ');
|
||||
string[] loc = vals[1].Split(',');
|
||||
@@ -146,37 +185,51 @@ namespace OpenRA.FileFormats
|
||||
}
|
||||
|
||||
// Rules
|
||||
Rules = yaml["Rules"].Nodes;
|
||||
Rules = yaml.NodesDict["Rules"].Nodes;
|
||||
|
||||
LoadUid();
|
||||
// Sequences
|
||||
Sequences = (yaml.NodesDict.ContainsKey("Sequences")) ? yaml.NodesDict["Sequences"].Nodes : new List<MiniYamlNode>();
|
||||
|
||||
// Weapons
|
||||
Weapons = (yaml.NodesDict.ContainsKey("Weapons")) ? yaml.NodesDict["Weapons"].Nodes : new List<MiniYamlNode>();
|
||||
|
||||
// Voices
|
||||
Voices = (yaml.NodesDict.ContainsKey("Voices")) ? yaml.NodesDict["Voices"].Nodes : new List<MiniYamlNode>();
|
||||
|
||||
CustomTerrain = new string[MapSize.X, MapSize.Y];
|
||||
LoadBinaryData();
|
||||
}
|
||||
|
||||
public void Save(string filepath)
|
||||
{
|
||||
MapFormat = 2;
|
||||
// Todo: save to a zip file in the support dir by default
|
||||
Container = new Folder(filepath, 0);
|
||||
MapFormat = 3;
|
||||
|
||||
var root = new Dictionary<string, MiniYaml>();
|
||||
foreach (var field in SimpleFields)
|
||||
var root = new List<MiniYamlNode>();
|
||||
foreach (var field in new string[] {"Selectable", "MapFormat", "Title", "Description", "Author", "PlayerCount", "Tileset", "MapSize", "TopLeft", "BottomRight"})
|
||||
{
|
||||
FieldInfo f = this.GetType().GetField(field);
|
||||
if (f.GetValue(this) == null) continue;
|
||||
root.Add(field, new MiniYaml(FieldSaver.FormatValue(this, f), null));
|
||||
root.Add( new MiniYamlNode( field, FieldSaver.FormatValue( this, f ) ) );
|
||||
}
|
||||
|
||||
root.Add("Players",
|
||||
new MiniYaml(null, Players.ToDictionary(
|
||||
p => "PlayerReference@{0}".F(p.Key),
|
||||
p => FieldSaver.Save(p.Value))));
|
||||
root.Add( new MiniYamlNode( "Players", null,
|
||||
Players.Select( p => new MiniYamlNode(
|
||||
"PlayerReference@{0}".F( p.Key ),
|
||||
FieldSaver.Save( p.Value ) ) ).ToList() ) );
|
||||
|
||||
root.Add("Actors",
|
||||
new MiniYaml(null, Actors.ToDictionary(
|
||||
a => "ActorReference@{0}".F(a.Key),
|
||||
a => FieldSaver.Save(a.Value))));
|
||||
|
||||
root.Add("Waypoints", MiniYaml.FromDictionary<string, int2>(Waypoints));
|
||||
root.Add("Smudges", MiniYaml.FromList<SmudgeReference>(Smudges));
|
||||
root.Add("Rules", new MiniYaml(null, Rules));
|
||||
root.Add( new MiniYamlNode( "Actors", null,
|
||||
Actors.Select( x => new MiniYamlNode(
|
||||
x.Key,
|
||||
x.Value.Save() ) ).ToList() ) );
|
||||
|
||||
root.Add( new MiniYamlNode( "Waypoints", MiniYaml.FromDictionary<string, int2>( Waypoints ) ) );
|
||||
root.Add( new MiniYamlNode( "Smudges", MiniYaml.FromList<SmudgeReference>( Smudges ) ) );
|
||||
root.Add(new MiniYamlNode("Rules", null, Rules));
|
||||
root.Add(new MiniYamlNode("Sequences", null, Sequences));
|
||||
root.Add(new MiniYamlNode("Weapons", null, Weapons));
|
||||
root.Add(new MiniYamlNode("Voices", null, Voices));
|
||||
|
||||
SaveBinaryData(Path.Combine(filepath, "map.bin"));
|
||||
root.WriteToFile(Path.Combine(filepath, "map.yaml"));
|
||||
@@ -201,7 +254,7 @@ namespace OpenRA.FileFormats
|
||||
|
||||
public void LoadBinaryData()
|
||||
{
|
||||
using (var dataStream = Package.GetContent("map.bin"))
|
||||
using (var dataStream = Container.GetContent("map.bin"))
|
||||
{
|
||||
if (ReadByte(dataStream) != 1)
|
||||
throw new InvalidDataException("Unknown binary map format");
|
||||
@@ -263,17 +316,12 @@ namespace OpenRA.FileFormats
|
||||
File.Move(filepath + ".tmp", filepath);
|
||||
}
|
||||
|
||||
public void LoadUid()
|
||||
{
|
||||
Uid = Package.GetContent("map.uid").ReadAllText();
|
||||
}
|
||||
|
||||
public void SaveUid(string filename)
|
||||
{
|
||||
// UID is calculated by taking an SHA1 of the yaml and binary data
|
||||
// Read the relevant data into a buffer
|
||||
var data = Exts.ReadAllBytes(Package.GetContent("map.yaml"))
|
||||
.Concat(Exts.ReadAllBytes(Package.GetContent("map.bin"))).ToArray();
|
||||
var data = Container.GetContent("map.yaml").ReadAllBytes()
|
||||
.Concat(Container.GetContent("map.bin").ReadAllBytes()).ToArray();
|
||||
|
||||
// Take the SHA1
|
||||
using (var csp = SHA1.Create())
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user