Compare commits
627 Commits
pkgtest-20
...
release-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ad5e1cbe3a | ||
|
|
3744a1af25 | ||
|
|
3780a70045 | ||
|
|
5d0282188c | ||
|
|
8174cbc88f | ||
|
|
582c1016e9 | ||
|
|
702b3f7d20 | ||
|
|
dbe64f496b | ||
|
|
686c043151 | ||
|
|
6e8a002dad | ||
|
|
6c1efac235 | ||
|
|
d2aa97c1d1 | ||
|
|
850fcd5100 | ||
|
|
5b0cee78cf | ||
|
|
e805461be7 | ||
|
|
c2ba2fe12b | ||
|
|
312041b9c8 | ||
|
|
0cf49ad49f | ||
|
|
87e425042f | ||
|
|
54191039a9 | ||
|
|
bcc32d15ed | ||
|
|
0f03d6bee8 | ||
|
|
a447e35695 | ||
|
|
58abd45ed9 | ||
|
|
8a65632851 | ||
|
|
42f963d687 | ||
|
|
7b10da6bde | ||
|
|
62820430de | ||
|
|
8f60b9b652 | ||
|
|
e3dae2edd0 | ||
|
|
8bce37710b | ||
|
|
709f29184a | ||
|
|
006f7b888a | ||
|
|
1ef3099910 | ||
|
|
aca0b9d7dd | ||
|
|
e7cd4e07f9 | ||
|
|
da001385ae | ||
|
|
a03d607878 | ||
|
|
d8df332d97 | ||
|
|
e512799eeb | ||
|
|
8afddd9497 | ||
|
|
b87ea6ddef | ||
|
|
70af7f3595 | ||
|
|
b6a39c5993 | ||
|
|
a357bceb35 | ||
|
|
43242245b8 | ||
|
|
5fa4a5fa20 | ||
|
|
393702fe67 | ||
|
|
1aacb21b04 | ||
|
|
fc882437f0 | ||
|
|
bac2b4f28e | ||
|
|
ee27b248d8 | ||
|
|
fd2254f9db | ||
|
|
be2357f509 | ||
|
|
0f363d4c0f | ||
|
|
efeba3ec4f | ||
|
|
ec69e05433 | ||
|
|
6af834c436 | ||
|
|
e8a7d4d93a | ||
|
|
f45d063f1e | ||
|
|
c6ed6dbeb9 | ||
|
|
17310b7234 | ||
|
|
d3128463c0 | ||
|
|
2e9e4cff5c | ||
|
|
05e1841e0e | ||
|
|
69077629a7 | ||
|
|
b09a301bb3 | ||
|
|
1600b30fde | ||
|
|
1973208694 | ||
|
|
f8ad69889c | ||
|
|
fd68c81b15 | ||
|
|
5f1a0ddb99 | ||
|
|
ab4a9388ce | ||
|
|
a816956b5e | ||
|
|
8b01ed034b | ||
|
|
4471891cae | ||
|
|
2524ead1c4 | ||
|
|
15ec2b40f2 | ||
|
|
dc2880e047 | ||
|
|
26ed4c24be | ||
|
|
befb11ce69 | ||
|
|
971ec55679 | ||
|
|
3491d3b9f8 | ||
|
|
83b559befc | ||
|
|
4e1f7dedba | ||
|
|
a46baeaf2b | ||
|
|
c8bd8336f7 | ||
|
|
ff78b0f7ea | ||
|
|
5a891daa59 | ||
|
|
5e96bb3f8c | ||
|
|
e5b863f926 | ||
|
|
c70087fdb2 | ||
|
|
c4dffa02da | ||
|
|
5740faef21 | ||
|
|
63d4df76a8 | ||
|
|
fa98eae2c3 | ||
|
|
fabca5dca6 | ||
|
|
b12c630e63 | ||
|
|
db7b7742a3 | ||
|
|
b765d5238c | ||
|
|
343de6a244 | ||
|
|
101e57eade | ||
|
|
1a81016bdc | ||
|
|
3918c992c4 | ||
|
|
1b222958d6 | ||
|
|
c639339a62 | ||
|
|
2b91a2363b | ||
|
|
5650d5fc98 | ||
|
|
802b6a652c | ||
|
|
18c9a25232 | ||
|
|
3c2d9910e3 | ||
|
|
b279de1edb | ||
|
|
e27e7ce87c | ||
|
|
a3cb5d2d1d | ||
|
|
dfc722847a | ||
|
|
77e3d17527 | ||
|
|
d2adc28a00 | ||
|
|
33b916a713 | ||
|
|
91a076728d | ||
|
|
f60fefd5f5 | ||
|
|
43bca0e73d | ||
|
|
5cdf0e6a67 | ||
|
|
4fb38c955b | ||
|
|
e4f8816486 | ||
|
|
ab26d4b0ad | ||
|
|
b8756d9de7 | ||
|
|
470dfa941a | ||
|
|
d0a972f3b7 | ||
|
|
ad375c5734 | ||
|
|
c352ff644f | ||
|
|
fa83507a62 | ||
|
|
17e41a7b79 | ||
|
|
96988fe563 | ||
|
|
d4627479b5 | ||
|
|
38a08c0967 | ||
|
|
59bea931a5 | ||
|
|
a4ba7f7158 | ||
|
|
c6299892e0 | ||
|
|
6f7816b653 | ||
|
|
e3e5de2b59 | ||
|
|
43ce9274e1 | ||
|
|
e3100171f0 | ||
|
|
c2a659f4d2 | ||
|
|
dc63171e0e | ||
|
|
4fb7d4ef41 | ||
|
|
a550febc94 | ||
|
|
dac2314051 | ||
|
|
0262a946be | ||
|
|
b466a066a9 | ||
|
|
305f76e300 | ||
|
|
6ad5c99815 | ||
|
|
82a8fd329e | ||
|
|
69209cd340 | ||
|
|
59dcd297f5 | ||
|
|
06039ce818 | ||
|
|
5a645adb2d | ||
|
|
a69f5857e6 | ||
|
|
cb216aa345 | ||
|
|
fe41ac7fa3 | ||
|
|
443b46ca64 | ||
|
|
3f7293b206 | ||
|
|
352067eb48 | ||
|
|
038146abb3 | ||
|
|
6a0c158ffa | ||
|
|
585264d3ad | ||
|
|
a67e2290d1 | ||
|
|
1f4b780450 | ||
|
|
2f55768c1b | ||
|
|
334605287c | ||
|
|
b2517b2c87 | ||
|
|
178bf0643f | ||
|
|
7b5e072994 | ||
|
|
dbb4132b66 | ||
|
|
cc64b41246 | ||
|
|
57a631c284 | ||
|
|
7783e988a7 | ||
|
|
14f71c55bf | ||
|
|
351c759793 | ||
|
|
08b1c989d6 | ||
|
|
7e496f8db9 | ||
|
|
bf1743ac6e | ||
|
|
bb38521d70 | ||
|
|
cb8ed251b2 | ||
|
|
cde7ec1948 | ||
|
|
565ea05bd7 | ||
|
|
52bc05c1b5 | ||
|
|
960248fe44 | ||
|
|
d1e18cad7a | ||
|
|
d580ca6417 | ||
|
|
394d635dae | ||
|
|
87fd576b26 | ||
|
|
58cb603803 | ||
|
|
9be8f4ce29 | ||
|
|
ebc6515d73 | ||
|
|
3a67b3dec3 | ||
|
|
ee2dc60eb3 | ||
|
|
636f926184 | ||
|
|
1ca218182a | ||
|
|
cc14f5ef17 | ||
|
|
b9d84cb422 | ||
|
|
0d33aec9d9 | ||
|
|
b5a514d868 | ||
|
|
07c75b5e27 | ||
|
|
a0a5d10e4b | ||
|
|
8743f39a79 | ||
|
|
88cd454ce1 | ||
|
|
da66a9a6b3 | ||
|
|
5e7e677ca9 | ||
|
|
8cdd7dce6c | ||
|
|
4a7687d7e4 | ||
|
|
18a77e0039 | ||
|
|
ef01fb289b | ||
|
|
ff1be8daea | ||
|
|
e04ff18060 | ||
|
|
a38d43019a | ||
|
|
2907273ef2 | ||
|
|
1a0bb726e6 | ||
|
|
8f805248ca | ||
|
|
d6c60f6436 | ||
|
|
f4f127e3d1 | ||
|
|
7385fcbf3f | ||
|
|
6734cd96a4 | ||
|
|
1e2e7bcf42 | ||
|
|
7b5f000ba0 | ||
|
|
4fed3371d0 | ||
|
|
9199cf4669 | ||
|
|
270975a590 | ||
|
|
bf50372f85 | ||
|
|
b1ac961adc | ||
|
|
cf6f32fb96 | ||
|
|
8cce30d472 | ||
|
|
dbfd1eaaa3 | ||
|
|
6250c9df12 | ||
|
|
15d8fadb60 | ||
|
|
31aaaf26b5 | ||
|
|
6deadd7658 | ||
|
|
8d6cd143d6 | ||
|
|
80f1dc6a56 | ||
|
|
6d3edb8725 | ||
|
|
29df6866d0 | ||
|
|
13e0dac141 | ||
|
|
0572220cc3 | ||
|
|
7428776e90 | ||
|
|
65d61dff3e | ||
|
|
d1251d412f | ||
|
|
79dd9a9c6b | ||
|
|
7824564a44 | ||
|
|
3c502117a5 | ||
|
|
c842f1cbc1 | ||
|
|
0feb5a7bdc | ||
|
|
16df8322c6 | ||
|
|
9e11e38005 | ||
|
|
ce99f02ba6 | ||
|
|
ae8b2cec74 | ||
|
|
7b5078c4f2 | ||
|
|
739865062a | ||
|
|
9e8c7ee145 | ||
|
|
6fa3f4207a | ||
|
|
b02ca7695f | ||
|
|
daed053a57 | ||
|
|
f5de0101fe | ||
|
|
0ffe88753c | ||
|
|
a4083f4597 | ||
|
|
1a88769c12 | ||
|
|
d92dc70a2f | ||
|
|
884fbc0ea9 | ||
|
|
e666c75883 | ||
|
|
6097b3eb19 | ||
|
|
8a89accab6 | ||
|
|
04f1ebe969 | ||
|
|
3c3f85a272 | ||
|
|
68a97b079b | ||
|
|
432638dcfa | ||
|
|
e13f8873c0 | ||
|
|
3a30748f05 | ||
|
|
30edee01c2 | ||
|
|
d011438ff3 | ||
|
|
0d61a1d19a | ||
|
|
9a167317dd | ||
|
|
ea86aac089 | ||
|
|
6adf453ad1 | ||
|
|
e8bccc33c6 | ||
|
|
392b77647d | ||
|
|
40cd491bff | ||
|
|
eca4504006 | ||
|
|
249c522c00 | ||
|
|
f5b749e9ce | ||
|
|
de64b31aa4 | ||
|
|
78e4e7a440 | ||
|
|
cf7bd75dad | ||
|
|
38dd3bbdc9 | ||
|
|
7cd259d2b8 | ||
|
|
b05e4217cf | ||
|
|
362c86764f | ||
|
|
a42ac640e4 | ||
|
|
5602e49179 | ||
|
|
6436088cdb | ||
|
|
5a7dbb6529 | ||
|
|
cefe26349f | ||
|
|
5bd3a21d34 | ||
|
|
0d625b6af6 | ||
|
|
96c9de2b96 | ||
|
|
0866903f20 | ||
|
|
68969203bb | ||
|
|
a30c8b53a7 | ||
|
|
43dccee1b6 | ||
|
|
68f8b5073a | ||
|
|
af0e948a67 | ||
|
|
3682bc7069 | ||
|
|
52af0d2c81 | ||
|
|
5130723fcd | ||
|
|
aae428be2b | ||
|
|
e6a501bb66 | ||
|
|
1c511ea6eb | ||
|
|
281423c8f4 | ||
|
|
dcaef3b0e9 | ||
|
|
a5ac1aa581 | ||
|
|
95c43132c7 | ||
|
|
492abc0853 | ||
|
|
f9d5a439d8 | ||
|
|
59c12c2a31 | ||
|
|
a6ad359914 | ||
|
|
ba1fa7cd81 | ||
|
|
7fa51712ec | ||
|
|
2431c34ca9 | ||
|
|
d0c3fae1a2 | ||
|
|
4216f66ca4 | ||
|
|
7030d8b2b6 | ||
|
|
19072775d4 | ||
|
|
5c82fff0ef | ||
|
|
000768dd4f | ||
|
|
7fa8cc10e9 | ||
|
|
f7e32aac60 | ||
|
|
bcbd1c2577 | ||
|
|
e9ee4a1e15 | ||
|
|
d7f1b1c9e2 | ||
|
|
a256e722d5 | ||
|
|
9487f49cd5 | ||
|
|
4bc09692e0 | ||
|
|
7b52fa52b6 | ||
|
|
b6d1d26eeb | ||
|
|
086ec07eb6 | ||
|
|
e4ea012b9e | ||
|
|
b52cdd4b45 | ||
|
|
0989a5ea08 | ||
|
|
8cd6f05b71 | ||
|
|
8f046c7c5a | ||
|
|
8c4dcb7fe0 | ||
|
|
c60f19aee0 | ||
|
|
78f8c94df8 | ||
|
|
5560f276ca | ||
|
|
e0df669de9 | ||
|
|
fd4d3b40d0 | ||
|
|
2a466d08c3 | ||
|
|
441971f6d7 | ||
|
|
435f47158f | ||
|
|
c5a13d4e65 | ||
|
|
997216aef0 | ||
|
|
ad730a44c3 | ||
|
|
ce331a28e8 | ||
|
|
c5b4d643af | ||
|
|
fb3477d630 | ||
|
|
7c463c414c | ||
|
|
8dc0967d2e | ||
|
|
baf27bc4cd | ||
|
|
295af5741f | ||
|
|
e733ee0434 | ||
|
|
5a00757eab | ||
|
|
386b71de82 | ||
|
|
52ab8f3ca1 | ||
|
|
97a61273dd | ||
|
|
2026747f2a | ||
|
|
e825205542 | ||
|
|
bbd1331536 | ||
|
|
ea6f76e4f6 | ||
|
|
2ad6af6801 | ||
|
|
9a4b4f5841 | ||
|
|
d70e4a9e32 | ||
|
|
02c7d727d1 | ||
|
|
9ddc4ddc6b | ||
|
|
9ddc53e3fc | ||
|
|
a9635e8c4a | ||
|
|
4db2cf6b2b | ||
|
|
4b2663015b | ||
|
|
749a947d3f | ||
|
|
2af123034d | ||
|
|
7d24053f52 | ||
|
|
32e0bf3edf | ||
|
|
d318d7c5e3 | ||
|
|
74be133e40 | ||
|
|
ca082e3cec | ||
|
|
d9e0559c7a | ||
|
|
66d9629520 | ||
|
|
7b3a0ebeb5 | ||
|
|
f46f71217e | ||
|
|
7dfc822d76 | ||
|
|
6536f92b12 | ||
|
|
d4227fa13e | ||
|
|
a5cc68efee | ||
|
|
c5089db19c | ||
|
|
d43acfe94b | ||
|
|
3c891f7c45 | ||
|
|
8d6d06fc5f | ||
|
|
48bd67b735 | ||
|
|
36c910fcae | ||
|
|
492513a89a | ||
|
|
e19dae8eec | ||
|
|
0ff66949fb | ||
|
|
66325f4941 | ||
|
|
3c9f589b5e | ||
|
|
50d12ee22e | ||
|
|
b297bb7e75 | ||
|
|
4018da3481 | ||
|
|
315fad8db7 | ||
|
|
04dbe9fc2a | ||
|
|
378dd66622 | ||
|
|
07fc446520 | ||
|
|
7f8e84848d | ||
|
|
177dd02cd1 | ||
|
|
0f115b0468 | ||
|
|
87ff787f26 | ||
|
|
2d8f0ce96e | ||
|
|
3b99e79fd0 | ||
|
|
4159aa4bba | ||
|
|
38617dc0a9 | ||
|
|
7cf2a32a2a | ||
|
|
e41791568d | ||
|
|
379686a64d | ||
|
|
8a60880cf1 | ||
|
|
a5d765e100 | ||
|
|
927b0499da | ||
|
|
cf2fad673d | ||
|
|
c12527e866 | ||
|
|
aa91020790 | ||
|
|
4587ce6cd2 | ||
|
|
6eabd080b8 | ||
|
|
b70c56927f | ||
|
|
2e4749680c | ||
|
|
3260590c59 | ||
|
|
0daf8c173e | ||
|
|
fad98df605 | ||
|
|
05609399eb | ||
|
|
98471092f6 | ||
|
|
48a5c69ab8 | ||
|
|
d3d74c4e5f | ||
|
|
775f707e03 | ||
|
|
52e2b83069 | ||
|
|
69ddcf3fee | ||
|
|
628c524494 | ||
|
|
235acea70a | ||
|
|
8bff7baf4b | ||
|
|
f48b53d5b1 | ||
|
|
f8e5217b11 | ||
|
|
3ed0f75ecc | ||
|
|
2e605ba0f7 | ||
|
|
ea4cde0da8 | ||
|
|
f13c5e20b4 | ||
|
|
46b08273e0 | ||
|
|
5760e665d3 | ||
|
|
b85aaa7bfa | ||
|
|
5cac1ed066 | ||
|
|
444380b3cf | ||
|
|
b9542e0f3f | ||
|
|
b592063a26 | ||
|
|
53930fdc81 | ||
|
|
e0d8d8cf80 | ||
|
|
bc92bc1774 | ||
|
|
57280e3eab | ||
|
|
a6cb60e583 | ||
|
|
fd78848de2 | ||
|
|
c8c05ea19c | ||
|
|
f481c04ce6 | ||
|
|
e607c04cce | ||
|
|
3e627d2eba | ||
|
|
30fa8f35d8 | ||
|
|
0e1f98c2a9 | ||
|
|
6e97c51530 | ||
|
|
ef2e02d008 | ||
|
|
8ff5d9ef9b | ||
|
|
d88fc7c3f2 | ||
|
|
cf3f79bf29 | ||
|
|
1c719cb34f | ||
|
|
18805779a8 | ||
|
|
54e53a1306 | ||
|
|
0ad767a05e | ||
|
|
e8473990ef | ||
|
|
22abf9b4c4 | ||
|
|
e8111e8ac6 | ||
|
|
52b09bdfe8 | ||
|
|
6d2f180cd4 | ||
|
|
85734defec | ||
|
|
909c5c7037 | ||
|
|
50d3929862 | ||
|
|
3be26e4cda | ||
|
|
1f7b0ad5d4 | ||
|
|
a8c029f130 | ||
|
|
4d2412f4b8 | ||
|
|
d25fd654bc | ||
|
|
db319f8f0b | ||
|
|
521ca70254 | ||
|
|
83e33b99e8 | ||
|
|
88480e0dc2 | ||
|
|
44ab94f03a | ||
|
|
6928a828e8 | ||
|
|
eb27c9ef9d | ||
|
|
1d276e4186 | ||
|
|
6d2dfabb41 | ||
|
|
e0ba2046b5 | ||
|
|
de005c284c | ||
|
|
8249012e4b | ||
|
|
60d973aab4 | ||
|
|
a220182c9e | ||
|
|
1db1a1b324 | ||
|
|
2180e1f3f1 | ||
|
|
afa3fc8143 | ||
|
|
2141656460 | ||
|
|
58c3f9ad0c | ||
|
|
64ab0a77a9 | ||
|
|
887a515e14 | ||
|
|
f5a44f3c41 | ||
|
|
90894aa03e | ||
|
|
dbffce81a6 | ||
|
|
23f0e00bcc | ||
|
|
5e641750aa | ||
|
|
831b9b3ca3 | ||
|
|
6b85660d7d | ||
|
|
375fc1c5f1 | ||
|
|
91bc1acca3 | ||
|
|
1169211893 | ||
|
|
cc3e9b55a8 | ||
|
|
91236b2ca0 | ||
|
|
8f64835898 | ||
|
|
0679940c77 | ||
|
|
3ee54fd00a | ||
|
|
88757eccfa | ||
|
|
dac12839fd | ||
|
|
fe0d7ab00e | ||
|
|
b3a2f81706 | ||
|
|
1ebfc6bb06 | ||
|
|
ee0df9c1cb | ||
|
|
fa0e4c3d0d | ||
|
|
2cc1d34078 | ||
|
|
7b5476aca7 | ||
|
|
479feadef3 | ||
|
|
525a0c4ff1 | ||
|
|
b7ca65fb7b | ||
|
|
473ca13b17 | ||
|
|
c58d737400 | ||
|
|
f115dda5df | ||
|
|
5e986b3079 | ||
|
|
ee4f3e5642 | ||
|
|
d22658011b | ||
|
|
3f2425f1d6 | ||
|
|
86febed0ce | ||
|
|
060d5326ed | ||
|
|
03b8096807 | ||
|
|
f0c672b70c | ||
|
|
77fb188585 | ||
|
|
c282fa1077 | ||
|
|
0cf2d608e4 | ||
|
|
96477b7c1a | ||
|
|
db53f8e648 | ||
|
|
092352729f | ||
|
|
ea276d466d | ||
|
|
83fc5085e3 | ||
|
|
89c9499909 | ||
|
|
6f5fbeceb1 | ||
|
|
3e24e89477 | ||
|
|
b8cdb224d1 | ||
|
|
f6f366c4b3 | ||
|
|
b8b8b1e2df | ||
|
|
e0c59511fb | ||
|
|
1c5c2b576c | ||
|
|
ecb7b5056c | ||
|
|
4ce8a4a648 | ||
|
|
783fd8eb32 | ||
|
|
e347cdfb32 | ||
|
|
a2ed4fd5f9 | ||
|
|
6fdb9e688a | ||
|
|
ccb34adb04 | ||
|
|
9dbbc23967 | ||
|
|
a598a01108 | ||
|
|
1821c52db0 | ||
|
|
8093942913 | ||
|
|
69d86cfcf2 | ||
|
|
c9a49538d6 | ||
|
|
ee7573d01c | ||
|
|
373529e110 | ||
|
|
00b95f754f | ||
|
|
3b9f1ed43c | ||
|
|
49def655c9 | ||
|
|
9df00ad8f9 | ||
|
|
5eab479c34 | ||
|
|
e63f330717 | ||
|
|
2e992a7310 | ||
|
|
334a210231 | ||
|
|
13fad65c19 | ||
|
|
7216688baf | ||
|
|
decdcf44d4 | ||
|
|
d8e5177a36 | ||
|
|
033f631f28 | ||
|
|
1c8a8ca6ff | ||
|
|
ea9601b128 | ||
|
|
1051728790 | ||
|
|
799966d376 | ||
|
|
a35d84bf5a | ||
|
|
80a4f33730 | ||
|
|
bc103f8ffd | ||
|
|
2c5f1de780 | ||
|
|
9762ef8119 | ||
|
|
3a1c41c8ce | ||
|
|
f06cbfa5fe | ||
|
|
0dee8208a8 | ||
|
|
1c92737798 | ||
|
|
a0723bfec3 | ||
|
|
bf47543a0a | ||
|
|
7e6f7c51e1 | ||
|
|
531e3b7861 | ||
|
|
5055764e04 | ||
|
|
0027434fbd | ||
|
|
7d352fdad1 | ||
|
|
f180f44542 | ||
|
|
e083b392ba | ||
|
|
441d602a6d | ||
|
|
b1d5f4edd9 | ||
|
|
0ea3509ee4 | ||
|
|
67594b844a |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -56,4 +56,8 @@ Lua-API.md
|
||||
*.html
|
||||
|
||||
# StyleCop
|
||||
*.Cache
|
||||
*.Cache
|
||||
|
||||
# SublimeText
|
||||
*.sublime-project
|
||||
*.sublime-workspace
|
||||
@@ -6,7 +6,8 @@ language: c
|
||||
|
||||
# Make sure build dependencies are installed.
|
||||
install:
|
||||
- sudo apt-get install mono-gmcs cli-common-dev libgl1-mesa-glx libopenal1 libfreetype6
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -qq mono-gmcs cli-common-dev libgl1-mesa-glx libopenal1 libfreetype6
|
||||
cache: apt
|
||||
|
||||
# Run the build script
|
||||
@@ -37,8 +38,10 @@ notifications:
|
||||
before_deploy:
|
||||
- sudo apt-get install nsis markdown dpkg rpm libarchive-dev m4 fakeroot bsdtar
|
||||
- wget ftp://ftp.archlinux.org/other/pacman/pacman-4.0.3.tar.gz -O /tmp/pacman-4.0.3.tar.gz
|
||||
- pushd /tmp
|
||||
- tar -xzvf pacman-4.0.3.tar.gz
|
||||
- cd pacman-4.0.3 && ./configure --disable-doc --prefix=/usr && make && sudo make install
|
||||
- popd
|
||||
- DOTVERSION=`echo ${TRAVIS_TAG} | sed "s/-/\\./g"`
|
||||
- cd packaging
|
||||
- mkdir build
|
||||
|
||||
9
AUTHORS
9
AUTHORS
@@ -6,7 +6,6 @@ The OpenRA developers are:
|
||||
* Curtis Shmyr (hamb)
|
||||
* Matthias Mailänder (Mailaender)
|
||||
* Paul Chote (pchote)
|
||||
* ScottNZ
|
||||
|
||||
Previous developers included:
|
||||
* Alli Witheford (alzeih)
|
||||
@@ -15,9 +14,12 @@ Previous developers included:
|
||||
* Megan Bowra-Dean (beedee)
|
||||
* Mike Bundy (kehaar)
|
||||
* Robert Pepperell (ytinasni)
|
||||
* ScottNZ
|
||||
|
||||
Also thanks to:
|
||||
* Adam Valy (Tschokky)
|
||||
* Akseli Virtanen (RAGEQUIT)
|
||||
* Allen262
|
||||
* Andrew Aldridge (i80and)
|
||||
* Andrew Perkins
|
||||
* Andrew Riedi
|
||||
@@ -35,6 +37,7 @@ Also thanks to:
|
||||
* Fahrradkette
|
||||
* Frank Razenberg (zzattack)
|
||||
* Gareth Needham (Ripley`)
|
||||
* Gordon Martin (Happy0)
|
||||
* Igor Popov (ihptru)
|
||||
* Iran
|
||||
* James Dunne (jsd)
|
||||
@@ -49,13 +52,16 @@ Also thanks to:
|
||||
* Lesueur Benjamin (Valkirie)
|
||||
* Maarten Meuris (Nyerguds)
|
||||
* Mark Olson (markolson)
|
||||
* Matija Hustic (matija-hustic)
|
||||
* Matthew Gatland (mgatland)
|
||||
* Matthew Uzzell (MUzzell)
|
||||
* Max621
|
||||
* Max Ugrumov (katzsmile)
|
||||
* Mustafa Alperen Seki (MustaphaTR)
|
||||
* Nukem
|
||||
* Okunev Yu Dmitry (xaionaro)
|
||||
* Olaf van der Spek
|
||||
* Oliver Brakmann
|
||||
* Paolo Chiodi (paolochiodi)
|
||||
* Paul Dovydaitis (pdovy)
|
||||
* Pavlos Touboulidis (pav)
|
||||
@@ -73,6 +79,7 @@ Also thanks to:
|
||||
* Teemu Nieminen (Temeez)
|
||||
* Tim Mylemans (gecko)
|
||||
* Tirili
|
||||
* Tom Roostan (RoosterDragon)
|
||||
* Tristan Keating (Kilkakon)
|
||||
* Tristan Mühlbacher (MicroBit)
|
||||
* Vladimir Komarov (VrKomarov)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<RootNamespace>OpenRA</RootNamespace>
|
||||
<AssemblyName>OpenRA.CrashDialog</AssemblyName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<OutputPath>..\</OutputPath>
|
||||
@@ -16,18 +16,10 @@
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\</OutputPath>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>OpenRA.ico</ApplicationIcon>
|
||||
<ApplicationIcon>..\OpenRA.Game\OpenRA.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
@@ -43,8 +35,5 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="OpenRA.ico" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 264 KiB |
@@ -15,7 +15,6 @@ using System.IO;
|
||||
using System.Media;
|
||||
using System.Reflection;
|
||||
using System.Windows.Forms;
|
||||
using OpenRA;
|
||||
|
||||
namespace OpenRA.CrashDialog
|
||||
{
|
||||
|
||||
344
OpenRA.CrashDialog/Settings.StyleCop
Normal file
344
OpenRA.CrashDialog/Settings.StyleCop
Normal file
@@ -0,0 +1,344 @@
|
||||
<StyleCopSettings Version="105">
|
||||
<Analyzers>
|
||||
<Analyzer AnalyzerId="StyleCop.CSharp.DocumentationRules">
|
||||
<Rules>
|
||||
<Rule Name="ElementsMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PartialElementsMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="EnumerationItemsMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationMustContainValidXml">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementDocumentationMustHaveSummary">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PartialElementDocumentationMustHaveSummary">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementDocumentationMustHaveSummaryText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PartialElementDocumentationMustHaveSummaryText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementDocumentationMustNotHaveDefaultSummary">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementParametersMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementParameterDocumentationMustMatchElementParameters">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementParameterDocumentationMustDeclareParameterName">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementParameterDocumentationMustHaveText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementReturnValueMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementReturnValueDocumentationMustHaveText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="VoidReturnValueMustNotBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParametersMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParametersMustBeDocumentedPartialClass">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParameterDocumentationMustMatchTypeParameters">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParameterDocumentationMustDeclareParameterName">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParameterDocumentationMustHaveText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PropertySummaryDocumentationMustMatchAccessors">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PropertySummaryDocumentationMustOmitSetAccessorWithRestrictedAccess">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementDocumentationMustNotBeCopiedAndPasted">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="SingleLineCommentsMustNotUseDocumentationStyleSlashes">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationTextMustNotBeEmpty">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationTextMustContainWhitespace">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationMustMeetCharacterPercentage">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ConstructorSummaryDocumentationMustBeginWithStandardText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DestructorSummaryDocumentationMustBeginWithStandardText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationHeadersMustNotContainBlankLines">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="IncludedDocumentationXPathDoesNotExist">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="IncludeNodeDoesNotContainValidFileAndPath">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="InheritDocMustBeUsedWithInheritingClass">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementDocumentationMustBeSpelledCorrectly">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileMustHaveHeader">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderMustShowCopyright">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderMustHaveCopyrightText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderMustContainFileName">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderFileNameDocumentationMustMatchFileName">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderMustHaveValidCompanyText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderFileNameDocumentationMustMatchTypeName">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
</Rules>
|
||||
<AnalyzerSettings />
|
||||
</Analyzer>
|
||||
<Analyzer AnalyzerId="StyleCop.CSharp.SpacingRules">
|
||||
<Rules>
|
||||
<Rule Name="TabsMustNotBeUsed">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
</Rules>
|
||||
<AnalyzerSettings />
|
||||
</Analyzer>
|
||||
<Analyzer AnalyzerId="StyleCop.CSharp.LayoutRules">
|
||||
<Rules>
|
||||
<Rule Name="CurlyBracketsForMultiLineStatementsMustNotShareLine">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="StatementMustNotBeOnSingleLine">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementMustNotBeOnSingleLine">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="CurlyBracketsMustNotBeOmitted">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementsMustBeSeparatedByBlankLine">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
</Rules>
|
||||
<AnalyzerSettings />
|
||||
</Analyzer>
|
||||
<Analyzer AnalyzerId="StyleCop.CSharp.OrderingRules">
|
||||
<Rules>
|
||||
<Rule Name="UsingDirectivesMustBePlacedWithinNamespace">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementsMustAppearInTheCorrectOrder">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementsMustBeOrderedByAccess">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
</Rules>
|
||||
<AnalyzerSettings />
|
||||
</Analyzer>
|
||||
<Analyzer AnalyzerId="StyleCop.CSharp.ReadabilityRules">
|
||||
<Rules>
|
||||
<Rule Name="CodeMustNotContainMultipleStatementsOnOneLine">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="UseStringEmptyForEmptyStrings">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PrefixLocalCallsWithThis">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PrefixCallsCorrectly">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ParametersMustBeOnSameLineOrSeparateLines">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ParameterMustFollowComma">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="SplitParametersMustStartOnLineAfterDeclaration">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
</Rules>
|
||||
<AnalyzerSettings />
|
||||
</Analyzer>
|
||||
<Analyzer AnalyzerId="StyleCop.CSharp.MaintainabilityRules">
|
||||
<Rules>
|
||||
<Rule Name="AccessModifierMustBeDeclared">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FieldsMustBePrivate">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileMayOnlyContainASingleClass">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ArithmeticExpressionsMustDeclarePrecedence">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
</Rules>
|
||||
<AnalyzerSettings />
|
||||
</Analyzer>
|
||||
</Analyzers>
|
||||
</StyleCopSettings>
|
||||
@@ -11,7 +11,6 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Editor
|
||||
{
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
#endregion
|
||||
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
using SGraphics = System.Drawing.Graphics;
|
||||
|
||||
namespace OpenRA.Editor
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Forms;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
using SGraphics = System.Drawing.Graphics;
|
||||
|
||||
namespace OpenRA.Editor
|
||||
@@ -39,16 +37,15 @@ namespace OpenRA.Editor
|
||||
for (var u = 0; u < template.Size.X; u++)
|
||||
for (var v = 0; v < template.Size.Y; v++)
|
||||
{
|
||||
if (surface.Map.IsInMap(new CVec(u, v) + pos))
|
||||
var cell = pos + new CVec(u, v);
|
||||
if (surface.Map.Contains(cell))
|
||||
{
|
||||
var z = u + v * template.Size.X;
|
||||
if (tile[z].Length > 0)
|
||||
surface.Map.MapTiles.Value[u + pos.X, v + pos.Y] =
|
||||
new TileReference<ushort, byte>
|
||||
{
|
||||
Type = brushTemplate.N,
|
||||
Index = template.PickAny ? (byte)((u + pos.X) % 4 + ((v + pos.Y) % 4) * 4) : (byte)z,
|
||||
};
|
||||
{
|
||||
var index = template.PickAny ? (byte)((u + pos.X) % 4 + ((v + pos.Y) % 4) * 4) : (byte)z;
|
||||
surface.Map.MapTiles.Value[cell] = new TerrainTile(brushTemplate.N, index);
|
||||
}
|
||||
|
||||
var ch = new int2((pos.X + u) / Surface.ChunkSize, (pos.Y + v) / Surface.ChunkSize);
|
||||
if (surface.Chunks.ContainsKey(ch))
|
||||
@@ -64,7 +61,7 @@ namespace OpenRA.Editor
|
||||
{
|
||||
g.DrawImage(brushTemplate.Bitmap,
|
||||
surface.TileSetRenderer.TileSize * surface.GetBrushLocation().X * surface.Zoom + surface.GetOffset().X,
|
||||
surface.TileSetRenderer.TileSize * surface.GetBrushLocation().Y * surface.Zoom + surface.GetOffset().Y,
|
||||
surface.TileSetRenderer.TileSize * surface.GetBrushLocation().Y * surface.Zoom + surface.GetOffset().Y,
|
||||
brushTemplate.Bitmap.Width * surface.Zoom,
|
||||
brushTemplate.Bitmap.Height * surface.Zoom);
|
||||
}
|
||||
@@ -72,14 +69,15 @@ namespace OpenRA.Editor
|
||||
void FloodFillWithBrush(Surface s, CPos pos)
|
||||
{
|
||||
var queue = new Queue<CPos>();
|
||||
var replace = s.Map.MapTiles.Value[pos.X, pos.Y];
|
||||
var replace = s.Map.MapTiles.Value[pos];
|
||||
var touched = new bool[s.Map.MapSize.X, s.Map.MapSize.Y];
|
||||
|
||||
Action<int, int> maybeEnqueue = (x, y) =>
|
||||
{
|
||||
if (s.Map.IsInMap(x, y) && !touched[x, y])
|
||||
var c = new CPos(x, y);
|
||||
if (s.Map.Contains(c) && !touched[x, y])
|
||||
{
|
||||
queue.Enqueue(new CPos(x, y));
|
||||
queue.Enqueue(c);
|
||||
touched[x, y] = true;
|
||||
}
|
||||
};
|
||||
@@ -88,7 +86,7 @@ namespace OpenRA.Editor
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
var p = queue.Dequeue();
|
||||
if (s.Map.MapTiles.Value[p.X, p.Y].Type != replace.Type)
|
||||
if (s.Map.MapTiles.Value[p].Type != replace.Type)
|
||||
continue;
|
||||
|
||||
var a = FindEdge(s, p, new CVec(-1, 0), replace);
|
||||
@@ -96,10 +94,10 @@ namespace OpenRA.Editor
|
||||
|
||||
for (var x = a.X; x <= b.X; x++)
|
||||
{
|
||||
s.Map.MapTiles.Value[x, p.Y] = new TileReference<ushort, byte> { Type = brushTemplate.N, Index = (byte)0 };
|
||||
if (s.Map.MapTiles.Value[x, p.Y - 1].Type == replace.Type)
|
||||
s.Map.MapTiles.Value[new CPos(x, p.Y)] = new TerrainTile(brushTemplate.N, (byte)0);
|
||||
if (s.Map.MapTiles.Value[new CPos(x, p.Y - 1)].Type == replace.Type)
|
||||
maybeEnqueue(x, p.Y - 1);
|
||||
if (s.Map.MapTiles.Value[x, p.Y + 1].Type == replace.Type)
|
||||
if (s.Map.MapTiles.Value[new CPos(x, p.Y + 1)].Type == replace.Type)
|
||||
maybeEnqueue(x, p.Y + 1);
|
||||
}
|
||||
}
|
||||
@@ -109,13 +107,13 @@ namespace OpenRA.Editor
|
||||
s.Chunks.Clear();
|
||||
}
|
||||
|
||||
static CPos FindEdge(Surface s, CPos p, CVec d, TileReference<ushort, byte> replace)
|
||||
static CPos FindEdge(Surface s, CPos p, CVec d, TerrainTile replace)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
var q = p + d;
|
||||
if (!s.Map.IsInMap(q)) return p;
|
||||
if (s.Map.MapTiles.Value[q.X, q.Y].Type != replace.Type) return p;
|
||||
if (!s.Map.Contains(q)) return p;
|
||||
if (s.Map.MapTiles.Value[q].Type != replace.Type) return p;
|
||||
p = q;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +88,11 @@ namespace OpenRA.Editor
|
||||
foreach (var init in Program.Rules.Actors[kv.Value.Type].GetInitKeys())
|
||||
apd.AddRow(init.First,
|
||||
apd.MakeEditorControl(init.Second,
|
||||
() => objSaved.NodesDict.ContainsKey(init.First) ? objSaved.NodesDict[init.First].Value : null,
|
||||
() =>
|
||||
{
|
||||
var nodesDict = objSaved.ToDictionary();
|
||||
return nodesDict.ContainsKey(init.First) ? nodesDict[init.First].Value : null;
|
||||
},
|
||||
_ => { }));
|
||||
|
||||
apd.ShowDialog();
|
||||
@@ -149,11 +153,11 @@ namespace OpenRA.Editor
|
||||
tileset = Program.Rules.TileSets[map.Tileset];
|
||||
tilesetRenderer = new TileSetRenderer(tileset, modData.Manifest.TileSize);
|
||||
var shadowIndex = new int[] { 3, 4 };
|
||||
var palette = new Palette(GlobalFileSystem.Open(tileset.Palette), shadowIndex);
|
||||
var palette = new ImmutablePalette(GlobalFileSystem.Open(tileset.Palette), shadowIndex);
|
||||
|
||||
// required for desert terrain in RA
|
||||
var playerPalette = tileset.PlayerPalette ?? tileset.Palette;
|
||||
var shadowedPalette = new Palette(GlobalFileSystem.Open(playerPalette), shadowIndex);
|
||||
var shadowedPalette = new ImmutablePalette(GlobalFileSystem.Open(playerPalette), shadowIndex);
|
||||
|
||||
surface1.Bind(map, tileset, tilesetRenderer, palette, shadowedPalette);
|
||||
|
||||
@@ -162,7 +166,7 @@ namespace OpenRA.Editor
|
||||
foreach (var p in palettes) { p.Visible = false; p.SuspendLayout(); }
|
||||
|
||||
var templateOrder = tileset.EditorTemplateOrder ?? new string[] { };
|
||||
foreach (var tc in tileset.Templates.GroupBy(t => t.Value.Category).OrderBy(t => templateOrder.ToList().IndexOf(t.Key)))
|
||||
foreach (var tc in tileset.Templates.GroupBy(t => t.Value.Category).OrderBy(t => Array.IndexOf(templateOrder, t.Key)))
|
||||
{
|
||||
var category = tc.Key ?? "(Uncategorized)";
|
||||
var categoryHeader = new Label
|
||||
@@ -633,11 +637,12 @@ namespace OpenRA.Editor
|
||||
|
||||
public int CalculateTotalResource()
|
||||
{
|
||||
int totalResource = 0;
|
||||
for (int i = 0; i < surface1.Map.MapSize.X; i++)
|
||||
for (int j = 0; j < surface1.Map.MapSize.Y; j++)
|
||||
var totalResource = 0;
|
||||
for (var i = 0; i < surface1.Map.MapSize.X; i++)
|
||||
for (var j = 0; j < surface1.Map.MapSize.Y; j++)
|
||||
{
|
||||
if (surface1.Map.MapResources.Value[i, j].Type != 0)
|
||||
var cell = new CPos(i, j);
|
||||
if (surface1.Map.MapResources.Value[cell].Type != 0)
|
||||
totalResource += GetResourceValue(i, j);
|
||||
}
|
||||
|
||||
@@ -646,13 +651,16 @@ namespace OpenRA.Editor
|
||||
|
||||
int GetAdjecentCellsWith(int resourceType, int x, int y)
|
||||
{
|
||||
int sum = 0;
|
||||
var sum = 0;
|
||||
for (var u = -1; u < 2; u++)
|
||||
for (var v = -1; v < 2; v++)
|
||||
{
|
||||
if (!surface1.Map.IsInMap(new CPos(x + u, y + v)))
|
||||
var cell = new CPos(x + u, y + v);
|
||||
|
||||
if (!surface1.Map.Contains(cell))
|
||||
continue;
|
||||
if (surface1.Map.MapResources.Value[x + u, y + v].Type == resourceType)
|
||||
|
||||
if (surface1.Map.MapResources.Value[cell].Type == resourceType)
|
||||
++sum;
|
||||
}
|
||||
|
||||
@@ -661,15 +669,15 @@ namespace OpenRA.Editor
|
||||
|
||||
int GetResourceValue(int x, int y)
|
||||
{
|
||||
int imageLength = 0;
|
||||
int type = surface1.Map.MapResources.Value[x, y].Type;
|
||||
var imageLength = 0;
|
||||
var type = surface1.Map.MapResources.Value[new CPos(x, y)].Type;
|
||||
var template = surface1.ResourceTemplates.FirstOrDefault(a => a.Value.Info.ResourceType == type).Value;
|
||||
if (type == 1)
|
||||
imageLength = 12;
|
||||
else if (type == 2)
|
||||
imageLength = 3;
|
||||
int density = (GetAdjecentCellsWith(type, x, y) * imageLength - 1) / 9;
|
||||
int value = template.Info.ValuePerUnit;
|
||||
var density = (GetAdjecentCellsWith(type, x, y) * imageLength - 1) / 9;
|
||||
var value = template.Info.ValuePerUnit;
|
||||
return density * value;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace OpenRA.Editor
|
||||
|
||||
foreach (var map in MapCache.FindMapsIn(MapFolderPath))
|
||||
{
|
||||
ListViewItem map1 = new ListViewItem();
|
||||
var map1 = new ListViewItem();
|
||||
map1.Tag = map;
|
||||
map1.Text = Path.GetFileNameWithoutExtension(map);
|
||||
map1.ImageIndex = 0;
|
||||
|
||||
@@ -32,30 +32,17 @@
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core">
|
||||
|
||||
@@ -10,10 +10,7 @@
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Editor
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||
* Copyright 2007-2014 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,
|
||||
@@ -8,21 +8,19 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.FileSystem;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Editor
|
||||
{
|
||||
static class RenderUtils
|
||||
{
|
||||
static Bitmap RenderShp(ISpriteSource shp, Palette p)
|
||||
static Bitmap RenderShp(ISpriteSource shp, IPalette p)
|
||||
{
|
||||
var frame = shp.Frames.First();
|
||||
|
||||
@@ -35,7 +33,7 @@ namespace OpenRA.Editor
|
||||
|
||||
unsafe
|
||||
{
|
||||
byte* q = (byte*)data.Scan0.ToPointer();
|
||||
var q = (byte*)data.Scan0.ToPointer();
|
||||
var stride2 = data.Stride;
|
||||
|
||||
for (var i = 0; i < frame.Size.Width; i++)
|
||||
@@ -47,7 +45,7 @@ namespace OpenRA.Editor
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
public static ActorTemplate RenderActor(ActorInfo info, TileSet tileset, Palette p)
|
||||
public static ActorTemplate RenderActor(ActorInfo info, TileSet tileset, IPalette p)
|
||||
{
|
||||
var image = RenderSprites.GetImage(info);
|
||||
|
||||
@@ -78,7 +76,7 @@ namespace OpenRA.Editor
|
||||
}
|
||||
}
|
||||
|
||||
public static ResourceTemplate RenderResourceType(ResourceTypeInfo info, string[] exts, Palette p)
|
||||
public static ResourceTemplate RenderResourceType(ResourceTypeInfo info, string[] exts, IPalette p)
|
||||
{
|
||||
var image = info.EditorSprite;
|
||||
using (var s = GlobalFileSystem.OpenWithExts(image, exts))
|
||||
@@ -94,7 +92,7 @@ namespace OpenRA.Editor
|
||||
|
||||
unsafe
|
||||
{
|
||||
byte* q = (byte*)data.Scan0.ToPointer();
|
||||
var q = (byte*)data.Scan0.ToPointer();
|
||||
var stride = data.Stride;
|
||||
|
||||
for (var i = 0; i < frame.Size.Width; i++)
|
||||
@@ -103,7 +101,7 @@ namespace OpenRA.Editor
|
||||
}
|
||||
|
||||
bitmap.UnlockBits(data);
|
||||
return new ResourceTemplate { Bitmap = bitmap, Info = info, Value = shp.Frames.Count() - 1 };
|
||||
return new ResourceTemplate { Bitmap = bitmap, Info = info, Value = shp.Frames.Count - 1 };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
using SGraphics = System.Drawing.Graphics;
|
||||
|
||||
namespace OpenRA.Editor
|
||||
@@ -23,12 +21,9 @@ namespace OpenRA.Editor
|
||||
|
||||
public void Apply(Surface surface)
|
||||
{
|
||||
surface.Map.MapResources.Value[surface.GetBrushLocation().X, surface.GetBrushLocation().Y]
|
||||
= new TileReference<byte, byte>
|
||||
{
|
||||
Type = (byte)resourceTemplate.Info.ResourceType,
|
||||
Index = (byte)random.Next(resourceTemplate.Info.MaxDensity)
|
||||
};
|
||||
var type = (byte)resourceTemplate.Info.ResourceType;
|
||||
var index = (byte)random.Next(resourceTemplate.Info.MaxDensity);
|
||||
surface.Map.MapResources.Value[surface.GetBrushLocation()] = new ResourceTile(type, index);
|
||||
|
||||
var ch = new int2(surface.GetBrushLocation().X / Surface.ChunkSize,
|
||||
surface.GetBrushLocation().Y / Surface.ChunkSize);
|
||||
|
||||
@@ -14,7 +14,6 @@ using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using OpenRA.FileSystem;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Traits;
|
||||
@@ -46,8 +45,8 @@ namespace OpenRA.Editor
|
||||
public Map Map { get; private set; }
|
||||
public TileSet TileSet { get; private set; }
|
||||
public TileSetRenderer TileSetRenderer { get; private set; }
|
||||
public Palette Palette { get; private set; }
|
||||
public Palette PlayerPalette { get; private set; }
|
||||
public IPalette Palette { get; private set; }
|
||||
public IPalette PlayerPalette { get; private set; }
|
||||
public int2 Offset;
|
||||
|
||||
public int2 GetOffset() { return Offset; }
|
||||
@@ -63,8 +62,8 @@ namespace OpenRA.Editor
|
||||
public bool ShowRuler;
|
||||
|
||||
public bool IsPaste { get { return TileSelection != null && ResourceSelection != null; } }
|
||||
public TileReference<ushort, byte>[,] TileSelection;
|
||||
public TileReference<byte, byte>[,] ResourceSelection;
|
||||
public TerrainTile[,] TileSelection;
|
||||
public ResourceTile[,] ResourceSelection;
|
||||
public CPos SelectionStart;
|
||||
public CPos SelectionEnd;
|
||||
|
||||
@@ -82,7 +81,7 @@ namespace OpenRA.Editor
|
||||
|
||||
public Keys GetModifiers() { return ModifierKeys; }
|
||||
|
||||
public void Bind(Map m, TileSet ts, TileSetRenderer tsr, Palette p, Palette pp)
|
||||
public void Bind(Map m, TileSet ts, TileSetRenderer tsr, IPalette p, IPalette pp)
|
||||
{
|
||||
Map = m;
|
||||
TileSet = ts;
|
||||
@@ -207,9 +206,9 @@ namespace OpenRA.Editor
|
||||
var key = Map.Actors.Value.FirstOrDefault(a => a.Value.Location() == brushLocation);
|
||||
if (key.Key != null) Map.Actors.Value.Remove(key.Key);
|
||||
|
||||
if (Map.MapResources.Value[brushLocation.X, brushLocation.Y].Type != 0)
|
||||
if (Map.MapResources.Value[brushLocation].Type != 0)
|
||||
{
|
||||
Map.MapResources.Value[brushLocation.X, brushLocation.Y] = new TileReference<byte, byte>();
|
||||
Map.MapResources.Value[brushLocation] = new ResourceTile(0, 0);
|
||||
var ch = new int2(brushLocation.X / ChunkSize, brushLocation.Y / ChunkSize);
|
||||
if (Chunks.ContainsKey(ch))
|
||||
{
|
||||
@@ -266,13 +265,14 @@ namespace OpenRA.Editor
|
||||
|
||||
unsafe
|
||||
{
|
||||
int* p = (int*)data.Scan0.ToPointer();
|
||||
var p = (int*)data.Scan0.ToPointer();
|
||||
var stride = data.Stride >> 2;
|
||||
|
||||
for (var i = 0; i < ChunkSize; i++)
|
||||
for (var j = 0; j < ChunkSize; j++)
|
||||
{
|
||||
var tr = Map.MapTiles.Value[u * ChunkSize + i, v * ChunkSize + j];
|
||||
var cell = new CPos(u * ChunkSize + i, v * ChunkSize + j);
|
||||
var tr = Map.MapTiles.Value[cell];
|
||||
var tile = TileSetRenderer.Data(tr.Type);
|
||||
var index = (tr.Index < tile.Count) ? tr.Index : (byte)0;
|
||||
var rawImage = tile[index];
|
||||
@@ -280,13 +280,13 @@ namespace OpenRA.Editor
|
||||
for (var y = 0; y < TileSetRenderer.TileSize; y++)
|
||||
p[(j * TileSetRenderer.TileSize + y) * stride + i * TileSetRenderer.TileSize + x] = Palette.GetColor(rawImage[x + TileSetRenderer.TileSize * y]).ToArgb();
|
||||
|
||||
if (Map.MapResources.Value[u * ChunkSize + i, v * ChunkSize + j].Type != 0)
|
||||
if (Map.MapResources.Value[cell].Type != 0)
|
||||
{
|
||||
var resourceImage = ResourceTemplates[Map.MapResources.Value[u * ChunkSize + i, v * ChunkSize + j].Type].Bitmap;
|
||||
var resourceImage = ResourceTemplates[Map.MapResources.Value[cell].Type].Bitmap;
|
||||
var srcdata = resourceImage.LockBits(resourceImage.Bounds(),
|
||||
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
|
||||
|
||||
int* q = (int*)srcdata.Scan0.ToPointer();
|
||||
var q = (int*)srcdata.Scan0.ToPointer();
|
||||
var srcstride = srcdata.Stride >> 2;
|
||||
|
||||
for (var x = 0; x < TileSetRenderer.TileSize; x++)
|
||||
@@ -345,10 +345,10 @@ namespace OpenRA.Editor
|
||||
float2 GetDrawPosition(CPos location, Bitmap bmp, bool centered)
|
||||
{
|
||||
float offsetX = centered ? bmp.Width / 2 - TileSetRenderer.TileSize / 2 : 0;
|
||||
float drawX = TileSetRenderer.TileSize * location.X * Zoom + Offset.X - offsetX;
|
||||
var drawX = TileSetRenderer.TileSize * location.X * Zoom + Offset.X - offsetX;
|
||||
|
||||
float offsetY = centered ? bmp.Height / 2 - TileSetRenderer.TileSize / 2 : 0;
|
||||
float drawY = TileSetRenderer.TileSize * location.Y * Zoom + Offset.Y - offsetY;
|
||||
var drawY = TileSetRenderer.TileSize * location.Y * Zoom + Offset.Y - offsetY;
|
||||
|
||||
return new float2(drawX, drawY);
|
||||
}
|
||||
@@ -381,7 +381,7 @@ namespace OpenRA.Editor
|
||||
var pr = Map.Players[name];
|
||||
var pcpi = Program.Rules.Actors["player"].Traits.Get<PlayerColorPaletteInfo>();
|
||||
var remap = new PlayerColorRemap(pcpi.RemapIndex, pr.Color, pcpi.Ramp);
|
||||
return new Palette(PlayerPalette, remap).AsSystemPalette();
|
||||
return new ImmutablePalette(PlayerPalette, remap).AsSystemPalette();
|
||||
}
|
||||
|
||||
Cache<string, ColorPalette> playerPalettes;
|
||||
@@ -418,8 +418,8 @@ namespace OpenRA.Editor
|
||||
|
||||
var drawX = TileSetRenderer.TileSize * (float)ChunkSize * (float)x.X * Zoom + Offset.X;
|
||||
var drawY = TileSetRenderer.TileSize * (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);
|
||||
var sourceRect = new RectangleF(0, 0, bmp.Width, bmp.Height);
|
||||
var destRect = new RectangleF(drawX, drawY, bmp.Width * Zoom, bmp.Height * Zoom);
|
||||
e.Graphics.DrawImage(bmp, destRect, sourceRect, GraphicsUnit.Pixel);
|
||||
}
|
||||
|
||||
@@ -468,20 +468,20 @@ namespace OpenRA.Editor
|
||||
|
||||
if (ShowRuler && Zoom > 0.2)
|
||||
{
|
||||
for (int i = Map.Bounds.Left; i <= Map.Bounds.Right; i += 8)
|
||||
for (var i = Map.Bounds.Left; i <= Map.Bounds.Right; i += 8)
|
||||
{
|
||||
if (i % 8 == 0)
|
||||
{
|
||||
PointF point = new PointF(i * TileSetRenderer.TileSize * Zoom + Offset.X, (Map.Bounds.Top - 8) * TileSetRenderer.TileSize * Zoom + Offset.Y);
|
||||
var point = new PointF(i * TileSetRenderer.TileSize * Zoom + Offset.X, (Map.Bounds.Top - 8) * TileSetRenderer.TileSize * Zoom + Offset.Y);
|
||||
e.Graphics.DrawString((i - Map.Bounds.Left).ToString(), MarkerFont, TextBrush, point);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = Map.Bounds.Top; i <= Map.Bounds.Bottom; i += 8)
|
||||
for (var i = Map.Bounds.Top; i <= Map.Bounds.Bottom; i += 8)
|
||||
{
|
||||
if (i % 8 == 0)
|
||||
{
|
||||
PointF point = new PointF((Map.Bounds.Left - 8) * TileSetRenderer.TileSize * Zoom + Offset.X, i * TileSetRenderer.TileSize * Zoom + Offset.Y);
|
||||
var point = new PointF((Map.Bounds.Left - 8) * TileSetRenderer.TileSize * Zoom + Offset.X, i * TileSetRenderer.TileSize * Zoom + Offset.Y);
|
||||
e.Graphics.DrawString((i - Map.Bounds.Left).ToString(), MarkerFont, TextBrush, point);
|
||||
}
|
||||
}
|
||||
@@ -506,19 +506,20 @@ namespace OpenRA.Editor
|
||||
|
||||
if (start == end) return;
|
||||
|
||||
int width = Math.Abs((start - end).X);
|
||||
int height = Math.Abs((start - end).Y);
|
||||
var width = Math.Abs((start - end).X);
|
||||
var height = Math.Abs((start - end).Y);
|
||||
|
||||
TileSelection = new TileReference<ushort, byte>[width, height];
|
||||
ResourceSelection = new TileReference<byte, byte>[width, height];
|
||||
TileSelection = new TerrainTile[width, height];
|
||||
ResourceSelection = new ResourceTile[width, height];
|
||||
|
||||
for (int x = 0; x < width; x++)
|
||||
for (var x = 0; x < width; x++)
|
||||
{
|
||||
for (int y = 0; y < height; y++)
|
||||
for (var y = 0; y < height; y++)
|
||||
{
|
||||
// TODO: crash prevention
|
||||
TileSelection[x, y] = Map.MapTiles.Value[start.X + x, start.Y + y];
|
||||
ResourceSelection[x, y] = Map.MapResources.Value[start.X + x, start.Y + y];
|
||||
var cell = new CPos(start.X + x, start.Y + y);
|
||||
TileSelection[x, y] = Map.MapTiles.Value[cell];
|
||||
ResourceSelection[x, y] = Map.MapResources.Value[cell];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -529,16 +530,17 @@ namespace OpenRA.Editor
|
||||
var width = Math.Abs((SelectionStart - SelectionEnd).X);
|
||||
var height = Math.Abs((SelectionStart - SelectionEnd).Y);
|
||||
|
||||
for (int x = 0; x < width; x++)
|
||||
for (var x = 0; x < width; x++)
|
||||
{
|
||||
for (int y = 0; y < height; y++)
|
||||
for (var y = 0; y < height; y++)
|
||||
{
|
||||
var mapX = loc.X + x;
|
||||
var mapY = loc.Y + y;
|
||||
var cell = new CPos(mapX, mapY);
|
||||
|
||||
// TODO: crash prevention for outside of bounds
|
||||
Map.MapTiles.Value[mapX, mapY] = TileSelection[x, y];
|
||||
Map.MapResources.Value[mapX, mapY] = ResourceSelection[x, y];
|
||||
Map.MapTiles.Value[cell] = TileSelection[x, y];
|
||||
Map.MapResources.Value[cell] = ResourceSelection[x, y];
|
||||
|
||||
var ch = new int2(mapX / ChunkSize, mapY / ChunkSize);
|
||||
if (Chunks.ContainsKey(ch))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
||||
* Copyright 2007-2014 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,
|
||||
@@ -12,7 +12,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using OpenRA.FileSystem;
|
||||
using OpenRA.Graphics;
|
||||
@@ -21,9 +20,9 @@ namespace OpenRA.Editor
|
||||
{
|
||||
public class TileSetRenderer
|
||||
{
|
||||
public readonly int TileSize;
|
||||
public TileSet TileSet;
|
||||
Dictionary<ushort, List<byte[]>> templates;
|
||||
public readonly int TileSize;
|
||||
|
||||
// Extract a square tile that the editor can render
|
||||
byte[] ExtractSquareTile(ISpriteFrame frame)
|
||||
@@ -62,7 +61,7 @@ namespace OpenRA.Editor
|
||||
if (frames != null)
|
||||
{
|
||||
var ret = new List<byte[]>();
|
||||
var srcFrames = source.Frames.ToArray();
|
||||
var srcFrames = source.Frames;
|
||||
foreach (var i in frames)
|
||||
ret.Add(ExtractSquareTile(srcFrames[i]));
|
||||
|
||||
@@ -83,7 +82,7 @@ namespace OpenRA.Editor
|
||||
templates.Add(t.Key, LoadTemplate(t.Value.Image, tileset.Extensions, sourceCache, t.Value.Frames));
|
||||
}
|
||||
|
||||
public Bitmap RenderTemplate(ushort id, Palette p)
|
||||
public Bitmap RenderTemplate(ushort id, IPalette p)
|
||||
{
|
||||
var template = TileSet.Templates[id];
|
||||
var templateData = templates[id];
|
||||
|
||||
@@ -21,7 +21,7 @@ using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public class Actor : IScriptBindable, IScriptNotifyBind, ILuaTableBinding, ILuaEqualityBinding, ILuaToStringBinding
|
||||
public class Actor : IScriptBindable, IScriptNotifyBind, ILuaTableBinding, ILuaEqualityBinding, ILuaToStringBinding, IEquatable<Actor>
|
||||
{
|
||||
public readonly ActorInfo Info;
|
||||
|
||||
@@ -160,7 +160,12 @@ namespace OpenRA
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var o = obj as Actor;
|
||||
return o != null && o.ActorID == ActorID;
|
||||
return o != null && Equals(o);
|
||||
}
|
||||
|
||||
public bool Equals(Actor other)
|
||||
{
|
||||
return ActorID == other.ActorID;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
@@ -212,6 +217,9 @@ namespace OpenRA
|
||||
{
|
||||
World.AddFrameEndTask(w =>
|
||||
{
|
||||
if (this.Destroyed)
|
||||
return;
|
||||
|
||||
var oldOwner = Owner;
|
||||
|
||||
// momentarily remove from world so the ownership queries don't get confused
|
||||
|
||||
@@ -16,7 +16,7 @@ using OpenRA.Scripting;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public struct CPos : IScriptBindable, ILuaAdditionBinding, ILuaSubtractionBinding, ILuaEqualityBinding, ILuaTableBinding
|
||||
public struct CPos : IScriptBindable, ILuaAdditionBinding, ILuaSubtractionBinding, ILuaEqualityBinding, ILuaTableBinding, IEquatable<CPos>
|
||||
{
|
||||
public readonly int X, Y;
|
||||
|
||||
@@ -37,13 +37,6 @@ namespace OpenRA
|
||||
public static CPos Max(CPos a, CPos b) { return new CPos(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); }
|
||||
public static CPos Min(CPos a, CPos b) { return new CPos(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); }
|
||||
|
||||
public float2 ToFloat2() { return new float2(X, Y); }
|
||||
public int2 ToInt2() { return new int2(X, Y); }
|
||||
|
||||
public WPos CenterPosition { get { return new WPos(1024 * X + 512, 1024 * Y + 512, 0); } }
|
||||
public WPos TopLeft { get { return new WPos(1024 * X, 1024 * Y, 0); } }
|
||||
public WPos BottomRight { get { return new WPos(1024 * X + 1023, 1024 * Y + 1023, 0); } }
|
||||
|
||||
public CPos Clamp(Rectangle r)
|
||||
{
|
||||
return new CPos(Math.Min(r.Right, Math.Max(X, r.Left)),
|
||||
@@ -52,13 +45,10 @@ namespace OpenRA
|
||||
|
||||
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); }
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var o = obj as CPos?;
|
||||
return o != null && o == this;
|
||||
}
|
||||
public bool Equals(CPos other) { return other == this; }
|
||||
public override bool Equals(object obj) { return obj is CPos && Equals((CPos)obj); }
|
||||
|
||||
public override string ToString() { return "{0},{1}".F(X, Y); }
|
||||
public override string ToString() { return X + "," + Y; }
|
||||
|
||||
#region Scripting interface
|
||||
|
||||
@@ -111,16 +101,4 @@ namespace OpenRA
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static class RectangleExtensions
|
||||
{
|
||||
public static CPos TopLeftAsCPos(this Rectangle r) { return new CPos(r.Left, r.Top); }
|
||||
public static CPos BottomRightAsCPos(this Rectangle r) { return new CPos(r.Right, r.Bottom); }
|
||||
}
|
||||
|
||||
public static class WorldCoordinateExtensions
|
||||
{
|
||||
public static CPos ToCPos(this WPos a) { return new CPos(a.X / 1024, a.Y / 1024); }
|
||||
public static CVec ToCVec(this WVec a) { return new CVec(a.X / 1024, a.Y / 1024); }
|
||||
}
|
||||
}
|
||||
@@ -16,18 +16,13 @@ using OpenRA.Scripting;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public struct CVec : IScriptBindable, ILuaAdditionBinding, ILuaSubtractionBinding, ILuaUnaryMinusBinding, ILuaEqualityBinding, ILuaTableBinding
|
||||
public struct CVec : IScriptBindable, ILuaAdditionBinding, ILuaSubtractionBinding, ILuaUnaryMinusBinding, ILuaEqualityBinding, ILuaTableBinding, IEquatable<CVec>
|
||||
{
|
||||
public readonly int X, Y;
|
||||
|
||||
public CVec(int x, int y) { X = x; Y = y; }
|
||||
public CVec(Size p) { X = p.Width; Y = p.Height; }
|
||||
|
||||
public static readonly CVec Zero = new CVec(0, 0);
|
||||
|
||||
public static explicit operator CVec(int2 a) { return new CVec(a.X, a.Y); }
|
||||
public static explicit operator CVec(float2 a) { return new CVec((int)a.X, (int)a.Y); }
|
||||
|
||||
public static CVec operator +(CVec a, CVec b) { return new CVec(a.X + b.X, a.Y + b.Y); }
|
||||
public static CVec operator -(CVec a, CVec b) { return new CVec(a.X - b.X, a.Y - b.Y); }
|
||||
public static CVec operator *(int a, CVec b) { return new CVec(a * b.X, a * b.Y); }
|
||||
@@ -47,11 +42,7 @@ namespace OpenRA
|
||||
public CVec Sign() { return new CVec(Math.Sign(X), Math.Sign(Y)); }
|
||||
public CVec Abs() { return new CVec(Math.Abs(X), Math.Abs(Y)); }
|
||||
public int LengthSquared { get { return X * X + Y * Y; } }
|
||||
public int Length { get { return (int)Math.Sqrt(LengthSquared); } }
|
||||
|
||||
public float2 ToFloat2() { return new float2(X, Y); }
|
||||
public int2 ToInt2() { return new int2(X, Y); }
|
||||
public WVec ToWVec() { return new WVec(X*1024, Y*1024, 0); }
|
||||
public int Length { get { return Exts.ISqrt(LengthSquared); } }
|
||||
|
||||
public CVec Clamp(Rectangle r)
|
||||
{
|
||||
@@ -63,13 +54,10 @@ namespace OpenRA
|
||||
|
||||
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); }
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var o = obj as CVec?;
|
||||
return o != null && o == this;
|
||||
}
|
||||
public bool Equals(CVec other) { return other == this; }
|
||||
public override bool Equals(object obj) { return obj is CVec && Equals((CVec)obj); }
|
||||
|
||||
public override string ToString() { return "{0},{1}".F(X, Y); }
|
||||
public override string ToString() { return X + "," + Y; }
|
||||
|
||||
public static readonly CVec[] directions =
|
||||
{
|
||||
@@ -125,7 +113,6 @@ namespace OpenRA
|
||||
{
|
||||
case "X": return X;
|
||||
case "Y": return Y;
|
||||
case "Facing": return Traits.Util.GetFacing(this, 0);
|
||||
default: throw new LuaException("CVec does not define a member '{0}'".F(key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@ namespace OpenRA
|
||||
{
|
||||
Game.OnQuit -= Cancel;
|
||||
wc.CancelAsync();
|
||||
wc.Dispose();
|
||||
cancelled = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
||||
* Copyright 2007-2014 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,
|
||||
@@ -13,15 +13,17 @@ using OpenRA.Graphics;
|
||||
|
||||
namespace OpenRA.Effects
|
||||
{
|
||||
public class MoveFlash : IEffect
|
||||
public class SpriteEffect : IEffect
|
||||
{
|
||||
string palette;
|
||||
Animation anim;
|
||||
WPos pos;
|
||||
|
||||
public MoveFlash(WPos pos, World world)
|
||||
public SpriteEffect(WPos pos, World world, string sprite, string palette)
|
||||
{
|
||||
this.pos = pos;
|
||||
anim = new Animation(world, "moveflsh");
|
||||
this.palette = palette;
|
||||
anim = new Animation(world, sprite);
|
||||
anim.PlayThen("idle", () => world.AddFrameEndTask(w => w.Remove(this)));
|
||||
}
|
||||
|
||||
@@ -32,7 +34,7 @@ namespace OpenRA.Effects
|
||||
|
||||
public IEnumerable<IRenderable> Render(WorldRenderer wr)
|
||||
{
|
||||
return anim.Render(pos, WVec.Zero, 0, wr.Palette("moveflash"), 1f / wr.Viewport.Zoom);
|
||||
return anim.Render(pos, WVec.Zero, 0, wr.Palette(palette), 1f / wr.Viewport.Zoom);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,11 @@ namespace OpenRA
|
||||
{
|
||||
public static class Exts
|
||||
{
|
||||
public static bool IsUppercase(this string str)
|
||||
{
|
||||
return string.Compare(str.ToUpperInvariant(), str, false) == 0;
|
||||
}
|
||||
|
||||
public static string F(this string fmt, params object[] args)
|
||||
{
|
||||
return string.Format(fmt, args);
|
||||
@@ -131,6 +136,54 @@ namespace OpenRA
|
||||
for (;;) { yield return t; t = f(t); }
|
||||
}
|
||||
|
||||
public static T MinBy<T, U>(this IEnumerable<T> ts, Func<T, U> selector)
|
||||
{
|
||||
return ts.CompareBy(selector, 1, true);
|
||||
}
|
||||
|
||||
public static T MaxBy<T, U>(this IEnumerable<T> ts, Func<T, U> selector)
|
||||
{
|
||||
return ts.CompareBy(selector, -1, true);
|
||||
}
|
||||
|
||||
public static T MinByOrDefault<T, U>(this IEnumerable<T> ts, Func<T, U> selector)
|
||||
{
|
||||
return ts.CompareBy(selector, 1, false);
|
||||
}
|
||||
|
||||
public static T MaxByOrDefault<T, U>(this IEnumerable<T> ts, Func<T, U> selector)
|
||||
{
|
||||
return ts.CompareBy(selector, -1, false);
|
||||
}
|
||||
|
||||
static T CompareBy<T, U>(this IEnumerable<T> ts, Func<T, U> selector, int modifier, bool throws)
|
||||
{
|
||||
var comparer = Comparer<U>.Default;
|
||||
T t;
|
||||
U u;
|
||||
using (var e = ts.GetEnumerator())
|
||||
{
|
||||
if (!e.MoveNext())
|
||||
if (throws)
|
||||
throw new ArgumentException("Collection must not be empty.", "ts");
|
||||
else
|
||||
return default(T);
|
||||
t = e.Current;
|
||||
u = selector(t);
|
||||
while (e.MoveNext())
|
||||
{
|
||||
var nextT = e.Current;
|
||||
var nextU = selector(nextT);
|
||||
if (comparer.Compare(nextU, u) * modifier < 0)
|
||||
{
|
||||
t = nextT;
|
||||
u = nextU;
|
||||
}
|
||||
}
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
public static int NextPowerOf2(int v)
|
||||
{
|
||||
--v;
|
||||
@@ -149,6 +202,91 @@ namespace OpenRA
|
||||
|
||||
public static Size NextPowerOf2(this Size s) { return new Size(NextPowerOf2(s.Width), NextPowerOf2(s.Height)); }
|
||||
|
||||
public enum ISqrtRoundMode { Floor, Nearest, Ceiling }
|
||||
public static int ISqrt(int number, ISqrtRoundMode round = ISqrtRoundMode.Floor)
|
||||
{
|
||||
if (number < 0)
|
||||
throw new InvalidOperationException("Attempted to calculate the square root of a negative integer: {0}".F(number));
|
||||
|
||||
return (int)ISqrt((uint)number, round);
|
||||
}
|
||||
|
||||
public static uint ISqrt(uint number, ISqrtRoundMode round = ISqrtRoundMode.Floor)
|
||||
{
|
||||
var divisor = 1U << 30;
|
||||
|
||||
var root = 0U;
|
||||
var remainder = number;
|
||||
|
||||
// Find the highest term in the divisor
|
||||
while (divisor > number)
|
||||
divisor >>= 2;
|
||||
|
||||
// Evaluate the root, two bits at a time
|
||||
while (divisor != 0)
|
||||
{
|
||||
if (root + divisor <= remainder)
|
||||
{
|
||||
remainder -= root + divisor;
|
||||
root += 2 * divisor;
|
||||
}
|
||||
|
||||
root >>= 1;
|
||||
divisor >>= 2;
|
||||
}
|
||||
|
||||
// Adjust for other rounding modes
|
||||
if (round == ISqrtRoundMode.Nearest && remainder > root)
|
||||
root += 1;
|
||||
|
||||
else if (round == ISqrtRoundMode.Ceiling && root * root < number)
|
||||
root += 1;
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
public static long ISqrt(long number, ISqrtRoundMode round = ISqrtRoundMode.Floor)
|
||||
{
|
||||
if (number < 0)
|
||||
throw new InvalidOperationException("Attempted to calculate the square root of a negative integer: {0}".F(number));
|
||||
|
||||
return (long)ISqrt((ulong)number, round);
|
||||
}
|
||||
|
||||
public static ulong ISqrt(ulong number, ISqrtRoundMode round = ISqrtRoundMode.Floor)
|
||||
{
|
||||
var divisor = 1UL << 62;
|
||||
|
||||
var root = 0UL;
|
||||
var remainder = number;
|
||||
|
||||
// Find the highest term in the divisor
|
||||
while (divisor > number)
|
||||
divisor >>= 2;
|
||||
|
||||
// Evaluate the root, two bits at a time
|
||||
while (divisor != 0)
|
||||
{
|
||||
if (root + divisor <= remainder)
|
||||
{
|
||||
remainder -= root + divisor;
|
||||
root += 2 * divisor;
|
||||
}
|
||||
|
||||
root >>= 1;
|
||||
divisor >>= 2;
|
||||
}
|
||||
|
||||
// Adjust for other rounding modes
|
||||
if (round == ISqrtRoundMode.Nearest && remainder > root)
|
||||
root += 1;
|
||||
|
||||
else if (round == ISqrtRoundMode.Ceiling && root * root < number)
|
||||
root += 1;
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
public static string JoinWith<T>(this IEnumerable<T> ts, string j)
|
||||
{
|
||||
return string.Join(j, ts);
|
||||
@@ -175,8 +313,8 @@ namespace OpenRA
|
||||
var d = new Dictionary<TKey, TElement>();
|
||||
foreach (var item in source)
|
||||
{
|
||||
TKey key = keySelector(item);
|
||||
TElement element = elementSelector(item);
|
||||
var key = keySelector(item);
|
||||
var element = elementSelector(item);
|
||||
|
||||
// Check for a key conflict:
|
||||
if (d.ContainsKey(key))
|
||||
@@ -221,8 +359,8 @@ namespace OpenRA
|
||||
|
||||
public static T[] MakeArray<T>(int count, Func<int, T> f)
|
||||
{
|
||||
T[] result = new T[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
var result = new T[count];
|
||||
for (var i = 0; i < count; i++)
|
||||
result[i] = f(i);
|
||||
|
||||
return result;
|
||||
|
||||
@@ -297,7 +297,7 @@ namespace OpenRA
|
||||
var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
var ret = Array.CreateInstance(fieldType.GetElementType(), parts.Length);
|
||||
for (int i = 0; i < parts.Length; i++)
|
||||
for (var i = 0; i < parts.Length; i++)
|
||||
ret.SetValue(GetValue(fieldName, fieldType.GetElementType(), parts[i].Trim(), field), i);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ namespace OpenRA.FileFormats
|
||||
while (dataSize > 0)
|
||||
{
|
||||
var chunk = Chunk.Read(s);
|
||||
for (int n = 0; n < chunk.CompressedSize; n++)
|
||||
for (var n = 0; n < chunk.CompressedSize; n++)
|
||||
{
|
||||
var b = s.ReadUInt8();
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace OpenRA.FileFormats
|
||||
// Magic number for "done"
|
||||
if (len == 519)
|
||||
{
|
||||
for (int i = 0; i < next; i++)
|
||||
for (var i = 0; i < next; i++)
|
||||
ms.WriteByte(outBuffer[i]);
|
||||
break;
|
||||
}
|
||||
@@ -135,7 +135,7 @@ namespace OpenRA.FileFormats
|
||||
// Flush window to outstream
|
||||
if (next == MAXWIN)
|
||||
{
|
||||
for (int i = 0; i < next; i++)
|
||||
for (var i = 0; i < next; i++)
|
||||
ms.WriteByte(outBuffer[i]);
|
||||
next = 0;
|
||||
first = false;
|
||||
@@ -149,7 +149,7 @@ namespace OpenRA.FileFormats
|
||||
outBuffer[next++] = (byte)symbol;
|
||||
if (next == MAXWIN)
|
||||
{
|
||||
for (int i = 0; i < next; i++)
|
||||
for (var i = 0; i < next; i++)
|
||||
ms.WriteByte(outBuffer[i]);
|
||||
next = 0;
|
||||
first = false;
|
||||
@@ -236,7 +236,7 @@ namespace OpenRA.FileFormats
|
||||
var s = 0; // current symbol
|
||||
|
||||
// convert compact repeat counts into symbol bit length list
|
||||
foreach (byte code in rep)
|
||||
foreach (var code in rep)
|
||||
{
|
||||
var num = (code >> 4) + 1; // Number of codes (top four bits plus 1)
|
||||
var len = (byte)(code & 15); // Code length (low four bits)
|
||||
@@ -250,7 +250,7 @@ namespace OpenRA.FileFormats
|
||||
|
||||
// count number of codes of each length
|
||||
Count = new short[Blast.MAXBITS + 1];
|
||||
for (int i = 0; i < n; i++)
|
||||
for (var i = 0; i < n; i++)
|
||||
Count[length[i]]++;
|
||||
|
||||
// no codes!
|
||||
@@ -259,7 +259,7 @@ namespace OpenRA.FileFormats
|
||||
|
||||
// check for an over-subscribed or incomplete set of lengths
|
||||
var left = 1; // one possible code of zero length
|
||||
for (int len = 1; len <= Blast.MAXBITS; len++)
|
||||
for (var len = 1; len <= Blast.MAXBITS; len++)
|
||||
{
|
||||
left <<= 1; // one more bit, double codes left
|
||||
left -= Count[len]; // deduct count from possible codes
|
||||
@@ -269,7 +269,7 @@ namespace OpenRA.FileFormats
|
||||
|
||||
// generate offsets into symbol table for each length for sorting
|
||||
var offs = new short[Blast.MAXBITS + 1];
|
||||
for (int len = 1; len < Blast.MAXBITS; len++)
|
||||
for (var 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
|
||||
|
||||
@@ -26,15 +26,15 @@ namespace OpenRA.FileFormats
|
||||
|
||||
uint l = 0, r = 0;
|
||||
|
||||
for (int i = 0; i < 18; )
|
||||
for (var i = 0; i < 18; )
|
||||
{
|
||||
Encrypt(ref l, ref r);
|
||||
m_p[i++] = l;
|
||||
m_p[i++] = r;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
for (int j = 0; j < 256; )
|
||||
for (var i = 0; i < 4; ++i)
|
||||
for (var j = 0; j < 256; )
|
||||
{
|
||||
Encrypt(ref l, ref r);
|
||||
m_s[i, j++] = l;
|
||||
@@ -49,14 +49,14 @@ namespace OpenRA.FileFormats
|
||||
|
||||
static uint[] RunCipher(uint[] data, CipherFunc f)
|
||||
{
|
||||
uint[] result = new uint[data.Length];
|
||||
var result = new uint[data.Length];
|
||||
|
||||
int size = data.Length / 2;
|
||||
int i = 0;
|
||||
var size = data.Length / 2;
|
||||
var i = 0;
|
||||
while (size-- > 0)
|
||||
{
|
||||
uint a = SwapBytes(data[i]);
|
||||
uint b = SwapBytes(data[i+1]);
|
||||
var a = SwapBytes(data[i]);
|
||||
var b = SwapBytes(data[i+1]);
|
||||
|
||||
f(ref a, ref b);
|
||||
|
||||
@@ -72,8 +72,8 @@ namespace OpenRA.FileFormats
|
||||
uint _a = a, _b = b;
|
||||
_a ^= m_p[0];
|
||||
|
||||
bool x = false;
|
||||
for( int i = 1; i <= 16; i++, x ^= true)
|
||||
var x = false;
|
||||
for( var i = 1; i <= 16; i++, x ^= true)
|
||||
{
|
||||
if (x)
|
||||
Round(ref _a, _b, i);
|
||||
@@ -91,8 +91,8 @@ namespace OpenRA.FileFormats
|
||||
uint _a = a, _b = b;
|
||||
_a ^= m_p[17];
|
||||
|
||||
bool x = false;
|
||||
for (int i = 16; i >= 1; i--, x ^= true)
|
||||
var x = false;
|
||||
for (var i = 16; i >= 1; i--, x ^= true)
|
||||
{
|
||||
if (x)
|
||||
Round(ref _a, _b, i);
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace OpenRA.FileFormats
|
||||
|
||||
static void init_bignum(uint[] n, uint val, uint len)
|
||||
{
|
||||
for (int i = 0; i < len; i++) n[i] = 0;
|
||||
for (var i = 0; i < len; i++) n[i] = 0;
|
||||
n[0] = val;
|
||||
}
|
||||
|
||||
@@ -52,8 +52,8 @@ namespace OpenRA.FileFormats
|
||||
{
|
||||
fixed (uint* _pn = &n[0])
|
||||
{
|
||||
byte* pn = (byte*)_pn;
|
||||
uint i = blen * 4;
|
||||
var pn = (byte*)_pn;
|
||||
var i = blen * 4;
|
||||
for (; i > klen; i--) pn[i - 1] = (byte)sign;
|
||||
for (; i > 0; i--) pn[i - 1] = key[klen - i];
|
||||
}
|
||||
@@ -65,7 +65,7 @@ namespace OpenRA.FileFormats
|
||||
uint keylen;
|
||||
int i;
|
||||
|
||||
int j = 0;
|
||||
var j = 0;
|
||||
|
||||
if (key[j] != 2) return;
|
||||
j++;
|
||||
@@ -118,7 +118,7 @@ namespace OpenRA.FileFormats
|
||||
|
||||
uint len_predata()
|
||||
{
|
||||
uint a = (pubkey.len - 1) / 8;
|
||||
var a = (pubkey.len - 1) / 8;
|
||||
return (55 / a + 1) * (a + 1);
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ namespace OpenRA.FileFormats
|
||||
|
||||
static void shr_bignum(uint[] n, int bits, int len)
|
||||
{
|
||||
int i; int i2 = bits / 32;
|
||||
int i; var i2 = bits / 32;
|
||||
|
||||
if (i2 > 0)
|
||||
{
|
||||
@@ -183,9 +183,9 @@ namespace OpenRA.FileFormats
|
||||
fixed (uint* _ps2 = &src2[0])
|
||||
fixed (uint* _pd = &dest[0])
|
||||
{
|
||||
ushort* ps1 = (ushort*)_ps1;
|
||||
ushort* ps2 = (ushort*)_ps2;
|
||||
ushort* pd = (ushort*)_pd;
|
||||
var ps1 = (ushort*)_ps1;
|
||||
var ps2 = (ushort*)_ps2;
|
||||
var pd = (ushort*)_pd;
|
||||
|
||||
while (--len != -1)
|
||||
{
|
||||
@@ -205,9 +205,9 @@ namespace OpenRA.FileFormats
|
||||
|
||||
len += len;
|
||||
|
||||
ushort* ps1 = (ushort*)src1;
|
||||
ushort* ps2 = (ushort*)src2;
|
||||
ushort* pd = (ushort*)dest;
|
||||
var ps1 = (ushort*)src1;
|
||||
var ps2 = (ushort*)src2;
|
||||
var pd = (ushort*)dest;
|
||||
|
||||
while (--len != -1)
|
||||
{
|
||||
@@ -222,11 +222,11 @@ namespace OpenRA.FileFormats
|
||||
|
||||
static void inv_bignum(uint[] n1, uint[] n2, uint len)
|
||||
{
|
||||
uint[] n_tmp = new uint[64];
|
||||
var n_tmp = new uint[64];
|
||||
uint n2_bytelen, bit;
|
||||
int n2_bitlen;
|
||||
|
||||
int j = 0;
|
||||
var j = 0;
|
||||
|
||||
init_bignum(n_tmp, 0, len);
|
||||
init_bignum(n1, 0, len);
|
||||
@@ -257,7 +257,7 @@ namespace OpenRA.FileFormats
|
||||
|
||||
static void inc_bignum(uint[] n, uint len)
|
||||
{
|
||||
int i = 0;
|
||||
var i = 0;
|
||||
while ((++n[i] == 0) && (--len > 0)) i++;
|
||||
}
|
||||
|
||||
@@ -289,7 +289,7 @@ namespace OpenRA.FileFormats
|
||||
{
|
||||
fixed (uint* _pn2 = &n2[0])
|
||||
{
|
||||
ushort* pn2 = (ushort*)_pn2;
|
||||
var pn2 = (ushort*)_pn2;
|
||||
|
||||
tmp = 0;
|
||||
for (i = 0; i < len; i++)
|
||||
@@ -314,8 +314,8 @@ namespace OpenRA.FileFormats
|
||||
fixed( uint * _psrc2 = &src2[0] )
|
||||
fixed(uint* _pdest = &dest[0])
|
||||
{
|
||||
ushort* psrc2 = (ushort*)_psrc2;
|
||||
ushort* pdest = (ushort*)_pdest;
|
||||
var psrc2 = (ushort*)_psrc2;
|
||||
var pdest = (ushort*)_pdest;
|
||||
|
||||
init_bignum(dest, 0, len * 2);
|
||||
for (i = 0; i < len * 2; i++)
|
||||
@@ -338,8 +338,8 @@ namespace OpenRA.FileFormats
|
||||
|
||||
unsafe uint get_mulword(uint* n)
|
||||
{
|
||||
ushort* wn = (ushort*)n;
|
||||
uint i = (uint)((((((((((*(wn - 1) ^ 0xffff) & 0xffff) * glob1_hi_inv_lo + 0x10000) >> 1)
|
||||
var wn = (ushort*)n;
|
||||
var i = (uint)((((((((((*(wn - 1) ^ 0xffff) & 0xffff) * glob1_hi_inv_lo + 0x10000) >> 1)
|
||||
+ (((*(wn - 2) ^ 0xffff) * glob1_hi_inv_hi + glob1_hi_inv_hi) >> 1) + 1)
|
||||
>> 16) + ((((*(wn - 1) ^ 0xffff) & 0xffff) * glob1_hi_inv_hi) >> 1) +
|
||||
(((*wn ^ 0xffff) * glob1_hi_inv_lo) >> 1) + 1) >> 14) + glob1_hi_inv_hi
|
||||
@@ -350,7 +350,7 @@ namespace OpenRA.FileFormats
|
||||
|
||||
static void dec_bignum(uint[] n, uint len)
|
||||
{
|
||||
int i = 0;
|
||||
var i = 0;
|
||||
while ((--n[i] == 0xffffffff) && (--len > 0))
|
||||
i++;
|
||||
}
|
||||
@@ -371,12 +371,12 @@ namespace OpenRA.FileFormats
|
||||
inc_bignum(glob2, len * 2 + 1);
|
||||
neg_bignum(glob2, len * 2 + 1);
|
||||
len_diff = g2_len_x2 + 1 - glob1_len_x2;
|
||||
ushort* esi = ((ushort*)g2) + (1 + g2_len_x2 - glob1_len_x2);
|
||||
ushort* edi = ((ushort*)g2) + (g2_len_x2 + 1);
|
||||
var esi = ((ushort*)g2) + (1 + g2_len_x2 - glob1_len_x2);
|
||||
var edi = ((ushort*)g2) + (g2_len_x2 + 1);
|
||||
for (; len_diff != 0; len_diff--)
|
||||
{
|
||||
edi--;
|
||||
uint tmp = get_mulword((uint*)edi);
|
||||
var tmp = get_mulword((uint*)edi);
|
||||
esi--;
|
||||
if (tmp > 0)
|
||||
{
|
||||
@@ -410,7 +410,7 @@ namespace OpenRA.FileFormats
|
||||
|
||||
void calc_a_key(uint[] n1, uint[] n2, uint[] n3, uint[] n4, uint len)
|
||||
{
|
||||
uint[] n_tmp = new uint[64];
|
||||
var n_tmp = new uint[64];
|
||||
uint n3_len, n4_len;
|
||||
int n3_bitlen;
|
||||
uint bit_mask;
|
||||
@@ -419,7 +419,7 @@ namespace OpenRA.FileFormats
|
||||
{
|
||||
fixed (uint* _pn3 = &n3[0])
|
||||
{
|
||||
uint* pn3 = _pn3;
|
||||
var pn3 = _pn3;
|
||||
|
||||
init_bignum(n1, 1, len);
|
||||
n4_len = len_bignum(n4, len);
|
||||
@@ -457,10 +457,10 @@ namespace OpenRA.FileFormats
|
||||
|
||||
unsafe void process_predata(byte* pre, uint pre_len, byte *buf)
|
||||
{
|
||||
uint[] n2 = new uint[64];
|
||||
uint[] n3 = new uint[64];
|
||||
var n2 = new uint[64];
|
||||
var n3 = new uint[64];
|
||||
|
||||
uint a = (pubkey.len - 1) / 8;
|
||||
var a = (pubkey.len - 1) / 8;
|
||||
while (a + 1 <= pre_len)
|
||||
{
|
||||
init_bignum(n2, 0, 64);
|
||||
@@ -480,7 +480,7 @@ namespace OpenRA.FileFormats
|
||||
public byte[] DecryptKey(byte[] src)
|
||||
{
|
||||
init_pubkey();
|
||||
byte[] dest = new byte[256];
|
||||
var dest = new byte[256];
|
||||
|
||||
unsafe
|
||||
{
|
||||
|
||||
@@ -98,8 +98,8 @@ namespace OpenRA.FileFormats
|
||||
/// </returns>
|
||||
public static uint Calculate(byte[] data, uint polynomial)
|
||||
{
|
||||
uint crc = polynomial;
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
var crc = polynomial;
|
||||
for (var i = 0; i < data.Length; i++)
|
||||
crc = (crc >> 8) ^ lookUp[(crc & 0xFF) ^ data[i]];
|
||||
crc ^= polynomial;
|
||||
return crc;
|
||||
@@ -119,8 +119,8 @@ namespace OpenRA.FileFormats
|
||||
/// <returns>The calculated checksum.</returns>
|
||||
public static unsafe uint Calculate(byte* data, uint len, uint polynomial)
|
||||
{
|
||||
uint crc = polynomial;
|
||||
for (int i = 0; i < len; i++)
|
||||
var crc = polynomial;
|
||||
for (var i = 0; i < len; i++)
|
||||
crc = (crc >> 8) ^ lookUp[(crc & 0xFF) ^ *data++];
|
||||
crc ^= polynomial;
|
||||
return crc;
|
||||
|
||||
@@ -12,58 +12,58 @@ namespace OpenRA.FileFormats
|
||||
{
|
||||
public static class Format40
|
||||
{
|
||||
public static int DecodeInto( byte[] src, byte[] dest )
|
||||
public static int DecodeInto(byte[] src, byte[] dest, int srcOffset)
|
||||
{
|
||||
var ctx = new FastByteReader(src);
|
||||
int destIndex = 0;
|
||||
var ctx = new FastByteReader(src, srcOffset);
|
||||
var destIndex = 0;
|
||||
|
||||
while( true )
|
||||
while (true)
|
||||
{
|
||||
byte i = ctx.ReadByte();
|
||||
if( ( i & 0x80 ) == 0 )
|
||||
var i = ctx.ReadByte();
|
||||
if ((i & 0x80) == 0)
|
||||
{
|
||||
int count = i & 0x7F;
|
||||
if( count == 0 )
|
||||
var count = i & 0x7F;
|
||||
if (count == 0)
|
||||
{
|
||||
// case 6
|
||||
count = ctx.ReadByte();
|
||||
byte value = ctx.ReadByte();
|
||||
for( int end = destIndex + count ; destIndex < end ; destIndex++ )
|
||||
dest[ destIndex ] ^= value;
|
||||
var value = ctx.ReadByte();
|
||||
for (var end = destIndex + count; destIndex < end; destIndex++)
|
||||
dest[destIndex] ^= value;
|
||||
}
|
||||
else
|
||||
{
|
||||
// case 5
|
||||
for( int end = destIndex + count ; destIndex < end ; destIndex++ )
|
||||
for (var end = destIndex + count; destIndex < end; destIndex++)
|
||||
dest[destIndex] ^= ctx.ReadByte();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int count = i & 0x7F;
|
||||
if( count == 0 )
|
||||
var count = i & 0x7F;
|
||||
if (count == 0)
|
||||
{
|
||||
count = ctx.ReadWord();
|
||||
if( count == 0 )
|
||||
if (count == 0)
|
||||
return destIndex;
|
||||
|
||||
if( ( count & 0x8000 ) == 0 )
|
||||
if ((count & 0x8000) == 0)
|
||||
{
|
||||
// case 2
|
||||
destIndex += ( count & 0x7FFF );
|
||||
destIndex += (count & 0x7FFF);
|
||||
}
|
||||
else if( ( count & 0x4000 ) == 0 )
|
||||
else if ((count & 0x4000) == 0)
|
||||
{
|
||||
// case 3
|
||||
for( int end = destIndex + ( count & 0x3FFF ) ; destIndex < end ; destIndex++ )
|
||||
for (var end = destIndex + (count & 0x3FFF); destIndex < end; destIndex++)
|
||||
dest[destIndex] ^= ctx.ReadByte();
|
||||
}
|
||||
else
|
||||
{
|
||||
// case 4
|
||||
byte value = ctx.ReadByte();
|
||||
for( int end = destIndex + ( count & 0x3FFF ) ; destIndex < end ; destIndex++ )
|
||||
dest[ destIndex ] ^= value;
|
||||
var value = ctx.ReadByte();
|
||||
for (var end = destIndex + (count & 0x3FFF); destIndex < end; destIndex++)
|
||||
dest[destIndex] ^= value;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
||||
* Copyright 2007-2014 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,
|
||||
@@ -16,11 +16,12 @@ namespace OpenRA.FileFormats
|
||||
class FastByteReader
|
||||
{
|
||||
readonly byte[] src;
|
||||
int offset = 0;
|
||||
int offset;
|
||||
|
||||
public FastByteReader(byte[] src)
|
||||
public FastByteReader(byte[] src, int offset = 0)
|
||||
{
|
||||
this.src = src;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
public bool Done() { return offset >= src.Length; }
|
||||
@@ -59,9 +60,9 @@ namespace OpenRA.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
public static int DecodeInto(byte[] src, byte[] dest)
|
||||
public static int DecodeInto(byte[] src, byte[] dest, int srcOffset = 0)
|
||||
{
|
||||
var ctx = new FastByteReader(src);
|
||||
var ctx = new FastByteReader(src, srcOffset);
|
||||
var destIndex = 0;
|
||||
|
||||
while (true)
|
||||
@@ -125,26 +126,78 @@ namespace OpenRA.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
static int CountSame(byte[] src, int offset, int maxCount)
|
||||
{
|
||||
maxCount = Math.Min(src.Length - offset, maxCount);
|
||||
if (maxCount <= 0)
|
||||
return 0;
|
||||
|
||||
var first = src[offset++];
|
||||
var count = 1;
|
||||
|
||||
while (count < maxCount && src[offset++] == first)
|
||||
count++;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static void WriteCopyBlocks(byte[] src, int offset, int count, MemoryStream output)
|
||||
{
|
||||
while (count > 0)
|
||||
{
|
||||
var writeNow = Math.Min(count, 0x3F);
|
||||
output.WriteByte((byte)(0x80 | writeNow));
|
||||
output.Write(src, offset, writeNow);
|
||||
|
||||
count -= writeNow;
|
||||
offset += writeNow;
|
||||
}
|
||||
}
|
||||
|
||||
// Quick and dirty Format80 encoder version 2
|
||||
// Uses raw copy and RLE compression
|
||||
public static byte[] Encode(byte[] src)
|
||||
{
|
||||
/* quick & dirty format80 encoder -- only uses raw copy operator, terminated with a zero-run. */
|
||||
/* this does not produce good compression, but it's valid format80 */
|
||||
|
||||
var ctx = new FastByteReader(src);
|
||||
var ms = new MemoryStream();
|
||||
|
||||
do
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
var len = Math.Min(ctx.Remaining(), 0x3F);
|
||||
ms.WriteByte((byte)(0x80 | len));
|
||||
while (len-- > 0)
|
||||
ms.WriteByte(ctx.ReadByte());
|
||||
var offset = 0;
|
||||
var left = src.Length;
|
||||
var blockStart = 0;
|
||||
|
||||
while (offset < left)
|
||||
{
|
||||
var repeatCount = CountSame(src, offset, 0xFFFF);
|
||||
if (repeatCount >= 4)
|
||||
{
|
||||
// Write what we haven't written up to now
|
||||
WriteCopyBlocks(src, blockStart, offset - blockStart, ms);
|
||||
|
||||
// Command 4: Repeat byte n times
|
||||
ms.WriteByte(0xFE);
|
||||
// Low byte
|
||||
ms.WriteByte((byte)(repeatCount & 0xFF));
|
||||
// High byte
|
||||
ms.WriteByte((byte)(repeatCount >> 8));
|
||||
// Value to repeat
|
||||
ms.WriteByte(src[offset]);
|
||||
|
||||
offset += repeatCount;
|
||||
blockStart = offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
|
||||
// Write what we haven't written up to now
|
||||
WriteCopyBlocks(src, blockStart, offset - blockStart, ms);
|
||||
|
||||
// Write terminator
|
||||
ms.WriteByte(0x80);
|
||||
|
||||
return ms.ToArray();
|
||||
}
|
||||
while (!ctx.Done());
|
||||
|
||||
ms.WriteByte(0x80); // terminator -- 0-length run.
|
||||
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace OpenRA.FileFormats
|
||||
|
||||
public void Load(Stream s)
|
||||
{
|
||||
StreamReader reader = new StreamReader(s);
|
||||
var reader = new StreamReader(s);
|
||||
IniSection currentSection = null;
|
||||
|
||||
while (!reader.EndOfStream)
|
||||
@@ -55,10 +55,10 @@ namespace OpenRA.FileFormats
|
||||
|
||||
IniSection ProcessSection(string line)
|
||||
{
|
||||
Match m = sectionPattern.Match(line);
|
||||
var m = sectionPattern.Match(line);
|
||||
if (!m.Success)
|
||||
return null;
|
||||
string sectionName = m.Groups[1].Value.ToLowerInvariant();
|
||||
var sectionName = m.Groups[1].Value.ToLowerInvariant();
|
||||
|
||||
IniSection ret;
|
||||
if (!sections.TryGetValue(sectionName, out ret))
|
||||
@@ -78,7 +78,7 @@ namespace OpenRA.FileFormats
|
||||
|
||||
var key = line;
|
||||
var value = "";
|
||||
int eq = line.IndexOf('=');
|
||||
var eq = line.IndexOf('=');
|
||||
if (eq >= 0)
|
||||
{
|
||||
key = line.Substring(0, eq);
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace OpenRA.FileFormats
|
||||
|
||||
Bitmap bitmap = null;
|
||||
Color[] palette = null;
|
||||
List<byte> data = new List<byte>();
|
||||
var data = new List<byte>();
|
||||
|
||||
for (; ; )
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
||||
* Copyright 2007-2014 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,
|
||||
@@ -8,72 +8,73 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using OpenRA.Graphics;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
class R8Image : ISpriteFrame
|
||||
{
|
||||
public Size Size { get; private set; }
|
||||
public Size FrameSize { get; private set; }
|
||||
public float2 Offset { get; private set; }
|
||||
public byte[] Data { get; set; }
|
||||
|
||||
public R8Image(Stream s)
|
||||
{
|
||||
// Scan forward until we find some data
|
||||
var type = s.ReadUInt8();
|
||||
while (type == 0)
|
||||
type = s.ReadUInt8();
|
||||
|
||||
var width = s.ReadInt32();
|
||||
var height = s.ReadInt32();
|
||||
var x = s.ReadInt32();
|
||||
var y = s.ReadInt32();
|
||||
|
||||
Size = new Size(width, height);
|
||||
Offset = new int2(width/2 - x, height/2 - y);
|
||||
|
||||
/*var imageOffset = */s.ReadInt32();
|
||||
var paletteOffset = s.ReadInt32();
|
||||
var bpp = s.ReadUInt8();
|
||||
if (bpp != 8)
|
||||
throw new InvalidDataException("Error: {0} bits per pixel are not supported.".F(bpp));
|
||||
|
||||
var frameHeight = s.ReadUInt8();
|
||||
var frameWidth = s.ReadUInt8();
|
||||
FrameSize = new Size(frameWidth, frameHeight);
|
||||
|
||||
// Skip alignment byte
|
||||
s.ReadUInt8();
|
||||
|
||||
Data = s.ReadBytes(width*height);
|
||||
|
||||
// Ignore palette
|
||||
if (type == 1 && paletteOffset != 0)
|
||||
s.Seek(520, SeekOrigin.Current);
|
||||
}
|
||||
}
|
||||
|
||||
public class R8Reader : ISpriteSource
|
||||
{
|
||||
readonly List<ISpriteFrame> frames = new List<ISpriteFrame>();
|
||||
public IEnumerable<ISpriteFrame> Frames { get { return frames; } }
|
||||
class R8Image : ISpriteFrame
|
||||
{
|
||||
public Size Size { get; private set; }
|
||||
public Size FrameSize { get; private set; }
|
||||
public float2 Offset { get; private set; }
|
||||
public byte[] Data { get; set; }
|
||||
|
||||
public R8Image(Stream s)
|
||||
{
|
||||
// Scan forward until we find some data
|
||||
var type = s.ReadUInt8();
|
||||
while (type == 0)
|
||||
type = s.ReadUInt8();
|
||||
|
||||
var width = s.ReadInt32();
|
||||
var height = s.ReadInt32();
|
||||
var x = s.ReadInt32();
|
||||
var y = s.ReadInt32();
|
||||
|
||||
Size = new Size(width, height);
|
||||
Offset = new int2(width / 2 - x, height / 2 - y);
|
||||
|
||||
/*var imageOffset = */
|
||||
s.ReadInt32();
|
||||
var paletteOffset = s.ReadInt32();
|
||||
var bpp = s.ReadUInt8();
|
||||
if (bpp != 8)
|
||||
throw new InvalidDataException("Error: {0} bits per pixel are not supported.".F(bpp));
|
||||
|
||||
var frameHeight = s.ReadUInt8();
|
||||
var frameWidth = s.ReadUInt8();
|
||||
FrameSize = new Size(frameWidth, frameHeight);
|
||||
|
||||
// Skip alignment byte
|
||||
s.ReadUInt8();
|
||||
|
||||
Data = s.ReadBytes(width * height);
|
||||
|
||||
// Ignore palette
|
||||
if (type == 1 && paletteOffset != 0)
|
||||
s.Seek(520, SeekOrigin.Current);
|
||||
}
|
||||
}
|
||||
|
||||
public IReadOnlyList<ISpriteFrame> Frames { get; private set; }
|
||||
public bool CacheWhenLoadingTileset { get { return true; } }
|
||||
|
||||
public readonly int ImageCount;
|
||||
public R8Reader(Stream stream)
|
||||
{
|
||||
var frames = new List<R8Image>();
|
||||
while (stream.Position < stream.Length)
|
||||
{
|
||||
frames.Add(new R8Image(stream));
|
||||
ImageCount++;
|
||||
}
|
||||
|
||||
Frames = frames.ToArray().AsReadOnly();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using OpenRA.Network;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
@@ -47,7 +46,7 @@ namespace OpenRA.FileFormats
|
||||
throw new NotSupportedException("Metadata version {0} is not supported".F(version));
|
||||
|
||||
// Read game info (max 100K limit as a safeguard against corrupted files)
|
||||
string data = fs.ReadString(Encoding.UTF8, 1024 * 100);
|
||||
var data = fs.ReadString(Encoding.UTF8, 1024 * 100);
|
||||
GameInfo = GameInformation.Deserialize(data);
|
||||
}
|
||||
|
||||
@@ -58,7 +57,7 @@ namespace OpenRA.FileFormats
|
||||
writer.Write(MetaVersion);
|
||||
|
||||
// Write data
|
||||
int dataLength = 0;
|
||||
var dataLength = 0;
|
||||
{
|
||||
// Write lobby info data
|
||||
writer.Flush();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
||||
* Copyright 2007-2014 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,
|
||||
@@ -9,85 +9,81 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using OpenRA.Graphics;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
[Flags] enum FormatFlags : int
|
||||
{
|
||||
PaletteTable = 1,
|
||||
SkipFormat80 = 2,
|
||||
VariableLengthTable = 4
|
||||
}
|
||||
|
||||
class Frame : ISpriteFrame
|
||||
{
|
||||
public Size Size { get; private set; }
|
||||
public Size FrameSize { get { return Size; } }
|
||||
public float2 Offset { get { return float2.Zero; } }
|
||||
public byte[] Data { get; set; }
|
||||
|
||||
public Frame(Stream s)
|
||||
{
|
||||
var flags = (FormatFlags)s.ReadUInt16();
|
||||
s.Position += 1;
|
||||
var width = s.ReadUInt16();
|
||||
var height = s.ReadUInt8();
|
||||
Size = new Size(width, height);
|
||||
|
||||
// Subtract header size
|
||||
var dataLeft = s.ReadUInt16() - 10;
|
||||
var dataSize = s.ReadUInt16();
|
||||
|
||||
byte[] table;
|
||||
if ((flags & FormatFlags.PaletteTable) != 0)
|
||||
{
|
||||
var n = (flags & FormatFlags.VariableLengthTable) != 0 ? s.ReadUInt8() : (byte)16;
|
||||
table = new byte[n];
|
||||
for (var i = 0; i < n; i++)
|
||||
table[i] = s.ReadUInt8();
|
||||
|
||||
dataLeft -= n;
|
||||
}
|
||||
else
|
||||
{
|
||||
table = new byte[256];
|
||||
for (var i = 0; i < 256; i++)
|
||||
table[i] = (byte)i;
|
||||
table[1] = 0x7f;
|
||||
table[2] = 0x7e;
|
||||
table[3] = 0x7d;
|
||||
table[4] = 0x7c;
|
||||
}
|
||||
|
||||
Data = new byte[width * height];
|
||||
|
||||
// Decode image data
|
||||
var compressed = s.ReadBytes(dataLeft);
|
||||
if ((flags & FormatFlags.SkipFormat80) == 0)
|
||||
{
|
||||
var temp = new byte[dataSize];
|
||||
Format80.DecodeInto(compressed, temp);
|
||||
compressed = temp;
|
||||
}
|
||||
|
||||
Format2.DecodeInto(compressed, Data, 0);
|
||||
|
||||
// Lookup values in lookup table
|
||||
for (var j = 0; j < Data.Length; j++)
|
||||
Data[j] = table[Data[j]];
|
||||
}
|
||||
}
|
||||
|
||||
public class ShpD2Reader : ISpriteSource
|
||||
{
|
||||
readonly List<ISpriteFrame> frames = new List<ISpriteFrame>();
|
||||
public IEnumerable<ISpriteFrame> Frames { get { return frames; } }
|
||||
[Flags] enum FormatFlags : int
|
||||
{
|
||||
PaletteTable = 1,
|
||||
SkipFormat80 = 2,
|
||||
VariableLengthTable = 4
|
||||
}
|
||||
|
||||
class Frame : ISpriteFrame
|
||||
{
|
||||
public Size Size { get; private set; }
|
||||
public Size FrameSize { get { return Size; } }
|
||||
public float2 Offset { get { return float2.Zero; } }
|
||||
public byte[] Data { get; set; }
|
||||
|
||||
public Frame(Stream s)
|
||||
{
|
||||
var flags = (FormatFlags)s.ReadUInt16();
|
||||
s.Position += 1;
|
||||
var width = s.ReadUInt16();
|
||||
var height = s.ReadUInt8();
|
||||
Size = new Size(width, height);
|
||||
|
||||
// Subtract header size
|
||||
var dataLeft = s.ReadUInt16() - 10;
|
||||
var dataSize = s.ReadUInt16();
|
||||
|
||||
byte[] table;
|
||||
if ((flags & FormatFlags.PaletteTable) != 0)
|
||||
{
|
||||
var n = (flags & FormatFlags.VariableLengthTable) != 0 ? s.ReadUInt8() : (byte)16;
|
||||
table = new byte[n];
|
||||
for (var i = 0; i < n; i++)
|
||||
table[i] = s.ReadUInt8();
|
||||
|
||||
dataLeft -= n;
|
||||
}
|
||||
else
|
||||
{
|
||||
table = new byte[256];
|
||||
for (var i = 0; i < 256; i++)
|
||||
table[i] = (byte)i;
|
||||
table[1] = 0x7f;
|
||||
table[2] = 0x7e;
|
||||
table[3] = 0x7d;
|
||||
table[4] = 0x7c;
|
||||
}
|
||||
|
||||
Data = new byte[width * height];
|
||||
|
||||
// Decode image data
|
||||
var compressed = s.ReadBytes(dataLeft);
|
||||
if ((flags & FormatFlags.SkipFormat80) == 0)
|
||||
{
|
||||
var temp = new byte[dataSize];
|
||||
Format80.DecodeInto(compressed, temp);
|
||||
compressed = temp;
|
||||
}
|
||||
|
||||
Format2.DecodeInto(compressed, Data, 0);
|
||||
|
||||
// Lookup values in lookup table
|
||||
for (var j = 0; j < Data.Length; j++)
|
||||
Data[j] = table[Data[j]];
|
||||
}
|
||||
}
|
||||
|
||||
public IReadOnlyList<ISpriteFrame> Frames { get; private set; }
|
||||
public bool CacheWhenLoadingTileset { get { return false; } }
|
||||
|
||||
public ShpD2Reader(Stream s)
|
||||
@@ -105,10 +101,12 @@ namespace OpenRA.FileFormats
|
||||
for (var i = 0; i < imageCount + 1; i++)
|
||||
offsets[i] = (twoByteOffset ? s.ReadUInt16() : s.ReadUInt32()) + 2;
|
||||
|
||||
for (var i = 0; i < imageCount; i++)
|
||||
var frames = new Frame[imageCount];
|
||||
Frames = frames.AsReadOnly();
|
||||
for (var i = 0; i < frames.Length; i++)
|
||||
{
|
||||
s.Position = offsets[i];
|
||||
frames.Add(new Frame(s));
|
||||
frames[i] = new Frame(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
||||
* Copyright 2007-2014 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,
|
||||
@@ -17,56 +17,58 @@ using OpenRA.Graphics;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
enum Format { Format20 = 0x20, Format40 = 0x40, Format80 = 0x80 }
|
||||
|
||||
class ImageHeader : ISpriteFrame
|
||||
{
|
||||
public Size Size { get { return reader.Size; } }
|
||||
public Size FrameSize { get { return reader.Size; } }
|
||||
public float2 Offset { get { return float2.Zero; } }
|
||||
public byte[] Data { get; set; }
|
||||
|
||||
public uint FileOffset;
|
||||
public Format Format;
|
||||
|
||||
public uint RefOffset;
|
||||
public Format RefFormat;
|
||||
public ImageHeader RefImage;
|
||||
|
||||
ShpReader reader;
|
||||
// Used by ShpWriter
|
||||
public ImageHeader() { }
|
||||
|
||||
public ImageHeader(Stream stream, ShpReader reader)
|
||||
{
|
||||
this.reader = reader;
|
||||
var data = stream.ReadUInt32();
|
||||
FileOffset = data & 0xffffff;
|
||||
Format = (Format)(data >> 24);
|
||||
|
||||
RefOffset = stream.ReadUInt16();
|
||||
RefFormat = (Format)stream.ReadUInt16();
|
||||
}
|
||||
|
||||
public void WriteTo(BinaryWriter writer)
|
||||
{
|
||||
writer.Write(FileOffset | ((uint)Format << 24));
|
||||
writer.Write((ushort)RefOffset);
|
||||
writer.Write((ushort)RefFormat);
|
||||
}
|
||||
}
|
||||
|
||||
public class ShpReader : ISpriteSource
|
||||
{
|
||||
readonly List<ImageHeader> headers = new List<ImageHeader>();
|
||||
Lazy<IEnumerable<ISpriteFrame>> spriteFrames;
|
||||
public IEnumerable<ISpriteFrame> Frames { get { return spriteFrames.Value; } }
|
||||
enum Format { Format20 = 0x20, Format40 = 0x40, Format80 = 0x80 }
|
||||
|
||||
class ImageHeader : ISpriteFrame
|
||||
{
|
||||
public Size Size { get { return reader.Size; } }
|
||||
public Size FrameSize { get { return reader.Size; } }
|
||||
public float2 Offset { get { return float2.Zero; } }
|
||||
public byte[] Data { get; set; }
|
||||
|
||||
public uint FileOffset;
|
||||
public Format Format;
|
||||
|
||||
public uint RefOffset;
|
||||
public Format RefFormat;
|
||||
public ImageHeader RefImage;
|
||||
|
||||
ShpReader reader;
|
||||
|
||||
// Used by ShpWriter
|
||||
public ImageHeader() { }
|
||||
|
||||
public ImageHeader(Stream stream, ShpReader reader)
|
||||
{
|
||||
this.reader = reader;
|
||||
var data = stream.ReadUInt32();
|
||||
FileOffset = data & 0xffffff;
|
||||
Format = (Format)(data >> 24);
|
||||
|
||||
RefOffset = stream.ReadUInt16();
|
||||
RefFormat = (Format)stream.ReadUInt16();
|
||||
}
|
||||
|
||||
public void WriteTo(BinaryWriter writer)
|
||||
{
|
||||
writer.Write(FileOffset | ((uint)Format << 24));
|
||||
writer.Write((ushort)RefOffset);
|
||||
writer.Write((ushort)RefFormat);
|
||||
}
|
||||
}
|
||||
|
||||
public IReadOnlyList<ISpriteFrame> Frames { get; private set; }
|
||||
public bool CacheWhenLoadingTileset { get { return false; } }
|
||||
public readonly Size Size;
|
||||
|
||||
int recurseDepth = 0;
|
||||
readonly int imageCount;
|
||||
|
||||
readonly long shpBytesFileOffset;
|
||||
readonly byte[] shpBytes;
|
||||
|
||||
public ShpReader(Stream stream)
|
||||
{
|
||||
imageCount = stream.ReadUInt16();
|
||||
@@ -76,8 +78,10 @@ namespace OpenRA.FileFormats
|
||||
Size = new Size(width, height);
|
||||
|
||||
stream.Position += 4;
|
||||
for (var i = 0; i < imageCount; i++)
|
||||
headers.Add(new ImageHeader(stream, this));
|
||||
var headers = new ImageHeader[imageCount];
|
||||
Frames = headers.AsReadOnly();
|
||||
for (var i = 0; i < headers.Length; i++)
|
||||
headers[i] = new ImageHeader(stream, this);
|
||||
|
||||
// Skip eof and zero headers
|
||||
stream.Position += 16;
|
||||
@@ -88,30 +92,18 @@ namespace OpenRA.FileFormats
|
||||
var h = headers[i];
|
||||
if (h.Format == Format.Format20)
|
||||
h.RefImage = headers[i - 1];
|
||||
|
||||
else if (h.Format == Format.Format40 && !offsets.TryGetValue(h.RefOffset, out h.RefImage))
|
||||
throw new InvalidDataException("Reference doesnt point to image data {0}->{1}".F(h.FileOffset, h.RefOffset));
|
||||
}
|
||||
|
||||
shpBytesFileOffset = stream.Position;
|
||||
shpBytes = stream.ReadBytes((int)(stream.Length - stream.Position));
|
||||
|
||||
foreach (var h in headers)
|
||||
Decompress(stream, h);
|
||||
|
||||
spriteFrames = Exts.Lazy(() => headers.Cast<ISpriteFrame>());
|
||||
Decompress(h);
|
||||
}
|
||||
|
||||
static byte[] ReadCompressedData(Stream stream, ImageHeader h)
|
||||
{
|
||||
stream.Position = h.FileOffset;
|
||||
|
||||
// Actually, far too big. There's no length field with the correct length though :(
|
||||
var compressedLength = (int)(stream.Length - stream.Position);
|
||||
var compressedBytes = new byte[compressedLength];
|
||||
stream.Read(compressedBytes, 0, compressedLength);
|
||||
|
||||
return compressedBytes;
|
||||
}
|
||||
|
||||
void Decompress(Stream stream, ImageHeader h)
|
||||
void Decompress(ImageHeader h)
|
||||
{
|
||||
// No extra work is required for empty frames
|
||||
if (h.Size.Width == 0 || h.Size.Height == 0)
|
||||
@@ -128,19 +120,19 @@ namespace OpenRA.FileFormats
|
||||
if (h.RefImage.Data == null)
|
||||
{
|
||||
++recurseDepth;
|
||||
Decompress(stream, h.RefImage);
|
||||
Decompress(h.RefImage);
|
||||
--recurseDepth;
|
||||
}
|
||||
|
||||
h.Data = CopyImageData(h.RefImage.Data);
|
||||
Format40.DecodeInto(ReadCompressedData(stream, h), h.Data);
|
||||
Format40.DecodeInto(shpBytes, h.Data, (int)(h.FileOffset - shpBytesFileOffset));
|
||||
break;
|
||||
}
|
||||
|
||||
case Format.Format80:
|
||||
{
|
||||
var imageBytes = new byte[Size.Width * Size.Height];
|
||||
Format80.DecodeInto(ReadCompressedData(stream, h), imageBytes);
|
||||
Format80.DecodeInto(shpBytes, imageBytes, (int)(h.FileOffset - shpBytesFileOffset));
|
||||
h.Data = imageBytes;
|
||||
break;
|
||||
}
|
||||
@@ -153,9 +145,7 @@ namespace OpenRA.FileFormats
|
||||
byte[] CopyImageData(byte[] baseImage)
|
||||
{
|
||||
var imageData = new byte[Size.Width * Size.Height];
|
||||
for (var i = 0; i < Size.Width * Size.Height; i++)
|
||||
imageData[i] = baseImage[i];
|
||||
|
||||
Array.Copy(baseImage, imageData, imageData.Length);
|
||||
return imageData;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
||||
* Copyright 2007-2014 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,
|
||||
@@ -8,47 +8,43 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using OpenRA.Graphics;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
class FrameHeader : ISpriteFrame
|
||||
{
|
||||
public Size Size { get; private set; }
|
||||
public Size FrameSize { get; private set; }
|
||||
public float2 Offset { get; private set; }
|
||||
public byte[] Data { get; set; }
|
||||
|
||||
public readonly uint FileOffset;
|
||||
public readonly byte Format;
|
||||
|
||||
public FrameHeader(Stream stream, Size frameSize)
|
||||
{
|
||||
var x = stream.ReadUInt16();
|
||||
var y = stream.ReadUInt16();
|
||||
var width = stream.ReadUInt16();
|
||||
var height = stream.ReadUInt16();
|
||||
|
||||
Offset = new float2(x + 0.5f * (width - frameSize.Width), y + 0.5f * (height - frameSize.Height));
|
||||
Size = new Size(width, height);
|
||||
FrameSize = frameSize;
|
||||
|
||||
Format = stream.ReadUInt8();
|
||||
stream.Position += 11;
|
||||
FileOffset = stream.ReadUInt32();
|
||||
}
|
||||
}
|
||||
|
||||
public class ShpTSReader : ISpriteSource
|
||||
{
|
||||
readonly List<FrameHeader> frames = new List<FrameHeader>();
|
||||
Lazy<IEnumerable<ISpriteFrame>> spriteFrames;
|
||||
public IEnumerable<ISpriteFrame> Frames { get { return spriteFrames.Value; } }
|
||||
class FrameHeader : ISpriteFrame
|
||||
{
|
||||
public Size Size { get; private set; }
|
||||
public Size FrameSize { get; private set; }
|
||||
public float2 Offset { get; private set; }
|
||||
public byte[] Data { get; set; }
|
||||
|
||||
public readonly uint FileOffset;
|
||||
public readonly byte Format;
|
||||
|
||||
public FrameHeader(Stream stream, Size frameSize)
|
||||
{
|
||||
var x = stream.ReadUInt16();
|
||||
var y = stream.ReadUInt16();
|
||||
var width = stream.ReadUInt16();
|
||||
var height = stream.ReadUInt16();
|
||||
|
||||
// Note: the mixed Integer / fp division is intentional, and required for calculating the correct offset.
|
||||
Offset = new float2(x + width / 2 - 0.5f * frameSize.Width, y + height / 2 - 0.5f * frameSize.Height);
|
||||
Size = new Size(width, height);
|
||||
FrameSize = frameSize;
|
||||
|
||||
Format = stream.ReadUInt8();
|
||||
stream.Position += 11;
|
||||
FileOffset = stream.ReadUInt32();
|
||||
}
|
||||
}
|
||||
|
||||
public IReadOnlyList<ISpriteFrame> Frames { get; private set; }
|
||||
public bool CacheWhenLoadingTileset { get { return false; } }
|
||||
|
||||
public ShpTSReader(Stream stream)
|
||||
@@ -59,8 +55,10 @@ namespace OpenRA.FileFormats
|
||||
var size = new Size(width, height);
|
||||
var frameCount = stream.ReadUInt16();
|
||||
|
||||
for (var i = 0; i < frameCount; i++)
|
||||
frames.Add(new FrameHeader(stream, size));
|
||||
var frames = new FrameHeader[frameCount];
|
||||
Frames = frames.AsReadOnly();
|
||||
for (var i = 0; i < frames.Length; i++)
|
||||
frames[i] = new FrameHeader(stream, size);
|
||||
|
||||
for (var i = 0; i < frameCount; i++)
|
||||
{
|
||||
@@ -70,35 +68,36 @@ namespace OpenRA.FileFormats
|
||||
|
||||
stream.Position = f.FileOffset;
|
||||
|
||||
var frameSize = f.Size.Width * f.Size.Height;
|
||||
|
||||
// Uncompressed
|
||||
if (f.Format == 1 || f.Format == 0)
|
||||
f.Data = stream.ReadBytes(f.Size.Width * f.Size.Height);
|
||||
f.Data = stream.ReadBytes(frameSize);
|
||||
|
||||
// Uncompressed scanlines
|
||||
else if (f.Format == 2)
|
||||
{
|
||||
f.Data = new byte[f.Size.Width * f.Size.Height];
|
||||
f.Data = new byte[frameSize];
|
||||
for (var j = 0; j < f.Size.Height; j++)
|
||||
{
|
||||
var length = stream.ReadUInt16() - 2;
|
||||
stream.Read(f.Data, f.Size.Width * j, length);
|
||||
var offset = f.Size.Width * j;
|
||||
stream.ReadBytes(f.Data, offset, length);
|
||||
}
|
||||
}
|
||||
|
||||
// RLE-zero compressed scanlines
|
||||
else if (f.Format == 3)
|
||||
{
|
||||
f.Data = new byte[f.Size.Width * f.Size.Height];
|
||||
|
||||
f.Data = new byte[frameSize];
|
||||
for (var j = 0; j < f.Size.Height; j++)
|
||||
{
|
||||
var length = stream.ReadUInt16() - 2;
|
||||
Format2.DecodeInto(stream.ReadBytes(length), f.Data, j * f.Size.Width);
|
||||
var offset = f.Size.Width * j;
|
||||
Format2.DecodeInto(stream.ReadBytes(length), f.Data, offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spriteFrames = Exts.Lazy(() => frames.Cast<ISpriteFrame>());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
||||
* Copyright 2007-2014 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,
|
||||
@@ -8,18 +8,15 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using OpenRA.Graphics;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class TmpRAReader : ISpriteSource
|
||||
{
|
||||
readonly List<ISpriteFrame> tiles = new List<ISpriteFrame>();
|
||||
public IEnumerable<ISpriteFrame> Frames { get { return tiles; } }
|
||||
public IReadOnlyList<ISpriteFrame> Frames { get; private set; }
|
||||
public bool CacheWhenLoadingTileset { get { return false; } }
|
||||
|
||||
public TmpRAReader(Stream s)
|
||||
@@ -36,15 +33,19 @@ namespace OpenRA.FileFormats
|
||||
var indexStart = s.ReadInt32();
|
||||
|
||||
s.Position = indexStart;
|
||||
foreach (byte b in s.ReadBytes(indexEnd - indexStart))
|
||||
var count = indexEnd - indexStart;
|
||||
var tiles = new TmpTile[count];
|
||||
Frames = tiles.AsReadOnly();
|
||||
var tilesIndex = 0;
|
||||
foreach (var b in s.ReadBytes(count))
|
||||
{
|
||||
if (b != 255)
|
||||
{
|
||||
s.Position = imgStart + b * width * height;
|
||||
tiles.Add(new TmpTile(s.ReadBytes(width * height), size));
|
||||
tiles[tilesIndex++] = new TmpTile(s.ReadBytes(width * height), size);
|
||||
}
|
||||
else
|
||||
tiles.Add(new TmpTile(null, size));
|
||||
tiles[tilesIndex++] = new TmpTile(null, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
||||
* Copyright 2007-2014 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,
|
||||
@@ -8,9 +8,7 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using OpenRA.Graphics;
|
||||
|
||||
@@ -37,8 +35,7 @@ namespace OpenRA.FileFormats
|
||||
|
||||
public class TmpTDReader : ISpriteSource
|
||||
{
|
||||
readonly List<ISpriteFrame> tiles = new List<ISpriteFrame>();
|
||||
public IEnumerable<ISpriteFrame> Frames { get { return tiles; } }
|
||||
public IReadOnlyList<ISpriteFrame> Frames { get; private set; }
|
||||
public bool CacheWhenLoadingTileset { get { return false; } }
|
||||
|
||||
public TmpTDReader(Stream s)
|
||||
@@ -54,15 +51,19 @@ namespace OpenRA.FileFormats
|
||||
var indexStart = s.ReadInt32();
|
||||
|
||||
s.Position = indexStart;
|
||||
foreach (byte b in s.ReadBytes(indexEnd - indexStart))
|
||||
var count = indexEnd - indexStart;
|
||||
var tiles = new TmpTile[count];
|
||||
Frames = tiles.AsReadOnly();
|
||||
var tilesIndex = 0;
|
||||
foreach (var b in s.ReadBytes(count))
|
||||
{
|
||||
if (b != 255)
|
||||
{
|
||||
s.Position = imgStart + b * width * height;
|
||||
tiles.Add(new TmpTile(s.ReadBytes(width * height), size));
|
||||
tiles[tilesIndex++] = new TmpTile(s.ReadBytes(width * height), size);
|
||||
}
|
||||
else
|
||||
tiles.Add(new TmpTile(null, size));
|
||||
tiles[tilesIndex++] = new TmpTile(null, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
||||
* Copyright 2007-2014 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,
|
||||
@@ -8,11 +8,9 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using OpenRA.Graphics;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
@@ -41,7 +39,7 @@ namespace OpenRA.FileFormats
|
||||
for (var j = 0; j < width; j++)
|
||||
Data[start + j] = s.ReadUInt8();
|
||||
|
||||
width += (i < size.Height / 2 - 1? 1 : -1) * 4;
|
||||
width += (i < size.Height / 2 - 1 ? 1 : -1) * 4;
|
||||
}
|
||||
|
||||
// Ignore Z-data for now
|
||||
@@ -51,8 +49,7 @@ namespace OpenRA.FileFormats
|
||||
|
||||
public class TmpTSReader : ISpriteSource
|
||||
{
|
||||
readonly List<ISpriteFrame> tiles = new List<ISpriteFrame>();
|
||||
public IEnumerable<ISpriteFrame> Frames { get { return tiles; } }
|
||||
public IReadOnlyList<ISpriteFrame> Frames { get; private set; }
|
||||
public bool CacheWhenLoadingTileset { get { return false; } }
|
||||
|
||||
public TmpTSReader(Stream s)
|
||||
@@ -66,11 +63,14 @@ namespace OpenRA.FileFormats
|
||||
for (var i = 0; i < offsets.Length; i++)
|
||||
offsets[i] = s.ReadUInt32();
|
||||
|
||||
var tiles = new List<TmpTSTile>();
|
||||
for (var i = 0; i < offsets.Length; i++)
|
||||
{
|
||||
s.Position = offsets[i];
|
||||
tiles.Add(new TmpTSTile(s, size));
|
||||
}
|
||||
|
||||
Frames = tiles.ToArray().AsReadOnly();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ namespace OpenRA.FileFormats
|
||||
|
||||
// Frame offsets
|
||||
offsets = new UInt32[Frames];
|
||||
for (int i = 0; i < Frames; i++)
|
||||
for (var i = 0; i < Frames; i++)
|
||||
{
|
||||
offsets[i] = stream.ReadUInt32();
|
||||
if (offsets[i] > 0x40000000)
|
||||
@@ -125,7 +125,7 @@ namespace OpenRA.FileFormats
|
||||
var ms = new MemoryStream();
|
||||
var adpcmIndex = 0;
|
||||
|
||||
bool compressed = false;
|
||||
var compressed = false;
|
||||
for (var i = 0; i < Frames; i++)
|
||||
{
|
||||
stream.Seek(offsets[i], SeekOrigin.Begin);
|
||||
@@ -201,7 +201,7 @@ namespace OpenRA.FileFormats
|
||||
// Chunks are aligned on even bytes; may be padded with a single null
|
||||
if (s.Peek() == 0) s.ReadByte();
|
||||
var type = s.ReadASCII(4);
|
||||
int subchunkLength = (int)int2.Swap(s.ReadUInt32());
|
||||
var subchunkLength = (int)int2.Swap(s.ReadUInt32());
|
||||
|
||||
switch(type)
|
||||
{
|
||||
@@ -235,11 +235,11 @@ namespace OpenRA.FileFormats
|
||||
|
||||
// Palette
|
||||
case "CPL0":
|
||||
for (int i = 0; i < numColors; i++)
|
||||
for (var i = 0; i < numColors; i++)
|
||||
{
|
||||
byte r = (byte)(s.ReadUInt8() << 2);
|
||||
byte g = (byte)(s.ReadUInt8() << 2);
|
||||
byte b = (byte)(s.ReadUInt8() << 2);
|
||||
var r = (byte)(s.ReadUInt8() << 2);
|
||||
var g = (byte)(s.ReadUInt8() << 2);
|
||||
var b = (byte)(s.ReadUInt8() << 2);
|
||||
palette[i] = (uint)((255 << 24) | (r << 16) | (g << 8) | b);
|
||||
}
|
||||
break;
|
||||
@@ -269,7 +269,7 @@ namespace OpenRA.FileFormats
|
||||
for (var i = 0; i < blockWidth; i++)
|
||||
{
|
||||
var cbfi = (mod*256 + px)*8 + j*blockWidth + i;
|
||||
byte color = (mod == 0x0f) ? px : cbf[cbfi];
|
||||
var color = (mod == 0x0f) ? px : cbf[cbfi];
|
||||
frameData[y*blockHeight + j, x*blockWidth + i] = palette[color];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,8 +79,8 @@ namespace OpenRA.FileFormats
|
||||
|
||||
s.Seek(dataStart + colStart[i], SeekOrigin.Begin);
|
||||
|
||||
byte x = (byte)(i % l.Size[0]);
|
||||
byte y = (byte)(i / l.Size[0]);
|
||||
var x = (byte)(i % l.Size[0]);
|
||||
var y = (byte)(i / l.Size[0]);
|
||||
byte z = 0;
|
||||
l.VoxelMap[x,y] = new Dictionary<byte, VxlElement>();
|
||||
do
|
||||
|
||||
@@ -56,10 +56,7 @@ namespace OpenRA.FileSystem
|
||||
return null;
|
||||
|
||||
s.Seek(e.Offset, SeekOrigin.Begin);
|
||||
var data = new byte[e.Length];
|
||||
s.Read(data, 0, (int)e.Length);
|
||||
|
||||
return new MemoryStream(data);
|
||||
return new MemoryStream(s.ReadBytes((int)e.Length));
|
||||
}
|
||||
|
||||
public Stream GetContent(string filename)
|
||||
|
||||
@@ -156,8 +156,7 @@ namespace OpenRA.FileSystem
|
||||
var index = type == PackageHashType.CRC32 ? crcHashIndex : classicHashIndex;
|
||||
var folder = index[PackageEntry.HashFilename(filename, type)]
|
||||
.Where(x => x.Exists(filename))
|
||||
.OrderBy(x => x.Priority)
|
||||
.FirstOrDefault();
|
||||
.MinByOrDefault(x => x.Priority);
|
||||
|
||||
if (folder != null)
|
||||
return folder.GetContent(filename);
|
||||
@@ -196,8 +195,7 @@ namespace OpenRA.FileSystem
|
||||
{
|
||||
var folder = MountedFolders
|
||||
.Where(x => x.Exists(filename + ext))
|
||||
.OrderByDescending(x => x.Priority)
|
||||
.FirstOrDefault();
|
||||
.MaxByOrDefault(x => x.Priority);
|
||||
|
||||
if (folder != null)
|
||||
{
|
||||
@@ -230,8 +228,7 @@ namespace OpenRA.FileSystem
|
||||
if (Exists(filename))
|
||||
using (var s = Open(filename))
|
||||
{
|
||||
var buf = new byte[s.Length];
|
||||
s.Read(buf, 0, buf.Length);
|
||||
var buf = s.ReadBytes((int)s.Length);
|
||||
a = Assembly.Load(buf);
|
||||
assemblyCache.Add(filename, a);
|
||||
return a;
|
||||
|
||||
@@ -32,8 +32,8 @@ namespace OpenRA.FileSystem
|
||||
s = GlobalFileSystem.Open(filename);
|
||||
|
||||
// Parse package header
|
||||
BinaryReader reader = new BinaryReader(s);
|
||||
uint signature = reader.ReadUInt32();
|
||||
var reader = new BinaryReader(s);
|
||||
var signature = reader.ReadUInt32();
|
||||
if (signature != 0x8C655D13)
|
||||
throw new InvalidDataException("Not an Installshield package");
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace OpenRA.FileSystem
|
||||
|
||||
// Parse the directory list
|
||||
s.Seek(TOCAddress, SeekOrigin.Begin);
|
||||
BinaryReader TOCreader = new BinaryReader(s);
|
||||
var TOCreader = new BinaryReader(s);
|
||||
|
||||
var fileCountInDirs = new List<uint>();
|
||||
// Parse directories
|
||||
@@ -103,8 +103,7 @@ namespace OpenRA.FileSystem
|
||||
return null;
|
||||
|
||||
s.Seek(dataStart + e.Offset, SeekOrigin.Begin);
|
||||
var data = new byte[e.Length];
|
||||
s.Read(data, 0, (int)e.Length);
|
||||
var data = s.ReadBytes((int)e.Length);
|
||||
|
||||
return new MemoryStream(Blast.Decompress(data));
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.FileSystem
|
||||
{
|
||||
public class MixFile : IFolder
|
||||
public sealed class MixFile : IFolder, IDisposable
|
||||
{
|
||||
readonly Dictionary<uint, PackageEntry> index;
|
||||
readonly long dataStart;
|
||||
@@ -157,8 +157,7 @@ namespace OpenRA.FileSystem
|
||||
return null;
|
||||
|
||||
s.Seek(dataStart + e.Offset, SeekOrigin.Begin);
|
||||
var data = new byte[e.Length];
|
||||
s.Read(data, 0, (int)e.Length);
|
||||
var data = s.ReadBytes((int)e.Length);
|
||||
return new MemoryStream(data);
|
||||
}
|
||||
|
||||
@@ -259,5 +258,11 @@ namespace OpenRA.FileSystem
|
||||
s.Write(file.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (s != null)
|
||||
s.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,10 +64,10 @@ namespace OpenRA.FileSystem
|
||||
if (name.Length % 4 != 0)
|
||||
name = name.PadRight(name.Length + (4 - name.Length % 4), '\0');
|
||||
|
||||
MemoryStream ms = new MemoryStream(Encoding.ASCII.GetBytes(name));
|
||||
BinaryReader reader = new BinaryReader(ms);
|
||||
var ms = new MemoryStream(Encoding.ASCII.GetBytes(name));
|
||||
var reader = new BinaryReader(ms);
|
||||
|
||||
int len = name.Length >> 2;
|
||||
var len = name.Length >> 2;
|
||||
uint result = 0;
|
||||
|
||||
while (len-- != 0)
|
||||
@@ -80,11 +80,11 @@ namespace OpenRA.FileSystem
|
||||
{
|
||||
name = name.ToUpperInvariant();
|
||||
var l = name.Length;
|
||||
int a = l >> 2;
|
||||
var a = l >> 2;
|
||||
if ((l & 3) != 0)
|
||||
{
|
||||
name += (char)(l - (a << 2));
|
||||
int i = 3 - (l & 3);
|
||||
var i = 3 - (l & 3);
|
||||
while (i-- != 0)
|
||||
name += name[a << 2];
|
||||
}
|
||||
@@ -99,9 +99,9 @@ namespace OpenRA.FileSystem
|
||||
|
||||
public static void AddStandardName(string s)
|
||||
{
|
||||
uint hash = HashFilename(s, PackageHashType.Classic); // RA1 and TD
|
||||
var hash = HashFilename(s, PackageHashType.Classic); // RA1 and TD
|
||||
Names.Add(hash, s);
|
||||
uint crcHash = HashFilename(s, PackageHashType.CRC32); // TS
|
||||
var crcHash = HashFilename(s, PackageHashType.CRC32); // TS
|
||||
Names.Add(crcHash, s);
|
||||
}
|
||||
|
||||
|
||||
@@ -59,8 +59,7 @@ namespace OpenRA.FileSystem
|
||||
return null;
|
||||
|
||||
stream.Seek(entry.Offset, SeekOrigin.Begin);
|
||||
var data = new byte[entry.Length];
|
||||
stream.Read(data, 0, (int)entry.Length);
|
||||
var data = stream.ReadBytes((int)entry.Length);
|
||||
return new MemoryStream(data);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
@@ -16,7 +17,7 @@ using SZipFile = ICSharpCode.SharpZipLib.Zip.ZipFile;
|
||||
|
||||
namespace OpenRA.FileSystem
|
||||
{
|
||||
public class ZipFile : IFolder
|
||||
public sealed class ZipFile : IFolder, IDisposable
|
||||
{
|
||||
string filename;
|
||||
SZipFile pkg;
|
||||
@@ -60,11 +61,7 @@ namespace OpenRA.FileSystem
|
||||
using (var z = pkg.GetInputStream(pkg.GetEntry(filename)))
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
int bufSize = 2048;
|
||||
byte[] buf = new byte[bufSize];
|
||||
while ((bufSize = z.Read(buf, 0, buf.Length)) > 0)
|
||||
ms.Write(buf, 0, bufSize);
|
||||
|
||||
z.CopyTo(ms);
|
||||
ms.Seek(0, SeekOrigin.Begin);
|
||||
return ms;
|
||||
}
|
||||
@@ -109,6 +106,12 @@ namespace OpenRA.FileSystem
|
||||
pkg.Close();
|
||||
pkg = new SZipFile(new MemoryStream(File.ReadAllBytes(filename)));
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (pkg != null)
|
||||
pkg.Close();
|
||||
}
|
||||
}
|
||||
|
||||
class StaticMemoryDataSource : IStaticDataSource
|
||||
|
||||
@@ -9,15 +9,13 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using OpenRA.FileSystem;
|
||||
using MaxMind.GeoIP2;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.FileSystem;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Network;
|
||||
using OpenRA.Primitives;
|
||||
@@ -141,12 +139,12 @@ namespace OpenRA
|
||||
// worldRenderer is null during the initial install/download screen
|
||||
if (worldRenderer != null)
|
||||
{
|
||||
Renderer.BeginFrame(worldRenderer.Viewport.TopLeft.ToFloat2(), worldRenderer.Viewport.Zoom);
|
||||
Renderer.BeginFrame(worldRenderer.Viewport.TopLeft, worldRenderer.Viewport.Zoom);
|
||||
Sound.SetListenerPosition(worldRenderer.Position(worldRenderer.Viewport.CenterLocation));
|
||||
worldRenderer.Draw();
|
||||
}
|
||||
else
|
||||
Renderer.BeginFrame(float2.Zero, 1f);
|
||||
Renderer.BeginFrame(int2.Zero, 1f);
|
||||
|
||||
using (new PerfSample("render_widgets"))
|
||||
{
|
||||
@@ -273,6 +271,8 @@ namespace OpenRA
|
||||
orderManager.LastTickTime = Environment.TickCount;
|
||||
orderManager.StartGame();
|
||||
worldRenderer.RefreshPalette();
|
||||
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
public static bool IsHost
|
||||
@@ -361,13 +361,13 @@ namespace OpenRA
|
||||
foreach (var mod in ModMetadata.AllMods)
|
||||
Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Title, mod.Value.Version);
|
||||
|
||||
InitializeWithMod(Settings.Game.Mod, args.GetValue("Launch.Replay", null));
|
||||
InitializeMod(Settings.Game.Mod, args);
|
||||
|
||||
if (Settings.Server.DiscoverNatDevices)
|
||||
RunAfterDelay(Settings.Server.NatDiscoveryTimeout, UPnP.TryStoppingNatDiscovery);
|
||||
RunAfterDelay(Settings.Server.NatDiscoveryTimeout, UPnP.StoppingNatDiscovery);
|
||||
}
|
||||
|
||||
public static void InitializeWithMod(string mod, string replay)
|
||||
public static void InitializeMod(string mod, Arguments args)
|
||||
{
|
||||
// Clear static state if we have switched mods
|
||||
LobbyInfoChanged = () => { };
|
||||
@@ -439,13 +439,46 @@ namespace OpenRA
|
||||
}
|
||||
else
|
||||
{
|
||||
modData.LoadScreen.StartGame();
|
||||
Settings.Save();
|
||||
if (!string.IsNullOrEmpty(replay))
|
||||
Game.JoinReplay(replay);
|
||||
var window = args != null ? args.GetValue("Launch.Window", null) : null;
|
||||
if (!string.IsNullOrEmpty(window))
|
||||
{
|
||||
var installData = modData.Manifest.ContentInstaller;
|
||||
if (installData.InstallerBackgroundWidget != null)
|
||||
Ui.LoadWidget(installData.InstallerBackgroundWidget, Ui.Root, new WidgetArgs());
|
||||
|
||||
Widgets.Ui.OpenWindow(window, new WidgetArgs());
|
||||
}
|
||||
else
|
||||
{
|
||||
modData.LoadScreen.StartGame();
|
||||
Settings.Save();
|
||||
var replay = args != null ? args.GetValue("Launch.Replay", null) : null;
|
||||
if (!string.IsNullOrEmpty(replay))
|
||||
Game.JoinReplay(replay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void TestAndContinue()
|
||||
{
|
||||
Ui.ResetAll();
|
||||
var installData = modData.Manifest.ContentInstaller;
|
||||
if (!installData.TestFiles.All(f => GlobalFileSystem.Exists(f)))
|
||||
{
|
||||
var args = new WidgetArgs()
|
||||
{
|
||||
{ "continueLoading", () => InitializeMod(Game.Settings.Game.Mod, null) },
|
||||
};
|
||||
|
||||
if (installData.InstallerBackgroundWidget != null)
|
||||
Ui.LoadWidget(installData.InstallerBackgroundWidget, Ui.Root, args);
|
||||
|
||||
Ui.OpenWindow(installData.InstallerMenuWidget, args);
|
||||
}
|
||||
else
|
||||
LoadShellMap();
|
||||
}
|
||||
|
||||
public static void LoadShellMap()
|
||||
{
|
||||
var shellmap = ChooseShellmap();
|
||||
@@ -466,16 +499,16 @@ namespace OpenRA
|
||||
return shellmaps.Random(CosmeticRandom);
|
||||
}
|
||||
|
||||
static bool quit;
|
||||
static RunStatus state = RunStatus.Running;
|
||||
public static event Action OnQuit = () => { };
|
||||
|
||||
static double idealFrameTime;
|
||||
public static void SetIdealFrameTime(int fps)
|
||||
{
|
||||
{
|
||||
idealFrameTime = 1.0 / fps;
|
||||
}
|
||||
|
||||
internal static void Run()
|
||||
internal static RunStatus Run()
|
||||
{
|
||||
if (Settings.Graphics.MaxFramerate < 1)
|
||||
{
|
||||
@@ -485,30 +518,47 @@ namespace OpenRA
|
||||
|
||||
SetIdealFrameTime(Settings.Graphics.MaxFramerate);
|
||||
|
||||
while (!quit)
|
||||
try
|
||||
{
|
||||
if (Settings.Graphics.CapFramerate)
|
||||
while (state == RunStatus.Running)
|
||||
{
|
||||
var sw = Stopwatch.StartNew();
|
||||
if (Settings.Graphics.CapFramerate)
|
||||
{
|
||||
var sw = Stopwatch.StartNew();
|
||||
|
||||
Tick(orderManager);
|
||||
Tick(orderManager);
|
||||
|
||||
var waitTime = Math.Min(idealFrameTime - sw.Elapsed.TotalSeconds, 1);
|
||||
if (waitTime > 0)
|
||||
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(waitTime));
|
||||
var waitTime = Math.Min(idealFrameTime - sw.Elapsed.TotalSeconds, 1);
|
||||
if (waitTime > 0)
|
||||
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(waitTime));
|
||||
}
|
||||
else
|
||||
Tick(orderManager);
|
||||
}
|
||||
else
|
||||
Tick(orderManager);
|
||||
}
|
||||
|
||||
// Ensure that the active replay is properly saved
|
||||
if (orderManager != null)
|
||||
orderManager.Dispose();
|
||||
finally
|
||||
{
|
||||
// Ensure that the active replay is properly saved
|
||||
if (orderManager != null)
|
||||
orderManager.Dispose();
|
||||
}
|
||||
|
||||
Renderer.Device.Dispose();
|
||||
|
||||
OnQuit();
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
public static void Exit() { quit = true; }
|
||||
public static void Exit()
|
||||
{
|
||||
state = RunStatus.Success;
|
||||
}
|
||||
|
||||
public static void Restart()
|
||||
{
|
||||
state = RunStatus.Restart;
|
||||
}
|
||||
|
||||
public static Action<Color, string, string> AddChatLine = (c, n, s) => { };
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Traits;
|
||||
|
||||
@@ -33,7 +32,7 @@ namespace OpenRA
|
||||
{
|
||||
try
|
||||
{
|
||||
var mergedNode = MergeWithParent(node, allUnits).NodesDict;
|
||||
var mergedNode = MergeWithParent(node, allUnits).ToDictionary();
|
||||
|
||||
Name = name;
|
||||
foreach (var t in mergedNode)
|
||||
@@ -49,7 +48,7 @@ namespace OpenRA
|
||||
static MiniYaml GetParent( MiniYaml node, Dictionary<string, MiniYaml> allUnits )
|
||||
{
|
||||
MiniYaml inherits;
|
||||
node.NodesDict.TryGetValue( "Inherits", out inherits );
|
||||
node.ToDictionary().TryGetValue( "Inherits", out inherits );
|
||||
if( inherits == null || string.IsNullOrEmpty( inherits.Value ) )
|
||||
return null;
|
||||
|
||||
@@ -90,11 +89,15 @@ namespace OpenRA
|
||||
{
|
||||
var ret = new List<ITraitInfo>();
|
||||
var t = Traits.WithInterface<ITraitInfo>().ToList();
|
||||
int index = 0;
|
||||
var index = 0;
|
||||
while (t.Count != 0)
|
||||
{
|
||||
var prereqs = PrerequisitesOf(t[index]);
|
||||
var unsatisfied = prereqs.Where(n => !ret.Any(x => x.GetType() == n || n.IsAssignableFrom(x.GetType())));
|
||||
var unsatisfied = prereqs.Where(n => !ret.Any(x =>
|
||||
{
|
||||
var type = x.GetType();
|
||||
return type == n || n.IsAssignableFrom(type);
|
||||
}));
|
||||
if (!unsatisfied.Any())
|
||||
{
|
||||
ret.Add(t[index]);
|
||||
@@ -111,14 +114,13 @@ namespace OpenRA
|
||||
return ret;
|
||||
}
|
||||
|
||||
static List<Type> PrerequisitesOf(ITraitInfo info)
|
||||
static IEnumerable<Type> PrerequisitesOf(ITraitInfo info)
|
||||
{
|
||||
return info
|
||||
.GetType()
|
||||
.GetInterfaces()
|
||||
.Where( t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof( Requires<> ) )
|
||||
.Select( t => t.GetGenericArguments()[ 0 ] )
|
||||
.ToList();
|
||||
.Where(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Requires<>))
|
||||
.Select(t => t.GetGenericArguments()[0]);
|
||||
}
|
||||
|
||||
public IEnumerable<Pair<string, Type>> GetInitKeys()
|
||||
|
||||
@@ -24,14 +24,15 @@ namespace OpenRA.GameRules
|
||||
{
|
||||
Title = value.Value;
|
||||
|
||||
var nd = value.NodesDict;
|
||||
var nd = value.ToDictionary();
|
||||
var ext = nd.ContainsKey("Extension") ? nd["Extension"].Value : "aud";
|
||||
Filename = (nd.ContainsKey("Filename") ? nd["Filename"].Value : key)+"."+ext;
|
||||
if (!GlobalFileSystem.Exists(Filename))
|
||||
return;
|
||||
|
||||
Exists = true;
|
||||
Length = (int)AudLoader.SoundLength(GlobalFileSystem.Open(Filename));
|
||||
using (var s = GlobalFileSystem.Open(Filename))
|
||||
Length = (int)AudLoader.SoundLength(s);
|
||||
}
|
||||
|
||||
public void Reload()
|
||||
@@ -40,7 +41,8 @@ namespace OpenRA.GameRules
|
||||
return;
|
||||
|
||||
Exists = true;
|
||||
Length = (int)AudLoader.SoundLength(GlobalFileSystem.Open(Filename));
|
||||
using (var s = GlobalFileSystem.Open(Filename))
|
||||
Length = (int)AudLoader.SoundLength(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.GameRules;
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Support;
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.GameRules
|
||||
{
|
||||
@@ -28,10 +27,9 @@ namespace OpenRA.GameRules
|
||||
|
||||
static Dictionary<string, string[]> Load(MiniYaml y, string name)
|
||||
{
|
||||
return y.NodesDict.ContainsKey(name)
|
||||
? y.NodesDict[name].NodesDict.ToDictionary(
|
||||
a => a.Key,
|
||||
a => FieldLoader.GetValue<string[]>("(value)", a.Value.Value))
|
||||
var nd = y.ToDictionary();
|
||||
return nd.ContainsKey(name)
|
||||
? nd[name].ToDictionary(my => FieldLoader.GetValue<string[]>("(value)", my.Value))
|
||||
: new Dictionary<string, string[]>();
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Effects;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.GameRules
|
||||
@@ -23,8 +22,10 @@ namespace OpenRA.GameRules
|
||||
[FieldLoader.LoadUsing("LoadVersus")]
|
||||
[Desc("Damage vs each armortype. 0% = can't target.")]
|
||||
public readonly Dictionary<string, float> Versus;
|
||||
[Desc("Can this damage ore?")]
|
||||
public readonly bool Ore = false;
|
||||
[Desc("Can this damage resource patches?")]
|
||||
public readonly bool DestroyResources = false;
|
||||
[Desc("Will this splatter resources and which?")]
|
||||
public readonly string AddsResourceType = null;
|
||||
[Desc("Explosion effect to use.")]
|
||||
public readonly string Explosion = null;
|
||||
[Desc("Palette to use for explosion effect.")]
|
||||
@@ -51,6 +52,8 @@ namespace OpenRA.GameRules
|
||||
public readonly DamageModel DamageModel = DamageModel.Normal;
|
||||
[Desc("Whether we should prevent prone response for infantry.")]
|
||||
public readonly bool PreventProne = false;
|
||||
[Desc("By what percentage should damage be modified against prone infantry.")]
|
||||
public readonly int ProneModifier = 50;
|
||||
|
||||
public float EffectivenessAgainst(ActorInfo ai)
|
||||
{
|
||||
@@ -73,10 +76,9 @@ namespace OpenRA.GameRules
|
||||
|
||||
static object LoadVersus(MiniYaml y)
|
||||
{
|
||||
return y.NodesDict.ContainsKey("Versus")
|
||||
? y.NodesDict["Versus"].NodesDict.ToDictionary(
|
||||
a => a.Key,
|
||||
a => FieldLoader.GetValue<float>("(value)", a.Value.Value))
|
||||
var nd = y.ToDictionary();
|
||||
return nd.ContainsKey("Versus")
|
||||
? nd["Versus"].ToDictionary(my => FieldLoader.GetValue<float>("(value)", my.Value))
|
||||
: new Dictionary<string, float>();
|
||||
}
|
||||
}
|
||||
@@ -126,7 +128,7 @@ namespace OpenRA.GameRules
|
||||
static object LoadProjectile(MiniYaml yaml)
|
||||
{
|
||||
MiniYaml proj;
|
||||
if (!yaml.NodesDict.TryGetValue("Projectile", out proj))
|
||||
if (!yaml.ToDictionary().TryGetValue("Projectile", out proj))
|
||||
return null;
|
||||
var ret = Game.CreateObject<IProjectileInfo>(proj.Value + "Info");
|
||||
FieldLoader.Load(ret, proj);
|
||||
@@ -179,11 +181,11 @@ namespace OpenRA.GameRules
|
||||
|
||||
if (target.Type == TargetType.Terrain)
|
||||
{
|
||||
var cell = target.CenterPosition.ToCPos();
|
||||
if (!world.Map.IsInMap(cell))
|
||||
var cell = world.Map.CellContaining(target.CenterPosition);
|
||||
if (!world.Map.Contains(cell))
|
||||
return false;
|
||||
|
||||
var cellInfo = world.GetTerrainInfo(cell);
|
||||
var cellInfo = world.Map.GetTerrainInfo(cell);
|
||||
if (!ValidTargets.Intersect(cellInfo.TargetTypes).Any()
|
||||
|| InvalidTargets.Intersect(cellInfo.TargetTypes).Any())
|
||||
return false;
|
||||
|
||||
@@ -23,9 +23,12 @@ namespace OpenRA.Graphics
|
||||
|
||||
int frame = 0;
|
||||
bool backwards = false;
|
||||
bool tickAlways;
|
||||
|
||||
string name;
|
||||
|
||||
readonly int defaultTick = 40; // 25 fps == 40 ms
|
||||
bool tickAlways;
|
||||
|
||||
public string Name { get { return name; } }
|
||||
|
||||
readonly SequenceProvider sequenceProvider;
|
||||
@@ -149,7 +152,7 @@ namespace OpenRA.Graphics
|
||||
while (timeUntilNextFrame <= 0)
|
||||
{
|
||||
tickFunc();
|
||||
timeUntilNextFrame += CurrentSequence != null ? CurrentSequence.Tick : 40; // 25 fps == 40 ms
|
||||
timeUntilNextFrame += CurrentSequence != null ? CurrentSequence.Tick : defaultTick;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,8 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
@@ -27,6 +25,8 @@ namespace OpenRA.Graphics
|
||||
static Dictionary<string, Sheet> cachedSheets;
|
||||
static Dictionary<string, Dictionary<string, Sprite>> cachedSprites;
|
||||
|
||||
static string[] storedChromeFiles;
|
||||
|
||||
public static void Initialize(params string[] chromeFiles)
|
||||
{
|
||||
collections = new Dictionary<string, Collection>();
|
||||
@@ -34,7 +34,13 @@ namespace OpenRA.Graphics
|
||||
cachedSprites = new Dictionary<string, Dictionary<string, Sprite>>();
|
||||
|
||||
if (chromeFiles.Length == 0)
|
||||
return;
|
||||
{
|
||||
chromeFiles = storedChromeFiles;
|
||||
if (chromeFiles == null || chromeFiles.Length == 0)
|
||||
return;
|
||||
}
|
||||
else
|
||||
storedChromeFiles = chromeFiles;
|
||||
|
||||
var chrome = chromeFiles.Select(s => MiniYaml.FromFile(s)).Aggregate(MiniYaml.MergeLiberal);
|
||||
|
||||
|
||||
@@ -67,13 +67,13 @@ namespace OpenRA.Graphics
|
||||
|
||||
// Start of the first line segment is the tail of the list - don't smooth it.
|
||||
var curPos = trail[idx(next - skip - 1)];
|
||||
var curCell = curPos.ToCPos();
|
||||
var curCell = wr.world.Map.CellContaining(curPos);
|
||||
var curColor = color;
|
||||
for (var i = 0; i < length - skip - 4; i++)
|
||||
{
|
||||
var j = next - skip - i - 2;
|
||||
var nextPos = Average(trail[idx(j)], trail[idx(j-1)], trail[idx(j-2)], trail[idx(j-3)]);
|
||||
var nextCell = nextPos.ToCPos();
|
||||
var nextCell = wr.world.Map.CellContaining(nextPos);
|
||||
var nextColor = Exts.ColorLerp(i * 1f / (length - 4), color, Color.Transparent);
|
||||
|
||||
if (!world.FogObscures(curCell) && !world.FogObscures(nextCell))
|
||||
|
||||
@@ -31,21 +31,22 @@ namespace OpenRA.Graphics
|
||||
var sequences = new MiniYaml(null, sequenceFiles.Select(s => MiniYaml.FromFile(s)).Aggregate(MiniYaml.MergeLiberal));
|
||||
var shadowIndex = new int[] { };
|
||||
|
||||
if (sequences.NodesDict.ContainsKey("ShadowIndex"))
|
||||
var nodesDict = sequences.ToDictionary();
|
||||
if (nodesDict.ContainsKey("ShadowIndex"))
|
||||
{
|
||||
Array.Resize(ref shadowIndex, shadowIndex.Length + 1);
|
||||
Exts.TryParseIntegerInvariant(sequences.NodesDict["ShadowIndex"].Value,
|
||||
Exts.TryParseIntegerInvariant(nodesDict["ShadowIndex"].Value,
|
||||
out shadowIndex[shadowIndex.Length - 1]);
|
||||
}
|
||||
|
||||
palette = new HardwarePalette();
|
||||
foreach (var p in sequences.NodesDict["Palettes"].Nodes)
|
||||
palette.AddPalette(p.Key, new Palette(GlobalFileSystem.Open(p.Value.Value), shadowIndex), false);
|
||||
|
||||
foreach (var p in nodesDict["Palettes"].Nodes)
|
||||
palette.AddPalette(p.Key, new ImmutablePalette(GlobalFileSystem.Open(p.Value.Value), shadowIndex), false);
|
||||
|
||||
var spriteLoader = new SpriteLoader(new string[0], new SheetBuilder(SheetType.Indexed));
|
||||
foreach (var s in sequences.NodesDict["Cursors"].Nodes)
|
||||
foreach (var s in nodesDict["Cursors"].Nodes)
|
||||
LoadSequencesForCursor(spriteLoader, s.Key, s.Value);
|
||||
spriteLoader.SheetBuilder.Current.ReleaseBuffer();
|
||||
|
||||
palette.Initialize();
|
||||
}
|
||||
@@ -53,9 +54,6 @@ namespace OpenRA.Graphics
|
||||
PaletteReference CreatePaletteReference(string name)
|
||||
{
|
||||
var pal = palette.GetPalette(name);
|
||||
if (pal == null)
|
||||
throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
|
||||
|
||||
return new PaletteReference(name, palette.GetPaletteIndex(name), pal);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
public class CursorSequence
|
||||
@@ -28,7 +26,7 @@ namespace OpenRA.Graphics
|
||||
public CursorSequence(SpriteLoader loader, string cursorSrc, string palette, MiniYaml info)
|
||||
{
|
||||
sprites = loader.LoadAllSprites(cursorSrc);
|
||||
var d = info.NodesDict;
|
||||
var d = info.ToDictionary();
|
||||
|
||||
start = Exts.ParseIntegerInvariant(d["start"].Value);
|
||||
this.palette = palette;
|
||||
|
||||
@@ -44,13 +44,13 @@ namespace OpenRA.Graphics
|
||||
float[] trgb = { h + 1 / 3.0f, h, h - 1 / 3.0f };
|
||||
float[] rgb = { 0, 0, 0 };
|
||||
|
||||
for (int k = 0; k < 3; k++)
|
||||
for (var 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++)
|
||||
for (var 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; }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||
* Copyright 2007-2014 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,
|
||||
@@ -10,8 +10,6 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
@@ -19,70 +17,101 @@ namespace OpenRA.Graphics
|
||||
public class HardwarePalette
|
||||
{
|
||||
public const int MaxPalettes = 256;
|
||||
int allocated = 0;
|
||||
|
||||
public ITexture Texture { get; private set; }
|
||||
Dictionary<string, Palette> palettes;
|
||||
Dictionary<string, int> indices;
|
||||
Dictionary<string, bool> allowsMods;
|
||||
readonly Dictionary<string, ImmutablePalette> palettes = new Dictionary<string, ImmutablePalette>();
|
||||
readonly Dictionary<string, MutablePalette> modifiablePalettes = new Dictionary<string, MutablePalette>();
|
||||
readonly IReadOnlyDictionary<string, MutablePalette> readOnlyModifiablePalettes;
|
||||
readonly Dictionary<string, int> indices = new Dictionary<string, int>();
|
||||
readonly uint[,] buffer = new uint[Palette.Size, MaxPalettes];
|
||||
|
||||
public HardwarePalette()
|
||||
{
|
||||
palettes = new Dictionary<string, Palette>();
|
||||
indices = new Dictionary<string, int>();
|
||||
allowsMods = new Dictionary<string, bool>();
|
||||
Texture = Game.Renderer.Device.CreateTexture();
|
||||
readOnlyModifiablePalettes = modifiablePalettes.AsReadOnly();
|
||||
}
|
||||
|
||||
public Palette GetPalette(string name)
|
||||
public IPalette GetPalette(string name)
|
||||
{
|
||||
Palette ret;
|
||||
if (!palettes.TryGetValue(name,out ret))
|
||||
throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
|
||||
return ret;
|
||||
MutablePalette mutable;
|
||||
if (modifiablePalettes.TryGetValue(name, out mutable))
|
||||
return mutable.AsReadOnly();
|
||||
ImmutablePalette immutable;
|
||||
if (palettes.TryGetValue(name, out immutable))
|
||||
return immutable;
|
||||
throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
|
||||
}
|
||||
|
||||
public int GetPaletteIndex(string name)
|
||||
{
|
||||
int ret;
|
||||
if (!indices.TryGetValue(name,out ret))
|
||||
if (!indices.TryGetValue(name, out ret))
|
||||
throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void AddPalette(string name, Palette p, bool allowModifiers)
|
||||
public void AddPalette(string name, ImmutablePalette p, bool allowModifiers)
|
||||
{
|
||||
if (palettes.Count >= MaxPalettes)
|
||||
throw new InvalidOperationException("Limit of {0} palettes reached. Cannot add {1}.".F(MaxPalettes, name));
|
||||
if (palettes.ContainsKey(name))
|
||||
throw new InvalidOperationException("Palette {0} has already been defined".F(name));
|
||||
|
||||
int index = palettes.Count;
|
||||
indices.Add(name, index);
|
||||
palettes.Add(name, p);
|
||||
indices.Add(name, allocated++);
|
||||
allowsMods.Add(name, allowModifiers);
|
||||
if (allowModifiers)
|
||||
modifiablePalettes.Add(name, new MutablePalette(p));
|
||||
else
|
||||
CopyPaletteToBuffer(index, p);
|
||||
}
|
||||
|
||||
uint[,] data = new uint[MaxPalettes, 256];
|
||||
public void ApplyModifiers(IEnumerable<IPaletteModifier> paletteMods)
|
||||
public void ReplacePalette(string name, IPalette p)
|
||||
{
|
||||
var copy = palettes.ToDictionary(p => p.Key, p => new Palette(p.Value));
|
||||
var modifiable = copy.Where(p => allowsMods[p.Key]).ToDictionary(p => p.Key, p => p.Value);
|
||||
|
||||
foreach (var mod in paletteMods)
|
||||
mod.AdjustPalette(modifiable);
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
Texture.SetData(data);
|
||||
if (modifiablePalettes.ContainsKey(name))
|
||||
CopyPaletteToBuffer(indices[name], modifiablePalettes[name] = new MutablePalette(p));
|
||||
else if (palettes.ContainsKey(name))
|
||||
CopyPaletteToBuffer(indices[name], palettes[name] = new ImmutablePalette(p));
|
||||
else
|
||||
throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
|
||||
Texture.SetData(buffer);
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
ApplyModifiers(new IPaletteModifier[] {});
|
||||
CopyModifiablePalettesToBuffer();
|
||||
Texture.SetData(buffer);
|
||||
}
|
||||
|
||||
void CopyPaletteToBuffer(int index, IPalette p)
|
||||
{
|
||||
for (var i = 0; i < Palette.Size; i++)
|
||||
buffer[i, index] = p[i];
|
||||
}
|
||||
|
||||
void CopyModifiablePalettesToBuffer()
|
||||
{
|
||||
foreach (var kvp in modifiablePalettes)
|
||||
CopyPaletteToBuffer(indices[kvp.Key], kvp.Value);
|
||||
}
|
||||
|
||||
public void ApplyModifiers(IEnumerable<IPaletteModifier> paletteMods)
|
||||
{
|
||||
foreach (var mod in paletteMods)
|
||||
mod.AdjustPalette(readOnlyModifiablePalettes);
|
||||
|
||||
// Update our texture with the changes.
|
||||
CopyModifiablePalettesToBuffer();
|
||||
Texture.SetData(buffer);
|
||||
|
||||
// Reset modified palettes back to their original colors, ready for next time.
|
||||
foreach (var kvp in modifiablePalettes)
|
||||
{
|
||||
var originalPalette = palettes[kvp.Key];
|
||||
var modifiedPalette = kvp.Value;
|
||||
for (var i = 0; i < Palette.Size; i++)
|
||||
modifiedPalette[i] = originalPalette[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace OpenRA
|
||||
|
||||
public enum BlendMode { None, Alpha, Additive, Subtractive, Multiply }
|
||||
|
||||
public interface IGraphicsDevice
|
||||
public interface IGraphicsDevice : IDisposable
|
||||
{
|
||||
IVertexBuffer<Vertex> CreateVertexBuffer(int length);
|
||||
ITexture CreateTexture(Bitmap bitmap);
|
||||
@@ -59,7 +59,8 @@ namespace OpenRA
|
||||
|
||||
void SetBlendMode(BlendMode mode);
|
||||
|
||||
void Quit();
|
||||
void GrabWindowMouseFocus();
|
||||
void ReleaseWindowMouseFocus();
|
||||
}
|
||||
|
||||
public interface IVertexBuffer<T>
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||
* Copyright 2007-2014 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,
|
||||
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
@@ -98,14 +99,14 @@ namespace OpenRA.Graphics
|
||||
var yc = (r.Bottom + r.Top) / 2;
|
||||
for (var y = r.Top; y <= r.Bottom; y++)
|
||||
{
|
||||
var dx = a * System.Convert.ToSingle(System.Math.Sqrt(1 - (y - yc) * (y - yc) / b / b));
|
||||
var dx = a * (float)(Math.Sqrt(1 - (y - yc) * (y - yc) / b / b));
|
||||
DrawLine(new float2(xc - dx, y), new float2(xc + dx, y), color, color);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetViewportParams(Size screen, float zoom, float2 scroll)
|
||||
public void SetViewportParams(Size screen, float zoom, int2 scroll)
|
||||
{
|
||||
shader.SetVec("Scroll", (int)scroll.X, (int)scroll.Y);
|
||||
shader.SetVec("Scroll", scroll.X, scroll.Y);
|
||||
shader.SetVec("r1", zoom*2f/screen.Width, -zoom*2f/screen.Height);
|
||||
shader.SetVec("r2", -1, 1);
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Drawing;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using OpenRA.Traits;
|
||||
|
||||
@@ -21,32 +20,35 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
public static Bitmap TerrainBitmap(TileSet tileset, Map map, bool actualSize = false)
|
||||
{
|
||||
var width = map.Bounds.Width;
|
||||
var height = map.Bounds.Height;
|
||||
var b = map.Bounds;
|
||||
var width = b.Width;
|
||||
var height = b.Height;
|
||||
|
||||
if (!actualSize)
|
||||
width = height = Exts.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height));
|
||||
width = height = Exts.NextPowerOf2(Math.Max(b.Width, b.Height));
|
||||
|
||||
var terrain = new Bitmap(width, height);
|
||||
|
||||
var bitmapData = terrain.LockBits(terrain.Bounds(),
|
||||
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||
|
||||
var mapTiles = map.MapTiles.Value;
|
||||
|
||||
unsafe
|
||||
{
|
||||
int* c = (int*)bitmapData.Scan0;
|
||||
var c = (int*)bitmapData.Scan0;
|
||||
|
||||
for (var x = 0; x < map.Bounds.Width; x++)
|
||||
for (var y = 0; y < map.Bounds.Height; y++)
|
||||
for (var x = 0; x < b.Width; x++)
|
||||
{
|
||||
for (var y = 0; y < b.Height; y++)
|
||||
{
|
||||
var mapX = x + map.Bounds.Left;
|
||||
var mapY = y + map.Bounds.Top;
|
||||
var type = tileset.GetTerrainType(map.MapTiles.Value[mapX, mapY]);
|
||||
if (!tileset.Terrain.ContainsKey(type))
|
||||
throw new InvalidDataException("Tileset {0} lacks terraintype {1}".F(tileset.Id, type));
|
||||
var mapX = x + b.Left;
|
||||
var mapY = y + b.Top;
|
||||
var type = tileset.GetTerrainInfo(mapTiles[mapX, mapY]);
|
||||
|
||||
*(c + (y * bitmapData.Stride >> 2) + x) = tileset.Terrain[type].Color.ToArgb();
|
||||
*(c + (y * bitmapData.Stride >> 2) + x) = type.Color.ToArgb();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
terrain.UnlockBits(bitmapData);
|
||||
@@ -57,31 +59,35 @@ namespace OpenRA.Graphics
|
||||
// in a world use AddCustomTerrain instead
|
||||
static Bitmap AddStaticResources(TileSet tileset, Map map, Ruleset resourceRules, Bitmap terrainBitmap)
|
||||
{
|
||||
Bitmap terrain = new Bitmap(terrainBitmap);
|
||||
var terrain = new Bitmap(terrainBitmap);
|
||||
var b = map.Bounds;
|
||||
|
||||
var bitmapData = terrain.LockBits(terrain.Bounds(),
|
||||
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||
|
||||
unsafe
|
||||
{
|
||||
int* c = (int*)bitmapData.Scan0;
|
||||
var c = (int*)bitmapData.Scan0;
|
||||
|
||||
for (var x = 0; x < map.Bounds.Width; x++)
|
||||
for (var y = 0; y < map.Bounds.Height; y++)
|
||||
for (var x = 0; x < b.Width; x++)
|
||||
{
|
||||
for (var y = 0; y < b.Height; y++)
|
||||
{
|
||||
var mapX = x + map.Bounds.Left;
|
||||
var mapY = y + map.Bounds.Top;
|
||||
var mapX = x + b.Left;
|
||||
var mapY = y + b.Top;
|
||||
if (map.MapResources.Value[mapX, mapY].Type == 0)
|
||||
continue;
|
||||
|
||||
var res = resourceRules.Actors["world"].Traits.WithInterface<ResourceTypeInfo>()
|
||||
.Where(t => t.ResourceType == map.MapResources.Value[mapX, mapY].Type)
|
||||
.Where(t => t.ResourceType == map.MapResources.Value[mapX, mapY].Type)
|
||||
.Select(t => t.TerrainType).FirstOrDefault();
|
||||
|
||||
if (res == null)
|
||||
continue;
|
||||
|
||||
*(c + (y * bitmapData.Stride >> 2) + x) = tileset.Terrain[res].Color.ToArgb();
|
||||
*(c + (y * bitmapData.Stride >> 2) + x) = tileset[tileset.GetTerrainIndex(res)].Color.ToArgb();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
terrain.UnlockBits(bitmapData);
|
||||
@@ -92,25 +98,30 @@ namespace OpenRA.Graphics
|
||||
public static Bitmap CustomTerrainBitmap(World world)
|
||||
{
|
||||
var map = world.Map;
|
||||
var size = Exts.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height));
|
||||
var b = map.Bounds;
|
||||
|
||||
var size = Exts.NextPowerOf2(Math.Max(b.Width, b.Height));
|
||||
var bitmap = new Bitmap(size, size);
|
||||
var bitmapData = bitmap.LockBits(bitmap.Bounds(),
|
||||
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||
|
||||
unsafe
|
||||
{
|
||||
int* c = (int*)bitmapData.Scan0;
|
||||
var c = (int*)bitmapData.Scan0;
|
||||
|
||||
for (var x = 0; x < map.Bounds.Width; x++)
|
||||
for (var y = 0; y < map.Bounds.Height; y++)
|
||||
for (var x = 0; x < b.Width; x++)
|
||||
{
|
||||
for (var y = 0; y < b.Height; y++)
|
||||
{
|
||||
var mapX = x + map.Bounds.Left;
|
||||
var mapY = y + map.Bounds.Top;
|
||||
var mapX = x + b.Left;
|
||||
var mapY = y + b.Top;
|
||||
var custom = map.CustomTerrain[mapX, mapY];
|
||||
if (custom == null)
|
||||
if (custom == -1)
|
||||
continue;
|
||||
*(c + (y * bitmapData.Stride >> 2) + x) = world.TileSet.Terrain[custom].Color.ToArgb();
|
||||
|
||||
*(c + (y * bitmapData.Stride >> 2) + x) = world.TileSet[custom].Color.ToArgb();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bitmap.UnlockBits(bitmapData);
|
||||
@@ -120,14 +131,16 @@ namespace OpenRA.Graphics
|
||||
public static Bitmap ActorsBitmap(World world)
|
||||
{
|
||||
var map = world.Map;
|
||||
var size = Exts.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height));
|
||||
var b = map.Bounds;
|
||||
|
||||
var size = Exts.NextPowerOf2(Math.Max(b.Width, b.Height));
|
||||
var bitmap = new Bitmap(size, size);
|
||||
var bitmapData = bitmap.LockBits(bitmap.Bounds(),
|
||||
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||
|
||||
unsafe
|
||||
{
|
||||
int* c = (int*)bitmapData.Scan0;
|
||||
var c = (int*)bitmapData.Scan0;
|
||||
|
||||
foreach (var t in world.ActorsWithTrait<IRadarSignature>())
|
||||
{
|
||||
@@ -136,8 +149,11 @@ namespace OpenRA.Graphics
|
||||
|
||||
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.Bounds.Top) * bitmapData.Stride >> 2) + cell.X - world.Map.Bounds.Left) = color.ToArgb();
|
||||
{
|
||||
var uv = Map.CellToMap(map.TileShape, cell);
|
||||
if (b.Contains(uv.X, uv.Y))
|
||||
*(c + ((uv.Y - b.Top) * bitmapData.Stride >> 2) + uv.X - b.Left) = color.ToArgb();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,7 +164,9 @@ namespace OpenRA.Graphics
|
||||
public static Bitmap ShroudBitmap(World world)
|
||||
{
|
||||
var map = world.Map;
|
||||
var size = Exts.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height));
|
||||
var b = map.Bounds;
|
||||
|
||||
var size = Exts.NextPowerOf2(Math.Max(b.Width, b.Height));
|
||||
var bitmap = new Bitmap(size, size);
|
||||
if (world.RenderPlayer == null)
|
||||
return bitmap;
|
||||
@@ -158,20 +176,20 @@ namespace OpenRA.Graphics
|
||||
|
||||
var shroud = Color.Black.ToArgb();
|
||||
var fog = Color.FromArgb(128, Color.Black).ToArgb();
|
||||
var offset = new CVec(b.Left, b.Top);
|
||||
|
||||
unsafe
|
||||
{
|
||||
int* c = (int*)bitmapData.Scan0;
|
||||
var c = (int*)bitmapData.Scan0;
|
||||
|
||||
for (var x = 0; x < map.Bounds.Width; x++)
|
||||
for (var y = 0; y < map.Bounds.Height; y++)
|
||||
{
|
||||
var p = new CPos(x + map.Bounds.Left, y + map.Bounds.Top);
|
||||
if (world.ShroudObscures(p))
|
||||
*(c + (y * bitmapData.Stride >> 2) + x) = shroud;
|
||||
else if (world.FogObscures(p))
|
||||
*(c + (y * bitmapData.Stride >> 2) + x) = fog;
|
||||
}
|
||||
foreach (var cell in map.Cells)
|
||||
{
|
||||
var uv = Map.CellToMap(map.TileShape, cell) - offset;
|
||||
if (world.ShroudObscures(cell))
|
||||
*(c + (uv.Y * bitmapData.Stride >> 2) + uv.X) = shroud;
|
||||
else if (world.FogObscures(cell))
|
||||
*(c + (uv.Y * bitmapData.Stride >> 2) + uv.X) = fog;
|
||||
}
|
||||
}
|
||||
|
||||
bitmap.UnlockBits(bitmapData);
|
||||
@@ -185,7 +203,7 @@ namespace OpenRA.Graphics
|
||||
|
||||
public static Bitmap RenderMapPreview(TileSet tileset, Map map, Ruleset resourceRules, bool actualSize)
|
||||
{
|
||||
Bitmap terrain = TerrainBitmap(tileset, map, actualSize);
|
||||
var terrain = TerrainBitmap(tileset, map, actualSize);
|
||||
return AddStaticResources(tileset, map, resourceRules, terrain);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2012 The OpenRA Developers (see AUTHORS)
|
||||
* Copyright 2007-2014 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,
|
||||
@@ -8,94 +8,35 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
public class Palette
|
||||
public interface IPalette { uint this[int index] { get; } }
|
||||
public interface IPaletteRemap { Color GetRemappedColor(Color original, int index); }
|
||||
|
||||
public static class Palette
|
||||
{
|
||||
public static Palette Load(string filename, int[] remap)
|
||||
public const int Size = 256;
|
||||
|
||||
public static Color GetColor(this IPalette palette, int index)
|
||||
{
|
||||
using (var s = File.OpenRead(filename))
|
||||
return new Palette(s, remap);
|
||||
return Color.FromArgb((int)palette[index]);
|
||||
}
|
||||
|
||||
uint[] colors;
|
||||
public Color GetColor(int 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 void ApplyRemap(IPaletteRemap r)
|
||||
{
|
||||
for (int i = 0; i < 256; i++)
|
||||
colors[i] = (uint)r.GetRemappedColor(Color.FromArgb((int)colors[i]), i).ToArgb();
|
||||
}
|
||||
|
||||
public Palette(Stream s, int[] remapShadow)
|
||||
{
|
||||
colors = new uint[256];
|
||||
|
||||
using (BinaryReader reader = new BinaryReader(s))
|
||||
{
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
byte r = (byte)(reader.ReadByte() << 2);
|
||||
byte g = (byte)(reader.ReadByte() << 2);
|
||||
byte b = (byte)(reader.ReadByte() << 2);
|
||||
colors[i] = (uint)((255 << 24) | (r << 16) | (g << 8) | b);
|
||||
}
|
||||
}
|
||||
|
||||
colors[0] = 0; // convert black background to transparency
|
||||
foreach (int i in remapShadow)
|
||||
colors[i] = 140u << 24;
|
||||
}
|
||||
|
||||
public Palette(Palette p, IPaletteRemap r)
|
||||
{
|
||||
colors = (uint[])p.colors.Clone();
|
||||
ApplyRemap(r);
|
||||
}
|
||||
|
||||
public Palette(Palette p)
|
||||
{
|
||||
colors = (uint[])p.colors.Clone();
|
||||
}
|
||||
|
||||
public Palette(uint[] data)
|
||||
{
|
||||
if (data.Length != 256)
|
||||
throw new InvalidDataException("Attempting to create palette with incorrect array size");
|
||||
colors = (uint[])data.Clone();
|
||||
}
|
||||
|
||||
public ColorPalette AsSystemPalette()
|
||||
public static ColorPalette AsSystemPalette(this IPalette palette)
|
||||
{
|
||||
ColorPalette pal;
|
||||
using (var b = new Bitmap(1, 1, PixelFormat.Format8bppIndexed))
|
||||
pal = b.Palette;
|
||||
|
||||
for (var i = 0; i < 256; i++)
|
||||
pal.Entries[i] = GetColor(i);
|
||||
for (var i = 0; i < Size; i++)
|
||||
pal.Entries[i] = palette.GetColor(i);
|
||||
|
||||
// hack around a mono bug -- the palette flags get set wrong.
|
||||
if (Platform.CurrentPlatform != PlatformType.Windows)
|
||||
@@ -105,22 +46,116 @@ namespace OpenRA.Graphics
|
||||
return pal;
|
||||
}
|
||||
|
||||
public Bitmap AsBitmap()
|
||||
public static Bitmap AsBitmap(this IPalette palette)
|
||||
{
|
||||
var b = new Bitmap(256, 1, PixelFormat.Format32bppArgb);
|
||||
var b = new Bitmap(Size, 1, PixelFormat.Format32bppArgb);
|
||||
var data = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),
|
||||
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
|
||||
unsafe
|
||||
{
|
||||
uint* c = (uint*)data.Scan0;
|
||||
for (var x = 0; x < 256; x++)
|
||||
*(c + x) = colors[x];
|
||||
}
|
||||
|
||||
var temp = new uint[Palette.Size];
|
||||
for (int i = 0; i < temp.Length; i++)
|
||||
temp[i] = palette[i];
|
||||
Marshal.Copy((int[])(object)temp, 0, data.Scan0, Size);
|
||||
b.UnlockBits(data);
|
||||
return b;
|
||||
}
|
||||
|
||||
public static IPalette AsReadOnly(this IPalette palette)
|
||||
{
|
||||
if (palette is ImmutablePalette)
|
||||
return palette;
|
||||
return new ReadOnlyPalette(palette);
|
||||
}
|
||||
|
||||
class ReadOnlyPalette : IPalette
|
||||
{
|
||||
IPalette palette;
|
||||
public ReadOnlyPalette(IPalette palette) { this.palette = palette; }
|
||||
public uint this[int index] { get { return palette[index]; } }
|
||||
}
|
||||
}
|
||||
|
||||
public interface IPaletteRemap { Color GetRemappedColor(Color original, int index); }
|
||||
public class ImmutablePalette : IPalette
|
||||
{
|
||||
readonly uint[] colors = new uint[Palette.Size];
|
||||
|
||||
public uint this[int index]
|
||||
{
|
||||
get { return colors[index]; }
|
||||
}
|
||||
|
||||
public ImmutablePalette(string filename, int[] remap)
|
||||
{
|
||||
using (var s = File.OpenRead(filename))
|
||||
LoadFromStream(s, remap);
|
||||
}
|
||||
|
||||
public ImmutablePalette(Stream s, int[] remapShadow)
|
||||
{
|
||||
LoadFromStream(s, remapShadow);
|
||||
}
|
||||
|
||||
void LoadFromStream(Stream s, int[] remapShadow)
|
||||
{
|
||||
using (var reader = new BinaryReader(s))
|
||||
for (var i = 0; i < Palette.Size; i++)
|
||||
{
|
||||
var r = (byte)(reader.ReadByte() << 2);
|
||||
var g = (byte)(reader.ReadByte() << 2);
|
||||
var b = (byte)(reader.ReadByte() << 2);
|
||||
colors[i] = (uint)((255 << 24) | (r << 16) | (g << 8) | b);
|
||||
}
|
||||
|
||||
colors[0] = 0; // Convert black background to transparency.
|
||||
foreach (var i in remapShadow)
|
||||
colors[i] = 140u << 24;
|
||||
}
|
||||
|
||||
public ImmutablePalette(IPalette p, IPaletteRemap r)
|
||||
: this(p)
|
||||
{
|
||||
for (var i = 0; i < Palette.Size; i++)
|
||||
colors[i] = (uint)r.GetRemappedColor(this.GetColor(i), i).ToArgb();
|
||||
}
|
||||
|
||||
public ImmutablePalette(IPalette p)
|
||||
{
|
||||
for (int i = 0; i < Palette.Size; i++)
|
||||
colors[i] = p[i];
|
||||
}
|
||||
|
||||
public ImmutablePalette(IEnumerable<uint> sourceColors)
|
||||
{
|
||||
var i = 0;
|
||||
foreach (var sourceColor in sourceColors)
|
||||
colors[i++] = sourceColor;
|
||||
}
|
||||
}
|
||||
|
||||
public class MutablePalette : IPalette
|
||||
{
|
||||
readonly uint[] colors = new uint[Palette.Size];
|
||||
|
||||
public uint this[int index]
|
||||
{
|
||||
get { return colors[index]; }
|
||||
set { colors[index] = value; }
|
||||
}
|
||||
|
||||
public MutablePalette(IPalette p)
|
||||
{
|
||||
for (int i = 0; i < Palette.Size; i++)
|
||||
this[i] = p[i];
|
||||
}
|
||||
|
||||
public void SetColor(int index, Color color)
|
||||
{
|
||||
colors[index] = (uint)color.ToArgb();
|
||||
}
|
||||
|
||||
public void ApplyRemap(IPaletteRemap r)
|
||||
{
|
||||
for (var i = 0; i < Palette.Size; i++)
|
||||
colors[i] = (uint)r.GetRemappedColor(this.GetColor(i), i).ToArgb();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,9 +58,9 @@ namespace OpenRA.Graphics
|
||||
nv += 4;
|
||||
}
|
||||
|
||||
public void SetViewportParams(Size screen, float zoom, float2 scroll)
|
||||
public void SetViewportParams(Size screen, float zoom, int2 scroll)
|
||||
{
|
||||
shader.SetVec("Scroll", (int)scroll.X, (int)scroll.Y);
|
||||
shader.SetVec("Scroll", scroll.X, scroll.Y);
|
||||
shader.SetVec("r1", zoom*2f/screen.Width, -zoom*2f/screen.Height);
|
||||
shader.SetVec("r2", -1, 1);
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace OpenRA.Graphics
|
||||
RgbaSpriteRenderer = new SpriteRenderer(this, device.CreateShader("rgba"));
|
||||
SpriteRenderer = new SpriteRenderer(this, device.CreateShader("shp"));
|
||||
|
||||
for (int i = 0; i < TempBufferCount; i++)
|
||||
for (var i = 0; i < TempBufferCount; i++)
|
||||
tempBuffers.Enqueue(device.CreateVertexBuffer(TempBufferSize));
|
||||
}
|
||||
|
||||
@@ -65,17 +65,34 @@ namespace OpenRA.Graphics
|
||||
|
||||
internal IGraphicsDevice Device { get { return device; } }
|
||||
|
||||
public void BeginFrame(float2 scroll, float zoom)
|
||||
Size? lastResolution;
|
||||
int2? lastScroll;
|
||||
float? lastZoom;
|
||||
|
||||
public void BeginFrame(int2 scroll, float zoom)
|
||||
{
|
||||
device.Clear();
|
||||
WorldSpriteRenderer.SetViewportParams(Resolution, zoom, scroll);
|
||||
WorldRgbaSpriteRenderer.SetViewportParams(Resolution, zoom, scroll);
|
||||
SpriteRenderer.SetViewportParams(Resolution, 1f, float2.Zero);
|
||||
RgbaSpriteRenderer.SetViewportParams(Resolution, 1f, float2.Zero);
|
||||
WorldLineRenderer.SetViewportParams(Resolution, zoom, scroll);
|
||||
WorldQuadRenderer.SetViewportParams(Resolution, zoom, scroll);
|
||||
LineRenderer.SetViewportParams(Resolution, 1f, float2.Zero);
|
||||
WorldVoxelRenderer.SetViewportParams(Resolution, zoom, scroll);
|
||||
|
||||
var resolutionChanged = lastResolution != Resolution;
|
||||
if (resolutionChanged)
|
||||
{
|
||||
lastResolution = Resolution;
|
||||
RgbaSpriteRenderer.SetViewportParams(Resolution, 1f, int2.Zero);
|
||||
SpriteRenderer.SetViewportParams(Resolution, 1f, int2.Zero);
|
||||
LineRenderer.SetViewportParams(Resolution, 1f, int2.Zero);
|
||||
}
|
||||
|
||||
// If zoom evaluates as different due to floating point weirdness that's OK, setting the parameters again is harmless.
|
||||
if (resolutionChanged || lastScroll != scroll || lastZoom != zoom)
|
||||
{
|
||||
lastScroll = scroll;
|
||||
lastZoom = zoom;
|
||||
WorldRgbaSpriteRenderer.SetViewportParams(Resolution, zoom, scroll);
|
||||
WorldSpriteRenderer.SetViewportParams(Resolution, zoom, scroll);
|
||||
WorldVoxelRenderer.SetViewportParams(Resolution, zoom, scroll);
|
||||
WorldLineRenderer.SetViewportParams(Resolution, zoom, scroll);
|
||||
WorldQuadRenderer.SetViewportParams(Resolution, zoom, scroll);
|
||||
}
|
||||
}
|
||||
|
||||
ITexture currentPaletteTexture;
|
||||
@@ -212,5 +229,15 @@ namespace OpenRA.Graphics
|
||||
Flush();
|
||||
Device.DisableDepthBuffer();
|
||||
}
|
||||
|
||||
public void GrabWindowMouseFocus()
|
||||
{
|
||||
device.GrabWindowMouseFocus();
|
||||
}
|
||||
|
||||
public void ReleaseWindowMouseFocus()
|
||||
{
|
||||
device.ReleaseWindowMouseFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
var srcOverride = info.Value;
|
||||
Name = name;
|
||||
var d = info.NodesDict;
|
||||
var d = info.ToDictionary();
|
||||
var offset = float2.Zero;
|
||||
var blendMode = BlendMode.Alpha;
|
||||
|
||||
|
||||
@@ -12,14 +12,15 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Primitives;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
using Sequences = IReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>;
|
||||
using UnitSequences = Lazy<IReadOnlyDictionary<string, Sequence>>;
|
||||
|
||||
public class SequenceProvider
|
||||
{
|
||||
readonly Lazy<IReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>> sequences;
|
||||
readonly Lazy<Sequences> sequences;
|
||||
public readonly SpriteLoader SpriteLoader;
|
||||
|
||||
public SequenceProvider(SequenceCache cache, Map map)
|
||||
@@ -30,7 +31,7 @@ namespace OpenRA.Graphics
|
||||
|
||||
public Sequence GetSequence(string unitName, string sequenceName)
|
||||
{
|
||||
Lazy<IReadOnlyDictionary<string, Sequence>> unitSeq;
|
||||
UnitSequences unitSeq;
|
||||
if (!sequences.Value.TryGetValue(unitName, out unitSeq))
|
||||
throw new InvalidOperationException("Unit `{0}` does not have any sequences defined.".F(unitName));
|
||||
|
||||
@@ -43,7 +44,7 @@ namespace OpenRA.Graphics
|
||||
|
||||
public bool HasSequence(string unitName, string sequenceName)
|
||||
{
|
||||
Lazy<IReadOnlyDictionary<string, Sequence>> unitSeq;
|
||||
UnitSequences unitSeq;
|
||||
if (!sequences.Value.TryGetValue(unitName, out unitSeq))
|
||||
throw new InvalidOperationException("Unit `{0}` does not have any sequences defined.".F(unitName));
|
||||
|
||||
@@ -52,7 +53,7 @@ namespace OpenRA.Graphics
|
||||
|
||||
public IEnumerable<string> Sequences(string unitName)
|
||||
{
|
||||
Lazy<IReadOnlyDictionary<string, Sequence>> unitSeq;
|
||||
UnitSequences unitSeq;
|
||||
if (!sequences.Value.TryGetValue(unitName, out unitSeq))
|
||||
throw new InvalidOperationException("Unit `{0}` does not have any sequences defined.".F(unitName));
|
||||
|
||||
@@ -62,16 +63,7 @@ namespace OpenRA.Graphics
|
||||
public void Preload()
|
||||
{
|
||||
foreach (var unitSeq in sequences.Value.Values)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var seq in unitSeq.Value.Values);
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
Log.Write("debug", ex.Message);
|
||||
}
|
||||
}
|
||||
foreach (var seq in unitSeq.Value.Values) { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +73,7 @@ namespace OpenRA.Graphics
|
||||
readonly Lazy<SpriteLoader> spriteLoader;
|
||||
public SpriteLoader SpriteLoader { get { return spriteLoader.Value; } }
|
||||
|
||||
readonly Dictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>> sequenceCache = new Dictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>();
|
||||
readonly Dictionary<string, UnitSequences> sequenceCache = new Dictionary<string, UnitSequences>();
|
||||
|
||||
public SequenceCache(ModData modData, TileSet tileSet)
|
||||
{
|
||||
@@ -90,13 +82,13 @@ namespace OpenRA.Graphics
|
||||
spriteLoader = Exts.Lazy(() => new SpriteLoader(tileSet.Extensions, new SheetBuilder(SheetType.Indexed)));
|
||||
}
|
||||
|
||||
public IReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>> LoadSequences(Map map)
|
||||
public Sequences LoadSequences(Map map)
|
||||
{
|
||||
using (new Support.PerfTimer("LoadSequences"))
|
||||
return Load(map.SequenceDefinitions);
|
||||
}
|
||||
|
||||
IReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>> Load(List<MiniYamlNode> sequenceNodes)
|
||||
Sequences Load(List<MiniYamlNode> sequenceNodes)
|
||||
{
|
||||
var sequenceFiles = modData.Manifest.Sequences;
|
||||
|
||||
@@ -104,7 +96,7 @@ namespace OpenRA.Graphics
|
||||
.Select(s => MiniYaml.FromFile(s))
|
||||
.Aggregate(sequenceNodes, MiniYaml.MergeLiberal);
|
||||
|
||||
var items = new Dictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>();
|
||||
var items = new Dictionary<string, UnitSequences>();
|
||||
foreach (var n in nodes)
|
||||
{
|
||||
// Work around the loop closure issue in older versions of C#
|
||||
@@ -112,23 +104,40 @@ namespace OpenRA.Graphics
|
||||
|
||||
var key = node.Value.ToLines(node.Key).JoinWith("|");
|
||||
|
||||
Lazy<IReadOnlyDictionary<string, Sequence>> t;
|
||||
UnitSequences t;
|
||||
if (sequenceCache.TryGetValue(key, out t))
|
||||
items.Add(node.Key, t);
|
||||
else
|
||||
{
|
||||
t = Exts.Lazy(() => (IReadOnlyDictionary<string, Sequence>)new ReadOnlyDictionary<string, Sequence>(
|
||||
node.Value.NodesDict.ToDictionary(x => x.Key, x =>
|
||||
{
|
||||
using (new Support.PerfTimer("new Sequence(\"{0}\")".F(node.Key), 20))
|
||||
return new Sequence(spriteLoader.Value, node.Key, x.Key, x.Value);
|
||||
})));
|
||||
t = Exts.Lazy(() => CreateUnitSequences(node));
|
||||
sequenceCache.Add(key, t);
|
||||
items.Add(node.Key, t);
|
||||
}
|
||||
}
|
||||
|
||||
return new ReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>(items);
|
||||
return new ReadOnlyDictionary<string, UnitSequences>(items);
|
||||
}
|
||||
|
||||
IReadOnlyDictionary<string, Sequence> CreateUnitSequences(MiniYamlNode node)
|
||||
{
|
||||
var unitSequences = new Dictionary<string, Sequence>();
|
||||
|
||||
foreach (var kvp in node.Value.ToDictionary())
|
||||
{
|
||||
using (new Support.PerfTimer("new Sequence(\"{0}\")".F(node.Key), 20))
|
||||
{
|
||||
try
|
||||
{
|
||||
unitSequences.Add(kvp.Key, new Sequence(spriteLoader.Value, node.Key, kvp.Key, kvp.Value));
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
Log.Write("debug", ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new ReadOnlyDictionary<string, Sequence>(unitSequences);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||
* Copyright 2007-2014 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,
|
||||
@@ -11,24 +11,28 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using OpenRA.FileFormats;
|
||||
using System.Runtime.InteropServices;
|
||||
using OpenRA.FileSystem;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
public class Sheet
|
||||
{
|
||||
ITexture texture;
|
||||
readonly object textureLock = new object();
|
||||
bool dirty;
|
||||
bool releaseBufferOnCommit;
|
||||
ITexture texture;
|
||||
byte[] data;
|
||||
|
||||
public readonly Size Size;
|
||||
public byte[] Data { get { return data ?? texture.GetData(); } }
|
||||
public bool Buffered { get { return data != null; } }
|
||||
|
||||
public Sheet(Size size)
|
||||
public Sheet(Size size, bool buffered)
|
||||
{
|
||||
Size = size;
|
||||
data = new byte[4*Size.Width*Size.Height];
|
||||
if (buffered)
|
||||
data = new byte[4 * Size.Width * Size.Height];
|
||||
}
|
||||
|
||||
public Sheet(ITexture texture)
|
||||
@@ -39,108 +43,118 @@ namespace OpenRA.Graphics
|
||||
|
||||
public Sheet(string filename)
|
||||
{
|
||||
var bitmap = (Bitmap)Image.FromStream(GlobalFileSystem.Open(filename));
|
||||
Size = bitmap.Size;
|
||||
|
||||
data = new byte[4*Size.Width*Size.Height];
|
||||
var b = bitmap.LockBits(bitmap.Bounds(),
|
||||
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
|
||||
|
||||
unsafe
|
||||
using (var stream = GlobalFileSystem.Open(filename))
|
||||
using (var bitmap = (Bitmap)Image.FromStream(stream))
|
||||
{
|
||||
int* c = (int*)b.Scan0;
|
||||
Size = bitmap.Size;
|
||||
|
||||
for (var x = 0; x < Size.Width; x++)
|
||||
for (var y = 0; y < Size.Height; y++)
|
||||
{
|
||||
var i = 4*Size.Width*y + 4*x;
|
||||
var dataStride = 4 * Size.Width;
|
||||
data = new byte[dataStride * Size.Height];
|
||||
|
||||
// Convert argb to bgra
|
||||
var argb = *(c + (y * b.Stride >> 2) + x);
|
||||
data[i++] = (byte)(argb >> 0);
|
||||
data[i++] = (byte)(argb >> 8);
|
||||
data[i++] = (byte)(argb >> 16);
|
||||
data[i++] = (byte)(argb >> 24);
|
||||
}
|
||||
var bd = bitmap.LockBits(bitmap.Bounds(),
|
||||
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
|
||||
for (var y = 0; y < Size.Height; y++)
|
||||
Marshal.Copy(IntPtr.Add(bd.Scan0, y * bd.Stride), data, y * dataStride, dataStride);
|
||||
bitmap.UnlockBits(bd);
|
||||
}
|
||||
bitmap.UnlockBits(b);
|
||||
|
||||
ReleaseBuffer();
|
||||
}
|
||||
|
||||
public ITexture Texture
|
||||
{
|
||||
// This is only called from the main thread but 'dirty'
|
||||
// is set from other threads too via CommitData().
|
||||
get
|
||||
{
|
||||
if (texture == null)
|
||||
{
|
||||
texture = Game.Renderer.Device.CreateTexture();
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
if (dirty)
|
||||
{
|
||||
texture.SetData(data, Size.Width, Size.Height);
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
GenerateTexture();
|
||||
return texture;
|
||||
}
|
||||
}
|
||||
|
||||
void GenerateTexture()
|
||||
{
|
||||
if (texture == null)
|
||||
{
|
||||
texture = Game.Renderer.Device.CreateTexture();
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
if (Buffered)
|
||||
{
|
||||
lock (textureLock)
|
||||
{
|
||||
if (dirty)
|
||||
{
|
||||
texture.SetData(data, Size.Width, Size.Height);
|
||||
dirty = false;
|
||||
if (releaseBufferOnCommit)
|
||||
data = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Bitmap AsBitmap()
|
||||
{
|
||||
var d = Data;
|
||||
var b = new Bitmap(Size.Width, Size.Height);
|
||||
var output = b.LockBits(new Rectangle(0, 0, Size.Width, Size.Height),
|
||||
var dataStride = 4 * Size.Width;
|
||||
var bitmap = new Bitmap(Size.Width, Size.Height);
|
||||
|
||||
var bd = bitmap.LockBits(bitmap.Bounds(),
|
||||
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
|
||||
for (var y = 0; y < Size.Height; y++)
|
||||
Marshal.Copy(d, y * dataStride, IntPtr.Add(bd.Scan0, y * bd.Stride), dataStride);
|
||||
bitmap.UnlockBits(bd);
|
||||
|
||||
unsafe
|
||||
{
|
||||
int* c = (int*)output.Scan0;
|
||||
|
||||
for (var x = 0; x < Size.Width; x++)
|
||||
for (var y = 0; y < Size.Height; y++)
|
||||
{
|
||||
var i = 4*Size.Width*y + 4*x;
|
||||
|
||||
// Convert bgra to argb
|
||||
var argb = (d[i+3] << 24) | (d[i+2] << 16) | (d[i+1] << 8) | d[i];
|
||||
*(c + (y * output.Stride >> 2) + x) = argb;
|
||||
}
|
||||
}
|
||||
b.UnlockBits(output);
|
||||
|
||||
return b;
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
public Bitmap AsBitmap(TextureChannel channel, Palette pal)
|
||||
public Bitmap AsBitmap(TextureChannel channel, IPalette pal)
|
||||
{
|
||||
var d = Data;
|
||||
var b = new Bitmap(Size.Width, Size.Height);
|
||||
var output = b.LockBits(new Rectangle(0, 0, Size.Width, Size.Height),
|
||||
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
|
||||
var dataStride = 4 * Size.Width;
|
||||
var bitmap = new Bitmap(Size.Width, Size.Height);
|
||||
var channelOffset = (int)channel;
|
||||
|
||||
var bd = bitmap.LockBits(bitmap.Bounds(),
|
||||
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
|
||||
unsafe
|
||||
{
|
||||
int* c = (int*)output.Scan0;
|
||||
|
||||
for (var x = 0; x < Size.Width; x++)
|
||||
for (var y = 0; y < Size.Height; y++)
|
||||
var colors = (uint*)bd.Scan0;
|
||||
for (var y = 0; y < Size.Height; y++)
|
||||
{
|
||||
var index = d[4*Size.Width*y + 4*x + (int)channel];
|
||||
*(c + (y * output.Stride >> 2) + x) = pal.GetColor(index).ToArgb();
|
||||
var dataRowIndex = y * dataStride + channelOffset;
|
||||
var bdRowIndex = y * bd.Stride / 4;
|
||||
for (var x = 0; x < Size.Width; x++)
|
||||
{
|
||||
var paletteIndex = d[dataRowIndex + 4 * x];
|
||||
colors[bdRowIndex + x] = pal[paletteIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
b.UnlockBits(output);
|
||||
|
||||
return b;
|
||||
bitmap.UnlockBits(bd);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
public void CommitData()
|
||||
{
|
||||
if (data == null)
|
||||
throw new InvalidOperationException("Texture-wrappers are read-only");
|
||||
if (!Buffered)
|
||||
throw new InvalidOperationException(
|
||||
"This sheet is unbuffered. You cannot call CommitData on an unbuffered sheet. " +
|
||||
"If you need to completely replace the texture data you should set data into the texture directly. " +
|
||||
"If you need to make only small changes to the texture data consider creating a buffered sheet instead.");
|
||||
|
||||
dirty = true;
|
||||
lock (textureLock)
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
public void ReleaseBuffer()
|
||||
{
|
||||
lock (textureLock)
|
||||
releaseBufferOnCommit = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||
* Copyright 2007-2014 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,
|
||||
@@ -10,7 +10,6 @@
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
@@ -18,7 +17,7 @@ namespace OpenRA.Graphics
|
||||
public class SheetOverflowException : Exception
|
||||
{
|
||||
public SheetOverflowException(string message)
|
||||
: base(message) {}
|
||||
: base(message) { }
|
||||
}
|
||||
|
||||
public enum SheetType
|
||||
@@ -39,11 +38,11 @@ namespace OpenRA.Graphics
|
||||
|
||||
public static Sheet AllocateSheet()
|
||||
{
|
||||
return new Sheet(new Size(Renderer.SheetSize, Renderer.SheetSize));
|
||||
return new Sheet(new Size(Renderer.SheetSize, Renderer.SheetSize), true);
|
||||
}
|
||||
|
||||
public SheetBuilder(SheetType t)
|
||||
: this(t, AllocateSheet) {}
|
||||
: this(t, AllocateSheet) { }
|
||||
|
||||
public SheetBuilder(SheetType t, Func<Sheet> allocateSheet)
|
||||
{
|
||||
@@ -110,6 +109,7 @@ namespace OpenRA.Graphics
|
||||
var next = NextChannel(channel);
|
||||
if (next == null)
|
||||
{
|
||||
current.ReleaseBuffer();
|
||||
current = allocateSheet();
|
||||
channel = TextureChannel.Red;
|
||||
}
|
||||
@@ -117,7 +117,7 @@ namespace OpenRA.Graphics
|
||||
channel = next.Value;
|
||||
|
||||
rowHeight = imageSize.Height;
|
||||
p = new Point(0,0);
|
||||
p = new Point(0, 0);
|
||||
}
|
||||
|
||||
var rect = new Sprite(current, new Rectangle(p, imageSize), spriteOffset, channel, BlendMode.Alpha);
|
||||
|
||||
@@ -11,9 +11,8 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using SharpFont;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Primitives;
|
||||
using SharpFont;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
@@ -86,7 +85,8 @@ namespace OpenRA.Graphics
|
||||
|
||||
public int2 Measure(string text)
|
||||
{
|
||||
return new int2((int)text.Split('\n').Max(s => s.Sum(a => glyphs[Pair.New(a, Color.White)].Advance)), text.Split('\n').Count()*size);
|
||||
var lines = text.Split('\n');
|
||||
return new int2((int)Math.Ceiling(lines.Max(s => s.Sum(a => glyphs[Pair.New(a, Color.White)].Advance))), lines.Length * size);
|
||||
}
|
||||
|
||||
Cache<Pair<char,Color>, GlyphInfo> glyphs;
|
||||
@@ -94,7 +94,7 @@ namespace OpenRA.Graphics
|
||||
|
||||
GlyphInfo CreateGlyph(Pair<char, Color> c)
|
||||
{
|
||||
uint index = face.GetCharIndex(c.First);
|
||||
var index = face.GetCharIndex(c.First);
|
||||
face.LoadGlyph(index, LoadFlags.Default, LoadTarget.Normal);
|
||||
face.Glyph.RenderGlyph(RenderMode.Normal);
|
||||
|
||||
@@ -108,27 +108,29 @@ namespace OpenRA.Graphics
|
||||
Offset = { X = face.Glyph.BitmapLeft, Y = -face.Glyph.BitmapTop }
|
||||
};
|
||||
|
||||
unsafe
|
||||
{
|
||||
var p = (byte*)face.Glyph.Bitmap.Buffer;
|
||||
var dest = s.sheet.Data;
|
||||
var destStride = s.sheet.Size.Width * 4;
|
||||
|
||||
for (var j = 0; j < s.size.Y; j++)
|
||||
// A new bitmap is generated each time this property is accessed, so we do need to dispose it.
|
||||
using (var bitmap = face.Glyph.Bitmap)
|
||||
unsafe
|
||||
{
|
||||
for (var i = 0; i < s.size.X; i++)
|
||||
if (p[i] != 0)
|
||||
{
|
||||
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];
|
||||
}
|
||||
var p = (byte*)bitmap.Buffer;
|
||||
var dest = s.sheet.Data;
|
||||
var destStride = s.sheet.Size.Width * 4;
|
||||
|
||||
p += face.Glyph.Bitmap.Pitch;
|
||||
for (var j = 0; j < s.size.Y; j++)
|
||||
{
|
||||
for (var i = 0; i < s.size.X; i++)
|
||||
if (p[i] != 0)
|
||||
{
|
||||
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 += bitmap.Pitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
s.sheet.CommitData();
|
||||
|
||||
return g;
|
||||
|
||||
@@ -8,9 +8,7 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.FileSystem;
|
||||
using OpenRA.Primitives;
|
||||
|
||||
@@ -33,10 +31,10 @@ namespace OpenRA.Graphics
|
||||
|
||||
Sprite[] CacheSpriteFrames(string filename)
|
||||
{
|
||||
var stream = GlobalFileSystem.OpenWithExts(filename, exts);
|
||||
return SpriteSource.LoadSpriteSource(stream, filename).Frames
|
||||
.Select(a => SheetBuilder.Add(a))
|
||||
.ToArray();
|
||||
using (var stream = GlobalFileSystem.OpenWithExts(filename, exts))
|
||||
return SpriteSource.LoadSpriteSource(stream, filename).Frames
|
||||
.Select(a => SheetBuilder.Add(a))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
public Sprite[] LoadAllSprites(string filename) { return sprites[filename]; }
|
||||
|
||||
@@ -120,9 +120,9 @@ namespace OpenRA.Graphics
|
||||
shader.SetTexture("Palette", palette);
|
||||
}
|
||||
|
||||
public void SetViewportParams(Size screen, float zoom, float2 scroll)
|
||||
public void SetViewportParams(Size screen, float zoom, int2 scroll)
|
||||
{
|
||||
shader.SetVec("Scroll", (int)scroll.X, (int)scroll.Y);
|
||||
shader.SetVec("Scroll", scroll.X, scroll.Y);
|
||||
shader.SetVec("r1", zoom*2f/screen.Width, -zoom*2f/screen.Height);
|
||||
shader.SetVec("r2", -1, 1);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||
* Copyright 2007-2014 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,
|
||||
@@ -8,10 +8,8 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
@@ -26,8 +24,7 @@ namespace OpenRA.Graphics
|
||||
|
||||
public interface ISpriteSource
|
||||
{
|
||||
// TODO: Change this to IReadOnlyList so users don't need to call .ToArray()
|
||||
IEnumerable<ISpriteFrame> Frames { get; }
|
||||
IReadOnlyList<ISpriteFrame> Frames { get; }
|
||||
bool CacheWhenLoadingTileset { get; }
|
||||
}
|
||||
|
||||
|
||||
@@ -26,17 +26,14 @@ namespace OpenRA.Graphics
|
||||
|
||||
var terrainPalette = wr.Palette("terrain").Index;
|
||||
var vertices = new Vertex[4 * map.Bounds.Height * map.Bounds.Width];
|
||||
int nv = 0;
|
||||
var nv = 0;
|
||||
|
||||
for (var j = map.Bounds.Top; j < map.Bounds.Bottom; j++)
|
||||
foreach (var cell in map.Cells)
|
||||
{
|
||||
for (var i = map.Bounds.Left; i < map.Bounds.Right; i++)
|
||||
{
|
||||
var tile = wr.Theater.TileSprite(map.MapTiles.Value[i, j]);
|
||||
var pos = wr.ScreenPosition(new CPos(i, j).CenterPosition) - 0.5f * tile.size;
|
||||
Util.FastCreateQuad(vertices, pos, tile, terrainPalette, nv, tile.size);
|
||||
nv += 4;
|
||||
}
|
||||
var tile = wr.Theater.TileSprite(map.MapTiles.Value[cell]);
|
||||
var pos = wr.ScreenPosition(map.CenterOfCell(cell)) - 0.5f * tile.size;
|
||||
Util.FastCreateQuad(vertices, pos, tile, terrainPalette, nv, tile.size);
|
||||
nv += 4;
|
||||
}
|
||||
|
||||
vertexBuffer = Game.Renderer.Device.CreateVertexBuffer(vertices.Length);
|
||||
@@ -46,12 +43,13 @@ namespace OpenRA.Graphics
|
||||
public void Draw(WorldRenderer wr, Viewport viewport)
|
||||
{
|
||||
var verticesPerRow = 4*map.Bounds.Width;
|
||||
var bounds = viewport.CellBounds;
|
||||
var firstRow = bounds.Top - map.Bounds.Top;
|
||||
var lastRow = bounds.Bottom - map.Bounds.Top;
|
||||
var cells = viewport.VisibleCells;
|
||||
var shape = wr.world.Map.TileShape;
|
||||
|
||||
if (lastRow < 0 || firstRow > map.Bounds.Height)
|
||||
return;
|
||||
// Only draw the rows that are visible.
|
||||
// VisibleCells is clamped to the map, so additional checks are unnecessary
|
||||
var firstRow = Map.CellToMap(shape, cells.TopLeft).Y - map.Bounds.Top;
|
||||
var lastRow = Map.CellToMap(shape, cells.BottomRight).Y - map.Bounds.Top + 1;
|
||||
|
||||
Game.Renderer.WorldSpriteRenderer.DrawVertexBuffer(
|
||||
vertexBuffer, verticesPerRow * firstRow, verticesPerRow * (lastRow - firstRow),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
||||
* Copyright 2007-2014 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,
|
||||
@@ -11,7 +11,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using OpenRA.FileSystem;
|
||||
|
||||
@@ -59,7 +58,7 @@ namespace OpenRA.Graphics
|
||||
throw new SheetOverflowException("Terrain sheet overflow. Try increasing the tileset SheetSize parameter.");
|
||||
allocated = true;
|
||||
|
||||
return new Sheet(new Size(tileset.SheetSize, tileset.SheetSize));
|
||||
return new Sheet(new Size(tileset.SheetSize, tileset.SheetSize), true);
|
||||
};
|
||||
|
||||
var sourceCache = new Dictionary<string, ISpriteSource>();
|
||||
@@ -70,9 +69,11 @@ namespace OpenRA.Graphics
|
||||
|
||||
// 1x1px transparent tile
|
||||
missingTile = sheetBuilder.Add(new byte[1], new Size(1, 1));
|
||||
|
||||
Sheet.ReleaseBuffer();
|
||||
}
|
||||
|
||||
public Sprite TileSprite(TileReference<ushort, byte> r)
|
||||
public Sprite TileSprite(TerrainTile r)
|
||||
{
|
||||
Sprite[] template;
|
||||
if (!templates.TryGetValue(r.Type, out template))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||
* Copyright 2007-2014 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,
|
||||
@@ -11,6 +11,7 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
@@ -51,7 +52,7 @@ namespace OpenRA.Graphics
|
||||
var srcOffset = 0;
|
||||
for (var j = 0; j < height; j++)
|
||||
{
|
||||
for (int i = 0; i < srcStride; i++, srcOffset++)
|
||||
for (var i = 0; i < srcStride; i++, srcOffset++)
|
||||
{
|
||||
data[destOffset] = src[srcOffset];
|
||||
destOffset += 4;
|
||||
@@ -62,32 +63,18 @@ namespace OpenRA.Graphics
|
||||
|
||||
public static void FastCopyIntoSprite(Sprite dest, Bitmap src)
|
||||
{
|
||||
var destStride = dest.sheet.Size.Width;
|
||||
var width = dest.bounds.Width;
|
||||
var data = dest.sheet.Data;
|
||||
var dataStride = dest.sheet.Size.Width * 4;
|
||||
var x = dest.bounds.Left * 4;
|
||||
var width = dest.bounds.Width * 4;
|
||||
var y = dest.bounds.Top;
|
||||
var height = dest.bounds.Height;
|
||||
|
||||
var srcData = src.LockBits(src.Bounds(),
|
||||
var bd = src.LockBits(src.Bounds(),
|
||||
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||
|
||||
unsafe
|
||||
{
|
||||
var c = (int*)srcData.Scan0;
|
||||
|
||||
// Cast the data to an int array so we can copy the src data directly
|
||||
fixed (byte* bd = &dest.sheet.Data[0])
|
||||
{
|
||||
var data = (int*)bd;
|
||||
var x = dest.bounds.Left;
|
||||
var y = dest.bounds.Top;
|
||||
|
||||
for (var j = 0; j < height; j++)
|
||||
for (var i = 0; i < width; i++)
|
||||
data[(y + j) * destStride + x + i] = *(c + (j * srcData.Stride >> 2) + i);
|
||||
}
|
||||
}
|
||||
|
||||
src.UnlockBits(srcData);
|
||||
|
||||
for (var row = 0; row < height; row++)
|
||||
Marshal.Copy(IntPtr.Add(bd.Scan0, row * bd.Stride), data, (y + row) * dataStride + x, width);
|
||||
src.UnlockBits(bd);
|
||||
}
|
||||
|
||||
public static float[] IdentityMatrix()
|
||||
|
||||
54
OpenRA.Game/Graphics/Viewport.cs
Executable file → Normal file
54
OpenRA.Game/Graphics/Viewport.cs
Executable file → Normal file
@@ -9,6 +9,7 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
@@ -46,7 +47,8 @@ namespace OpenRA.Graphics
|
||||
public int2 TopLeft { get { return CenterLocation - viewportSize / 2; } }
|
||||
public int2 BottomRight { get { return CenterLocation + viewportSize / 2; } }
|
||||
int2 viewportSize;
|
||||
bool cellBoundsDirty = true;
|
||||
CellRegion cells;
|
||||
bool cellsDirty = true;
|
||||
|
||||
float zoom = 1f;
|
||||
public float Zoom
|
||||
@@ -60,7 +62,7 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
zoom = value;
|
||||
viewportSize = (1f / zoom * new float2(Game.Renderer.Resolution)).ToInt2();
|
||||
cellBoundsDirty = true;
|
||||
cellsDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,14 +90,21 @@ namespace OpenRA.Graphics
|
||||
|
||||
// Calculate map bounds in world-px
|
||||
var b = map.Bounds;
|
||||
var tl = wr.ScreenPxPosition(new CPos(b.Left, b.Top).TopLeft);
|
||||
var br = wr.ScreenPxPosition(new CPos(b.Right, b.Bottom).BottomRight);
|
||||
|
||||
// Expand to corners of cells
|
||||
var tl = wr.ScreenPxPosition(map.CenterOfCell(Map.MapToCell(map.TileShape, new CPos(b.Left, b.Top))) - new WVec(512, 512, 0));
|
||||
var br = wr.ScreenPxPosition(map.CenterOfCell(Map.MapToCell(map.TileShape, new CPos(b.Right, b.Bottom))) + new WVec(511, 511, 0));
|
||||
mapBounds = Rectangle.FromLTRB(tl.X, tl.Y, br.X, br.Y);
|
||||
|
||||
CenterLocation = (tl + br) / 2;
|
||||
Zoom = Game.Settings.Graphics.PixelDouble ? 2 : 1;
|
||||
}
|
||||
|
||||
public CPos ViewToWorld(int2 view)
|
||||
{
|
||||
return worldRenderer.world.Map.CellContaining(worldRenderer.Position(ViewToWorldPx(view)));
|
||||
}
|
||||
|
||||
public int2 ViewToWorldPx(int2 view) { return (1f / Zoom * view.ToFloat2()).ToInt2() + TopLeft; }
|
||||
public int2 WorldToViewPx(int2 world) { return (Zoom * (world - TopLeft).ToFloat2()).ToInt2(); }
|
||||
|
||||
@@ -110,14 +119,14 @@ namespace OpenRA.Graphics
|
||||
public void Center(WPos pos)
|
||||
{
|
||||
CenterLocation = worldRenderer.ScreenPxPosition(pos).Clamp(mapBounds);
|
||||
cellBoundsDirty = true;
|
||||
cellsDirty = true;
|
||||
}
|
||||
|
||||
public void Scroll(float2 delta, bool ignoreBorders)
|
||||
{
|
||||
// Convert scroll delta from world-px to viewport-px
|
||||
CenterLocation += (1f / Zoom * delta).ToInt2();
|
||||
cellBoundsDirty = true;
|
||||
cellsDirty = true;
|
||||
|
||||
if (!ignoreBorders)
|
||||
CenterLocation = CenterLocation.Clamp(mapBounds);
|
||||
@@ -129,33 +138,38 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
get
|
||||
{
|
||||
var r = CellBounds;
|
||||
var ctl = new CPos(r.Left, r.Top).TopLeft;
|
||||
var cbr = new CPos(r.Right, r.Bottom).TopLeft;
|
||||
// Visible rectangle in world coordinates (expanded to the corners of the cells)
|
||||
var map = worldRenderer.world.Map;
|
||||
var ctl = map.CenterOfCell(VisibleCells.TopLeft) - new WVec(512, 512, 0);
|
||||
var cbr = map.CenterOfCell(VisibleCells.BottomRight) + new WVec(512, 512, 0);
|
||||
|
||||
// Convert to screen coordinates
|
||||
var tl = WorldToViewPx(worldRenderer.ScreenPxPosition(ctl)).Clamp(ScreenClip);
|
||||
var br = WorldToViewPx(worldRenderer.ScreenPxPosition(cbr)).Clamp(ScreenClip);
|
||||
return Rectangle.FromLTRB(tl.X, tl.Y, br.X, br.Y);
|
||||
}
|
||||
}
|
||||
|
||||
// Rectangle (in cell coords) of cells that are currently visible on the screen
|
||||
Rectangle cachedRect;
|
||||
public Rectangle CellBounds
|
||||
public CellRegion VisibleCells
|
||||
{
|
||||
get
|
||||
{
|
||||
if (cellBoundsDirty)
|
||||
if (cellsDirty)
|
||||
{
|
||||
var boundary = new CVec(1, 1);
|
||||
var tl = worldRenderer.Position(TopLeft).ToCPos() - boundary;
|
||||
var br = worldRenderer.Position(BottomRight).ToCPos() + boundary;
|
||||
// Visible rectangle in map coordinates
|
||||
var map = worldRenderer.world.Map;
|
||||
var ctl = Map.CellToMap(map.TileShape, map.CellContaining(worldRenderer.Position(TopLeft)));
|
||||
var cbr = Map.CellToMap(map.TileShape, map.CellContaining(worldRenderer.Position(BottomRight)));
|
||||
|
||||
cachedRect = Rectangle.Intersect(Rectangle.FromLTRB(tl.X, tl.Y, br.X, br.Y), worldRenderer.world.Map.Bounds);
|
||||
cellBoundsDirty = false;
|
||||
// Add a 2 cell cordon to prevent holes, then convert back to cell coordinates
|
||||
var tl = map.Clamp(Map.MapToCell(map.TileShape, ctl - new CVec(2, 2)));
|
||||
var br = map.Clamp(Map.MapToCell(map.TileShape, cbr + new CVec(2, 2)));
|
||||
|
||||
cells = new CellRegion(map.TileShape, tl, br);
|
||||
cellsDirty = false;
|
||||
}
|
||||
|
||||
var b = worldRenderer.world.VisibleBounds;
|
||||
return b.HasValue ? Rectangle.Intersect(cachedRect, b.Value) : cachedRect;
|
||||
return cells;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace OpenRA.Graphics
|
||||
c++;
|
||||
}
|
||||
|
||||
Sprite s = sheetBuilder.Allocate(new Size(su, sv));
|
||||
var s = sheetBuilder.Allocate(new Size(su, sv));
|
||||
Util.FastCopyIntoChannel(s, 0, colors);
|
||||
Util.FastCopyIntoChannel(s, 1, normals);
|
||||
s.sheet.CommitData();
|
||||
@@ -179,6 +179,7 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
// Sheet overflow - allocate a new sheet and try once more
|
||||
Log.Write("debug", "Voxel sheet overflow! Generating new sheet");
|
||||
sheetBuilder.Current.ReleaseBuffer();
|
||||
sheetBuilder = CreateSheetBuilder();
|
||||
v = GenerateSlicePlanes(l).SelectMany(x => x).ToArray();
|
||||
}
|
||||
@@ -210,8 +211,12 @@ namespace OpenRA.Graphics
|
||||
|
||||
Voxel LoadFile(Pair<string,string> files)
|
||||
{
|
||||
var vxl = new VxlReader(GlobalFileSystem.OpenWithExts(files.First, ".vxl"));
|
||||
var hva = new HvaReader(GlobalFileSystem.OpenWithExts(files.Second, ".hva"));
|
||||
VxlReader vxl;
|
||||
HvaReader hva;
|
||||
using (var s = GlobalFileSystem.OpenWithExts(files.First, ".vxl"))
|
||||
vxl = new VxlReader(s);
|
||||
using (var s = GlobalFileSystem.OpenWithExts(files.Second, ".hva"))
|
||||
hva = new HvaReader(s);
|
||||
return new Voxel(this, vxl, hva);
|
||||
}
|
||||
|
||||
@@ -219,5 +224,10 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
return voxels[Pair.New(vxl, hva)];
|
||||
}
|
||||
|
||||
public void Finish()
|
||||
{
|
||||
sheetBuilder.Current.ReleaseBuffer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace OpenRA.Graphics
|
||||
Game.modData.VoxelLoader.RefreshBuffer();
|
||||
}
|
||||
|
||||
static Voxel LoadVoxel(string unit, string name, MiniYaml info)
|
||||
static Voxel LoadVoxel(string unit, MiniYaml info)
|
||||
{
|
||||
var vxl = unit;
|
||||
var hva = unit;
|
||||
@@ -55,7 +55,7 @@ namespace OpenRA.Graphics
|
||||
Game.modData.LoadScreen.Display();
|
||||
try
|
||||
{
|
||||
var seq = sequences.NodesDict.ToDictionary(x => x.Key, x => LoadVoxel(unit,x.Key,x.Value));
|
||||
var seq = sequences.ToDictionary(my => LoadVoxel(unit, my));
|
||||
units.Add(unit, seq);
|
||||
}
|
||||
catch (FileNotFoundException) {} // Do nothing; we can crash later if we actually wanted art
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
||||
* Copyright 2007-2014 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,
|
||||
@@ -89,10 +89,12 @@ namespace OpenRA.Graphics
|
||||
static readonly float[] groundNormal = new float[] {0,0,1,1};
|
||||
public void BeforeRender(WorldRenderer wr)
|
||||
{
|
||||
var draw = voxels.Where(v => v.DisableFunc == null || !v.DisableFunc());
|
||||
|
||||
renderProxy = Game.Renderer.WorldVoxelRenderer.RenderAsync(
|
||||
wr, voxels, camera, scale, groundNormal, lightSource,
|
||||
wr, draw, camera, scale, groundNormal, lightSource,
|
||||
lightAmbientColor, lightDiffuseColor,
|
||||
palette, normalsPalette, shadowPalette);
|
||||
palette, normalsPalette, shadowPalette);
|
||||
}
|
||||
|
||||
public void Render(WorldRenderer wr)
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace OpenRA.Graphics
|
||||
shader.SetTexture("Palette", palette);
|
||||
}
|
||||
|
||||
public void SetViewportParams(Size screen, float zoom, float2 scroll)
|
||||
public void SetViewportParams(Size screen, float zoom, int2 scroll)
|
||||
{
|
||||
var a = 2f / Renderer.SheetSize;
|
||||
var view = new float[]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||
* Copyright 2007-2014 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,
|
||||
@@ -12,8 +12,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
@@ -22,8 +20,8 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
public readonly string Name;
|
||||
public readonly int Index;
|
||||
public readonly Palette Palette;
|
||||
public PaletteReference(string name, int index, Palette palette)
|
||||
public IPalette Palette { get; internal set; }
|
||||
public PaletteReference(string name, int index, IPalette palette)
|
||||
{
|
||||
Name = name;
|
||||
Index = index;
|
||||
@@ -37,10 +35,10 @@ namespace OpenRA.Graphics
|
||||
public readonly Theater Theater;
|
||||
public Viewport Viewport { get; private set; }
|
||||
|
||||
internal readonly TerrainRenderer terrainRenderer;
|
||||
internal readonly HardwarePalette palette;
|
||||
internal Cache<string, PaletteReference> palettes;
|
||||
Lazy<DeveloperMode> devTrait;
|
||||
readonly TerrainRenderer terrainRenderer;
|
||||
readonly HardwarePalette palette;
|
||||
readonly Dictionary<string, PaletteReference> palettes;
|
||||
readonly Lazy<DeveloperMode> devTrait;
|
||||
|
||||
internal WorldRenderer(World world)
|
||||
{
|
||||
@@ -48,9 +46,9 @@ namespace OpenRA.Graphics
|
||||
Viewport = new Viewport(this, world.Map);
|
||||
palette = new HardwarePalette();
|
||||
|
||||
palettes = new Cache<string, PaletteReference>(CreatePaletteReference);
|
||||
foreach (var pal in world.traitDict.ActorsWithTraitMultiple<IPalette>(world))
|
||||
pal.Trait.InitPalette(this);
|
||||
palettes = new Dictionary<string, PaletteReference>();
|
||||
foreach (var pal in world.traitDict.ActorsWithTrait<ILoadsPalettes>())
|
||||
pal.Trait.LoadPalettes(this);
|
||||
|
||||
palette.Initialize();
|
||||
|
||||
@@ -63,14 +61,13 @@ namespace OpenRA.Graphics
|
||||
PaletteReference CreatePaletteReference(string name)
|
||||
{
|
||||
var pal = palette.GetPalette(name);
|
||||
if (pal == null)
|
||||
throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
|
||||
|
||||
return new PaletteReference(name, palette.GetPaletteIndex(name), pal);
|
||||
}
|
||||
|
||||
public PaletteReference Palette(string name) { return palettes[name]; }
|
||||
public void AddPalette(string name, Palette pal, bool allowModifiers) { palette.AddPalette(name, pal, allowModifiers); }
|
||||
public PaletteReference Palette(string name) { return palettes.GetOrAdd(name, CreatePaletteReference); }
|
||||
public void AddPalette(string name, ImmutablePalette pal) { palette.AddPalette(name, pal, false); }
|
||||
public void AddPalette(string name, ImmutablePalette pal, bool allowModifiers) { palette.AddPalette(name, pal, allowModifiers); }
|
||||
public void ReplacePalette(string name, IPalette pal) { palette.ReplacePalette(name, pal); palettes[name].Palette = pal; }
|
||||
|
||||
List<IRenderable> GenerateRenderables()
|
||||
{
|
||||
|
||||
@@ -18,6 +18,22 @@ using OpenRA.FileSystem;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public class InstallData
|
||||
{
|
||||
public readonly string InstallerMenuWidget = null;
|
||||
public readonly string InstallerBackgroundWidget = null;
|
||||
public readonly string[] TestFiles = {};
|
||||
public readonly string[] DiskTestFiles = {};
|
||||
public readonly string PackageToExtractFromCD = null;
|
||||
public readonly string[] ExtractFilesFromCD = {};
|
||||
public readonly string[] CopyFilesFromCD = {};
|
||||
|
||||
public readonly string PackageMirrorList = null;
|
||||
|
||||
public readonly string MusicPackageMirrorList = null;
|
||||
public readonly int ShippedSoundtracks = 0;
|
||||
}
|
||||
|
||||
public static class InstallUtils
|
||||
{
|
||||
static IEnumerable<ZipEntry> GetEntries(this ZipInputStream z)
|
||||
@@ -39,23 +55,26 @@ namespace OpenRA
|
||||
}
|
||||
|
||||
// TODO: The package should be mounted into its own context to avoid name collisions with installed files
|
||||
public static bool ExtractFromPackage(string srcPath, string package, string[] files, string destPath, Action<string> onProgress, Action<string> onError)
|
||||
public static bool ExtractFromPackage(string srcPath, string package, string annotation, string[] files, string destPath, Action<string> onProgress, Action<string> onError)
|
||||
{
|
||||
if (!Directory.Exists(destPath))
|
||||
Directory.CreateDirectory(destPath);
|
||||
|
||||
if (!GlobalFileSystem.Exists(srcPath)) { onError("Cannot find " + package); return false; }
|
||||
Log.Write("debug", "Mounting {0}".F(srcPath));
|
||||
GlobalFileSystem.Mount(srcPath);
|
||||
if (!GlobalFileSystem.Exists(package)) { onError("Cannot find " + package); return false; }
|
||||
GlobalFileSystem.Mount(package);
|
||||
Log.Write("debug", "Mounting {0}".F(package));
|
||||
GlobalFileSystem.Mount(package, annotation);
|
||||
|
||||
foreach (string s in files)
|
||||
foreach (var file in files)
|
||||
{
|
||||
var destFile = Path.Combine(destPath, s);
|
||||
using (var sourceStream = GlobalFileSystem.Open(s))
|
||||
using (var destStream = File.Create(destFile))
|
||||
var dest = Path.Combine(destPath, file);
|
||||
if (File.Exists(dest))
|
||||
File.Delete(dest);
|
||||
using (var sourceStream = GlobalFileSystem.Open(file))
|
||||
using (var destStream = File.Create(dest))
|
||||
{
|
||||
onProgress("Extracting " + s);
|
||||
Log.Write("debug", "Extracting {0} to {1}".F(file, dest));
|
||||
onProgress("Extracting " + file);
|
||||
destStream.Write(sourceStream.ReadAllBytes());
|
||||
}
|
||||
}
|
||||
@@ -75,8 +94,12 @@ namespace OpenRA
|
||||
}
|
||||
|
||||
var destFile = Path.GetFileName(file).ToLowerInvariant();
|
||||
onProgress("Extracting " + destFile);
|
||||
File.Copy(fromPath, Path.Combine(destPath, destFile), true);
|
||||
var dest = Path.Combine(destPath, destFile);
|
||||
if (File.Exists(dest))
|
||||
File.Delete(dest);
|
||||
onProgress("Copying " + destFile);
|
||||
Log.Write("debug", "Copy {0} to {1}".F(fromPath, dest));
|
||||
File.Copy(fromPath, dest, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -90,11 +113,12 @@ namespace OpenRA
|
||||
return false;
|
||||
}
|
||||
|
||||
List<string> extracted = new List<string>();
|
||||
var extracted = new List<string>();
|
||||
try
|
||||
{
|
||||
var z = new ZipInputStream(File.OpenRead(zipFile));
|
||||
z.ExtractZip(dest, extracted, s => onProgress("Extracting " + s));
|
||||
using (var stream = File.OpenRead(zipFile))
|
||||
using (var z = new ZipInputStream(stream))
|
||||
z.ExtractZip(dest, extracted, s => onProgress("Extracting " + s));
|
||||
}
|
||||
catch (SharpZipBaseException)
|
||||
{
|
||||
@@ -122,12 +146,7 @@ namespace OpenRA
|
||||
extracted.Add(path);
|
||||
|
||||
using (var f = File.Create(path))
|
||||
{
|
||||
int bufSize = 2048;
|
||||
byte[] buf = new byte[bufSize];
|
||||
while ((bufSize = z.Read(buf, 0, buf.Length)) > 0)
|
||||
f.Write(buf, 0, bufSize);
|
||||
}
|
||||
z.CopyTo(f);
|
||||
}
|
||||
|
||||
z.Close();
|
||||
|
||||
@@ -16,6 +16,8 @@ using OpenRA.Primitives;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public enum TileShape { Rectangle, Diamond }
|
||||
|
||||
// Describes what is to be loaded in order to run a mod
|
||||
public class Manifest
|
||||
{
|
||||
@@ -30,14 +32,15 @@ namespace OpenRA
|
||||
public readonly IReadOnlyDictionary<string, string> MapFolders;
|
||||
public readonly MiniYaml LoadScreen;
|
||||
public readonly MiniYaml LobbyDefaults;
|
||||
public readonly InstallData ContentInstaller;
|
||||
public readonly Dictionary<string, Pair<string, int>> Fonts;
|
||||
public readonly Size TileSize = new Size(24, 24);
|
||||
public readonly string NewsUrl;
|
||||
public readonly TileShape TileShape = TileShape.Rectangle;
|
||||
|
||||
public Manifest(string mod)
|
||||
{
|
||||
var path = new[] { "mods", mod, "mod.yaml" }.Aggregate(Path.Combine);
|
||||
var yaml = new MiniYaml(null, MiniYaml.FromFile(path)).NodesDict;
|
||||
var yaml = new MiniYaml(null, MiniYaml.FromFile(path)).ToDictionary();
|
||||
|
||||
Mod = FieldLoader.Load<ModMetadata>(yaml["Metadata"]);
|
||||
Mod.Id = mod;
|
||||
@@ -68,13 +71,22 @@ namespace OpenRA
|
||||
|
||||
LoadScreen = yaml["LoadScreen"];
|
||||
LobbyDefaults = yaml["LobbyDefaults"];
|
||||
Fonts = yaml["Fonts"].NodesDict.ToDictionary(x => x.Key,
|
||||
x => Pair.New(x.Value.NodesDict["Font"].Value,
|
||||
Exts.ParseIntegerInvariant(x.Value.NodesDict["Size"].Value)));
|
||||
|
||||
if (yaml.ContainsKey("ContentInstaller"))
|
||||
ContentInstaller = FieldLoader.Load<InstallData>(yaml["ContentInstaller"]);
|
||||
|
||||
Fonts = yaml["Fonts"].ToDictionary(my =>
|
||||
{
|
||||
var nd = my.ToDictionary();
|
||||
return Pair.New(nd["Font"].Value, Exts.ParseIntegerInvariant(nd["Size"].Value));
|
||||
});
|
||||
|
||||
if (yaml.ContainsKey("TileSize"))
|
||||
TileSize = FieldLoader.GetValue<Size>("TileSize", yaml["TileSize"].Value);
|
||||
|
||||
if (yaml.ContainsKey("TileShape"))
|
||||
TileShape = FieldLoader.GetValue<TileShape>("TileShape", yaml["TileShape"].Value);
|
||||
|
||||
// Allow inherited mods to import parent maps.
|
||||
var compat = new List<string>();
|
||||
compat.Add(mod);
|
||||
@@ -84,9 +96,6 @@ namespace OpenRA
|
||||
compat.Add(c.Trim());
|
||||
|
||||
MapCompatibility = compat.ToArray();
|
||||
|
||||
if (yaml.ContainsKey("NewsUrl"))
|
||||
NewsUrl = yaml["NewsUrl"].Value;
|
||||
}
|
||||
|
||||
static string[] YamlList(Dictionary<string, MiniYaml> yaml, string key)
|
||||
@@ -94,7 +103,7 @@ namespace OpenRA
|
||||
if (!yaml.ContainsKey(key))
|
||||
return new string[] { };
|
||||
|
||||
return yaml[key].NodesDict.Keys.ToArray();
|
||||
return yaml[key].ToDictionary().Keys.ToArray();
|
||||
}
|
||||
|
||||
static IReadOnlyDictionary<string, string> YamlDictionary(Dictionary<string, MiniYaml> yaml, string key)
|
||||
@@ -102,7 +111,7 @@ namespace OpenRA
|
||||
if (!yaml.ContainsKey(key))
|
||||
return new ReadOnlyDictionary<string, string>();
|
||||
|
||||
var inner = yaml[key].NodesDict.ToDictionary(x => x.Key, x => x.Value.Value);
|
||||
var inner = yaml[key].ToDictionary(my => my.Value);
|
||||
return new ReadOnlyDictionary<string, string>(inner);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,10 +57,10 @@ namespace OpenRA
|
||||
|
||||
public class LocationInit : IActorInit<CPos>
|
||||
{
|
||||
[FieldFromYamlKey] public readonly int2 value = int2.Zero;
|
||||
[FieldFromYamlKey] public readonly CPos value = CPos.Zero;
|
||||
public LocationInit() { }
|
||||
public LocationInit(CPos init) { value = init.ToInt2(); }
|
||||
public CPos Value(World world) { return (CPos)value; }
|
||||
public LocationInit(CPos init) { value = init; }
|
||||
public CPos Value(World world) { return value; }
|
||||
}
|
||||
|
||||
public class SubCellInit : IActorInit<SubCell>
|
||||
|
||||
@@ -24,9 +24,9 @@ namespace OpenRA
|
||||
}
|
||||
Lazy<TypeDictionary> initDict;
|
||||
|
||||
public ActorReference( string type ) : this( type, new Dictionary<string, MiniYaml>() ) { }
|
||||
public ActorReference( string type ) : this(type, new Dictionary<string, MiniYaml>()) { }
|
||||
|
||||
public ActorReference( string type, Dictionary<string, MiniYaml> inits )
|
||||
public ActorReference(string type, Dictionary<string, MiniYaml> inits)
|
||||
{
|
||||
Type = type;
|
||||
initDict = Exts.Lazy(() =>
|
||||
@@ -47,17 +47,17 @@ namespace OpenRA
|
||||
|
||||
public MiniYaml Save()
|
||||
{
|
||||
var ret = new MiniYaml( Type );
|
||||
foreach( var init in InitDict )
|
||||
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 ) ) );
|
||||
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 void Add(object o) { InitDict.Add(o); }
|
||||
public IEnumerator GetEnumerator() { return InitDict.GetEnumerator(); }
|
||||
}
|
||||
}
|
||||
|
||||
107
OpenRA.Game/Map/CellLayer.cs
Normal file
107
OpenRA.Game/Map/CellLayer.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2014 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 COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using OpenRA.Graphics;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
// Represents a layer of "something" that covers the map
|
||||
public class CellLayer<T> : IEnumerable<T>
|
||||
{
|
||||
public readonly Size Size;
|
||||
public readonly TileShape Shape;
|
||||
T[] entries;
|
||||
|
||||
public CellLayer(Map map)
|
||||
: this(map.TileShape, new Size(map.MapSize.X, map.MapSize.Y)) { }
|
||||
|
||||
public CellLayer(TileShape shape, Size size)
|
||||
{
|
||||
Size = size;
|
||||
Shape = shape;
|
||||
entries = new T[size.Width * size.Height];
|
||||
}
|
||||
|
||||
// Resolve an array index from cell coordinates
|
||||
int Index(CPos cell)
|
||||
{
|
||||
var uv = Map.CellToMap(Shape, cell);
|
||||
return uv.Y * Size.Width + uv.X;
|
||||
}
|
||||
|
||||
/// <summary>Gets or sets the <see cref="OpenRA.CellLayer"/> using cell coordinates</summary>
|
||||
public T this[CPos cell]
|
||||
{
|
||||
get
|
||||
{
|
||||
return entries[Index(cell)];
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
entries[Index(cell)] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gets or sets the layer contents using raw map coordinates (not CPos!)</summary>
|
||||
public T this[int u, int v]
|
||||
{
|
||||
get
|
||||
{
|
||||
return entries[v * Size.Width + u];
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
entries[v * Size.Width + u] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Clears the layer contents with a known value</summary>
|
||||
public void Clear(T clearValue)
|
||||
{
|
||||
for (var i = 0; i < entries.Length; i++)
|
||||
entries[i] = clearValue;
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return (IEnumerator<T>)entries.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
// Helper functions
|
||||
public static class CellLayer
|
||||
{
|
||||
/// <summary>Create a new layer by resizing another layer. New cells are filled with defaultValue.</summary>
|
||||
public static CellLayer<T> Resize<T>(CellLayer<T> layer, Size newSize, T defaultValue)
|
||||
{
|
||||
var result = new CellLayer<T>(layer.Shape, newSize);
|
||||
var width = Math.Min(layer.Size.Width, newSize.Width);
|
||||
var height = Math.Min(layer.Size.Height, newSize.Height);
|
||||
|
||||
result.Clear(defaultValue);
|
||||
for (var j = 0; j < height; j++)
|
||||
for (var i = 0; i < width; i++)
|
||||
result[i, j] = layer[i, j];
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
112
OpenRA.Game/Map/CellRegion.cs
Normal file
112
OpenRA.Game/Map/CellRegion.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2014 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 COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using OpenRA.Graphics;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
// Represents a (on-screen) rectangular collection of tiles.
|
||||
// TopLeft and BottomRight are inclusive
|
||||
public class CellRegion : IEnumerable<CPos>
|
||||
{
|
||||
// Corners of the region
|
||||
public readonly CPos TopLeft;
|
||||
public readonly CPos BottomRight;
|
||||
readonly TileShape shape;
|
||||
|
||||
// Corners in map coordinates
|
||||
// These will only equal TopLeft and BottomRight for TileShape.Rectangular
|
||||
readonly CPos mapTopLeft;
|
||||
readonly CPos mapBottomRight;
|
||||
|
||||
public CellRegion(TileShape shape, CPos topLeft, CPos bottomRight)
|
||||
{
|
||||
this.shape = shape;
|
||||
TopLeft = topLeft;
|
||||
BottomRight = bottomRight;
|
||||
|
||||
mapTopLeft = Map.CellToMap(shape, TopLeft);
|
||||
mapBottomRight = Map.CellToMap(shape, BottomRight);
|
||||
}
|
||||
|
||||
/// <summary>Expand the specified region with an additional cordon. This may expand the region outside the map borders.</summary>
|
||||
public static CellRegion Expand(CellRegion region, int cordon)
|
||||
{
|
||||
var offset = new CVec(cordon, cordon);
|
||||
var tl = Map.MapToCell(region.shape, Map.CellToMap(region.shape, region.TopLeft) - offset);
|
||||
var br = Map.MapToCell(region.shape, Map.CellToMap(region.shape, region.BottomRight) + offset);
|
||||
|
||||
return new CellRegion(region.shape, tl, br);
|
||||
}
|
||||
|
||||
public bool Contains(CPos cell)
|
||||
{
|
||||
var uv = Map.CellToMap(shape, cell);
|
||||
return uv.X >= mapTopLeft.X && uv.X <= mapBottomRight.X && uv.Y >= mapTopLeft.Y && uv.Y <= mapBottomRight.Y;
|
||||
}
|
||||
|
||||
public IEnumerator<CPos> GetEnumerator()
|
||||
{
|
||||
return new CellRegionEnumerator(this);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
class CellRegionEnumerator : IEnumerator<CPos>
|
||||
{
|
||||
readonly CellRegion r;
|
||||
|
||||
// Current position, in map coordinates
|
||||
int u, v;
|
||||
|
||||
public CellRegionEnumerator(CellRegion region)
|
||||
{
|
||||
r = region;
|
||||
Reset();
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
u += 1;
|
||||
|
||||
// Check for column overflow
|
||||
if (u > r.mapBottomRight.X)
|
||||
{
|
||||
v += 1;
|
||||
u = r.mapTopLeft.X;
|
||||
|
||||
// Check for row overflow
|
||||
if (v > r.mapBottomRight.Y)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
// Enumerator starts *before* the first element in the sequence.
|
||||
u = r.mapTopLeft.X - 1;
|
||||
v = r.mapTopLeft.Y;
|
||||
}
|
||||
|
||||
public CPos Current { get { return Map.MapToCell(r.shape, new CPos(u, v)); } }
|
||||
object IEnumerator.Current { get { return Current; } }
|
||||
public void Dispose() { }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
@@ -16,9 +17,10 @@ using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using OpenRA.FileSystem;
|
||||
using OpenRA.Network;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Network;
|
||||
using OpenRA.Support;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
@@ -74,14 +76,17 @@ namespace OpenRA
|
||||
public bool AllowStartUnitConfig = true;
|
||||
public Bitmap CustomPreview;
|
||||
|
||||
public readonly TileShape TileShape;
|
||||
|
||||
[FieldLoader.LoadUsing("LoadOptions")]
|
||||
public MapOptions Options;
|
||||
|
||||
static object LoadOptions(MiniYaml y)
|
||||
{
|
||||
var options = new MapOptions();
|
||||
if (y.NodesDict.ContainsKey("Options"))
|
||||
FieldLoader.Load(options, y.NodesDict["Options"]);
|
||||
var nodesDict = y.ToDictionary();
|
||||
if (nodesDict.ContainsKey("Options"))
|
||||
FieldLoader.Load(options, nodesDict["Options"]);
|
||||
|
||||
return options;
|
||||
}
|
||||
@@ -108,29 +113,40 @@ namespace OpenRA
|
||||
[FieldLoader.Ignore] public byte TileFormat = 1;
|
||||
public int2 MapSize;
|
||||
|
||||
[FieldLoader.Ignore] public Lazy<TileReference<ushort, byte>[,]> MapTiles;
|
||||
[FieldLoader.Ignore] public Lazy<TileReference<byte, byte>[,]> MapResources;
|
||||
[FieldLoader.Ignore] public string[,] CustomTerrain;
|
||||
[FieldLoader.Ignore] public Lazy<CellLayer<TerrainTile>> MapTiles;
|
||||
[FieldLoader.Ignore] public Lazy<CellLayer<ResourceTile>> MapResources;
|
||||
[FieldLoader.Ignore] public CellLayer<int> CustomTerrain;
|
||||
|
||||
[FieldLoader.Ignore] Lazy<TileSet> cachedTileSet;
|
||||
[FieldLoader.Ignore] Lazy<Ruleset> rules;
|
||||
public Ruleset Rules { get { return rules != null ? rules.Value : null; } }
|
||||
public SequenceProvider SequenceProvider { get { return Rules.Sequences[Tileset]; } }
|
||||
|
||||
[FieldLoader.Ignore] public CellRegion Cells;
|
||||
|
||||
public static Map FromTileset(TileSet tileset)
|
||||
{
|
||||
var tile = tileset.Templates.First();
|
||||
var tileRef = new TileReference<ushort, byte> { Type = tile.Key, Index = (byte)0 };
|
||||
var size = new Size(1, 1);
|
||||
var tileShape = Game.modData.Manifest.TileShape;
|
||||
var tileRef = new TerrainTile(tileset.Templates.First().Key, (byte)0);
|
||||
|
||||
Map map = new Map()
|
||||
var makeMapTiles = Exts.Lazy(() =>
|
||||
{
|
||||
var ret = new CellLayer<TerrainTile>(tileShape, size);
|
||||
ret.Clear(tileRef);
|
||||
return ret;
|
||||
});
|
||||
|
||||
var map = new Map()
|
||||
{
|
||||
Title = "Name your map here",
|
||||
Description = "Describe your map here",
|
||||
Author = "Your name here",
|
||||
MapSize = new int2(1, 1),
|
||||
MapSize = new int2(size),
|
||||
Tileset = tileset.Id,
|
||||
Options = new MapOptions(),
|
||||
MapResources = Exts.Lazy(() => new TileReference<byte, byte>[1, 1]),
|
||||
MapTiles = Exts.Lazy(() => new TileReference<ushort, byte>[1, 1] { { tileRef } }),
|
||||
MapResources = Exts.Lazy(() => new CellLayer<ResourceTile>(tileShape, size)),
|
||||
MapTiles = makeMapTiles,
|
||||
Actors = Exts.Lazy(() => new Dictionary<string, ActorReference>()),
|
||||
Smudges = Exts.Lazy(() => new List<SmudgeReference>())
|
||||
};
|
||||
@@ -185,18 +201,20 @@ namespace OpenRA
|
||||
RequiresMod = upgradeForMod;
|
||||
}
|
||||
|
||||
var nd = yaml.ToDictionary();
|
||||
|
||||
// Load players
|
||||
foreach (var kv in yaml.NodesDict["Players"].NodesDict)
|
||||
foreach (var my in nd["Players"].ToDictionary().Values)
|
||||
{
|
||||
var player = new PlayerReference(kv.Value);
|
||||
var player = new PlayerReference(my);
|
||||
Players.Add(player.Name, player);
|
||||
}
|
||||
|
||||
Actors = Exts.Lazy(() =>
|
||||
{
|
||||
var ret = new Dictionary<string, ActorReference>();
|
||||
foreach (var kv in yaml.NodesDict["Actors"].NodesDict)
|
||||
ret.Add(kv.Key, new ActorReference(kv.Value.Value, kv.Value.NodesDict));
|
||||
foreach (var kv in nd["Actors"].ToDictionary())
|
||||
ret.Add(kv.Key, new ActorReference(kv.Value.Value, kv.Value.ToDictionary()));
|
||||
return ret;
|
||||
});
|
||||
|
||||
@@ -204,9 +222,9 @@ namespace OpenRA
|
||||
Smudges = Exts.Lazy(() =>
|
||||
{
|
||||
var ret = new List<SmudgeReference>();
|
||||
foreach (var kv in yaml.NodesDict["Smudges"].NodesDict)
|
||||
foreach (var name in nd["Smudges"].ToDictionary().Keys)
|
||||
{
|
||||
var vals = kv.Key.Split(' ');
|
||||
var vals = name.Split(' ');
|
||||
var loc = vals[1].Split(',');
|
||||
ret.Add(new SmudgeReference(vals[0], new int2(
|
||||
Exts.ParseIntegerInvariant(loc[0]),
|
||||
@@ -225,10 +243,9 @@ namespace OpenRA
|
||||
NotificationDefinitions = MiniYaml.NodesOrEmpty(yaml, "Notifications");
|
||||
TranslationDefinitions = MiniYaml.NodesOrEmpty(yaml, "Translations");
|
||||
|
||||
CustomTerrain = new string[MapSize.X, MapSize.Y];
|
||||
|
||||
MapTiles = Exts.Lazy(() => LoadMapTiles());
|
||||
MapResources = Exts.Lazy(() => LoadResourceTiles());
|
||||
TileShape = Game.modData.Manifest.TileShape;
|
||||
|
||||
// The Uid is calculated from the data on-disk, so
|
||||
// format changes must be flushed to disk.
|
||||
@@ -247,6 +264,15 @@ namespace OpenRA
|
||||
void PostInit()
|
||||
{
|
||||
rules = Exts.Lazy(() => Game.modData.RulesetCache.LoadMapRules(this));
|
||||
cachedTileSet = Exts.Lazy(() => Rules.TileSets[Tileset]);
|
||||
|
||||
var tl = Map.MapToCell(TileShape, new CPos(Bounds.Left, Bounds.Top));
|
||||
var br = Map.MapToCell(TileShape, new CPos(Bounds.Right - 1, Bounds.Bottom - 1));
|
||||
Cells = new CellRegion(TileShape, tl, br);
|
||||
|
||||
CustomTerrain = new CellLayer<int>(this);
|
||||
foreach (var cell in Cells)
|
||||
CustomTerrain[cell] = -1;
|
||||
}
|
||||
|
||||
public Ruleset PreloadRules()
|
||||
@@ -339,9 +365,9 @@ namespace OpenRA
|
||||
Container.Write(entries);
|
||||
}
|
||||
|
||||
public TileReference<ushort, byte>[,] LoadMapTiles()
|
||||
public CellLayer<TerrainTile> LoadMapTiles()
|
||||
{
|
||||
var tiles = new TileReference<ushort, byte>[MapSize.X, MapSize.Y];
|
||||
var tiles = new CellLayer<TerrainTile>(this);
|
||||
using (var dataStream = Container.GetContent("map.bin"))
|
||||
{
|
||||
if (dataStream.ReadUInt8() != 1)
|
||||
@@ -355,24 +381,30 @@ namespace OpenRA
|
||||
throw new InvalidDataException("Invalid tile data");
|
||||
|
||||
// Load tile data
|
||||
for (int i = 0; i < MapSize.X; i++)
|
||||
for (int j = 0; j < MapSize.Y; j++)
|
||||
var data = dataStream.ReadBytes(MapSize.X * MapSize.Y * 3);
|
||||
var d = 0;
|
||||
for (var i = 0; i < MapSize.X; i++)
|
||||
{
|
||||
for (var j = 0; j < MapSize.Y; j++)
|
||||
{
|
||||
var tile = dataStream.ReadUInt16();
|
||||
var index = dataStream.ReadUInt8();
|
||||
var tile = BitConverter.ToUInt16(data, d);
|
||||
d += 2;
|
||||
|
||||
var index = data[d++];
|
||||
if (index == byte.MaxValue)
|
||||
index = (byte)(i % 4 + (j % 4) * 4);
|
||||
|
||||
tiles[i, j] = new TileReference<ushort, byte>(tile, index);
|
||||
tiles[i, j] = new TerrainTile(tile, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tiles;
|
||||
}
|
||||
|
||||
public TileReference<byte, byte>[,] LoadResourceTiles()
|
||||
public CellLayer<ResourceTile> LoadResourceTiles()
|
||||
{
|
||||
var resources = new TileReference<byte, byte>[MapSize.X, MapSize.Y];
|
||||
var resources = new CellLayer<ResourceTile>(this);
|
||||
|
||||
using (var dataStream = Container.GetContent("map.bin"))
|
||||
{
|
||||
@@ -389,14 +421,13 @@ namespace OpenRA
|
||||
// Skip past tile data
|
||||
dataStream.Seek(3 * MapSize.X * MapSize.Y, SeekOrigin.Current);
|
||||
|
||||
var data = dataStream.ReadBytes(MapSize.X * MapSize.Y * 2);
|
||||
var d = 0;
|
||||
|
||||
// Load resource data
|
||||
for (var i = 0; i < MapSize.X; i++)
|
||||
for (var j = 0; j < MapSize.Y; j++)
|
||||
{
|
||||
var type = dataStream.ReadUInt8();
|
||||
var index = dataStream.ReadUInt8();
|
||||
resources[i, j] = new TileReference<byte, byte>(type, index);
|
||||
}
|
||||
resources[i, j] = new ResourceTile(data[d++], data[d++]);
|
||||
}
|
||||
|
||||
return resources;
|
||||
@@ -416,38 +447,126 @@ namespace OpenRA
|
||||
for (var i = 0; i < MapSize.X; i++)
|
||||
for (var j = 0; j < MapSize.Y; j++)
|
||||
{
|
||||
writer.Write(MapTiles.Value[i, j].Type);
|
||||
writer.Write(MapTiles.Value[i, j].Index);
|
||||
var tile = MapTiles.Value[new CPos(i, j)];
|
||||
writer.Write(tile.Type);
|
||||
writer.Write(tile.Index);
|
||||
}
|
||||
|
||||
// Resource data
|
||||
for (var i = 0; i < MapSize.X; i++)
|
||||
{
|
||||
for (var j = 0; j < MapSize.Y; j++)
|
||||
{
|
||||
writer.Write(MapResources.Value[i, j].Type);
|
||||
writer.Write(MapResources.Value[i, j].Index);
|
||||
var tile = MapResources.Value[new CPos(i, j)];
|
||||
writer.Write(tile.Type);
|
||||
writer.Write(tile.Index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dataStream.ToArray();
|
||||
}
|
||||
|
||||
public bool IsInMap(CPos xy) { return IsInMap(xy.X, xy.Y); }
|
||||
public bool IsInMap(int x, int y) { return Bounds.Contains(x, y); }
|
||||
public bool Contains(CPos cell)
|
||||
{
|
||||
var uv = CellToMap(TileShape, cell);
|
||||
return Bounds.Contains(uv.X, uv.Y);
|
||||
}
|
||||
|
||||
public WPos CenterOfCell(CPos cell)
|
||||
{
|
||||
if (TileShape == TileShape.Rectangle)
|
||||
return new WPos(1024 * cell.X + 512, 1024 * cell.Y + 512, 0);
|
||||
|
||||
// Convert from diamond cell position (x, y) to world position (u, v):
|
||||
// (a) Consider the relationships:
|
||||
// - Center of origin cell is (512, 512)
|
||||
// - +x adds (512, 512) to world pos
|
||||
// - +y adds (-512, 512) to world pos
|
||||
// (b) Therefore:
|
||||
// - ax + by adds (a - b) * 512 + 512 to u
|
||||
// - ax + by adds (a + b) * 512 + 512 to v
|
||||
return new WPos(512 * (cell.X - cell.Y + 1), 512 * (cell.X + cell.Y + 1), 0);
|
||||
}
|
||||
|
||||
public CPos CellContaining(WPos pos)
|
||||
{
|
||||
if (TileShape == TileShape.Rectangle)
|
||||
return new CPos(pos.X / 1024, pos.Y / 1024);
|
||||
|
||||
// Convert from world position to diamond cell position:
|
||||
// (a) Subtract (512, 512) to move the rotation center to the middle of the corner cell
|
||||
// (b) Rotate axes by -pi/4
|
||||
// (c) Add 512 to x (but not y) to realign the cell
|
||||
// (d) Divide by 1024 to find final cell coords
|
||||
var u = (pos.Y + pos.X - 512) / 1024;
|
||||
var v = (pos.Y - pos.X) / 1024;
|
||||
return new CPos(u, v);
|
||||
}
|
||||
|
||||
public static CPos MapToCell(TileShape shape, CPos map)
|
||||
{
|
||||
if (shape == TileShape.Rectangle)
|
||||
return map;
|
||||
|
||||
// Convert from rectangular map position to diamond cell position
|
||||
// - The staggered rows make this fiddly (hint: draw a diagram!)
|
||||
// (a) Consider the relationships:
|
||||
// - +1u (even -> odd) adds (1, -1) to (x, y)
|
||||
// - +1v (even -> odd) adds (1, 0) to (x, y)
|
||||
// - +1v (odd -> even) adds (0, 1) to (x, y)
|
||||
// (b) Therefore:
|
||||
// - au + 2bv adds (a + b) to (x, y)
|
||||
// - a correction factor is added if v is odd
|
||||
var offset = (map.Y & 1) == 1 ? 1 : 0;
|
||||
var y = (map.Y - offset) / 2 - map.X;
|
||||
var x = map.Y - y;
|
||||
return new CPos(x, y);
|
||||
}
|
||||
|
||||
public static CPos CellToMap(TileShape shape, CPos cell)
|
||||
{
|
||||
if (shape == TileShape.Rectangle)
|
||||
return cell;
|
||||
|
||||
// Convert from diamond cell (x, y) position to rectangular map position (u, v)
|
||||
// - The staggered rows make this fiddly (hint: draw a diagram!)
|
||||
// (a) Consider the relationships:
|
||||
// - +1x (even -> odd) adds (0, 1) to (u, v)
|
||||
// - +1x (odd -> even) adds (1, 1) to (u, v)
|
||||
// - +1y (even -> odd) adds (-1, 1) to (u, v)
|
||||
// - +1y (odd -> even) adds (0, 1) to (u, v)
|
||||
// (b) Therefore:
|
||||
// - ax + by adds (a - b)/2 to u (only even increments count)
|
||||
// - ax + by adds a + b to v
|
||||
var u = (cell.X - cell.Y) / 2;
|
||||
var v = cell.X + cell.Y;
|
||||
return new CPos(u, v);
|
||||
}
|
||||
|
||||
public int FacingBetween(CPos cell, CPos towards, int fallbackfacing)
|
||||
{
|
||||
return Traits.Util.GetFacing(CenterOfCell(towards) - CenterOfCell(cell), fallbackfacing);
|
||||
}
|
||||
|
||||
public void Resize(int width, int height) // editor magic.
|
||||
{
|
||||
var oldMapTiles = MapTiles.Value;
|
||||
var oldMapResources = MapResources.Value;
|
||||
var newSize = new Size(width, height);
|
||||
|
||||
MapTiles = Exts.Lazy(() => Exts.ResizeArray(oldMapTiles, oldMapTiles[0, 0], width, height));
|
||||
MapResources = Exts.Lazy(() => Exts.ResizeArray(oldMapResources, oldMapResources[0, 0], width, height));
|
||||
MapSize = new int2(width, height);
|
||||
MapTiles = Exts.Lazy(() => CellLayer.Resize(oldMapTiles, newSize, oldMapTiles[0, 0]));
|
||||
MapResources = Exts.Lazy(() => CellLayer.Resize(oldMapResources, newSize, oldMapResources[0, 0]));
|
||||
MapSize = new int2(newSize);
|
||||
}
|
||||
|
||||
public void ResizeCordon(int left, int top, int right, int bottom)
|
||||
{
|
||||
Bounds = Rectangle.FromLTRB(left, top, right, bottom);
|
||||
|
||||
var tl = Map.MapToCell(TileShape, new CPos(Bounds.Left, Bounds.Top));
|
||||
var br = Map.MapToCell(TileShape, new CPos(Bounds.Right - 1, Bounds.Bottom - 1));
|
||||
Cells = new CellRegion(TileShape, tl, br);
|
||||
}
|
||||
|
||||
string ComputeHash()
|
||||
@@ -517,19 +636,138 @@ namespace OpenRA
|
||||
{
|
||||
for (var i = Bounds.Left; i < Bounds.Right; i++)
|
||||
{
|
||||
var tr = MapTiles.Value[i, j];
|
||||
if (!tileset.Templates.ContainsKey(tr.Type))
|
||||
var cell = new CPos(i, j);
|
||||
var type = MapTiles.Value[cell].Type;
|
||||
var index = MapTiles.Value[cell].Index;
|
||||
if (!tileset.Templates.ContainsKey(type))
|
||||
{
|
||||
Console.WriteLine("Unknown Tile ID {0}".F(tr.Type));
|
||||
Console.WriteLine("Unknown Tile ID {0}".F(type));
|
||||
continue;
|
||||
}
|
||||
var template = tileset.Templates[tr.Type];
|
||||
|
||||
var template = tileset.Templates[type];
|
||||
if (!template.PickAny)
|
||||
continue;
|
||||
tr.Index = (byte)r.Next(0, template.Tiles.Count);
|
||||
MapTiles.Value[i, j] = tr;
|
||||
|
||||
index = (byte)r.Next(0, template.TilesCount);
|
||||
MapTiles.Value[cell] = new TerrainTile(type, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int GetTerrainIndex(CPos cell)
|
||||
{
|
||||
var custom = CustomTerrain[cell];
|
||||
return custom != -1 ? custom : cachedTileSet.Value.GetTerrainIndex(MapTiles.Value[cell]);
|
||||
}
|
||||
|
||||
public TerrainTypeInfo GetTerrainInfo(CPos cell)
|
||||
{
|
||||
return cachedTileSet.Value[GetTerrainIndex(cell)];
|
||||
}
|
||||
|
||||
public CPos Clamp(CPos cell)
|
||||
{
|
||||
var bounds = new Rectangle(Bounds.X, Bounds.Y, Bounds.Width - 1, Bounds.Height - 1);
|
||||
return MapToCell(TileShape, CellToMap(TileShape, cell).Clamp(bounds));
|
||||
}
|
||||
|
||||
public CPos ChooseRandomCell(MersenneTwister rand)
|
||||
{
|
||||
var x = rand.Next(Bounds.Left, Bounds.Right);
|
||||
var y = rand.Next(Bounds.Top, Bounds.Bottom);
|
||||
|
||||
return MapToCell(TileShape, new CPos(x, y));
|
||||
}
|
||||
|
||||
public CPos ChooseRandomEdgeCell(MersenneTwister rand)
|
||||
{
|
||||
var isX = rand.Next(2) == 0;
|
||||
var edge = rand.Next(2) == 0;
|
||||
|
||||
var x = isX ? rand.Next(Bounds.Left, Bounds.Right) : (edge ? Bounds.Left : Bounds.Right);
|
||||
var y = !isX ? rand.Next(Bounds.Top, Bounds.Bottom) : (edge ? Bounds.Top : Bounds.Bottom);
|
||||
|
||||
return MapToCell(TileShape, new CPos(x, y));
|
||||
}
|
||||
|
||||
public WRange DistanceToEdge(WPos pos, WVec dir)
|
||||
{
|
||||
var tl = CenterOfCell(Cells.TopLeft) - new WVec(512, 512, 0);
|
||||
var br = CenterOfCell(Cells.BottomRight) + new WVec(511, 511, 0);
|
||||
var x = dir.X == 0 ? int.MaxValue : ((dir.X < 0 ? tl.X : br.X) - pos.X) / dir.X;
|
||||
var y = dir.Y == 0 ? int.MaxValue : ((dir.Y < 0 ? tl.Y : br.Y) - pos.Y) / dir.Y;
|
||||
return new WRange(Math.Min(x, y) * dir.Length);
|
||||
}
|
||||
|
||||
public const int MaxTilesInCircleRange = 50;
|
||||
static CVec[][] TilesByDistance = InitTilesByDistance(MaxTilesInCircleRange);
|
||||
|
||||
static CVec[][] InitTilesByDistance(int max)
|
||||
{
|
||||
var ts = new List<CVec>[max + 1];
|
||||
for (var i = 0; i < max + 1; i++)
|
||||
ts [i] = new List<CVec>();
|
||||
|
||||
for (var j = -max; j <= max; j++)
|
||||
for (var i = -max; i <= max; i++)
|
||||
if (max * max >= i * i + j * j)
|
||||
ts [Exts.ISqrt(i * i + j * j, Exts.ISqrtRoundMode.Ceiling)].Add(new CVec(i, j));
|
||||
|
||||
// Sort each integer-distance group by the actual distance
|
||||
foreach (var list in ts)
|
||||
{
|
||||
list.Sort((a, b) =>
|
||||
{
|
||||
var result = a.LengthSquared.CompareTo(b.LengthSquared);
|
||||
if (result != 0)
|
||||
return result;
|
||||
|
||||
// If the lengths are equal, use other means to sort them.
|
||||
// Try the hashcode first because it gives more
|
||||
// random-appearing results than X or Y that would always
|
||||
// prefer the leftmost/topmost position.
|
||||
result = a.GetHashCode().CompareTo(b.GetHashCode());
|
||||
if (result != 0)
|
||||
return result;
|
||||
|
||||
result = a.X.CompareTo(b.X);
|
||||
if (result != 0)
|
||||
return result;
|
||||
|
||||
return a.Y.CompareTo(b.Y);
|
||||
});
|
||||
}
|
||||
|
||||
return ts.Select(list => list.ToArray()).ToArray();
|
||||
}
|
||||
|
||||
// Both ranges are inclusive because everything that calls it is designed for maxRange being inclusive:
|
||||
// it rounds the actual distance up to the next integer so that this call
|
||||
// will return any cells that intersect with the requested range circle.
|
||||
// The returned positions are sorted by distance from the center.
|
||||
public IEnumerable<CPos> FindTilesInAnnulus(CPos center, int minRange, int maxRange)
|
||||
{
|
||||
if (maxRange < minRange)
|
||||
throw new ArgumentOutOfRangeException("maxRange", "Maximum range is less than the minimum range.");
|
||||
|
||||
if (maxRange > TilesByDistance.Length)
|
||||
throw new ArgumentOutOfRangeException("maxRange", "The requested range ({0}) exceeds the maximum allowed ({1})".F(maxRange, MaxTilesInCircleRange));
|
||||
|
||||
for (var i = minRange; i <= maxRange; i++)
|
||||
{
|
||||
foreach (var offset in TilesByDistance[i])
|
||||
{
|
||||
var t = offset + center;
|
||||
if (Contains(t))
|
||||
yield return t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<CPos> FindTilesInCircle(CPos center, int maxRange)
|
||||
{
|
||||
return FindTilesInAnnulus(center, 0, maxRange);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user