Compare commits
1438 Commits
playtest-2
...
release-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
65b580374e | ||
|
|
a4f1e5f103 | ||
|
|
0bd733d7a0 | ||
|
|
23c0524738 | ||
|
|
e2af08f812 | ||
|
|
47aad3b04b | ||
|
|
e3fda8c68e | ||
|
|
7f8e75c089 | ||
|
|
b3967a3d8d | ||
|
|
1ee788f095 | ||
|
|
700b6d6d5e | ||
|
|
0f17fa34a8 | ||
|
|
de26b63fd2 | ||
|
|
4b0ab1c461 | ||
|
|
0c954367a0 | ||
|
|
8765e986b1 | ||
|
|
ed6a83db89 | ||
|
|
6afbb5550a | ||
|
|
8d41f0d680 | ||
|
|
3d5f00fbe9 | ||
|
|
c3c16c4fd8 | ||
|
|
2fa4285281 | ||
|
|
7693f3d16a | ||
|
|
afcb724793 | ||
|
|
639a7e316b | ||
|
|
fdb85d67eb | ||
|
|
0ddcff7ec7 | ||
|
|
c79ac2f504 | ||
|
|
39a9bd7e20 | ||
|
|
504fe9e427 | ||
|
|
45e89491d7 | ||
|
|
b69388b5e7 | ||
|
|
e28ed916aa | ||
|
|
310556877f | ||
|
|
9c63292a83 | ||
|
|
4aaafd18f1 | ||
|
|
73a08624ef | ||
|
|
7c2a7db794 | ||
|
|
4b3c6cc62a | ||
|
|
451e06190f | ||
|
|
bf2f3cacd9 | ||
|
|
8002ed0893 | ||
|
|
d85411f816 | ||
|
|
2daeb45bfe | ||
|
|
467c2a969d | ||
|
|
ee144373a0 | ||
|
|
e234816c13 | ||
|
|
8fca705077 | ||
|
|
5f65d4102b | ||
|
|
cd5e7409ef | ||
|
|
0c4bf5b2b3 | ||
|
|
51ab2b4969 | ||
|
|
6e1cb23f10 | ||
|
|
d595b36cf5 | ||
|
|
c8a68659a0 | ||
|
|
a0926a49ec | ||
|
|
ccf04240cf | ||
|
|
7f3f783187 | ||
|
|
7a4380e7bd | ||
|
|
79a46272ac | ||
|
|
1c8cd44465 | ||
|
|
3c9891cdea | ||
|
|
7b7900bda2 | ||
|
|
39aa171425 | ||
|
|
5fce6ec2c4 | ||
|
|
4be20e7aac | ||
|
|
40f88e5c47 | ||
|
|
81468a5190 | ||
|
|
c3b08a60b8 | ||
|
|
8874b6ef72 | ||
|
|
1dc8de3fc1 | ||
|
|
4b538fd2fe | ||
|
|
9b17bfe697 | ||
|
|
d45db9eb9c | ||
|
|
9a4fb0a5b9 | ||
|
|
4d7cf23521 | ||
|
|
1e241ebd56 | ||
|
|
add5c0ee6d | ||
|
|
95e259db3b | ||
|
|
ce8d787a9c | ||
|
|
a8d848b3c4 | ||
|
|
0f3b6a7cd4 | ||
|
|
22c146d056 | ||
|
|
1185386f96 | ||
|
|
08fd311c4b | ||
|
|
687406ccbd | ||
|
|
37f26c652b | ||
|
|
3aac953522 | ||
|
|
5d623b6ca8 | ||
|
|
e543c3b8c1 | ||
|
|
6ddce1c171 | ||
|
|
d3ddefbaa3 | ||
|
|
c1fefe0b96 | ||
|
|
8470399a0c | ||
|
|
492c025844 | ||
|
|
38b98bf358 | ||
|
|
746c3d068c | ||
|
|
562d07f11a | ||
|
|
ef462c5164 | ||
|
|
817ac42954 | ||
|
|
1474cd147a | ||
|
|
d74c93c66e | ||
|
|
4eaf97f90e | ||
|
|
a81c865620 | ||
|
|
1c67242210 | ||
|
|
96a6bda142 | ||
|
|
580b9014b3 | ||
|
|
4c053dae24 | ||
|
|
1bdadb6631 | ||
|
|
646863b85b | ||
|
|
3fe549d0a4 | ||
|
|
5353ae32a6 | ||
|
|
a6900c256d | ||
|
|
44d8e83773 | ||
|
|
c93bdf73aa | ||
|
|
8e5f307ba8 | ||
|
|
724a72c98e | ||
|
|
a3f26cec46 | ||
|
|
aa319ee403 | ||
|
|
388e5df377 | ||
|
|
d39adf67b2 | ||
|
|
3609de8ca5 | ||
|
|
be9d8d96ce | ||
|
|
2c0a928b48 | ||
|
|
11aab8705e | ||
|
|
37fc836b46 | ||
|
|
f44903b50f | ||
|
|
d32e2be941 | ||
|
|
84cc94bcb6 | ||
|
|
9227e09f18 | ||
|
|
b7357b1711 | ||
|
|
792c82c2d4 | ||
|
|
5ce5d48b04 | ||
|
|
775ccc112b | ||
|
|
421058866d | ||
|
|
7dad013b31 | ||
|
|
42a5b0a993 | ||
|
|
ea9003d6fc | ||
|
|
827a19adef | ||
|
|
6a90f00298 | ||
|
|
abcc43222a | ||
|
|
908a927929 | ||
|
|
6c14b78b7c | ||
|
|
6776d6f906 | ||
|
|
8d2a78abc6 | ||
|
|
108b90f192 | ||
|
|
3c1f5e18f9 | ||
|
|
cae65ddd05 | ||
|
|
8cda9d6d8b | ||
|
|
0bd466a9e9 | ||
|
|
9db41f5638 | ||
|
|
ad0e0a18bd | ||
|
|
6f807c4501 | ||
|
|
1b3f769f34 | ||
|
|
848622054d | ||
|
|
f032322948 | ||
|
|
1d7f57941e | ||
|
|
0f84ac5215 | ||
|
|
e6c6e8aa96 | ||
|
|
180d58c35a | ||
|
|
f52620f6fc | ||
|
|
b7ea695f0c | ||
|
|
272ba08c21 | ||
|
|
58f1589f95 | ||
|
|
b9e32e5c06 | ||
|
|
2fca9b0b19 | ||
|
|
1fb42f47b6 | ||
|
|
481cc7807b | ||
|
|
e3c090a201 | ||
|
|
2f31928a53 | ||
|
|
06612d0f68 | ||
|
|
d835c14988 | ||
|
|
a25087a9f3 | ||
|
|
b362d9f9fc | ||
|
|
cb3eca9d5f | ||
|
|
4b3f0e9a4b | ||
|
|
808cc59c59 | ||
|
|
727d72123f | ||
|
|
c76822531e | ||
|
|
9387029b51 | ||
|
|
b4109b12ca | ||
|
|
70afea85a9 | ||
|
|
3426b52247 | ||
|
|
e2ff40dc7f | ||
|
|
07abeffc5e | ||
|
|
126e200e2e | ||
|
|
5c343caeaf | ||
|
|
8264c6c8dc | ||
|
|
db63724aeb | ||
|
|
303525a5ba | ||
|
|
93a56f9a18 | ||
|
|
712eb437ea | ||
|
|
e46b00f9c4 | ||
|
|
9f38df013e | ||
|
|
60e3f7621f | ||
|
|
d395c5e05d | ||
|
|
975682c57b | ||
|
|
e50dc9a550 | ||
|
|
63ee3ebf9f | ||
|
|
a993116085 | ||
|
|
eb158e6d21 | ||
|
|
6a7c968e25 | ||
|
|
5665d40e29 | ||
|
|
3aff455fba | ||
|
|
0d038f00ba | ||
|
|
8dcba13491 | ||
|
|
0cef2e4f53 | ||
|
|
7443b3ce89 | ||
|
|
7cabe920db | ||
|
|
5254deedcb | ||
|
|
df460d7407 | ||
|
|
3e1db3e8ae | ||
|
|
7b5b84b1b7 | ||
|
|
2e9a0b8162 | ||
|
|
22bf9e7aff | ||
|
|
40b0408ce7 | ||
|
|
c6fb1b641e | ||
|
|
6998871adf | ||
|
|
2885fbb99b | ||
|
|
cc1c183d66 | ||
|
|
418284672c | ||
|
|
558647b987 | ||
|
|
f03e6e6258 | ||
|
|
f44ac769bf | ||
|
|
e02ed86088 | ||
|
|
dcbb6ee4eb | ||
|
|
fe720186f5 | ||
|
|
0803d10746 | ||
|
|
d26ee1094a | ||
|
|
68a38c85f9 | ||
|
|
4de390d173 | ||
|
|
fb8812a7fd | ||
|
|
c8a74ef05a | ||
|
|
de562939d4 | ||
|
|
cc356bcfee | ||
|
|
ece50b0d57 | ||
|
|
76216b8dd9 | ||
|
|
4a47641656 | ||
|
|
03185fe46b | ||
|
|
cbd3baa6d4 | ||
|
|
6287b132a0 | ||
|
|
6e7156e023 | ||
|
|
1ced0d7ab9 | ||
|
|
abeffbbbf7 | ||
|
|
7f7c7217ba | ||
|
|
a4de4cc266 | ||
|
|
8ead8635c2 | ||
|
|
ecea2471ca | ||
|
|
a3e67611e6 | ||
|
|
562ab0eee0 | ||
|
|
ad478e8872 | ||
|
|
ec572635b7 | ||
|
|
44fae60dbd | ||
|
|
0a1e6d16bd | ||
|
|
9739e7f51f | ||
|
|
1e4196e8d3 | ||
|
|
2e309b46e8 | ||
|
|
5991ecdcf5 | ||
|
|
360c572e14 | ||
|
|
16a84ba86e | ||
|
|
fcec3cb590 | ||
|
|
61f7e1df7f | ||
|
|
650195e31c | ||
|
|
6fbc7bc7c4 | ||
|
|
7e41e75643 | ||
|
|
df00b8cf23 | ||
|
|
69ee1399b9 | ||
|
|
a561dd376e | ||
|
|
c9bd3e8a1f | ||
|
|
a4493f48d5 | ||
|
|
de5d9abec3 | ||
|
|
3674accd0c | ||
|
|
9ffdce7957 | ||
|
|
38df0a28cd | ||
|
|
f659f55801 | ||
|
|
f3da258763 | ||
|
|
2048900c10 | ||
|
|
7b5a8cf089 | ||
|
|
a4bbce32b8 | ||
|
|
19aed01822 | ||
|
|
ba2ec557bc | ||
|
|
a8b4e640e7 | ||
|
|
d1966ab476 | ||
|
|
d90dec9c8e | ||
|
|
e2b739cd3e | ||
|
|
dffb5293d0 | ||
|
|
cf2ad68a7c | ||
|
|
119b0c063d | ||
|
|
b948b9d2b7 | ||
|
|
d98e09e096 | ||
|
|
cf17bc7e5c | ||
|
|
42096cc5c9 | ||
|
|
1d3b2334d0 | ||
|
|
64304635b7 | ||
|
|
dc9de20553 | ||
|
|
486fa9a978 | ||
|
|
e2d1eec56e | ||
|
|
8f9e32dcc0 | ||
|
|
dc012c0faf | ||
|
|
4f6f3eb80d | ||
|
|
fd49ca75d7 | ||
|
|
cb50182fac | ||
|
|
47bbc3a6de | ||
|
|
39ed6087cb | ||
|
|
428999fc0b | ||
|
|
b7975031bc | ||
|
|
e652a15b01 | ||
|
|
fc6438e311 | ||
|
|
829fe6530a | ||
|
|
58797c0d37 | ||
|
|
f6d9923305 | ||
|
|
c3ff679f3a | ||
|
|
fa36c71023 | ||
|
|
d4033f57bc | ||
|
|
13f6a13ad9 | ||
|
|
44e668e804 | ||
|
|
aecf19ed64 | ||
|
|
2a0c0bb991 | ||
|
|
99a0bd9609 | ||
|
|
c20b3b90f4 | ||
|
|
1cee570207 | ||
|
|
382435e629 | ||
|
|
637dbee32f | ||
|
|
81f6843791 | ||
|
|
cc6d445ef1 | ||
|
|
cc2efdfa4a | ||
|
|
f7b34e1c5e | ||
|
|
4d0f3b1554 | ||
|
|
ae1710896a | ||
|
|
6425fc8a4b | ||
|
|
38d267e439 | ||
|
|
95cf0bb827 | ||
|
|
d42bdfa102 | ||
|
|
5a7c62e24a | ||
|
|
29818ba60c | ||
|
|
1c4f4b7886 | ||
|
|
e127095437 | ||
|
|
d8eaa7c841 | ||
|
|
888fe35f08 | ||
|
|
59fdbe8725 | ||
|
|
24a5b3ba03 | ||
|
|
9d768fa1c1 | ||
|
|
31b98c0eb4 | ||
|
|
3dd52a59c9 | ||
|
|
f3997ba3bd | ||
|
|
4a94cf656b | ||
|
|
439bb7d02f | ||
|
|
9ad23b10f0 | ||
|
|
e2a0134c5b | ||
|
|
c6f1740875 | ||
|
|
50834911fe | ||
|
|
2cce1ce23c | ||
|
|
3d47584cd8 | ||
|
|
3ce055da80 | ||
|
|
51d3743b18 | ||
|
|
ce609195cd | ||
|
|
54cf2e7993 | ||
|
|
b5b6b47e95 | ||
|
|
6ff0e41650 | ||
|
|
fcdb3b536d | ||
|
|
14ad5099a0 | ||
|
|
dc3bf2515a | ||
|
|
275dfc43be | ||
|
|
3149f3efa2 | ||
|
|
e8a85db309 | ||
|
|
c1fb6c2732 | ||
|
|
68e8565561 | ||
|
|
92e6570f50 | ||
|
|
e94e21fd32 | ||
|
|
d320a689a2 | ||
|
|
29fbeb2c5d | ||
|
|
7ef884532d | ||
|
|
54c49dfa15 | ||
|
|
8809cbb4f1 | ||
|
|
112dd3b1f6 | ||
|
|
92b0f77867 | ||
|
|
dcec748911 | ||
|
|
7d61e75862 | ||
|
|
2d2bb58054 | ||
|
|
bd0b3edccb | ||
|
|
d66439aa0c | ||
|
|
c85dbfb53d | ||
|
|
d6c71c6618 | ||
|
|
7802931e54 | ||
|
|
14737cc1dc | ||
|
|
d8d33811e4 | ||
|
|
c99f89c987 | ||
|
|
7c76b25a44 | ||
|
|
4fdc8222e8 | ||
|
|
07d2e54bcc | ||
|
|
f3d0e4b8ed | ||
|
|
2fad6f3bf1 | ||
|
|
9482955a83 | ||
|
|
9d75c8d820 | ||
|
|
e3925b752d | ||
|
|
f990006587 | ||
|
|
0b7bee480c | ||
|
|
05f4aeea9f | ||
|
|
5f37b9e7d2 | ||
|
|
734b464de3 | ||
|
|
4206cf1b09 | ||
|
|
17e3ef131c | ||
|
|
2c13ebc6e7 | ||
|
|
4f3b16cab2 | ||
|
|
25ebdea758 | ||
|
|
8b82df8298 | ||
|
|
0298a9e3a9 | ||
|
|
f2f60fb1f7 | ||
|
|
b07eb9b8a1 | ||
|
|
f5bffc4da9 | ||
|
|
55d60bd466 | ||
|
|
c2a945b7ed | ||
|
|
48b7cdad44 | ||
|
|
c7500084df | ||
|
|
d1850e8b4b | ||
|
|
c465a58976 | ||
|
|
6b05b2c2f0 | ||
|
|
cd10fb1db0 | ||
|
|
172e1eb295 | ||
|
|
9e16eb513f | ||
|
|
24b322053c | ||
|
|
e52771c367 | ||
|
|
76f792bfdf | ||
|
|
c6fad7fe98 | ||
|
|
915cb589b3 | ||
|
|
664692cef9 | ||
|
|
220579ff85 | ||
|
|
1a8e964c04 | ||
|
|
3a309ec916 | ||
|
|
d46c64fad5 | ||
|
|
3f47715c36 | ||
|
|
94715a1561 | ||
|
|
a752c47b5a | ||
|
|
4d0535daa9 | ||
|
|
a3e64d1733 | ||
|
|
2618a7dadc | ||
|
|
5617465294 | ||
|
|
9c20fba4a0 | ||
|
|
05718f9e8e | ||
|
|
81dad0bd34 | ||
|
|
c177cf9f9a | ||
|
|
e1761d8969 | ||
|
|
0ae464d1f7 | ||
|
|
4913d82bce | ||
|
|
4f6027e772 | ||
|
|
fa84cfb26e | ||
|
|
971287e989 | ||
|
|
deed6c7267 | ||
|
|
f58f460355 | ||
|
|
2c897d4454 | ||
|
|
b4101c03ee | ||
|
|
200e90a590 | ||
|
|
be8f042e49 | ||
|
|
4b1eb993e4 | ||
|
|
f6ce673345 | ||
|
|
08eeec4d99 | ||
|
|
564a4598b9 | ||
|
|
7e25b6e58e | ||
|
|
57f74606f0 | ||
|
|
b44cb9ad57 | ||
|
|
dfd5906d7f | ||
|
|
2e7b5e8712 | ||
|
|
eb8682fd0e | ||
|
|
2d224a207c | ||
|
|
5070a81db4 | ||
|
|
e97dd2ee47 | ||
|
|
da74c6ad23 | ||
|
|
c7f1d08748 | ||
|
|
7850acc6fb | ||
|
|
ec5b9a1150 | ||
|
|
83f67a9d48 | ||
|
|
fb799ad436 | ||
|
|
60186efca6 | ||
|
|
20ab3b6caa | ||
|
|
32db66eb7e | ||
|
|
112844a9f7 | ||
|
|
745df591e0 | ||
|
|
9c7759d131 | ||
|
|
4bb70f11e9 | ||
|
|
ce5ca9dbca | ||
|
|
0b9a984b7a | ||
|
|
45cd6caeec | ||
|
|
4c517c0e59 | ||
|
|
7884cb310b | ||
|
|
306bece709 | ||
|
|
748a055a24 | ||
|
|
240b26a265 | ||
|
|
ac82121460 | ||
|
|
3189a4f457 | ||
|
|
291e7588e1 | ||
|
|
b8e274e0f9 | ||
|
|
e81a1f78a4 | ||
|
|
51c3455ffe | ||
|
|
583fa0aa39 | ||
|
|
f768f8d969 | ||
|
|
0e26f0ce26 | ||
|
|
2a8beca0f8 | ||
|
|
b5813ebff8 | ||
|
|
0f6f36411a | ||
|
|
f798639125 | ||
|
|
6014095ab3 | ||
|
|
52e265557c | ||
|
|
f9f9fbf3e4 | ||
|
|
d559b5cdb7 | ||
|
|
d6733e62d6 | ||
|
|
00a0aac7a3 | ||
|
|
840ade5b78 | ||
|
|
13d3137ae4 | ||
|
|
62c652a645 | ||
|
|
76428cbda2 | ||
|
|
434ea26950 | ||
|
|
9655b34e5f | ||
|
|
e91caa4e7a | ||
|
|
3b0810a096 | ||
|
|
1d81e71bcb | ||
|
|
29ac9a594a | ||
|
|
fb0e399ab9 | ||
|
|
7c5c989eb2 | ||
|
|
41fd19c766 | ||
|
|
b423889c06 | ||
|
|
5f43923b80 | ||
|
|
5470264f00 | ||
|
|
06ed722b7a | ||
|
|
8565b7be0c | ||
|
|
a3861823c9 | ||
|
|
84fd45ad69 | ||
|
|
dd6a431af2 | ||
|
|
fa31fb199f | ||
|
|
fbeb638582 | ||
|
|
1aebd59062 | ||
|
|
7182908728 | ||
|
|
58a92de5a1 | ||
|
|
4ea04f461a | ||
|
|
26c084cfb8 | ||
|
|
ac513557a1 | ||
|
|
db5b5698a7 | ||
|
|
1f61d22489 | ||
|
|
520f602f23 | ||
|
|
8c5c63a4b5 | ||
|
|
a0741ba26b | ||
|
|
9f21d944d1 | ||
|
|
10f9e3e787 | ||
|
|
eff5e409c0 | ||
|
|
f108735f74 | ||
|
|
e62149398b | ||
|
|
d6e831eb07 | ||
|
|
dcf3912d24 | ||
|
|
efad699d4b | ||
|
|
77a35fd132 | ||
|
|
2fe7e10750 | ||
|
|
6f66a19b18 | ||
|
|
2fc88e439d | ||
|
|
b4b05c3f4e | ||
|
|
0ee1d39bac | ||
|
|
c3521a2490 | ||
|
|
cb93955cc5 | ||
|
|
666efc94d1 | ||
|
|
d2a52fd529 | ||
|
|
085685a769 | ||
|
|
034196ddd6 | ||
|
|
3dc16bdbb4 | ||
|
|
f42f39f9c9 | ||
|
|
40235db52e | ||
|
|
810b73e1f0 | ||
|
|
82850cf4fb | ||
|
|
21e597ca2d | ||
|
|
ed8203c896 | ||
|
|
de7668e8ff | ||
|
|
7271dd5248 | ||
|
|
16dd07bab3 | ||
|
|
5cbfc45819 | ||
|
|
6a238ab51a | ||
|
|
4d9c2a30df | ||
|
|
8b18927c67 | ||
|
|
d77563bdb0 | ||
|
|
d0466714c8 | ||
|
|
08c9c1a92f | ||
|
|
ea3943daf4 | ||
|
|
6ac92c45f1 | ||
|
|
96cd0e2259 | ||
|
|
fc5830a687 | ||
|
|
1dfe437641 | ||
|
|
b8eda5a152 | ||
|
|
de8603832f | ||
|
|
f11bcd27cc | ||
|
|
00dc91cf49 | ||
|
|
8b0255e2f7 | ||
|
|
3a2279f378 | ||
|
|
8085bcb232 | ||
|
|
5e6f325df1 | ||
|
|
f892eb629e | ||
|
|
1629958970 | ||
|
|
2079627030 | ||
|
|
2072b78489 | ||
|
|
3d1d4a1aff | ||
|
|
41665f7e95 | ||
|
|
604aae5980 | ||
|
|
ac613f7bea | ||
|
|
46d0a6d00d | ||
|
|
402afc82ca | ||
|
|
1cd59a0892 | ||
|
|
7b7bcf1005 | ||
|
|
be701007df | ||
|
|
fef6285436 | ||
|
|
b3c4afa620 | ||
|
|
8df1813afd | ||
|
|
6a28bcb49a | ||
|
|
730ed8c597 | ||
|
|
7b5be4a0ec | ||
|
|
30fb1250b3 | ||
|
|
a363bf841c | ||
|
|
da5830845b | ||
|
|
23e6eada26 | ||
|
|
490b0801a0 | ||
|
|
49ab704a84 | ||
|
|
4a12b78f14 | ||
|
|
656dbdcd28 | ||
|
|
88398afba6 | ||
|
|
2f74207bf6 | ||
|
|
f4f9abe4d4 | ||
|
|
e50b8ec7dc | ||
|
|
70f92494b2 | ||
|
|
c07fee3b3b | ||
|
|
07b635672e | ||
|
|
edc4c7ab2b | ||
|
|
6edcc36f17 | ||
|
|
3a2a6c231e | ||
|
|
cf26e4aa8a | ||
|
|
8ca1da8828 | ||
|
|
5764bc1c1c | ||
|
|
dba7335594 | ||
|
|
1461309dba | ||
|
|
d7e8388600 | ||
|
|
e79d039aa0 | ||
|
|
3d8b3efb9e | ||
|
|
58367fdeac | ||
|
|
63d54952d0 | ||
|
|
5904563653 | ||
|
|
5d0b750a64 | ||
|
|
43e99631a8 | ||
|
|
8cd6d60839 | ||
|
|
047d012fff | ||
|
|
0064543989 | ||
|
|
b61b7b5431 | ||
|
|
0c319e88c3 | ||
|
|
da384af339 | ||
|
|
f98f3d0b39 | ||
|
|
439c366ba2 | ||
|
|
d93c42e89c | ||
|
|
850d26a628 | ||
|
|
c3e79405f7 | ||
|
|
03b23d88d2 | ||
|
|
d5d6cea84c | ||
|
|
fb173af647 | ||
|
|
a1bc31883b | ||
|
|
52854c77c2 | ||
|
|
8f58e41304 | ||
|
|
25525b4155 | ||
|
|
66cc0bd8ff | ||
|
|
01c6127545 | ||
|
|
2794e1f62d | ||
|
|
83c9e9e6dd | ||
|
|
39742d02bb | ||
|
|
f1b68a5207 | ||
|
|
493631cd90 | ||
|
|
9a1ce6945b | ||
|
|
ccf66cde2f | ||
|
|
233e9326f0 | ||
|
|
ba97c99f98 | ||
|
|
37edd072a6 | ||
|
|
00358e9fe8 | ||
|
|
888710cbc5 | ||
|
|
518e00c78a | ||
|
|
f2a20a182e | ||
|
|
a058eb06b2 | ||
|
|
64a7592fed | ||
|
|
bfb076b9bc | ||
|
|
5292272902 | ||
|
|
1db3ce4b59 | ||
|
|
060d544390 | ||
|
|
b0e3364a77 | ||
|
|
d78dde4db1 | ||
|
|
a94b2df865 | ||
|
|
e4bb788fb9 | ||
|
|
6dcc401342 | ||
|
|
26a7e06b40 | ||
|
|
2ba8120d79 | ||
|
|
b9b045098b | ||
|
|
a0682d80c0 | ||
|
|
1ff39761b7 | ||
|
|
bddd058b38 | ||
|
|
8efb717cf4 | ||
|
|
65ac607d90 | ||
|
|
0af653b101 | ||
|
|
175b07c0ff | ||
|
|
585cba8af8 | ||
|
|
2a7525122e | ||
|
|
7f7c293856 | ||
|
|
fbb117705e | ||
|
|
78dea9eecb | ||
|
|
be9f52e029 | ||
|
|
000dd6de7b | ||
|
|
5e8e4dd9d5 | ||
|
|
b31a35d34b | ||
|
|
414b3a03c3 | ||
|
|
a7f42dcf0c | ||
|
|
7bd7f4e56b | ||
|
|
9584c78500 | ||
|
|
bc7a9c14d0 | ||
|
|
c1eacc225d | ||
|
|
e56bbe367d | ||
|
|
6cf9939ab3 | ||
|
|
b2f3b8f2af | ||
|
|
80e897abfb | ||
|
|
d152d21338 | ||
|
|
f4e04ece12 | ||
|
|
e7a07ea9c3 | ||
|
|
f8e6245903 | ||
|
|
7c146a9d5d | ||
|
|
846286c988 | ||
|
|
ba25bc6df4 | ||
|
|
622f9bfe71 | ||
|
|
8df47f5a60 | ||
|
|
d2a0647085 | ||
|
|
0e750a3f25 | ||
|
|
0e6dbe28a8 | ||
|
|
cc0c45bceb | ||
|
|
af3e734561 | ||
|
|
1ac61c5e3e | ||
|
|
5d3622b79d | ||
|
|
b3ddf1ae86 | ||
|
|
17770631a2 | ||
|
|
05f6958286 | ||
|
|
bd9c748b17 | ||
|
|
6b40abb58c | ||
|
|
6d67ab2240 | ||
|
|
8b3512e2f1 | ||
|
|
5b71bee4c8 | ||
|
|
75e7124af0 | ||
|
|
9ad55d5e28 | ||
|
|
9e93edf336 | ||
|
|
5608756a24 | ||
|
|
ebca421856 | ||
|
|
22e61a5700 | ||
|
|
7306de3730 | ||
|
|
10ed3db71d | ||
|
|
04e05d9aed | ||
|
|
caae95f12e | ||
|
|
dfa14f16d3 | ||
|
|
8e007131c9 | ||
|
|
ed4c588701 | ||
|
|
d33806e932 | ||
|
|
e83838e9ff | ||
|
|
b77dcd476c | ||
|
|
836b3a598b | ||
|
|
967b16fc0e | ||
|
|
ee3437d0f6 | ||
|
|
e20c736e3f | ||
|
|
a98d20ea72 | ||
|
|
38486e8184 | ||
|
|
047a09bbbd | ||
|
|
d55e58ea1c | ||
|
|
17afe80a54 | ||
|
|
42bf568d80 | ||
|
|
50157c43de | ||
|
|
41988a1298 | ||
|
|
86058ec19f | ||
|
|
356c750b23 | ||
|
|
26cbb9d9c6 | ||
|
|
4a0b78c1e6 | ||
|
|
fcb7c845ba | ||
|
|
12f9c0bce9 | ||
|
|
47ed79b912 | ||
|
|
a265d11a5f | ||
|
|
8a96c5f7b5 | ||
|
|
5e5456191c | ||
|
|
aae7f56e7d | ||
|
|
3645b3ee13 | ||
|
|
e0f357390c | ||
|
|
9c3cb62838 | ||
|
|
14225b8e79 | ||
|
|
e01bf735d9 | ||
|
|
1904f8ced1 | ||
|
|
3caca8c323 | ||
|
|
dd7ce2d45e | ||
|
|
f793f4548b | ||
|
|
56675a61f5 | ||
|
|
3dd27fcb77 | ||
|
|
13d76f8e9c | ||
|
|
9a2cdcde11 | ||
|
|
155e7320cb | ||
|
|
750fd84494 | ||
|
|
924adc68a9 | ||
|
|
0f8d9d7fb3 | ||
|
|
801aa1156f | ||
|
|
aa0c14c214 | ||
|
|
8fcbb670d8 | ||
|
|
85a26ecdf7 | ||
|
|
480c5edd75 | ||
|
|
fdfa1ddf97 | ||
|
|
80caf1818b | ||
|
|
5c0cd50797 | ||
|
|
8129d5d7dc | ||
|
|
a77b7af5fd | ||
|
|
ecf41722c3 | ||
|
|
39b09780f6 | ||
|
|
98dec6dc8e | ||
|
|
50b1ba3acc | ||
|
|
c3fc7b98f3 | ||
|
|
f5b8b18d86 | ||
|
|
e7c61fac5c | ||
|
|
2640603f6c | ||
|
|
1a011276bf | ||
|
|
bc7cf09287 | ||
|
|
7762241653 | ||
|
|
9489196911 | ||
|
|
e32e060d37 | ||
|
|
5e3fce6820 | ||
|
|
6655b6ba6a | ||
|
|
0b4b003c10 | ||
|
|
380e7e8b20 | ||
|
|
9b3533abc0 | ||
|
|
1409016cbd | ||
|
|
4aa1fb4b86 | ||
|
|
40126c52e8 | ||
|
|
dd600d4590 | ||
|
|
532f420338 | ||
|
|
e25878e78d | ||
|
|
002cc4842a | ||
|
|
eac548ac8b | ||
|
|
3fc4d1b219 | ||
|
|
80e3b8be0d | ||
|
|
fa35f6caa4 | ||
|
|
526cf6059a | ||
|
|
1527e472b6 | ||
|
|
94f7c6db97 | ||
|
|
e3ddb8f757 | ||
|
|
d7d0d371c6 | ||
|
|
527c60daa7 | ||
|
|
c30050396a | ||
|
|
60a8acf4d4 | ||
|
|
5164c3cd7d | ||
|
|
6276e659cd | ||
|
|
298314626e | ||
|
|
0112bc4df7 | ||
|
|
c8dbed938a | ||
|
|
278f35e4aa | ||
|
|
dd38e45f2e | ||
|
|
3e08f9b1b1 | ||
|
|
8392a44314 | ||
|
|
d050d1a4b9 | ||
|
|
56598ce2ff | ||
|
|
2fb72155eb | ||
|
|
030bd4b28d | ||
|
|
b9c40ad3ce | ||
|
|
4490a90332 | ||
|
|
15d6facdb9 | ||
|
|
b80962b365 | ||
|
|
814c6a8713 | ||
|
|
eea89c1d33 | ||
|
|
9ec0367ecb | ||
|
|
f5fe1013ee | ||
|
|
c338d28d35 | ||
|
|
2f962452e5 | ||
|
|
10f5e68f7f | ||
|
|
1cde37f32b | ||
|
|
291899de8a | ||
|
|
cc70669f1a | ||
|
|
c568dfa486 | ||
|
|
ff7daf8727 | ||
|
|
fc72066ed2 | ||
|
|
253ccd6d9b | ||
|
|
01accaeb38 | ||
|
|
46c3bc09a1 | ||
|
|
2f0b7566e5 | ||
|
|
9b8ec714d2 | ||
|
|
5d408fe3c7 | ||
|
|
aa0b7bedf0 | ||
|
|
c5358f7c82 | ||
|
|
158d6e5647 | ||
|
|
e091781104 | ||
|
|
25582cb9f8 | ||
|
|
fece294cc6 | ||
|
|
c3501f68e3 | ||
|
|
c4ee5fbd41 | ||
|
|
9a54074b1b | ||
|
|
10e918c375 | ||
|
|
bbcad99fa7 | ||
|
|
c8198a1a1c | ||
|
|
8d5241f419 | ||
|
|
448b681c5b | ||
|
|
826f7a29b5 | ||
|
|
0629b1e2d2 | ||
|
|
0d9cf63dd2 | ||
|
|
6513bd5fe0 | ||
|
|
f933e3de3f | ||
|
|
88a8d84153 | ||
|
|
8e4f5da791 | ||
|
|
a61d21e501 | ||
|
|
2bcf33661a | ||
|
|
f6df7a06f2 | ||
|
|
de92a2fc0c | ||
|
|
6012f1d592 | ||
|
|
caf676dc33 | ||
|
|
e3ae1bec75 | ||
|
|
b98b517e35 | ||
|
|
5d9f25eef5 | ||
|
|
5bf69eb539 | ||
|
|
09f7778294 | ||
|
|
c8ec5f3579 | ||
|
|
a54c7ecc18 | ||
|
|
0064caf1f4 | ||
|
|
fc2fbd4689 | ||
|
|
0f0793cde5 | ||
|
|
2fed6f61e9 | ||
|
|
3df310df6e | ||
|
|
c2b3a749ca | ||
|
|
2d2220f38f | ||
|
|
7509bf85aa | ||
|
|
64e8088ae4 | ||
|
|
15584b9b34 | ||
|
|
79c1d1b0a6 | ||
|
|
50860614cf | ||
|
|
90d1d3e053 | ||
|
|
3bf83b52fb | ||
|
|
5f57dd7a62 | ||
|
|
8e1185b56f | ||
|
|
26098df2a1 | ||
|
|
9ac9d83745 | ||
|
|
51edd5a3f4 | ||
|
|
fc07f90f91 | ||
|
|
b64dcbf502 | ||
|
|
5694c113be | ||
|
|
01cf5c21a7 | ||
|
|
4206d2e131 | ||
|
|
83968553aa | ||
|
|
aa2aba1250 | ||
|
|
bba9c4b976 | ||
|
|
999eef2ec9 | ||
|
|
f28c8903aa | ||
|
|
f58eabe667 | ||
|
|
86695dfe29 | ||
|
|
9ae452e8d6 | ||
|
|
3e547102d2 | ||
|
|
e883e63c87 | ||
|
|
a904047a16 | ||
|
|
ad1af792e6 | ||
|
|
6c9527d9dc | ||
|
|
da2d461aa8 | ||
|
|
49bfd69707 | ||
|
|
2a02df9411 | ||
|
|
185ba80e99 | ||
|
|
127cbf3f96 | ||
|
|
4bdf675def | ||
|
|
9c944924de | ||
|
|
28f79533eb | ||
|
|
5a834c9500 | ||
|
|
3255218d5c | ||
|
|
9befe377d5 | ||
|
|
f39b4f0750 | ||
|
|
1794625cea | ||
|
|
42092fe6dd | ||
|
|
1a451fe813 | ||
|
|
0e845a9f3a | ||
|
|
2a3c149769 | ||
|
|
7cfcd94e23 | ||
|
|
247a8c9717 | ||
|
|
4afd8ad783 | ||
|
|
dca77956cb | ||
|
|
22c6c3b3f6 | ||
|
|
1e8e5c8f5c | ||
|
|
c0fcc862d6 | ||
|
|
5a3ccdf0c5 | ||
|
|
1bd802c386 | ||
|
|
3a4e2abedd | ||
|
|
f13343ef2e | ||
|
|
2b1ac6a60f | ||
|
|
8aa180c1f4 | ||
|
|
260e420f85 | ||
|
|
1a203afd89 | ||
|
|
c150fd9475 | ||
|
|
566303a8f1 | ||
|
|
10f8364b99 | ||
|
|
7c31f72db6 | ||
|
|
6b6c9639f9 | ||
|
|
7ca9fcdac9 | ||
|
|
20276291ce | ||
|
|
34fc207a6c | ||
|
|
c974e61680 | ||
|
|
09db76f89f | ||
|
|
6bbf878314 | ||
|
|
4cd3195f9f | ||
|
|
6ea2a06e4b | ||
|
|
597dba8584 | ||
|
|
1c1483377c | ||
|
|
0873741983 | ||
|
|
e0afc08e5f | ||
|
|
cb1deacbb2 | ||
|
|
ab1e930ba3 | ||
|
|
10bf85f57e | ||
|
|
17990ab8b7 | ||
|
|
beecb8aeb1 | ||
|
|
6a25d989a7 | ||
|
|
f8776d773d | ||
|
|
3724f46a3e | ||
|
|
915ad7fb7b | ||
|
|
07023b6c35 | ||
|
|
b78b5b22a3 | ||
|
|
eca098b0b4 | ||
|
|
011a20e8b4 | ||
|
|
9c362f7d41 | ||
|
|
99d92ee095 | ||
|
|
b905d343af | ||
|
|
024b564b8c | ||
|
|
9c0e3ac4c9 | ||
|
|
a2205e9031 | ||
|
|
0df9815d2c | ||
|
|
79d6eb4a2b | ||
|
|
0d8557eadb | ||
|
|
70f6fc7a7a | ||
|
|
11f6a8b945 | ||
|
|
e3d71acb05 | ||
|
|
580f1cfe97 | ||
|
|
3d7434f42e | ||
|
|
ef96604f9e | ||
|
|
465f5d295b | ||
|
|
1feb377d43 | ||
|
|
a065fb464e | ||
|
|
e39917ca19 | ||
|
|
318f496bf9 | ||
|
|
ed8a155249 | ||
|
|
40ac5f7b6e | ||
|
|
517754027e | ||
|
|
ef4f478e10 | ||
|
|
92c30b89f8 | ||
|
|
7331a9c4fb | ||
|
|
d2b9e150f1 | ||
|
|
8ba329f1be | ||
|
|
8868eab247 | ||
|
|
f12889e684 | ||
|
|
5c095bc174 | ||
|
|
0c24a08436 | ||
|
|
9762b540b0 | ||
|
|
fd34f2ba99 | ||
|
|
ad6481c8e8 | ||
|
|
7426d47cd5 | ||
|
|
761f62292f | ||
|
|
63b8555bc9 | ||
|
|
3209da4a4a | ||
|
|
aebef4f1c8 | ||
|
|
d3244184c1 | ||
|
|
39e62354a8 | ||
|
|
f525c3808e | ||
|
|
87a0b52ce5 | ||
|
|
4bc9e01516 | ||
|
|
711d05da98 | ||
|
|
3d805ff40d | ||
|
|
0cd140849b | ||
|
|
d6110b9ef0 | ||
|
|
26d1db778e | ||
|
|
f41aa474aa | ||
|
|
0002e80a19 | ||
|
|
759a52d86e | ||
|
|
44fe0396bb | ||
|
|
dd6d8d916e | ||
|
|
5af8f5e2d9 | ||
|
|
c85503811c | ||
|
|
ab431fe9ee | ||
|
|
7ec9958d47 | ||
|
|
cfc74a6dee | ||
|
|
cecdd73e08 | ||
|
|
381e080b11 | ||
|
|
c6a047cb1a | ||
|
|
4c51733e04 | ||
|
|
8f613b80e8 | ||
|
|
10de282daa | ||
|
|
915e123956 | ||
|
|
8cb7a7b8ce | ||
|
|
ce5cf93077 | ||
|
|
1390bb7428 | ||
|
|
3c5b136216 | ||
|
|
66785e606a | ||
|
|
e2239fa50c | ||
|
|
7f7712aa64 | ||
|
|
b1605e115a | ||
|
|
69b2da86be | ||
|
|
18e965e5aa | ||
|
|
24f0c28f56 | ||
|
|
25af51b4ac | ||
|
|
ecd7064cc3 | ||
|
|
477a21e782 | ||
|
|
899d9af62b | ||
|
|
17eca983ef | ||
|
|
2fc219ecd5 | ||
|
|
49a645cd2d | ||
|
|
7cb8da411d | ||
|
|
4bcdf3cf11 | ||
|
|
1b525ff809 | ||
|
|
cdec3fce26 | ||
|
|
7bdf6a953f | ||
|
|
06b20c8ba5 | ||
|
|
9b484b53ec | ||
|
|
9620b4ed46 | ||
|
|
d8908c44d0 | ||
|
|
cfe705531a | ||
|
|
9a2fd38ab6 | ||
|
|
911e7f62de | ||
|
|
403b81bdc9 | ||
|
|
a0714b00b3 | ||
|
|
d5239ee77a | ||
|
|
03ec97f302 | ||
|
|
3255f95ee9 | ||
|
|
4c8fd5e73d | ||
|
|
7179ef0f45 | ||
|
|
6d5918b11d | ||
|
|
81c484d1c9 | ||
|
|
de1044c24c | ||
|
|
e4c31939d9 | ||
|
|
7f48d6796e | ||
|
|
4fd77aec8e | ||
|
|
92fece01de | ||
|
|
d8d987f844 | ||
|
|
de429a4c62 | ||
|
|
c0ca35a4ff | ||
|
|
1bff8559fb | ||
|
|
de98274165 | ||
|
|
59e2228b2a | ||
|
|
96d1408d45 | ||
|
|
ff45ae2d16 | ||
|
|
47950c9113 | ||
|
|
f402ec7898 | ||
|
|
a3c0448e15 | ||
|
|
699b4b1154 | ||
|
|
911db3feb1 | ||
|
|
c790db8e84 | ||
|
|
d6dd392028 | ||
|
|
636b2a8ea7 | ||
|
|
959d3f8bd7 | ||
|
|
193cb929f1 | ||
|
|
f93e270fe4 | ||
|
|
f19953c39a | ||
|
|
59d5ce1bc8 | ||
|
|
43cf7cd074 | ||
|
|
aba76f4b50 | ||
|
|
8021fc3b20 | ||
|
|
7bf4cb85fa | ||
|
|
6dd03bb339 | ||
|
|
14e517cab5 | ||
|
|
cdcfeb6276 | ||
|
|
c77c63a380 | ||
|
|
9921fe8fad | ||
|
|
f848c5d7d4 | ||
|
|
62c47e3b12 | ||
|
|
094986d066 | ||
|
|
d87e02ab41 | ||
|
|
3f415a8fdf | ||
|
|
846371cf3e | ||
|
|
45c77e64ee | ||
|
|
66493031c8 | ||
|
|
384b26db60 | ||
|
|
d66dbeb312 | ||
|
|
ba9611f544 | ||
|
|
b6e56560d4 | ||
|
|
1f047d439f | ||
|
|
5233ae4770 | ||
|
|
562e07264a | ||
|
|
4dab4ed73f | ||
|
|
a97ddffa53 | ||
|
|
8e589e3c16 | ||
|
|
96f72ce842 | ||
|
|
d8de477edb | ||
|
|
694fb6831a | ||
|
|
c16a515224 | ||
|
|
e2eae7973b | ||
|
|
9e3c938706 | ||
|
|
ef665df2e9 | ||
|
|
271a3eea8d | ||
|
|
2f6315b816 | ||
|
|
ac8d408ba7 | ||
|
|
0fdd49c96a | ||
|
|
e390cf8ab0 | ||
|
|
64d700cd70 | ||
|
|
d3db9d3710 | ||
|
|
9eb05a43f9 | ||
|
|
3165ec5359 | ||
|
|
f4699132d6 | ||
|
|
086bdfb4bd | ||
|
|
61fd12c7da | ||
|
|
9979209c34 | ||
|
|
b0c06d4cd9 | ||
|
|
3a617f8934 | ||
|
|
b35a7d9f8d | ||
|
|
67fa079658 | ||
|
|
c9edbd8a80 | ||
|
|
4b49bf03dc | ||
|
|
6cfad6f2ab | ||
|
|
c0c4e7299b | ||
|
|
afda1647fd | ||
|
|
aff6889995 | ||
|
|
65515d54af | ||
|
|
c5b7c43d23 | ||
|
|
dba5adc91c | ||
|
|
0073a03ca4 | ||
|
|
5509d0d2e9 | ||
|
|
fe52e3722e | ||
|
|
3ddd1581f1 | ||
|
|
56efc3930b | ||
|
|
2f8d81a0f7 | ||
|
|
46486073ab | ||
|
|
3dc11eaa05 | ||
|
|
b62ee4d37c | ||
|
|
532afc3ff8 | ||
|
|
9ddb2beced | ||
|
|
1e758ec3e0 | ||
|
|
aa1d44428d | ||
|
|
23da8a24bd | ||
|
|
fef291a27e | ||
|
|
f49e56d660 | ||
|
|
927ab00f4d | ||
|
|
3f870e7e48 | ||
|
|
f2a321186f | ||
|
|
410daecab6 | ||
|
|
966e3bb71a | ||
|
|
652f06f604 | ||
|
|
2a10af2007 | ||
|
|
4cb26c0e3c | ||
|
|
8455dadb3c | ||
|
|
3c19b3df73 | ||
|
|
c796e155e7 | ||
|
|
ce9caec291 | ||
|
|
0330ef2b9e | ||
|
|
872a304714 | ||
|
|
59cc50df4c | ||
|
|
a1fd84fb15 | ||
|
|
317007f7ce | ||
|
|
387212d9ea | ||
|
|
c9ca5e207b | ||
|
|
ce78944a9e | ||
|
|
1fb336b7da | ||
|
|
e4d05407d9 | ||
|
|
f7eca1157e | ||
|
|
a64245fc10 | ||
|
|
ad8038867d | ||
|
|
fb90400524 | ||
|
|
08b25d10c1 | ||
|
|
ba09bbba8e | ||
|
|
0d2e1d7de5 | ||
|
|
22861fca5a | ||
|
|
692ef539f9 | ||
|
|
d07b0e4400 | ||
|
|
9848d1f403 | ||
|
|
83eae029b7 | ||
|
|
99e225c279 | ||
|
|
1785c4e4a8 | ||
|
|
69753f8a08 | ||
|
|
5593b9ffdd | ||
|
|
1b66635670 | ||
|
|
f1b1f3bd52 | ||
|
|
ff611dac32 | ||
|
|
e0a4cb4763 | ||
|
|
a3246866fb | ||
|
|
b94c2fc7c4 | ||
|
|
d530cf22da | ||
|
|
94e5b02a39 | ||
|
|
40533a50c1 | ||
|
|
d4182b1929 | ||
|
|
482129499d | ||
|
|
366cd02761 | ||
|
|
f549e7e5a8 | ||
|
|
4cab7c7fc4 | ||
|
|
e3939d4805 | ||
|
|
2ae6983bc2 | ||
|
|
ad00193a17 | ||
|
|
810667abbc | ||
|
|
a66efd56f2 | ||
|
|
36ba15e7f9 | ||
|
|
d809fb1e7b | ||
|
|
d0bc834a57 | ||
|
|
483ca8cc4c | ||
|
|
06aba5da46 | ||
|
|
106fbcd5af | ||
|
|
f456e41a45 | ||
|
|
7dc3aee4a2 | ||
|
|
c91bee8091 | ||
|
|
82875e15f9 | ||
|
|
d6f8b7d850 | ||
|
|
72fe873b26 | ||
|
|
e9f34b1e21 | ||
|
|
d15ab79370 | ||
|
|
303613b052 | ||
|
|
051c451867 | ||
|
|
ac8a3526a4 | ||
|
|
be47fb55e8 | ||
|
|
5b8fc75d4a | ||
|
|
629e73ac29 | ||
|
|
7e5b861caf | ||
|
|
f3dcc14fca | ||
|
|
fee68d0231 | ||
|
|
83f56d152f | ||
|
|
a04ea789f5 | ||
|
|
94becc3ddc | ||
|
|
8452e1bdf0 | ||
|
|
5a513bc69d | ||
|
|
5a173a2bd3 | ||
|
|
d29b068d59 | ||
|
|
8dbbaca8da | ||
|
|
10a1f7ec1e | ||
|
|
8286dba919 | ||
|
|
bd735059d0 | ||
|
|
147acbf096 | ||
|
|
91aa5302a8 | ||
|
|
2b6328f0ee | ||
|
|
1bc2136771 | ||
|
|
4ad0a52104 | ||
|
|
b9450b0f63 | ||
|
|
03bb74ea84 | ||
|
|
8b4551c605 | ||
|
|
f645049054 | ||
|
|
aa832244fb | ||
|
|
190311c68c | ||
|
|
b8ed9d7da5 | ||
|
|
ca32d51375 | ||
|
|
b0e5bb3718 | ||
|
|
96ebbfe75c | ||
|
|
5c6a6ee350 | ||
|
|
bbf2d68e9d | ||
|
|
59cf76b4ae | ||
|
|
e97440819d | ||
|
|
87cd37a30b | ||
|
|
f406dfa277 | ||
|
|
24039f593c | ||
|
|
cceb4401aa | ||
|
|
f9445cb282 | ||
|
|
706adb6d0b | ||
|
|
dd7e578fe6 | ||
|
|
83d1df19ba | ||
|
|
975fa28f62 | ||
|
|
452f7f7bff | ||
|
|
626db661ab | ||
|
|
9ea3a404a3 | ||
|
|
55c3e9d5bb | ||
|
|
f616a527ee | ||
|
|
a594e9f830 | ||
|
|
45d712d390 | ||
|
|
dbbdc171d2 | ||
|
|
befe22e170 | ||
|
|
b284e82aa7 | ||
|
|
ed5a3338fe | ||
|
|
68dcec87c7 | ||
|
|
39d7e54e7f | ||
|
|
404a4ad578 | ||
|
|
c9d0a7a301 | ||
|
|
54ffdc51b4 | ||
|
|
9e53774299 | ||
|
|
f70a6aafb1 | ||
|
|
c3fa9f7aa8 | ||
|
|
a73ef3affd | ||
|
|
4e5d26a2d1 | ||
|
|
4b1bc7acd4 | ||
|
|
95d29c6910 | ||
|
|
c88ea2bd7c | ||
|
|
af157867d8 | ||
|
|
9476e16df6 | ||
|
|
9c148bf3f0 | ||
|
|
c8c96b9f6b | ||
|
|
108d7764ec | ||
|
|
5396cad2b9 | ||
|
|
2bae3d9d2f | ||
|
|
9cbaa9679d | ||
|
|
6228a962f6 | ||
|
|
1baff27553 | ||
|
|
4855b6bca6 | ||
|
|
ff0c66e38c | ||
|
|
83d2ca07f1 | ||
|
|
26152489f3 | ||
|
|
4ca4d7b5dd | ||
|
|
0dddf12831 | ||
|
|
25c098bad6 | ||
|
|
be9528dcb2 | ||
|
|
965385980f | ||
|
|
ca92cd03db | ||
|
|
cdec95b73a | ||
|
|
76bf3077e9 | ||
|
|
53858a7789 | ||
|
|
b98e25c9a7 | ||
|
|
be46f44bc9 | ||
|
|
fee6d450e4 | ||
|
|
173dc59039 | ||
|
|
950dd4e85c | ||
|
|
6632feb696 | ||
|
|
7b2622e67b | ||
|
|
9e5528ef83 | ||
|
|
3d920670e5 | ||
|
|
4d2afd827f | ||
|
|
9a4d0dfe5e | ||
|
|
2a240e62aa | ||
|
|
7a88adcf96 | ||
|
|
b84d2f2c29 | ||
|
|
2945838eef | ||
|
|
43aa8812b3 | ||
|
|
9a2467dc21 | ||
|
|
5a75625eef | ||
|
|
2f2890596d | ||
|
|
01fa0b357e | ||
|
|
c5f0dad84e | ||
|
|
7f7f4e81a5 | ||
|
|
8b423908ca | ||
|
|
598fe9f956 | ||
|
|
06e8b530ea | ||
|
|
d5c25f73bd | ||
|
|
73fa306719 | ||
|
|
8d0cea6fe4 | ||
|
|
273b57ee69 | ||
|
|
c1578b92e1 | ||
|
|
c69a741c90 | ||
|
|
f8d537c0c5 | ||
|
|
e371159826 | ||
|
|
7d912715bc | ||
|
|
d6449c2902 | ||
|
|
8a3868abd0 | ||
|
|
112047d2b3 | ||
|
|
cd9f584729 | ||
|
|
31741a1ab3 | ||
|
|
eb6440694a | ||
|
|
2c388308c7 | ||
|
|
1c8f744719 | ||
|
|
dfdc893d63 | ||
|
|
669aaab6b4 | ||
|
|
73017d3f5c | ||
|
|
38fa809656 | ||
|
|
0ed21a4acb | ||
|
|
9ae7d98193 | ||
|
|
07e60286f2 | ||
|
|
7f918b8a69 | ||
|
|
4e0ace6ec5 | ||
|
|
dca5f8d27b | ||
|
|
6478276064 | ||
|
|
7d603f97fe |
21
.gitignore
vendored
21
.gitignore
vendored
@@ -10,22 +10,13 @@ obj
|
||||
mods/*/*.dll
|
||||
|
||||
# Red Alert binary files
|
||||
*.[mM][iI][xX]
|
||||
|
||||
# Crap generated by OpenRa
|
||||
sheet-*.png
|
||||
log.txt
|
||||
|
||||
*.rep
|
||||
mods/*/packages/*.[mM][iI][xX]
|
||||
|
||||
#binary stuff
|
||||
/*.dll
|
||||
*.pdb
|
||||
*.mdb
|
||||
*.exe
|
||||
OpenRA
|
||||
OpenRA.app
|
||||
*.vqa
|
||||
|
||||
# backup files by various editors
|
||||
*~
|
||||
@@ -33,10 +24,8 @@ OpenRA.app
|
||||
# dependency DLLs (different for every platform!)
|
||||
cg.dll
|
||||
cgGL.dll
|
||||
glfw.dll
|
||||
|
||||
/OpenRa.Gl.dll
|
||||
settings.ini
|
||||
|
||||
#monodevelop
|
||||
*.pidb
|
||||
@@ -44,6 +33,9 @@ settings.ini
|
||||
|
||||
packaging/windows/*.exe
|
||||
|
||||
# osx crap
|
||||
.DS_Store
|
||||
|
||||
# osx build crap
|
||||
packaging/osx/launcher/build/
|
||||
packaging/osx/launcher/OpenRA.xcodeproj/*.pbxuser
|
||||
@@ -52,6 +44,9 @@ packaging/osx/launcher/OpenRA.xcodeproj/*.mode1v3
|
||||
temp.c
|
||||
temp.o
|
||||
temp.s
|
||||
|
||||
OpenRA.Launcher.Mac/build/
|
||||
OpenRA.Launcher.Mac/OpenRA.xcodeproj/*.pbxuser
|
||||
OpenRA.Launcher.Mac/OpenRA.xcodeproj/*.perspectivev3
|
||||
OpenRA.Launcher.Mac/OpenRA.xcodeproj/*.mode1v3
|
||||
*.config
|
||||
*.resources
|
||||
|
||||
4
AUTHORS
4
AUTHORS
@@ -6,4 +6,6 @@ The OpenRA developers are:
|
||||
* Matthew Bowra-Dean
|
||||
* Paul Chote
|
||||
* Alli Witheford
|
||||
* Joakim Lindberg
|
||||
* Joakim Lindberg
|
||||
* Andrew Riedi
|
||||
* Tim Mylemans
|
||||
|
||||
502
CHANGELOG
Normal file
502
CHANGELOG
Normal file
@@ -0,0 +1,502 @@
|
||||
20110207
|
||||
Engine:
|
||||
Informative drop messages - user is notified of kick vs game has started vs server unavailable
|
||||
Fixed render errors with the build palette on the first game tick
|
||||
Improved sync check performance
|
||||
Shp writing capabilities for mod tools
|
||||
Fixed desync due to floating point calculations in unit facing
|
||||
Fixed idle animations
|
||||
Removed launchers on all platforms
|
||||
Asset download/install is now performed ingame
|
||||
Mod selector is now available from the main menu
|
||||
Fixed `lock teams' checkbox
|
||||
Lots of misc. engine refactoring
|
||||
Fixed exploit allowing stance changes when teams are locked
|
||||
Fix crash when capturing last enemy silo
|
||||
Fix units continuing to attack a building after it has been captured
|
||||
Fix floating point issues with missiles (manifests as broken torpedos in ra)
|
||||
Fix location calculation for flying units (manifests as invincible helicopters in cnc)
|
||||
Infantry stack 5-to-a-cell like the original games
|
||||
Craters and scorches smoke for a limited time
|
||||
Added a scatter key (bound to `x')
|
||||
|
||||
C&C:
|
||||
Fixed commando c4
|
||||
Fixed Airfield production notification ("Reinforcements have arrived")
|
||||
Fixed palette bugs with Oil Derricks and walls
|
||||
Fixed tech tree bugs after capturing enemy productions structures
|
||||
"Repairing" eva
|
||||
Proper "pop up" SAM sites. Closed SAMs receive a 50% armor bonus.
|
||||
SAM sites require power to operate
|
||||
Advanced Guard Tower requires power to operate
|
||||
Support structures no longer grant build radius
|
||||
Lower Barracks/Hand health
|
||||
Increase Weapons Factory health
|
||||
Increase rocket bike damage
|
||||
New Map: Crossing the Rubicon (Arcturus)
|
||||
|
||||
RA:
|
||||
Game assets can be installed from one of the Red Alert cds
|
||||
"Repairing" eva
|
||||
GPS is now shared between allies
|
||||
Submarines are no longer visible to everyone
|
||||
Fixed paradrop flare, spyplane from capturing KOTH points
|
||||
New Map: Nuclear Winter (nudalz)
|
||||
New Map: Seaside (nudalz)
|
||||
|
||||
Editor:
|
||||
Ability to switch mods after launch
|
||||
Refactor hardcoded tools into a generic interface
|
||||
|
||||
|
||||
20110109
|
||||
Launchers:
|
||||
New GTK based launcher for linux.
|
||||
Mod version, version check, and MOTD moved from the main menu into the launchers.
|
||||
Fixes for non-standard mono installations under OSX.
|
||||
Fixes for filepaths with spaces under OSX.
|
||||
|
||||
Map Editor / Maps:
|
||||
Fixed crash when using floodfill.
|
||||
New map format (version 4). Open and resave maps with the editor to upgrade them.
|
||||
Added support for compressed (.oramap or .zip) maps.
|
||||
Removed .uid files from maps -- compute the hash on demand now.
|
||||
|
||||
General:
|
||||
Mod versions are checked when joining a server. Clients with a different game version / wrong mods will not be able to join.
|
||||
Added 'Stop' command on 'S'.
|
||||
Stop units from autotargeting walls.
|
||||
Added different pip colour for gems vs ore.
|
||||
Fixed several exploits in support powers.
|
||||
Continue to show selected units when firing special powers.
|
||||
Fixed palette effects (nuke, chronoshift) being applied to fog / shroud.
|
||||
Added a replay viewer.
|
||||
Fixed building previews being rendered below bridges.
|
||||
Forced the AI to leave gaps between its buildings.
|
||||
Fixed captured buildings still drawing power from the original owner.
|
||||
Fixed various crashes in the editor when trying to make a new map.
|
||||
Support multiple bot types; added another bot difficulty.
|
||||
Removed option to not save syncreports.
|
||||
Fixed desync related to aircraft.
|
||||
Fixed sync not being checked on World traits.
|
||||
Pick a random available door on production structures with more than one (barracks, subpens, etc).
|
||||
Fixed some rare Harvester-related crashes.
|
||||
Added labels to the perf graph.
|
||||
Locked teams by default.
|
||||
Fixed "No games found" not being displayed when there was an in-progress (hidden) game detected.
|
||||
Added support for multiple shellmaps. Chooses randomly.
|
||||
Fixed dropdowns possibly getting stuck open when the host force-starts the game.
|
||||
Improved scrollpanels - added scrollbars and mousewheel support.
|
||||
Fixed potential desyncs in building refund calculation and unit repair.
|
||||
Added black outline to text drawn over the world, so it can be seen in all cases.
|
||||
Many performance improvements.
|
||||
|
||||
C&C:
|
||||
Fixed footprint of ATWR.
|
||||
Improved harvester docking.
|
||||
Made Oil Derricks capturable.
|
||||
Fixed nuke detonation sound.
|
||||
|
||||
RA:
|
||||
Fixed Tanya not having the correct pip color.
|
||||
Fixed helicopters spawning in the wrong place.
|
||||
Fixed Spy-related crashes when disguising as civilians.
|
||||
Allow using C4 on friendly buildings.
|
||||
Improved harvester docking.
|
||||
Added proper shareable/revokable GPS.
|
||||
Nerf 1tnk hard.
|
||||
Increase cost of 2tnk slightly, but increase its HP too.
|
||||
Require power to operate SAM sites.
|
||||
Fixed missing tooltips for SHOK and TTNK.
|
||||
Fixed chronoshift power requiring two clicks to cancel.
|
||||
Fixed desync related to chronoshift.
|
||||
Fixed bogus bottom-left spawnpoint on Central Conflict.
|
||||
Production tabs with an item ready now light up yellow.
|
||||
Fixed crash when a WEAP is half-destroyed before it finishes deploying.
|
||||
|
||||
|
||||
20101202
|
||||
General:
|
||||
New launcher for Windows and OS X (Linux coming in a later release) for downloading and installing mods, and launching the game.
|
||||
Disable Surrender button when you win or lose.
|
||||
Fix Minimap orders outside viewport.
|
||||
Render building previews when placing a structure.
|
||||
Buttons offset their contents when pressed.
|
||||
Dropdown listboxes in the game lobby and diplomacy panel.
|
||||
Allow moving the cursor and editing anywhere in textfields.
|
||||
Don't render things outside the map.
|
||||
Render selection boxes / health bars, target lines above everything else
|
||||
Show "cannot move here" cursor when mousing over invalid terrain under the fog, or outside the map.
|
||||
Remove move flashes (they are obsoleted by target lines).
|
||||
Buildings are always visible under fog.
|
||||
Captured refineries no longer give cash to the original owner.
|
||||
New rally point artwork.
|
||||
Fix broken airstrike / parabomb special powers.
|
||||
Fix diplomacy cycling shroud exploit.
|
||||
Change the .rpm package to target Fedora.
|
||||
Fixed idle animations
|
||||
|
||||
RA:
|
||||
Added "A Path Beyond" map
|
||||
Fix crash when selling iron curtained buildings.
|
||||
Don't stack multiple Invuln render effect on an actor.
|
||||
Fix exploit in Iron Curtain, Chronosphere, Nuke.
|
||||
Fix paradrop flare remaining forever if drop plane is killed.
|
||||
Area of effect Iron Curtain.
|
||||
Area of effect Chronoshift.
|
||||
Remove sandbag in water of "Equal Opportunity" map.
|
||||
Allow chronoshifted and paradropped units to collect crates.
|
||||
Fixed medic crash.
|
||||
Removed end of game crash.
|
||||
Fix dog attack.
|
||||
Missile silo requires power but can be powered down.
|
||||
Fix shellmap low power and invalid gap generator position.
|
||||
Removed Naval Transport until it's cargo capabilities are fixed
|
||||
|
||||
CNC:
|
||||
Fix exploit in Ion Cannon, Nuke.
|
||||
Add some basic scripting to the shellmap.
|
||||
Fix invulnerable stealth tanks.
|
||||
Oil derricks spurt fire when killed.
|
||||
New load screen (unfinished).
|
||||
Fix observers.
|
||||
Helicopters automatically target enemy units
|
||||
|
||||
Engine:
|
||||
Refactored Orders to use less network bandwidth and remove duplication.
|
||||
Dump available extensions to graphics.log when GL Renderer fails to init.
|
||||
Fix Makefile constantly rebuilding, and refactor for readability.
|
||||
Display soft shroud around edge of map instead of hard border.
|
||||
Standardise engine naming of Theatre -> Tileset.
|
||||
Refactor map size queries to all use Map.Bounds.
|
||||
Move all widget delegate into the RA mod dll.
|
||||
Renamed ListBoxWidget -> ScrollPanelWidget.
|
||||
Fix ScrollPanelWidget scrolling beyond the start by 1 velocity tick.
|
||||
Removed duplication from target lines.
|
||||
Extensive refactoring of shroud.
|
||||
Refactor Scale trait to a property on Render*.
|
||||
Refactor idle behavior
|
||||
|
||||
|
||||
20101121-2
|
||||
Bug fixes:
|
||||
Fixed Tesla causing an out of memory exception
|
||||
Fixed Tesla animations.
|
||||
All players can now see AI players in lobby.
|
||||
Weapon factory sell animation now plays correctly.
|
||||
Utility app now extracts downloaded content packages properly.
|
||||
Fixed helicopters landing in silly places.
|
||||
|
||||
New Features:
|
||||
New default renderer using GLSL instead of CG. Removes the dependency on the CG toolkit and fixes issues with Radeon graphics cards using latest drivers.
|
||||
Order queuing with <shift>
|
||||
Unlimited power option in dev mode.
|
||||
New King of the Hill game mode with two maps: Crossroads and Island Hoppers
|
||||
Smoke trails for damaged aircraft.
|
||||
|
||||
|
||||
20101107
|
||||
Fix Engineer/Tanya/etc refusing to enter buildings in 2010-11-06.
|
||||
|
||||
|
||||
20101106
|
||||
Bug Fixes:
|
||||
Fix crash when hosting a second game.
|
||||
Fixed exploit where you could place a building anywhere.
|
||||
Fix aircraft, infantry becoming invincible in some circumstances.
|
||||
Fix a common aircraft desync.
|
||||
Unmuted the shellmap; it's now at 25% volume.
|
||||
|
||||
Balance Changes:
|
||||
reduce cooldown on Chronosphere to 2 minutes (was 4 minutes)
|
||||
reduce cooldown on Iron Curtain to 2 minutes (was 6 minutes)
|
||||
reduce invulnerable time on Iron Curtain the 30 seconds (was 45 seconds)
|
||||
reduce anti-ground damage of rocket soldier to 50 (was 60) and anti-air damage to 40 (was 50)
|
||||
|
||||
|
||||
|
||||
20101025
|
||||
Fix crash in C&C when harvesters return to the refinery (sorry guys)
|
||||
Fix crash in both mods when transports unload
|
||||
Fix ore/tiberium growth not working correctly
|
||||
Fix graphical glitches on screenshake, etc
|
||||
Add contrails to RA planes
|
||||
Added plane crashes in RA
|
||||
Added explosions on impact for all RA aircraft
|
||||
Added more scripting to the RA shellmap
|
||||
Fix Tesla not doing the correct amount of damage
|
||||
Lots of internal cleanup
|
||||
|
||||
|
||||
|
||||
20101023
|
||||
New C&C Maps:
|
||||
Into the River Below (6p)
|
||||
Algernon (4p)
|
||||
Wargames (4p)
|
||||
Yellowstone II (4p)
|
||||
|
||||
Bug Fixes:
|
||||
Client disconnects no longer "double-quit".
|
||||
Units can no longer move over certain water tiles.
|
||||
Checks for destroyed actors to ensure they don't try to perform actions after death.
|
||||
Loose files in mod folders take priority over ones in .mix packages.
|
||||
Fixes for syncing in replays.
|
||||
Fix Iron Curtain.
|
||||
Fixes for units entering a building from the east or south
|
||||
MOTD no longer spits out garbage when behind a proxy needing web authentication.
|
||||
|
||||
RA Balance Tweaks:
|
||||
Airfield cost reduced from 1100 to 300
|
||||
Yak cost increased from 800 to 1000
|
||||
Mig cost increased from 1200 to 2000
|
||||
Helipad cost reduced from 1500 to 300
|
||||
Longbow cost increased from 1200 to 2000
|
||||
Hind cost increased from 1200 to 1500
|
||||
Anti-air gun range increased from 6 to 10, spread increased from 3 to 5
|
||||
Flack truck range increased from 6 to 8, spread increased from 3 to 5
|
||||
|
||||
|
||||
20101017
|
||||
Fix crash when repair indicator was visible, but the building got destroyed or sold
|
||||
Fix crash if an actor got destroyed twice (blown up & sold, etc)
|
||||
Fix putting units back in BADR and C17.
|
||||
Fix C&C crates being invisible
|
||||
Fix bogus overlapping of MINE with ore trucks
|
||||
Add MCV, napalm, nuke crates to C&C.
|
||||
Fix "(dead)" tags in chat
|
||||
Mute shellmap combat
|
||||
Fix FMV player
|
||||
Fix bug in voice system which made it impossible to add extra sides (thanks raminator)
|
||||
Fixed bogus Missile Silo cameo from RA
|
||||
Fixed engineer goldwrench cursors being reversed
|
||||
Add support for actors that give the owner a small flow of cash (to be used with Oil Derricks)
|
||||
Make teamchat toggle more flexible
|
||||
Fix cloakable units being untargetable while uncloaked (thanks pdovy)
|
||||
Fix crash when clicking `repair` with no MCV
|
||||
Fix unit crates spawning in inappropriate places
|
||||
Updated 'The Sentinel' map
|
||||
Add base cycling (backspace) in C&C (it previously worked only in RA)
|
||||
Fix planes getting stuck on the edge of the map
|
||||
Fix explosions in air being drawn at ground level
|
||||
Allow map slots to disallow bots
|
||||
Allow map slots to enforce race/color selection
|
||||
Replace C&C LST art (thanks, KatzSmile)
|
||||
Push HackyAI setup into system.yaml, fix HackyAI for C&C
|
||||
Reduce effectiveness of RA GUN vs unarmored
|
||||
Improved mod content download infrastructure for Linux
|
||||
Nerf C&C Orca slightly
|
||||
Nerf speed of C&C bggy/jeep/bike/apc
|
||||
Add new C&C 1v1 map: 'Chokepoint' (thanks Tiberian)
|
||||
Reduce bandwidth usage in multiplayer (1/2)
|
||||
Fix version string showing up twice in bottom-right corner after a game
|
||||
Buff arty damage slightly
|
||||
Nerf V2 reload slightly
|
||||
Add trails to C&C SAM missiles
|
||||
Increase speed of most C&C AA missiles
|
||||
Reduce power requirement for RA AFLD from 50 to 20
|
||||
|
||||
|
||||
20101013
|
||||
Fix crash when ordering a helicopter to move while it was falling out of the sky
|
||||
Add blue tiberium
|
||||
Fix aircraft not showing up on radar
|
||||
Fix canceling of production not quite working (would cancel 2 if one was half-built)
|
||||
Fix base-cycling for mac
|
||||
Fix leaks between shellmap world and ingame world
|
||||
Fix crash when the network connection is lost
|
||||
Run the shellmap behind the lobby
|
||||
Fix host not being able to teamchat
|
||||
Declaring war automatically breaks the alliance in both directions
|
||||
Aircraft can attack from their airfields correctly now
|
||||
Attack move added ('A' and then left-click)
|
||||
Add Tiberian's 'The Sentinel' 1v1 C&C map
|
||||
Show the server name in the lobby dialog title
|
||||
Random actually means random
|
||||
Fix crash when destroying a Refinery with docked harvester
|
||||
Add pchote's 'Tundra' 1v1 C&C SNOW! map
|
||||
Lots of internal engine improvements
|
||||
|
||||
|
||||
20101009
|
||||
Fix 64bit Linux compatibility
|
||||
Nerf C&C Attack Bike
|
||||
Show mod info in server browser
|
||||
Show MOTD in the main menu
|
||||
Fixed exploit with selling walls
|
||||
Fixed auto-attack not working properly
|
||||
Add an example mod, which adds a single unit to RA.
|
||||
Fix dogs eating walls
|
||||
Fix crash on destroying ore storage buildings
|
||||
Fix Obelisk missing moving target
|
||||
Ban cloak crates for infantry
|
||||
Add nuke "bad" crate
|
||||
Prevent aircraft from firing while landed
|
||||
Reduce nuke charge time from 13min to 9min
|
||||
Reduce parabombs charge time to 1min
|
||||
Add support for minimum ranges on weapons
|
||||
Add support for excluding specific actor types from picking up certain crates
|
||||
FIx silent nukes in RA if they didn't hit a building
|
||||
Fix all AI players getting the same color
|
||||
Fix AI players getting the same team setting as the host
|
||||
Fix AI attacking each other
|
||||
Prevent most awful-looking colors
|
||||
Remove most of the debug spam for aircraft
|
||||
Increase construction yard health (50% in RA, 25% in CNC)
|
||||
AI players now build defenses
|
||||
AI players no longer attack with medics (e1/e2/e3/1tnk/2tnk/3tnk)
|
||||
Much improved order targeting system
|
||||
Add crash animations for helicopters
|
||||
Nerf Hind chainguns
|
||||
Reduce cost of Cruisers from 3.2k to 2.4k
|
||||
Fix CNC airdrop planes getting stuck if the Airfield goes away
|
||||
Fix phantom voices for dead units in control groups
|
||||
Fix dogs sometimes not killing infantry
|
||||
Fix scroll jumping if opposite scroll inputs were applied
|
||||
Fix bogus targeting lines being drawn to 0,0 sometimes
|
||||
Fix VS2010 compatibility
|
||||
Fix the game getting screwed up when people leave
|
||||
|
||||
|
||||
20101002
|
||||
Fix various crashes
|
||||
Fix CNC AI never building anything (it's still crap, but at least it does *something*)
|
||||
Added shader fallbacks for Cg-2.1
|
||||
Fix editor crashing on File->Open on Windows
|
||||
Added scroll speed control (thanks, Gecko)
|
||||
|
||||
|
||||
20100922 through 20100922-4
|
||||
Allow queueing of buildings when a building is ready to place
|
||||
Change the pathfinder to use integers instead of floating point (fixes desync)
|
||||
Create ui widgets on demand instead of at gamestart
|
||||
Begin refactoring activity queuing for cleaner code
|
||||
Reenable crates
|
||||
Remove desync debug logging
|
||||
Fix editor crash
|
||||
Fix crash when a building being repaired is killed
|
||||
|
||||
|
||||
|
||||
20100921 through 20100921-6
|
||||
Add yet more logging to search for the packaged build desync
|
||||
|
||||
|
||||
20100920 through 20100920-7
|
||||
Fix crash when building cnc weapons factory
|
||||
Fix crash when harvester and refinery are killed by the same bullet (eg nuke)
|
||||
Move several traits from engine into ra mod
|
||||
Fix several editor bugs
|
||||
Add a lot more logging to search for the packaged build desync
|
||||
|
||||
|
||||
20100919-2
|
||||
Fix crash when un/deploying a damaged mcv
|
||||
|
||||
|
||||
20100919
|
||||
Cache the power state of buildings for large performance gains
|
||||
Changes to sync logging for large performance gains
|
||||
Changes to shroud and ore rendering for large performace gains
|
||||
Changes to renderer to fix several z-order bugs
|
||||
Fix osx version string
|
||||
Rename Repeat -> Loop in the music player
|
||||
Fix team selection in the game lobby
|
||||
Don't change production tab when selecting enemy structures
|
||||
|
||||
|
||||
20100918-2 through 20100918-4
|
||||
Fix crashes in the map editor
|
||||
Include menu and desktop shortcuts to the RPM package
|
||||
Add debugging to track down a desync between packaged versions on .net vs packaged versions on mono
|
||||
|
||||
|
||||
20100918
|
||||
Fixed lots of crashes
|
||||
AI only tries to attack players that exist (and not itself)
|
||||
Fixed speed of idle animations
|
||||
Fixed exploit with A10 (infinite napalm)
|
||||
Fixed exploits with remote building capturing/destroying
|
||||
Added ability to change tilesize per-mod
|
||||
Fixed delivering ore to an ally's proc
|
||||
Fixed dog attacking ground forever (banned)
|
||||
Fixed most z-order bugs
|
||||
Fixed lots of editor usability problems
|
||||
Fixed bogus XML generated by TSB
|
||||
Added notification when cheats are used
|
||||
Fixed exploit with reverse enter-transport order (didn't check if the passenger was compatible)
|
||||
Fixed a bunch of techtree bugs
|
||||
Fixed walkability of north rivermouth template in RA.
|
||||
Added ability to export minimap as PNG from the editor
|
||||
|
||||
|
||||
20100914
|
||||
Infantry idle sequences for ra mod
|
||||
Enable music player by default (requires scores.mix to be installed manually)
|
||||
Flak truck for soviets in ra mod
|
||||
Give dog a selection voice
|
||||
Only scroll when the game window is focused
|
||||
Fixed cursor/order bugs (includes force-fire c4 on allied structures, harvesting ore under shroud, move orders for aircraft, etc)
|
||||
Fixed a collection of crashes related to dead actors
|
||||
Fixed broken rpm package
|
||||
Create Debian packages
|
||||
|
||||
|
||||
20100910-2
|
||||
Fixed attacking helipads
|
||||
Deployed more mirrors
|
||||
Added idle animations in C&C
|
||||
Fixed an issue with the sidebar palette in C&C Desert
|
||||
Integrated Jk's C&C Snow theater
|
||||
Go back to classic C&C refinery model
|
||||
Improve building explosions
|
||||
Add nuke flash to C&C
|
||||
Fix crash when losing FACT with a building ready to place
|
||||
Remove unused MIX files
|
||||
Add support for custom armor types
|
||||
Adjust bounding boxes on vehicles
|
||||
Windows installer prompts to install .NET if you don't have it
|
||||
Windows installer remembers previous location for upgrades
|
||||
Fix various crashes when refineries going away
|
||||
Fix serious performace issue -- Actor leak when failing to spawn units
|
||||
Add support for mobile production units
|
||||
Remove splash damage from Tiberium
|
||||
Fix a crash with actors dying with a projectile in-flight
|
||||
Correctly clean up cargo when a transport dies
|
||||
Fix client crash when the server disconnects
|
||||
Right-clicking on a valid passenger with a transport loads cargo
|
||||
Added zoom to editor
|
||||
Convert sequences to yaml
|
||||
Clean up the mod folders
|
||||
Add a shellmap for C&C
|
||||
Make pathfinder work with a MobileInfo rather than a live actor
|
||||
Add a loadscreen for C&C
|
||||
Correctly back up MIX files when upgrading windows installs
|
||||
|
||||
|
||||
20100907
|
||||
Changed MiG prerequisites to AFLD+STEK
|
||||
Removed KENN, build DOG directly from BARR now
|
||||
Chronotank can only teleport when fully charged
|
||||
Improved OpenGL error logging
|
||||
Fixed targeting of FIX
|
||||
Fixed crash when an engineer is trying to repair a building, but it dies/gets sold/etc.
|
||||
Added muzzle flashes to Yak and Hind chainguns
|
||||
Fixed bounding boxes on some units
|
||||
Fixed accuracy of Tesla weapons
|
||||
Changed ownership of GUN and GTWR in CNC to both
|
||||
Fixed crash on destroying things that have a building reserved
|
||||
If ordered to move to an unpathable cell, move somewhere nearby that is pathable instead
|
||||
Fixed RPM linux package
|
||||
|
||||
|
||||
20100906-2
|
||||
Shows game version in main menu screen for windows and linux
|
||||
|
||||
|
||||
20100906
|
||||
Improvements to Render performance
|
||||
Improved debugging for performance issues
|
||||
"Give Exploration" developer-mode option
|
||||
Check for .net framework on windows install
|
||||
Allow the viewport to scroll past the map edge to prevent ui from blocking buildings
|
||||
75
HACKING
75
HACKING
@@ -5,43 +5,82 @@ There are n main sections to OpenRA: UI, Rendering, unit behaviour, ...
|
||||
All units/structures/most things in the map are Actors. Actors contain a collection of traits.
|
||||
Traits consist of an info class and a class that does stuff
|
||||
|
||||
Actor assembly is done via the mod's yaml files. A section exists for each actor type, and within that section we list the traits the actor should have. These get looked up in the loaded mod DLLs. Each trait can contain properties, which are automatically loaded into the corresponding fields on the trait's ITraitInfo.
|
||||
Actor assembly is done via the mod's yaml files. A section exists for each actor type,
|
||||
and within that section we list the traits the actor should have.
|
||||
These get looked up in the loaded mod DLLs. Each trait can contain properties,
|
||||
which are automatically loaded into the corresponding fields on the trait's ITraitInfo.
|
||||
|
||||
- Traits: look at TraitInterfaces.cs
|
||||
We've tried to make individual traits implement as self-contained a unit of functionality as possible - all cross-trait references should be in terms of an interface from TraitInterfaces.cs.
|
||||
We've tried to make individual traits implement as self-contained a unit of functionality
|
||||
as possible - all cross-trait references should be in terms of an interface from
|
||||
TraitInterfaces.cs.
|
||||
|
||||
- Things an actor can be *doing* are represented as IActivity implementations. Actor has a queue of these. There's a standard set of activities in OpenRa.Game/Traits/Activities, and mods tend to define more as they need them. (RA defines various special-infantry actions as activities).
|
||||
- Things an actor can be *doing* are represented as IActivity implementations.
|
||||
Actor has a queue of these. There's a standard set of activities in
|
||||
OpenRa.Game/Traits/Activities, and mods tend to define more as they need them. (RA
|
||||
defines various special-infantry actions as activities).
|
||||
|
||||
- Units offer orders they can perform (given context) through traits that implement IIssueOrder. Every trait with this interface is given a chance to generate orders for the current context.
|
||||
- Units offer orders they can perform (given context) through traits that implement IIssueOrder.
|
||||
Every trait with this interface is given a chance to generate orders for the current context.
|
||||
|
||||
- For more complex things that require modal UI (like special abilities, RA-style sell/repair buttons, etc) we have IOrderGenerator implementations. This can completely replace the normal actors-provide-orders model temporarily. IOGs wiring is provided through OpenRa.Game/Controller.cs (ToggleInputMode<T>, CancelInputMode)
|
||||
- For more complex things that require modal UI (like special abilities,
|
||||
RA-style sell/repair buttons, etc) we have IOrderGenerator implementations. This can
|
||||
completely replace the normal actors-provide-orders model temporarily. IOGs wiring is
|
||||
provided through OpenRa.Game/Controller.cs (ToggleInputMode<T>, CancelInputMode)
|
||||
|
||||
- Things that don't affect gameplay, or (increasingly) are just transient are implemented as IEffect, rather than real Actors. This is similar to the temp ents mechanism in many other game engines.
|
||||
- Things that don't affect gameplay, or (increasingly) are just transient are implemented as
|
||||
IEffect, rather than real Actors. This is similar to the temp ents mechanism in many other
|
||||
game engines.
|
||||
|
||||
- Most player-level or global-level game behavior is implemented as traits on special Player and World actors. These are accessible via Player.PlayerActor and World.WorldActor. This includes production queue support, ore/tiberium growth, various palette manipulation magic.
|
||||
- Most player-level or global-level game behavior is implemented as traits on special Player
|
||||
and World actors. These are accessible via Player.PlayerActor and World.WorldActor. This
|
||||
includes production queue support, ore/tiberium growth, various palette manipulation magic.
|
||||
|
||||
- Many traits can be modified by adding an appropriate IFooModifier implementation to the unit. This includes rendering, where IRenderModifier allows you to define an arbitrary transform on the Renderables emitted by the actor's IRender implementation(s). Examples are things like cloaking, invisibility to certain players, flying units with shadows, etc. Other modifiers can affect movement speed, damage taken, weapon firepower, etc.
|
||||
- Many traits can be modified by adding an appropriate IFooModifier implementation to the unit.
|
||||
This includes rendering, where IRenderModifier allows you to define an arbitrary transform on
|
||||
the Renderables emitted by the actor's IRender implementation(s). Examples are things like
|
||||
cloaking, invisibility to certain players, flying units with shadows, etc. Other modifiers
|
||||
can affect movement speed, damage taken, weapon firepower, etc.
|
||||
|
||||
Game code is collected into "Mod" units. Mods can be added prior to starting the game. Currently there is no dependancy mechanism, but provided you are doing additions or overrides you can add multiple mods without problem.
|
||||
Game code is collected into "Mod" units. Mods can be added prior to starting the game.
|
||||
Currently there is no dependancy mechanism, but provided you are doing additions or overrides
|
||||
you can add multiple mods without problem.
|
||||
Everything is a mod (including RA - which is loaded by default).
|
||||
|
||||
The contents of the mod is defined in a manifest file mod.yaml. This lists the packages containing art assets (typically .mix files), yaml files defining actor defintions, and ini files containing legacy information that have yet to be ported over to the (relatively new) yaml system.
|
||||
The contents of the mod is defined in a manifest file mod.yaml. This lists the packages
|
||||
containing art assets (typically .mix files), yaml files defining actor defintions,
|
||||
and ini files containing legacy information that have yet to be ported over to
|
||||
the (relatively new) yaml system.
|
||||
|
||||
The unit artwork itself must be defined in a Sequences file (typically Sequences.xml; check mod.yaml for a list of what the mod uses); the format is self explanatory. There is also the SequenceEditor tool to make this easy.
|
||||
The unit artwork itself must be defined in a Sequences file (typically Sequences.xml;
|
||||
check mod.yaml for a list of what the mod uses); the format is self explanatory. There is
|
||||
also the SequenceEditor tool to make this easy.
|
||||
|
||||
Chrome artwork is similarly defined in Chrome.xml. Chrome is already mod dependent. Sortof ;) mod-dependent *behavior* would be nice too, not just skinning. This is a property of the traits however; once we port UI into traits this will become a non-issue.
|
||||
Chrome artwork is similarly defined in Chrome.xml. Chrome is already mod dependent. Sortof ;)
|
||||
mod-dependent *behavior* would be nice too, not just skinning. This is a property of the traits
|
||||
however; once we port UI into traits this will become a non-issue.
|
||||
|
||||
Rendering
|
||||
OpenRa.Game/Chrome.cs is the user interface.
|
||||
Three renderers (SpriteRenderer, LineRenderer, Rgba?Renderer) render most stuff. Don't forget to flush the renderer (if you want to see anything).
|
||||
Three renderers (SpriteRenderer, LineRenderer, Rgba?Renderer) render most stuff. Don't forget
|
||||
to flush the renderer (if you want to see anything).
|
||||
|
||||
UserSettings stores the data loaded from settings.ini (or defaults). Eventually we need to be able to save values changed in game into settings.ini (not yet implemented)
|
||||
UserSettings stores the data loaded from settings.ini (or defaults). Eventually we need to be
|
||||
able to save values changed in game into settings.ini (not yet implemented)
|
||||
|
||||
Bugs: There is a list of known bugs and features at http://openra.res0l.net/projects/openra/issues . There's also a few at http://github.com/chrisforbes/OpenRA/issues (which won't be ported over, but no more bugs should be added here).
|
||||
Bugs: There is a list of known bugs and features at http://bugs.open-ra.org/ .
|
||||
|
||||
We also have a website at http://www.open-ra.org/ .
|
||||
|
||||
As far as using git, get your own repository on github. You probably want to set up the gitbot to spam irc when you make commits (its nice to know). Push your changes into your git repository, and it will/might :P be merged into chrisforbes/OpenRA . Alli: setup howto for this?
|
||||
Our IRC channel is #openra on irc.freenode.net .
|
||||
|
||||
As far as using git, get your own repository on github. You probably want to set up the gitbot
|
||||
to spam irc when you make commits (its nice to know). Push your changes into your git
|
||||
repository, and it will/might :P be merged into http://github.com/OpenRA/OpenRA .
|
||||
See http://help.github.com/ for working with GitHub and see http://progit.org/ for working
|
||||
with Git.
|
||||
|
||||
|
||||
|
||||
Other things we probably want to put in here:
|
||||
- A guide on how to add a generic unit via yaml using existing traits
|
||||
@@ -50,6 +89,6 @@ Other things we probably want to put in here:
|
||||
- VFS (OpenRa.FileFormats.FileSystem, Package, Folder classes)
|
||||
- Trait inheritance (and the magicness of ^ActorType)
|
||||
- Removing inherited traits (prepend `-` to the trait name)
|
||||
- Multiple instances of a trait (`@` and all subsequent characters are ignored for the purposes
|
||||
of looking up the trait.
|
||||
- Multiple instances of a trait (`@` and all subsequent characters are ignored for
|
||||
the purposes of looking up the trait.
|
||||
|
||||
|
||||
120
INSTALL
120
INSTALL
@@ -1,44 +1,51 @@
|
||||
Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean,
|
||||
Paul Chote, Alli Witheford.
|
||||
|
||||
This file is part of OpenRA.
|
||||
Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
This file is part of OpenRA, which is free software. It is made
|
||||
available to you under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation. For more information,
|
||||
see LICENSE.
|
||||
|
||||
OpenRA is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
To run OpenRA, several files are needed from the original game disks.
|
||||
|
||||
OpenRA is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
The required files for the Red Alert mod are:
|
||||
EITHER:
|
||||
* conquer.mix
|
||||
* temperat.mix
|
||||
* interior.mix
|
||||
* snow.mix
|
||||
* sounds.mix
|
||||
* allies.mix
|
||||
* russian.mix
|
||||
OR:
|
||||
* main.mix
|
||||
AND:
|
||||
* redalert.mix
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
These need to be copied into the mods/ra/packages/ directory.
|
||||
|
||||
To compile OpenRA, open the OpenRA.sln solution in the main folder,
|
||||
or build it from the command-line with MSBuild.
|
||||
|
||||
To run OpenRA, several files from the original game’s install need
|
||||
to be copied to the root of the project directory. The required files are:
|
||||
The required files for the Command and Conquer mod are:
|
||||
* cclocal.mix
|
||||
* speech.mix
|
||||
* conquer.mix
|
||||
* sounds.mix
|
||||
* tempicnh.mix
|
||||
* temperat.mix
|
||||
* winter.mix
|
||||
* desert.mix
|
||||
|
||||
redalert.mix
|
||||
conquer.mix
|
||||
temperat.mix
|
||||
interior.mix
|
||||
snow.mix
|
||||
sounds.mix
|
||||
allies.mix
|
||||
russian.mix
|
||||
general.mix
|
||||
|
||||
hires1.mix
|
||||
expand2.mix
|
||||
These need to be copied into the mods/cnc/packages/ directory.
|
||||
If you have a case-sensitive filesystem you must change the filenames to
|
||||
lower case.
|
||||
|
||||
Red Alert has been released by EA Games as freeware so it shouldn’t
|
||||
be too hard to find a legal copy of the CD images. Unfortunately the
|
||||
installer is 16-bit and so won’t run on 64-bit operating systems. This
|
||||
can be worked around by using the Red Alert Setup Manager
|
||||
The files can be downloaded from:
|
||||
http://open-ra.org/get-dependency.php?file=ra-packages for the Red Alert files and
|
||||
http://open-ra.org/get-dependency.php?file=cnc-packages for the Command & Conquer files.
|
||||
|
||||
Alternatively:
|
||||
Red Alert and C&C have been released by EA Games as freeware. They can be
|
||||
downloaded from http://www.commandandconquer.com/classic
|
||||
Unfortunately the installer is 16-bit and so won’t run on 64-bit operating
|
||||
systems. This can be worked around by using the Red Alert Setup Manager
|
||||
(http://ra.afraid.org/html/downloads/utilities-3.html).
|
||||
Make sure you apply the no-CD protection fix so all the files needed
|
||||
are installed to the hard drive.
|
||||
@@ -46,12 +53,51 @@ are installed to the hard drive.
|
||||
Dependencies - Make sure you have these installed, or you'll
|
||||
have very strange errors.
|
||||
|
||||
|
||||
WINDOWS:
|
||||
|
||||
* .NET Framework >= 3.5-SP1
|
||||
(http://www.microsoft.com/downloads/details.aspx?FamilyID=AB99342F-5D1A-413D-8319-81DA479AB0D7&displaylang=en)
|
||||
* Tao Framework >= 2.1.0
|
||||
(http://sourceforge.net/projects/taoframework/)
|
||||
(required libs: Tao.OpenGL, Tao.Cg, Tao.Platform.Windows)
|
||||
This is now bundled with OpenRA, copy the files in thirdparty/Tao to the game root directory.
|
||||
* OpenAL >= 1.1
|
||||
(http://connect.creativelabs.com/openal/Downloads/oalinst.zip)
|
||||
* Cg Toolkit >= 2.2
|
||||
(http://developer.download.nvidia.com/cg/Cg_2.2/Cg-2.2_October2009_Setup.exe)
|
||||
(http://developer.download.nvidia.com/cg/Cg_2.2/Cg-2.2_October2009_Setup.exe)
|
||||
|
||||
To compile OpenRA, open the OpenRA.sln solution in the main folder,
|
||||
or build it from the command-line with MSBuild.
|
||||
|
||||
Run the game with `OpenRA.Game.exe Game.Mods=ra` for Red Alert
|
||||
or `OpenRA.Game.exe Game.Mods=cnc` for Command & Conquer
|
||||
|
||||
|
||||
UBUNTU (substitute comparable packages for other linux distros):
|
||||
|
||||
* mono-gmcs
|
||||
* freetype
|
||||
* libmono-corlib1.0-cil
|
||||
* libmono-winforms2.0-cil
|
||||
* libopenal1
|
||||
* libsdl1.2-dev
|
||||
* nvidia-cg-toolkit (download the latest version from
|
||||
http://developer.nvidia.com/object/cg_download.html)
|
||||
|
||||
OpenRA is incompatible with Compiz, please disable desktop effects when trying
|
||||
to run OpenRA or the game will crash.
|
||||
|
||||
You will need to copy the third party dependencies (.dll and .config) from the
|
||||
thirdparty and thirdparty/Tao directories into the game root, or install them permanently into
|
||||
your GAC with the following script
|
||||
|
||||
#!/bin/sh
|
||||
gacutil -i thirdparty/Tao/Tao.Cg.dll
|
||||
gacutil -i thirdparty/Tao/Tao.OpenGl.dll
|
||||
gacutil -i thirdparty/Tao/Tao.OpenAl.dll
|
||||
gacutil -i thirdparty/Tao/Tao.Sdl.dll
|
||||
gacutil -i thirdparty/Tao/Tao.FreeType.dll
|
||||
gacutil -i thirdparty/ICSharpCode.SharpZipLib.dll
|
||||
|
||||
To compile OpenRA, run `make' from the command line.
|
||||
Run the game with `mono OpenRA.Game.exe Game.Mods=ra` for Red Alert
|
||||
or `mono OpenRA.Game.exe Game.Mods=cnc` for Command & Conquer
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean,
|
||||
Paul Chote, Alli Witheford.
|
||||
|
||||
This file is part of OpenRA.
|
||||
|
||||
OpenRA is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenRA is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
To compile OpenRA, open the OpenRA.sln solution in the main folder,
|
||||
or build it from the command-line with MSBuild.
|
||||
|
||||
To run OpenRA, several files from the original game’s install need
|
||||
to be copied to the root of the project directory. The required files are:
|
||||
|
||||
redalert.mix
|
||||
conquer.mix
|
||||
temperat.mix
|
||||
interior.mix
|
||||
snow.mix
|
||||
sounds.mix
|
||||
allies.mix
|
||||
russian.mix
|
||||
general.mix
|
||||
|
||||
hires1.mix
|
||||
expand2.mix
|
||||
|
||||
Red Alert has been released by EA Games as freeware so it shouldn’t
|
||||
be too hard to find a legal copy of the CD images. Unfortunately the
|
||||
installer is 16-bit and so won’t run on 64-bit operating systems. This
|
||||
can be worked around by using the Red Alert Setup Manager
|
||||
(http://ra.afraid.org/html/downloads/utilities-3.html).
|
||||
Make sure you apply the no-CD protection fix so all the files needed
|
||||
are installed to the hard drive.
|
||||
|
||||
Dependencies - Make sure you have these installed, or you'll
|
||||
have very strange errors.
|
||||
|
||||
* mono-gmcs
|
||||
* libglfw2
|
||||
* nvidia-cg-toolkit
|
||||
* libmono-*
|
||||
350
Makefile
350
Makefile
@@ -1,7 +1,191 @@
|
||||
CSC = gmcs
|
||||
CSFLAGS = -nologo -warn:4 -debug:+ -debug:full -optimize- -codepage:utf8 -unsafe
|
||||
DEFINE = DEBUG;TRACE
|
||||
PROGRAMS =fileformats gl game ra cnc seqed editor ralint filex tsbuild
|
||||
CSC = gmcs
|
||||
CSFLAGS = -nologo -warn:4 -debug:+ -debug:full -optimize- -codepage:utf8 -unsafe
|
||||
DEFINE = DEBUG;TRACE
|
||||
COMMON_LIBS = System.dll System.Core.dll System.Drawing.dll System.Xml.dll thirdparty/ICSharpCode.SharpZipLib.dll
|
||||
PHONY = core tools package all mods clean distclean
|
||||
|
||||
.SUFFIXES:
|
||||
core: game renderers mod_ra mod_cnc
|
||||
tools: editor ralint seqed filex tsbuild utility
|
||||
package: fixheader core editor utility
|
||||
mods: mod_ra mod_cnc
|
||||
all: core tools
|
||||
clean:
|
||||
@-rm *.exe *.dll *.mdb mods/**/*.dll mods/**/*.mdb *.resources
|
||||
distclean: clean
|
||||
|
||||
#
|
||||
# Core binaries
|
||||
#
|
||||
fileformats_SRCS = $(shell find OpenRA.FileFormats/ -iname '*.cs')
|
||||
fileformats_TARGET = OpenRA.FileFormats.dll
|
||||
#fileformats_DEPS = fixheader
|
||||
fileformats_KIND = library
|
||||
fileformats_LIBS = $(COMMON_LIBS) thirdparty/Tao/Tao.Sdl.dll System.Windows.Forms.dll
|
||||
PROGRAMS = fileformats
|
||||
fileformats: $(fileformats_TARGET)
|
||||
|
||||
game_SRCS = $(shell find OpenRA.Game/ -iname '*.cs')
|
||||
game_TARGET = OpenRA.Game.exe
|
||||
game_KIND = winexe
|
||||
game_DEPS = $(fileformats_TARGET)
|
||||
game_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll $(game_DEPS) \
|
||||
thirdparty/Tao/Tao.OpenAl.dll thirdparty/Tao/Tao.FreeType.dll
|
||||
game_FLAGS = -win32icon:OpenRA.Game/OpenRA.ico
|
||||
PROGRAMS += game
|
||||
game: $(game_TARGET)
|
||||
|
||||
#
|
||||
# Renderer dlls
|
||||
#
|
||||
rcg_SRCS = $(shell find OpenRA.Renderer.Cg/ -iname '*.cs')
|
||||
rcg_TARGET = OpenRA.Renderer.Cg.dll
|
||||
rcg_KIND = library
|
||||
rcg_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
||||
rcg_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll \
|
||||
thirdparty/Tao/Tao.Cg.dll thirdparty/Tao/Tao.OpenGl.dll thirdparty/Tao/Tao.Sdl.dll \
|
||||
$(rcg_DEPS) $(game_TARGET)
|
||||
|
||||
rgl_SRCS = $(shell find OpenRA.Renderer.Gl/ -iname '*.cs')
|
||||
rgl_TARGET = OpenRA.Renderer.Gl.dll
|
||||
rgl_KIND = library
|
||||
rgl_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
||||
rgl_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll \
|
||||
thirdparty/Tao/Tao.Cg.dll thirdparty/Tao/Tao.OpenGl.dll thirdparty/Tao/Tao.Sdl.dll \
|
||||
$(rgl_DEPS) $(game_TARGET)
|
||||
|
||||
rnull_SRCS = $(shell find OpenRA.Renderer.Null/ -iname '*.cs')
|
||||
rnull_TARGET = OpenRA.Renderer.Null.dll
|
||||
rnull_KIND = library
|
||||
rnull_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
||||
rnull_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll \
|
||||
$(rnull_DEPS) $(game_TARGET)
|
||||
PROGRAMS += rcg rgl rnull
|
||||
renderers: $(rcg_TARGET) $(rgl_TARGET) $(rnull_TARGET)
|
||||
|
||||
#
|
||||
# Official Mods
|
||||
#
|
||||
# Red Alert
|
||||
mod_ra_SRCS = $(shell find OpenRA.Mods.RA/ -iname '*.cs')
|
||||
mod_ra_TARGET = mods/ra/OpenRA.Mods.RA.dll
|
||||
mod_ra_KIND = library
|
||||
mod_ra_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
||||
mod_ra_LIBS = $(COMMON_LIBS) $(mod_ra_DEPS)
|
||||
PROGRAMS += mod_ra
|
||||
mod_ra: $(mod_ra_TARGET)
|
||||
# mono RALint.exe ra
|
||||
|
||||
# Command and Conquer
|
||||
mod_cnc_SRCS = $(shell find OpenRA.Mods.Cnc/ -iname '*.cs')
|
||||
mod_cnc_TARGET = mods/cnc/OpenRA.Mods.Cnc.dll
|
||||
mod_cnc_KIND = library
|
||||
mod_cnc_DEPS = $(fileformats_TARGET) $(game_TARGET) $(mod_ra_TARGET)
|
||||
mod_cnc_LIBS = $(COMMON_LIBS) $(mod_cnc_DEPS)
|
||||
PROGRAMS += mod_cnc
|
||||
mod_cnc: $(mod_cnc_TARGET)
|
||||
# mono RALint.exe cnc
|
||||
|
||||
#
|
||||
# Tools
|
||||
#
|
||||
# Sequence editor (defunct)
|
||||
seqed_SRCS = $(shell find SequenceEditor/ -iname '*.cs')
|
||||
seqed_TARGET = SequenceEditor.exe
|
||||
seqed_KIND = winexe
|
||||
seqed_DEPS = $(fileformats_TARGET)
|
||||
seqed_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll $(seqed_DEPS)
|
||||
seqed_EXTRA = -resource:SequenceEditor.Form1.resources
|
||||
PROGRAMS += seqed
|
||||
SequenceEditor.Form1.resources:
|
||||
resgen2 SequenceEditor/Form1.resx SequenceEditor.Form1.resources 1> /dev/null
|
||||
seqed: SequenceEditor.Form1.resources $(seqed_TARGET)
|
||||
|
||||
# Map Editor
|
||||
editor_SRCS = $(shell find OpenRA.Editor/ -iname '*.cs')
|
||||
editor_TARGET = OpenRA.Editor.exe
|
||||
editor_KIND = winexe
|
||||
editor_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
||||
editor_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll System.Data.dll $(editor_DEPS)
|
||||
editor_EXTRA = -resource:OpenRA.Editor.Form1.resources -resource:OpenRA.Editor.MapSelect.resources
|
||||
PROGRAMS += editor
|
||||
OpenRA.Editor.MapSelect.resources:
|
||||
resgen2 OpenRA.Editor/MapSelect.resx OpenRA.Editor.MapSelect.resources 1> /dev/null
|
||||
OpenRA.Editor.Form1.resources:
|
||||
resgen2 OpenRA.Editor/Form1.resx OpenRA.Editor.Form1.resources 1> /dev/null
|
||||
editor: OpenRA.Editor.MapSelect.resources OpenRA.Editor.Form1.resources $(editor_TARGET)
|
||||
|
||||
# Analyses mod yaml for easy to detect errors
|
||||
ralint_SRCS = $(shell find RALint/ -iname '*.cs')
|
||||
ralint_TARGET = RALint.exe
|
||||
ralint_KIND = exe
|
||||
ralint_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
||||
ralint_LIBS = $(COMMON_LIBS) $(ralint_DEPS)
|
||||
PROGRAMS += ralint
|
||||
ralint: $(ralint_TARGET)
|
||||
|
||||
# Extracts files from packages (mixfiles, zips, etc)
|
||||
filex_SRCS = $(shell find FileExtractor/ -iname '*.cs')
|
||||
filex_TARGET = FileExtractor.exe
|
||||
filex_KIND = exe
|
||||
filex_DEPS = $(fileformats_TARGET)
|
||||
filex_LIBS = $(COMMON_LIBS) $(filex_DEPS)
|
||||
PROGRAMS += filex
|
||||
filex: $(filex_TARGET)
|
||||
|
||||
# Builds and exports tilesets from a bitmap
|
||||
tsbuild_SRCS = $(shell find OpenRA.TilesetBuilder/ -iname '*.cs')
|
||||
tsbuild_TARGET = TilesetBuilder.exe
|
||||
tsbuild_KIND = winexe
|
||||
tsbuild_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
||||
tsbuild_LIBS = $(COMMON_LIBS) $(tsbuild_DEPS) System.Windows.Forms.dll
|
||||
tsbuild_EXTRA = -resource:OpenRA.TilesetBuilder.Form1.resources
|
||||
PROGRAMS += tsbuild
|
||||
OpenRA.TilesetBuilder.Form1.resources:
|
||||
resgen2 OpenRA.TilesetBuilder/Form1.resx OpenRA.TilesetBuilder.Form1.resources 1> /dev/null
|
||||
tsbuild: OpenRA.TilesetBuilder.Form1.resources $(tsbuild_TARGET)
|
||||
|
||||
#
|
||||
# Launchers / Utilities
|
||||
#
|
||||
# Patches binary headers to work around a mono bug
|
||||
fixheader: packaging/fixheader.cs
|
||||
@$(CSC) packaging/fixheader.cs $(CSFLAGS) -out:fixheader.exe -t:exe $(COMMON_LIBS:%=-r:%)
|
||||
PHONY += fixheader
|
||||
|
||||
# Backend for the launcher apps - queries game/mod info and applies actions to an install
|
||||
utility_SRCS = $(shell find OpenRA.Utility/ -iname '*.cs')
|
||||
utility_TARGET = OpenRA.Utility.exe
|
||||
utility_KIND = exe
|
||||
utility_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
||||
utility_LIBS = $(COMMON_LIBS) $(utility_DEPS) thirdparty/ICSharpCode.SharpZipLib.dll System.Windows.Forms.dll
|
||||
PROGRAMS += utility
|
||||
utility: $(utility_TARGET)
|
||||
|
||||
.PHONY: $(PHONY) $(PROGRAMS)
|
||||
|
||||
#
|
||||
# Generate build rules for each target defined above in PROGRAMS
|
||||
#
|
||||
define BUILD_ASSEMBLY
|
||||
|
||||
$$($(1)_TARGET): $$($(1)_SRCS) Makefile $$($(1)_DEPS)
|
||||
@echo CSC $$(@)
|
||||
@$(CSC) $$($(1)_LIBS:%=-r:%) \
|
||||
-out:$$(@) $(CSFLAGS) $$($(1)_FLAGS) \
|
||||
-define:"$(DEFINE)" \
|
||||
-t:"$$($(1)_KIND)" \
|
||||
$$($(1)_EXTRA) \
|
||||
$$($(1)_SRCS)
|
||||
@test -e fixheader.exe && mono fixheader.exe $$(@) || ``
|
||||
endef
|
||||
|
||||
$(foreach prog,$(PROGRAMS),$(eval $(call BUILD_ASSEMBLY,$(prog))))
|
||||
|
||||
|
||||
#
|
||||
# Install / Uninstall for *nix
|
||||
#
|
||||
prefix = /usr/local
|
||||
datarootdir = $(prefix)/share
|
||||
datadir = $(datarootdir)
|
||||
@@ -10,165 +194,47 @@ BIN_INSTALL_DIR = $(DESTDIR)$(bindir)
|
||||
INSTALL_DIR = $(DESTDIR)$(datadir)/openra
|
||||
INSTALL = install
|
||||
INSTALL_PROGRAM = $(INSTALL)
|
||||
|
||||
COMMON_LIBS = System.dll System.Core.dll System.Drawing.dll System.Xml.dll
|
||||
|
||||
fileformats_SRCS = $(shell find OpenRA.FileFormats/ -iname '*.cs')
|
||||
fileformats_TARGET = OpenRA.FileFormats.dll
|
||||
fileformats_KIND = library
|
||||
fileformats_LIBS = $(COMMON_LIBS) thirdparty/Tao/Tao.Sdl.dll thirdparty/WindowsBase.dll
|
||||
|
||||
gl_SRCS = $(shell find OpenRA.Gl/ -iname '*.cs')
|
||||
gl_TARGET = OpenRA.Gl.dll
|
||||
gl_KIND = library
|
||||
gl_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
||||
gl_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll \
|
||||
thirdparty/Tao/Tao.Cg.dll thirdparty/Tao/Tao.OpenGl.dll thirdparty/Tao/Tao.Sdl.dll \
|
||||
$(gl_DEPS) $(game_TARGET)
|
||||
|
||||
game_SRCS = $(shell find OpenRA.Game/ -iname '*.cs')
|
||||
game_TARGET = OpenRA.Game.exe
|
||||
game_KIND = winexe
|
||||
game_DEPS = $(fileformats_TARGET)
|
||||
game_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll $(game_DEPS) \
|
||||
thirdparty/Tao/Tao.OpenAl.dll thirdparty/Tao/Tao.FreeType.dll
|
||||
game_FLAGS = -win32icon:OpenRA.Game/OpenRA.ico
|
||||
|
||||
ra_SRCS = $(shell find OpenRA.Mods.RA/ -iname '*.cs')
|
||||
ra_TARGET = mods/ra/OpenRA.Mods.RA.dll
|
||||
ra_KIND = library
|
||||
ra_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
||||
ra_LIBS = $(COMMON_LIBS) $(ra_DEPS)
|
||||
|
||||
cnc_SRCS = $(shell find OpenRA.Mods.Cnc/ -iname '*.cs')
|
||||
cnc_TARGET = mods/cnc/OpenRA.Mods.Cnc.dll
|
||||
cnc_KIND = library
|
||||
cnc_DEPS = $(fileformats_TARGET) $(game_TARGET) $(ra_TARGET)
|
||||
cnc_LIBS = $(COMMON_LIBS) $(cnc_DEPS)
|
||||
|
||||
seqed_SRCS = $(shell find SequenceEditor/ -iname '*.cs')
|
||||
seqed_TARGET = SequenceEditor.exe
|
||||
seqed_KIND = winexe
|
||||
seqed_DEPS = $(fileformats_TARGET)
|
||||
seqed_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll $(seqed_DEPS)
|
||||
seqed_EXTRA = -resource:SequenceEditor.Form1.resources
|
||||
|
||||
editor_SRCS = $(shell find OpenRA.Editor/ -iname '*.cs')
|
||||
editor_TARGET = OpenRA.Editor.exe
|
||||
editor_KIND = winexe
|
||||
editor_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
||||
editor_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll System.Data.dll $(editor_DEPS)
|
||||
editor_EXTRA = -resource:OpenRA.Editor.Form1.resources
|
||||
|
||||
ralint_SRCS = $(shell find RALint/ -iname '*.cs')
|
||||
ralint_TARGET = RALint.exe
|
||||
ralint_KIND = winexe
|
||||
ralint_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
||||
ralint_LIBS = $(COMMON_LIBS) $(ralint_DEPS)
|
||||
|
||||
filex_SRCS = $(shell find FileExtractor/ -iname '*.cs')
|
||||
filex_TARGET = FileExtractor.exe
|
||||
filex_KIND = winexe
|
||||
filex_DEPS = $(fileformats_TARGET)
|
||||
filex_LIBS = $(COMMON_LIBS) $(filex_DEPS)
|
||||
|
||||
tsbuild_SRCS = $(shell find OpenRA.TilesetBuilder/ -iname '*.cs')
|
||||
tsbuild_TARGET = TilesetBuilder.exe
|
||||
tsbuild_KIND = winexe
|
||||
tsbuild_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
||||
tsbuild_LIBS = $(COMMON_LIBS) $(tsbuild_DEPS) System.Windows.Forms.dll
|
||||
tsbuild_EXTRA = -resource:OpenRA.TilesetBuilder.Form1.resources
|
||||
|
||||
# -platform:x86
|
||||
|
||||
.SUFFIXES:
|
||||
.PHONY: clean all game tool default mods mod_ra mod_cnc install uninstall editor_res editor tsbuild ralint seqed filex
|
||||
|
||||
game: $(fileformats_TARGET) $(gl_TARGET) $(game_TARGET) $(ra_TARGET) $(cnc_TARGET)
|
||||
|
||||
clean:
|
||||
@-rm *.exe *.dll *.mdb mods/**/*.dll mods/**/*.mdb *.resources
|
||||
|
||||
distclean: clean
|
||||
|
||||
CORE = fileformats gl game seqed
|
||||
CORE = fileformats rcg rgl rnull game editor utility
|
||||
|
||||
install: all
|
||||
@-echo "Installing OpenRA to $(INSTALL_DIR)"
|
||||
@$(INSTALL_PROGRAM) -d $(INSTALL_DIR)
|
||||
@$(INSTALL_PROGRAM) $(foreach prog,$(CORE),$($(prog)_TARGET)) $(INSTALL_DIR)
|
||||
|
||||
@$(INSTALL_PROGRAM) -d $(INSTALL_DIR)/mods/cnc
|
||||
@$(INSTALL_PROGRAM) $(cnc_TARGET) $(INSTALL_DIR)/mods/cnc
|
||||
@$(INSTALL_PROGRAM) $(mod_cnc_TARGET) $(INSTALL_DIR)/mods/cnc
|
||||
|
||||
@-cp $(foreach f,$(shell ls mods/cnc --hide=*.dll),mods/cnc/$(f)) $(INSTALL_DIR)/mods/cnc
|
||||
@cp -r mods/cnc/maps $(INSTALL_DIR)/mods/cnc
|
||||
@cp -r mods/cnc/chrome $(INSTALL_DIR)/mods/cnc
|
||||
|
||||
@cp -r mods/cnc/bits $(INSTALL_DIR)/mods/cnc
|
||||
@cp -r mods/cnc/rules $(INSTALL_DIR)/mods/cnc
|
||||
@cp -r mods/cnc/sequences $(INSTALL_DIR)/mods/cnc
|
||||
@cp -r mods/cnc/tilesets $(INSTALL_DIR)/mods/cnc
|
||||
@cp -r mods/cnc/uibits $(INSTALL_DIR)/mods/cnc
|
||||
@$(INSTALL_PROGRAM) -d $(INSTALL_DIR)/mods/ra
|
||||
@$(INSTALL_PROGRAM) $(ra_TARGET) $(INSTALL_DIR)/mods/ra
|
||||
@$(INSTALL_PROGRAM) $(mod_ra_TARGET) $(INSTALL_DIR)/mods/ra
|
||||
|
||||
@-cp $(foreach f,$(shell ls mods/ra --hide=*.dll),mods/ra/$(f)) $(INSTALL_DIR)/mods/ra
|
||||
@cp -r mods/ra/maps $(INSTALL_DIR)/mods/ra
|
||||
@cp -r mods/ra/extras $(INSTALL_DIR)/mods/ra
|
||||
@cp -r mods/ra/bits $(INSTALL_DIR)/mods/ra
|
||||
@cp -r mods/ra/chrome $(INSTALL_DIR)/mods/ra
|
||||
|
||||
@cp -r shaders $(INSTALL_DIR)
|
||||
@cp -r mods/ra/rules $(INSTALL_DIR)/mods/ra
|
||||
@cp -r mods/ra/tilesets $(INSTALL_DIR)/mods/ra
|
||||
@cp -r mods/ra/uibits $(INSTALL_DIR)/mods/ra
|
||||
|
||||
@cp -r glsl $(INSTALL_DIR)
|
||||
@cp -r cg $(INSTALL_DIR)
|
||||
@cp *.ttf $(INSTALL_DIR)
|
||||
@cp --parents -r thirdparty/Tao $(INSTALL_DIR)
|
||||
@$(INSTALL_PROGRAM) thirdparty/WindowsBase.dll $(INSTALL_DIR)
|
||||
|
||||
@$(INSTALL_PROGRAM) thirdparty/ICSharpCode.SharpZipLib.dll $(INSTALL_DIR)
|
||||
|
||||
@echo "#!/bin/sh" > openra
|
||||
@echo "cd "$(datadir)"/openra" >> openra
|
||||
@echo "mono "$(datadir)"/openra/OpenRA.Game.exe SupportDir=~/.openra \"$$""@\"" >> openra
|
||||
|
||||
@$(INSTALL_PROGRAM) -d $(BIN_INSTALL_DIR)
|
||||
@$(INSTALL_PROGRAM) -m +rx openra $(BIN_INSTALL_DIR)
|
||||
|
||||
@echo "OpenRA is now installed. You will now want to download"
|
||||
@echo "http://open-ra.org/packages/ra-packages.zip and"
|
||||
@echo "http://open-ra.org/packages/cnc-packages.zip"
|
||||
@echo "and extract their contents to"
|
||||
@echo "$(INSTALL_DIR)/mods/ra/packages and "
|
||||
@echo "$(INSTALL_DIR)/mods/cnc/packages respectively."
|
||||
@echo "It is also advised to install the contents of $(INSTALL_DIR)/thirdparty to the Mono Global Assembly Cache \
|
||||
with gacutil."
|
||||
|
||||
uninstall:
|
||||
@-rm -r $(INSTALL_DIR)
|
||||
@-rm $(DESTDIR)$(bindir)/openra
|
||||
|
||||
mod_ra: $(ra_TARGET) $(ralint_TARGET)
|
||||
mono RALint.exe ra
|
||||
mod_cnc: $(cnc_TARGET) $(ralint_TARGET)
|
||||
mono RALint.exe cnc
|
||||
mods: mod_ra mod_cnc
|
||||
|
||||
OpenRA.Editor.Form1.resources:
|
||||
resgen2 OpenRA.Editor/Form1.resx OpenRA.Editor.Form1.resources 1> /dev/null
|
||||
editor: OpenRA.Editor.Form1.resources $(editor_TARGET)
|
||||
ralint: $(ralint_TARGET)
|
||||
seqed: SequenceEditor.Form1.resources $(seqed_TARGET)
|
||||
SequenceEditor.Form1.resources:
|
||||
resgen2 SequenceEditor/Form1.resx SequenceEditor.Form1.resources 1> /dev/null
|
||||
filex: $(filex_TARGET)
|
||||
tsbuild: OpenRA.TilesetBuilder.Form1.resources $(tsbuild_TARGET)
|
||||
OpenRA.TilesetBuilder.Form1.resources:
|
||||
resgen2 OpenRA.TilesetBuilder/Form1.resx OpenRA.TilesetBuilder.Form1.resources 1> /dev/null
|
||||
tools: editor ralint seqed filex tsbuild
|
||||
all: game tools
|
||||
|
||||
fixheader: packaging/fixheader.cs
|
||||
@$(CSC) packaging/fixheader.cs $(CSFLAGS) -out:fixheader.exe -t:exe $(COMMON_LIBS:%=-r:%)
|
||||
|
||||
define BUILD_ASSEMBLY
|
||||
|
||||
$$($(1)_TARGET): $$($(1)_SRCS) Makefile $$($(1)_DEPS) fixheader
|
||||
@echo CSC $$(@)
|
||||
@$(CSC) $$($(1)_LIBS:%=-r:%) \
|
||||
-out:$$(@) $(CSFLAGS) $$($(1)_FLAGS) \
|
||||
-define:"$(DEFINE)" \
|
||||
-t:"$$($(1)_KIND)" \
|
||||
$$($(1)_EXTRA) \
|
||||
$$($(1)_SRCS)
|
||||
@mono fixheader.exe $$(@)
|
||||
endef
|
||||
|
||||
$(foreach prog,$(PROGRAMS),$(eval $(call BUILD_ASSEMBLY,$(prog))))
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace OpenRA.Editor
|
||||
{
|
||||
public Bitmap Bitmap;
|
||||
public ActorInfo Info;
|
||||
public bool Centered;
|
||||
public EditorAppearanceInfo Appearance;
|
||||
}
|
||||
|
||||
class BrushTemplate
|
||||
|
||||
55
OpenRA.Editor/ActorTool.cs
Normal file
55
OpenRA.Editor/ActorTool.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
using SGraphics = System.Drawing.Graphics;
|
||||
|
||||
namespace OpenRA.Editor
|
||||
{
|
||||
class ActorTool : ITool
|
||||
{
|
||||
ActorTemplate Actor;
|
||||
public ActorTool(ActorTemplate actor) { this.Actor = actor; }
|
||||
|
||||
public void Preview(Surface surface, SGraphics g)
|
||||
{
|
||||
/* todo: include the player
|
||||
* in the brush so we can color new buildings too */
|
||||
|
||||
surface.DrawActor(g, surface.GetBrushLocation(), Actor, null);
|
||||
}
|
||||
|
||||
public void Apply(Surface surface)
|
||||
{
|
||||
if (surface.Map.Actors.Any(a => a.Value.Location() == surface.GetBrushLocation()))
|
||||
return;
|
||||
|
||||
var owner = "Neutral";
|
||||
var id = NextActorName(surface);
|
||||
surface.Map.Actors[id] = new ActorReference(Actor.Info.Name.ToLowerInvariant())
|
||||
{
|
||||
new LocationInit( surface.GetBrushLocation() ),
|
||||
new OwnerInit( owner)
|
||||
};
|
||||
}
|
||||
|
||||
string NextActorName(Surface surface)
|
||||
{
|
||||
var id = 0;
|
||||
for (; ; )
|
||||
{
|
||||
var possible = "Actor{0}".F(id++);
|
||||
if (!surface.Map.Actors.ContainsKey(possible)) return possible;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
124
OpenRA.Editor/BrushTool.cs
Normal file
124
OpenRA.Editor/BrushTool.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Forms;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
using SGraphics = System.Drawing.Graphics;
|
||||
|
||||
namespace OpenRA.Editor
|
||||
{
|
||||
class BrushTool : ITool
|
||||
{
|
||||
BrushTemplate Brush;
|
||||
|
||||
public BrushTool(BrushTemplate brush) { this.Brush = brush; }
|
||||
|
||||
public void Apply(Surface surface)
|
||||
{
|
||||
// change the bits in the map
|
||||
var tile = surface.TileSet.Tiles[Brush.N];
|
||||
var template = surface.TileSet.Templates[Brush.N];
|
||||
var pos = surface.GetBrushLocation();
|
||||
|
||||
if (surface.GetModifiers() == Keys.Shift)
|
||||
{
|
||||
FloodFillWithBrush(surface, pos);
|
||||
return;
|
||||
}
|
||||
|
||||
for (var u = 0; u < template.Size.X; u++)
|
||||
for (var v = 0; v < template.Size.Y; v++)
|
||||
{
|
||||
if (surface.Map.IsInMap(new int2(u, v) + pos))
|
||||
{
|
||||
var z = u + v * template.Size.X;
|
||||
if (tile.TileBitmapBytes[z] != null)
|
||||
surface.Map.MapTiles[u + pos.X, v + pos.Y] =
|
||||
new TileReference<ushort, byte>
|
||||
{
|
||||
type = Brush.N,
|
||||
index = template.PickAny ? byte.MaxValue : (byte)z,
|
||||
image = template.PickAny ? (byte)((u + pos.X) % 4 + ((v + pos.Y) % 4) * 4) : (byte)z,
|
||||
};
|
||||
|
||||
var ch = new int2((pos.X + u) / Surface.ChunkSize, (pos.Y + v) / Surface.ChunkSize);
|
||||
if (surface.Chunks.ContainsKey(ch))
|
||||
{
|
||||
surface.Chunks[ch].Dispose();
|
||||
surface.Chunks.Remove(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Preview(Surface surface, SGraphics g)
|
||||
{
|
||||
g.DrawImage(Brush.Bitmap,
|
||||
surface.TileSet.TileSize * surface.GetBrushLocation().X * surface.Zoom + surface.GetOffset().X,
|
||||
surface.TileSet.TileSize * surface.GetBrushLocation().Y * surface.Zoom + surface.GetOffset().Y,
|
||||
Brush.Bitmap.Width * surface.Zoom,
|
||||
Brush.Bitmap.Height * surface.Zoom);
|
||||
}
|
||||
|
||||
void FloodFillWithBrush(Surface s, int2 pos)
|
||||
{
|
||||
var queue = new Queue<int2>();
|
||||
var replace = s.Map.MapTiles[pos.X, pos.Y];
|
||||
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])
|
||||
{
|
||||
queue.Enqueue(new int2(x, y));
|
||||
touched[x, y] = true;
|
||||
}
|
||||
};
|
||||
|
||||
queue.Enqueue(pos);
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
var p = queue.Dequeue();
|
||||
if (!s.Map.MapTiles[p.X, p.Y].Equals(replace))
|
||||
continue;
|
||||
|
||||
var a = FindEdge(s, p, new int2(-1, 0), replace);
|
||||
var b = FindEdge(s, p, new int2(1, 0), replace);
|
||||
|
||||
for (var x = a.X; x <= b.X; x++)
|
||||
{
|
||||
s.Map.MapTiles[x, p.Y] = new TileReference<ushort, byte> { type = Brush.N, image = (byte)0, index = (byte)0 };
|
||||
if (s.Map.MapTiles[x, p.Y - 1].Equals(replace))
|
||||
MaybeEnqueue(x, p.Y - 1);
|
||||
if (s.Map.MapTiles[x, p.Y + 1].Equals(replace))
|
||||
MaybeEnqueue(x, p.Y + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* todo: optimize */
|
||||
foreach (var ch in s.Chunks.Values) ch.Dispose();
|
||||
s.Chunks.Clear();
|
||||
}
|
||||
|
||||
int2 FindEdge(Surface s, int2 p, int2 d, TileReference<ushort, byte> replace)
|
||||
{
|
||||
for (; ; )
|
||||
{
|
||||
var q = p + d;
|
||||
if (!s.Map.IsInMap(q)) return p;
|
||||
if (!s.Map.MapTiles[q.X, q.Y].Equals(replace)) return p;
|
||||
p = q;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
316
OpenRA.Editor/Form1.Designer.cs
generated
Normal file → Executable file
316
OpenRA.Editor/Form1.Designer.cs
generated
Normal file → Executable file
@@ -30,8 +30,9 @@
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
|
||||
this.toolStripContainer1 = new System.Windows.Forms.ToolStripContainer();
|
||||
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
|
||||
this.splitContainer2 = new System.Windows.Forms.SplitContainer();
|
||||
this.pmMiniMap = new System.Windows.Forms.PictureBox();
|
||||
this.tabControl1 = new System.Windows.Forms.TabControl();
|
||||
this.tabPage1 = new System.Windows.Forms.TabPage();
|
||||
this.tilePalette = new System.Windows.Forms.FlowLayoutPanel();
|
||||
@@ -39,6 +40,10 @@
|
||||
this.actorPalette = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.tabPage3 = new System.Windows.Forms.TabPage();
|
||||
this.resourcePalette = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.surface1 = new OpenRA.Editor.Surface();
|
||||
this.tt = new System.Windows.Forms.ToolTip(this.components);
|
||||
this.saveFileDialog = new System.Windows.Forms.SaveFileDialog();
|
||||
this.splitContainer3 = new System.Windows.Forms.SplitContainer();
|
||||
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
|
||||
this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.newToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
@@ -50,47 +55,40 @@
|
||||
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.cCRedAlertMapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.bitmapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuExport = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuMinimapToPNG = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.exotToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.propertiesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.resizeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.spawnpointsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.tt = new System.Windows.Forms.ToolTip(this.components);
|
||||
this.folderBrowser = new System.Windows.Forms.FolderBrowserDialog();
|
||||
this.surface1 = new OpenRA.Editor.Surface();
|
||||
this.toolStripContainer1.ContentPanel.SuspendLayout();
|
||||
this.toolStripContainer1.TopToolStripPanel.SuspendLayout();
|
||||
this.toolStripContainer1.SuspendLayout();
|
||||
this.toolsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.layersFloaterToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripComboBox1 = new System.Windows.Forms.ToolStripComboBox();
|
||||
this.toolStripLabel1 = new System.Windows.Forms.ToolStripLabel();
|
||||
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
|
||||
this.toolStripStatusLabelFiller = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.toolStripStatusLabelMousePosition = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.splitContainer1.Panel1.SuspendLayout();
|
||||
this.splitContainer1.Panel2.SuspendLayout();
|
||||
this.splitContainer1.SuspendLayout();
|
||||
this.splitContainer2.Panel1.SuspendLayout();
|
||||
this.splitContainer2.Panel2.SuspendLayout();
|
||||
this.splitContainer2.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pmMiniMap)).BeginInit();
|
||||
this.tabControl1.SuspendLayout();
|
||||
this.tabPage1.SuspendLayout();
|
||||
this.tabPage2.SuspendLayout();
|
||||
this.tabPage3.SuspendLayout();
|
||||
this.splitContainer3.Panel1.SuspendLayout();
|
||||
this.splitContainer3.Panel2.SuspendLayout();
|
||||
this.splitContainer3.SuspendLayout();
|
||||
this.menuStrip1.SuspendLayout();
|
||||
this.statusStrip1.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// toolStripContainer1
|
||||
//
|
||||
//
|
||||
// toolStripContainer1.ContentPanel
|
||||
//
|
||||
this.toolStripContainer1.ContentPanel.Controls.Add(this.splitContainer1);
|
||||
this.toolStripContainer1.ContentPanel.Size = new System.Drawing.Size(985, 681);
|
||||
this.toolStripContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.toolStripContainer1.Location = new System.Drawing.Point(0, 0);
|
||||
this.toolStripContainer1.Name = "toolStripContainer1";
|
||||
this.toolStripContainer1.Size = new System.Drawing.Size(985, 705);
|
||||
this.toolStripContainer1.TabIndex = 1;
|
||||
this.toolStripContainer1.Text = "toolStripContainer1";
|
||||
//
|
||||
// toolStripContainer1.TopToolStripPanel
|
||||
//
|
||||
this.toolStripContainer1.TopToolStripPanel.Controls.Add(this.menuStrip1);
|
||||
//
|
||||
// splitContainer1
|
||||
//
|
||||
this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
@@ -99,15 +97,45 @@
|
||||
//
|
||||
// splitContainer1.Panel1
|
||||
//
|
||||
this.splitContainer1.Panel1.Controls.Add(this.tabControl1);
|
||||
this.splitContainer1.Panel1.Controls.Add(this.splitContainer2);
|
||||
//
|
||||
// splitContainer1.Panel2
|
||||
//
|
||||
this.splitContainer1.Panel2.Controls.Add(this.surface1);
|
||||
this.splitContainer1.Size = new System.Drawing.Size(985, 681);
|
||||
this.splitContainer1.Size = new System.Drawing.Size(985, 744);
|
||||
this.splitContainer1.SplitterDistance = 198;
|
||||
this.splitContainer1.TabIndex = 0;
|
||||
//
|
||||
// splitContainer2
|
||||
//
|
||||
this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.splitContainer2.Location = new System.Drawing.Point(0, 0);
|
||||
this.splitContainer2.Name = "splitContainer2";
|
||||
this.splitContainer2.Orientation = System.Windows.Forms.Orientation.Horizontal;
|
||||
//
|
||||
// splitContainer2.Panel1
|
||||
//
|
||||
this.splitContainer2.Panel1.Controls.Add(this.pmMiniMap);
|
||||
//
|
||||
// splitContainer2.Panel2
|
||||
//
|
||||
this.splitContainer2.Panel2.Controls.Add(this.tabControl1);
|
||||
this.splitContainer2.Size = new System.Drawing.Size(198, 744);
|
||||
this.splitContainer2.SplitterDistance = 164;
|
||||
this.splitContainer2.TabIndex = 1;
|
||||
//
|
||||
// pmMiniMap
|
||||
//
|
||||
this.pmMiniMap.BackColor = System.Drawing.Color.Black;
|
||||
this.pmMiniMap.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
|
||||
this.pmMiniMap.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.pmMiniMap.Location = new System.Drawing.Point(0, 0);
|
||||
this.pmMiniMap.Name = "pmMiniMap";
|
||||
this.pmMiniMap.Size = new System.Drawing.Size(198, 164);
|
||||
this.pmMiniMap.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
|
||||
this.pmMiniMap.TabIndex = 1;
|
||||
this.pmMiniMap.TabStop = false;
|
||||
//
|
||||
// tabControl1
|
||||
//
|
||||
this.tabControl1.Controls.Add(this.tabPage1);
|
||||
@@ -115,19 +143,21 @@
|
||||
this.tabControl1.Controls.Add(this.tabPage3);
|
||||
this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tabControl1.Location = new System.Drawing.Point(0, 0);
|
||||
this.tabControl1.Margin = new System.Windows.Forms.Padding(3, 3, 3, 0);
|
||||
this.tabControl1.Multiline = true;
|
||||
this.tabControl1.Name = "tabControl1";
|
||||
this.tabControl1.Padding = new System.Drawing.Point(6, 0);
|
||||
this.tabControl1.SelectedIndex = 0;
|
||||
this.tabControl1.Size = new System.Drawing.Size(198, 681);
|
||||
this.tabControl1.Size = new System.Drawing.Size(198, 576);
|
||||
this.tabControl1.TabIndex = 0;
|
||||
//
|
||||
// tabPage1
|
||||
//
|
||||
this.tabPage1.Controls.Add(this.tilePalette);
|
||||
this.tabPage1.Location = new System.Drawing.Point(4, 22);
|
||||
this.tabPage1.Location = new System.Drawing.Point(4, 20);
|
||||
this.tabPage1.Name = "tabPage1";
|
||||
this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tabPage1.Size = new System.Drawing.Size(190, 655);
|
||||
this.tabPage1.Size = new System.Drawing.Size(190, 552);
|
||||
this.tabPage1.TabIndex = 0;
|
||||
this.tabPage1.Text = "Templates";
|
||||
this.tabPage1.UseVisualStyleBackColor = true;
|
||||
@@ -139,16 +169,16 @@
|
||||
this.tilePalette.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tilePalette.Location = new System.Drawing.Point(3, 3);
|
||||
this.tilePalette.Name = "tilePalette";
|
||||
this.tilePalette.Size = new System.Drawing.Size(184, 649);
|
||||
this.tilePalette.Size = new System.Drawing.Size(184, 546);
|
||||
this.tilePalette.TabIndex = 1;
|
||||
//
|
||||
// tabPage2
|
||||
//
|
||||
this.tabPage2.Controls.Add(this.actorPalette);
|
||||
this.tabPage2.Location = new System.Drawing.Point(4, 22);
|
||||
this.tabPage2.Location = new System.Drawing.Point(4, 20);
|
||||
this.tabPage2.Name = "tabPage2";
|
||||
this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tabPage2.Size = new System.Drawing.Size(190, 655);
|
||||
this.tabPage2.Size = new System.Drawing.Size(190, 552);
|
||||
this.tabPage2.TabIndex = 1;
|
||||
this.tabPage2.Text = "Actors";
|
||||
this.tabPage2.UseVisualStyleBackColor = true;
|
||||
@@ -160,15 +190,15 @@
|
||||
this.actorPalette.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.actorPalette.Location = new System.Drawing.Point(3, 3);
|
||||
this.actorPalette.Name = "actorPalette";
|
||||
this.actorPalette.Size = new System.Drawing.Size(184, 649);
|
||||
this.actorPalette.Size = new System.Drawing.Size(184, 546);
|
||||
this.actorPalette.TabIndex = 2;
|
||||
//
|
||||
// tabPage3
|
||||
//
|
||||
this.tabPage3.Controls.Add(this.resourcePalette);
|
||||
this.tabPage3.Location = new System.Drawing.Point(4, 22);
|
||||
this.tabPage3.Location = new System.Drawing.Point(4, 20);
|
||||
this.tabPage3.Name = "tabPage3";
|
||||
this.tabPage3.Size = new System.Drawing.Size(190, 655);
|
||||
this.tabPage3.Size = new System.Drawing.Size(190, 552);
|
||||
this.tabPage3.TabIndex = 2;
|
||||
this.tabPage3.Text = "Resources";
|
||||
this.tabPage3.UseVisualStyleBackColor = true;
|
||||
@@ -180,18 +210,60 @@
|
||||
this.resourcePalette.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.resourcePalette.Location = new System.Drawing.Point(0, 0);
|
||||
this.resourcePalette.Name = "resourcePalette";
|
||||
this.resourcePalette.Size = new System.Drawing.Size(190, 655);
|
||||
this.resourcePalette.Size = new System.Drawing.Size(190, 552);
|
||||
this.resourcePalette.TabIndex = 3;
|
||||
//
|
||||
// surface1
|
||||
//
|
||||
this.surface1.BackColor = System.Drawing.Color.Black;
|
||||
this.surface1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.surface1.Location = new System.Drawing.Point(0, 0);
|
||||
this.surface1.Name = "surface1";
|
||||
this.surface1.Size = new System.Drawing.Size(783, 744);
|
||||
this.surface1.TabIndex = 5;
|
||||
this.surface1.Text = "surface1";
|
||||
//
|
||||
// tt
|
||||
//
|
||||
this.tt.ShowAlways = true;
|
||||
//
|
||||
// saveFileDialog
|
||||
//
|
||||
this.saveFileDialog.DefaultExt = "*.png";
|
||||
this.saveFileDialog.Filter = "PNG Image (*.png)|";
|
||||
this.saveFileDialog.Title = "Export minimap to PNG";
|
||||
//
|
||||
// splitContainer3
|
||||
//
|
||||
this.splitContainer3.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.splitContainer3.FixedPanel = System.Windows.Forms.FixedPanel.Panel1;
|
||||
this.splitContainer3.IsSplitterFixed = true;
|
||||
this.splitContainer3.Location = new System.Drawing.Point(0, 0);
|
||||
this.splitContainer3.Name = "splitContainer3";
|
||||
this.splitContainer3.Orientation = System.Windows.Forms.Orientation.Horizontal;
|
||||
//
|
||||
// splitContainer3.Panel1
|
||||
//
|
||||
this.splitContainer3.Panel1.Controls.Add(this.menuStrip1);
|
||||
//
|
||||
// splitContainer3.Panel2
|
||||
//
|
||||
this.splitContainer3.Panel2.Controls.Add(this.splitContainer1);
|
||||
this.splitContainer3.Size = new System.Drawing.Size(985, 773);
|
||||
this.splitContainer3.SplitterDistance = 25;
|
||||
this.splitContainer3.TabIndex = 6;
|
||||
//
|
||||
// menuStrip1
|
||||
//
|
||||
this.menuStrip1.Dock = System.Windows.Forms.DockStyle.None;
|
||||
this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.fileToolStripMenuItem,
|
||||
this.mapToolStripMenuItem});
|
||||
this.mapToolStripMenuItem,
|
||||
this.toolsToolStripMenuItem,
|
||||
this.toolStripComboBox1,
|
||||
this.toolStripLabel1});
|
||||
this.menuStrip1.Location = new System.Drawing.Point(0, 0);
|
||||
this.menuStrip1.Name = "menuStrip1";
|
||||
this.menuStrip1.Size = new System.Drawing.Size(985, 24);
|
||||
this.menuStrip1.Size = new System.Drawing.Size(985, 27);
|
||||
this.menuStrip1.TabIndex = 1;
|
||||
this.menuStrip1.Text = "menuStrip1";
|
||||
//
|
||||
@@ -205,10 +277,11 @@
|
||||
this.saveAsToolStripMenuItem,
|
||||
this.toolStripSeparator2,
|
||||
this.toolStripMenuItem1,
|
||||
this.mnuExport,
|
||||
this.toolStripSeparator3,
|
||||
this.exotToolStripMenuItem});
|
||||
this.exitToolStripMenuItem});
|
||||
this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
|
||||
this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20);
|
||||
this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 23);
|
||||
this.fileToolStripMenuItem.Text = "&File";
|
||||
//
|
||||
// newToolStripMenuItem
|
||||
@@ -216,42 +289,44 @@
|
||||
this.newToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("newToolStripMenuItem.Image")));
|
||||
this.newToolStripMenuItem.ImageTransparentColor = System.Drawing.Color.Fuchsia;
|
||||
this.newToolStripMenuItem.Name = "newToolStripMenuItem";
|
||||
this.newToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
|
||||
this.newToolStripMenuItem.Size = new System.Drawing.Size(123, 22);
|
||||
this.newToolStripMenuItem.Text = "&New...";
|
||||
this.newToolStripMenuItem.Click += new System.EventHandler(this.NewClicked);
|
||||
//
|
||||
// toolStripSeparator1
|
||||
//
|
||||
this.toolStripSeparator1.Name = "toolStripSeparator1";
|
||||
this.toolStripSeparator1.Size = new System.Drawing.Size(149, 6);
|
||||
this.toolStripSeparator1.Size = new System.Drawing.Size(120, 6);
|
||||
//
|
||||
// openToolStripMenuItem
|
||||
//
|
||||
this.openToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("openToolStripMenuItem.Image")));
|
||||
this.openToolStripMenuItem.Name = "openToolStripMenuItem";
|
||||
this.openToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
|
||||
this.openToolStripMenuItem.Size = new System.Drawing.Size(123, 22);
|
||||
this.openToolStripMenuItem.Text = "&Open...";
|
||||
this.openToolStripMenuItem.Click += new System.EventHandler(this.OpenClicked);
|
||||
//
|
||||
// saveToolStripMenuItem
|
||||
//
|
||||
this.saveToolStripMenuItem.Enabled = false;
|
||||
this.saveToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("saveToolStripMenuItem.Image")));
|
||||
this.saveToolStripMenuItem.Name = "saveToolStripMenuItem";
|
||||
this.saveToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
|
||||
this.saveToolStripMenuItem.Size = new System.Drawing.Size(123, 22);
|
||||
this.saveToolStripMenuItem.Text = "&Save";
|
||||
this.saveToolStripMenuItem.Click += new System.EventHandler(this.SaveClicked);
|
||||
//
|
||||
// saveAsToolStripMenuItem
|
||||
//
|
||||
this.saveAsToolStripMenuItem.Enabled = false;
|
||||
this.saveAsToolStripMenuItem.Name = "saveAsToolStripMenuItem";
|
||||
this.saveAsToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
|
||||
this.saveAsToolStripMenuItem.Size = new System.Drawing.Size(123, 22);
|
||||
this.saveAsToolStripMenuItem.Text = "Save &As...";
|
||||
this.saveAsToolStripMenuItem.Click += new System.EventHandler(this.SaveAsClicked);
|
||||
//
|
||||
// toolStripSeparator2
|
||||
//
|
||||
this.toolStripSeparator2.Name = "toolStripSeparator2";
|
||||
this.toolStripSeparator2.Size = new System.Drawing.Size(149, 6);
|
||||
this.toolStripSeparator2.Size = new System.Drawing.Size(120, 6);
|
||||
//
|
||||
// toolStripMenuItem1
|
||||
//
|
||||
@@ -259,7 +334,7 @@
|
||||
this.cCRedAlertMapToolStripMenuItem,
|
||||
this.bitmapToolStripMenuItem});
|
||||
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
|
||||
this.toolStripMenuItem1.Size = new System.Drawing.Size(152, 22);
|
||||
this.toolStripMenuItem1.Size = new System.Drawing.Size(123, 22);
|
||||
this.toolStripMenuItem1.Text = "&Import";
|
||||
//
|
||||
// cCRedAlertMapToolStripMenuItem
|
||||
@@ -276,18 +351,36 @@
|
||||
this.bitmapToolStripMenuItem.Name = "bitmapToolStripMenuItem";
|
||||
this.bitmapToolStripMenuItem.Size = new System.Drawing.Size(195, 22);
|
||||
this.bitmapToolStripMenuItem.Text = "&Bitmap...";
|
||||
this.bitmapToolStripMenuItem.Visible = false;
|
||||
//
|
||||
// mnuExport
|
||||
//
|
||||
this.mnuExport.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.mnuMinimapToPNG});
|
||||
this.mnuExport.Name = "mnuExport";
|
||||
this.mnuExport.Size = new System.Drawing.Size(123, 22);
|
||||
this.mnuExport.Text = "&Export";
|
||||
//
|
||||
// mnuMinimapToPNG
|
||||
//
|
||||
this.mnuMinimapToPNG.Enabled = false;
|
||||
this.mnuMinimapToPNG.Image = ((System.Drawing.Image)(resources.GetObject("mnuMinimapToPNG.Image")));
|
||||
this.mnuMinimapToPNG.Name = "mnuMinimapToPNG";
|
||||
this.mnuMinimapToPNG.Size = new System.Drawing.Size(163, 22);
|
||||
this.mnuMinimapToPNG.Text = "Minimap to PNG";
|
||||
this.mnuMinimapToPNG.Click += new System.EventHandler(this.ExportMinimap);
|
||||
//
|
||||
// toolStripSeparator3
|
||||
//
|
||||
this.toolStripSeparator3.Name = "toolStripSeparator3";
|
||||
this.toolStripSeparator3.Size = new System.Drawing.Size(149, 6);
|
||||
this.toolStripSeparator3.Size = new System.Drawing.Size(120, 6);
|
||||
//
|
||||
// exotToolStripMenuItem
|
||||
// exitToolStripMenuItem
|
||||
//
|
||||
this.exotToolStripMenuItem.Name = "exotToolStripMenuItem";
|
||||
this.exotToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
|
||||
this.exotToolStripMenuItem.Text = "E&xit";
|
||||
this.exotToolStripMenuItem.Click += new System.EventHandler(this.CloseClicked);
|
||||
this.exitToolStripMenuItem.Name = "exitToolStripMenuItem";
|
||||
this.exitToolStripMenuItem.Size = new System.Drawing.Size(123, 22);
|
||||
this.exitToolStripMenuItem.Text = "E&xit";
|
||||
this.exitToolStripMenuItem.Click += new System.EventHandler(this.CloseClicked);
|
||||
//
|
||||
// mapToolStripMenuItem
|
||||
//
|
||||
@@ -297,11 +390,12 @@
|
||||
this.toolStripSeparator4,
|
||||
this.spawnpointsToolStripMenuItem});
|
||||
this.mapToolStripMenuItem.Name = "mapToolStripMenuItem";
|
||||
this.mapToolStripMenuItem.Size = new System.Drawing.Size(43, 20);
|
||||
this.mapToolStripMenuItem.Size = new System.Drawing.Size(43, 23);
|
||||
this.mapToolStripMenuItem.Text = "&Map";
|
||||
//
|
||||
// propertiesToolStripMenuItem
|
||||
//
|
||||
this.propertiesToolStripMenuItem.Enabled = false;
|
||||
this.propertiesToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("propertiesToolStripMenuItem.Image")));
|
||||
this.propertiesToolStripMenuItem.Name = "propertiesToolStripMenuItem";
|
||||
this.propertiesToolStripMenuItem.Size = new System.Drawing.Size(142, 22);
|
||||
@@ -310,6 +404,7 @@
|
||||
//
|
||||
// resizeToolStripMenuItem
|
||||
//
|
||||
this.resizeToolStripMenuItem.Enabled = false;
|
||||
this.resizeToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("resizeToolStripMenuItem.Image")));
|
||||
this.resizeToolStripMenuItem.Name = "resizeToolStripMenuItem";
|
||||
this.resizeToolStripMenuItem.Size = new System.Drawing.Size(142, 22);
|
||||
@@ -323,60 +418,109 @@
|
||||
//
|
||||
// spawnpointsToolStripMenuItem
|
||||
//
|
||||
this.spawnpointsToolStripMenuItem.Enabled = false;
|
||||
this.spawnpointsToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("spawnpointsToolStripMenuItem.Image")));
|
||||
this.spawnpointsToolStripMenuItem.Name = "spawnpointsToolStripMenuItem";
|
||||
this.spawnpointsToolStripMenuItem.Size = new System.Drawing.Size(142, 22);
|
||||
this.spawnpointsToolStripMenuItem.Text = "&Spawnpoints";
|
||||
this.spawnpointsToolStripMenuItem.Click += new System.EventHandler(this.SpawnPointsClicked);
|
||||
//
|
||||
// tt
|
||||
// toolsToolStripMenuItem
|
||||
//
|
||||
this.tt.ShowAlways = true;
|
||||
this.toolsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.layersFloaterToolStripMenuItem});
|
||||
this.toolsToolStripMenuItem.Name = "toolsToolStripMenuItem";
|
||||
this.toolsToolStripMenuItem.Size = new System.Drawing.Size(48, 23);
|
||||
this.toolsToolStripMenuItem.Text = "Tools";
|
||||
this.toolsToolStripMenuItem.Visible = false;
|
||||
//
|
||||
// surface1
|
||||
// layersFloaterToolStripMenuItem
|
||||
//
|
||||
this.surface1.BackColor = System.Drawing.Color.Black;
|
||||
this.surface1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.surface1.Location = new System.Drawing.Point(0, 0);
|
||||
this.surface1.Name = "surface1";
|
||||
this.surface1.Size = new System.Drawing.Size(783, 681);
|
||||
this.surface1.TabIndex = 5;
|
||||
this.surface1.Text = "surface1";
|
||||
this.layersFloaterToolStripMenuItem.Name = "layersFloaterToolStripMenuItem";
|
||||
this.layersFloaterToolStripMenuItem.Size = new System.Drawing.Size(144, 22);
|
||||
this.layersFloaterToolStripMenuItem.Text = "Layers floater";
|
||||
this.layersFloaterToolStripMenuItem.Click += new System.EventHandler(this.layersFloaterToolStripMenuItem_Click);
|
||||
//
|
||||
// toolStripComboBox1
|
||||
//
|
||||
this.toolStripComboBox1.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;
|
||||
this.toolStripComboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.toolStripComboBox1.Name = "toolStripComboBox1";
|
||||
this.toolStripComboBox1.Size = new System.Drawing.Size(121, 23);
|
||||
//
|
||||
// toolStripLabel1
|
||||
//
|
||||
this.toolStripLabel1.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;
|
||||
this.toolStripLabel1.Name = "toolStripLabel1";
|
||||
this.toolStripLabel1.Size = new System.Drawing.Size(71, 20);
|
||||
this.toolStripLabel1.Text = "Active Mod:";
|
||||
//
|
||||
// statusStrip1
|
||||
//
|
||||
this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.toolStripStatusLabelFiller,
|
||||
this.toolStripStatusLabelMousePosition});
|
||||
this.statusStrip1.Location = new System.Drawing.Point(0, 751);
|
||||
this.statusStrip1.Name = "statusStrip1";
|
||||
this.statusStrip1.Size = new System.Drawing.Size(985, 22);
|
||||
this.statusStrip1.TabIndex = 7;
|
||||
this.statusStrip1.Text = "statusStrip1";
|
||||
//
|
||||
// toolStripStatusLabelFiller
|
||||
//
|
||||
this.toolStripStatusLabelFiller.Name = "toolStripStatusLabelFiller";
|
||||
this.toolStripStatusLabelFiller.Size = new System.Drawing.Size(948, 17);
|
||||
this.toolStripStatusLabelFiller.Spring = true;
|
||||
//
|
||||
// toolStripStatusLabelMousePosition
|
||||
//
|
||||
this.toolStripStatusLabelMousePosition.Name = "toolStripStatusLabelMousePosition";
|
||||
this.toolStripStatusLabelMousePosition.RightToLeft = System.Windows.Forms.RightToLeft.Yes;
|
||||
this.toolStripStatusLabelMousePosition.Size = new System.Drawing.Size(22, 17);
|
||||
this.toolStripStatusLabelMousePosition.Text = "0,0";
|
||||
//
|
||||
// Form1
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(985, 705);
|
||||
this.Controls.Add(this.toolStripContainer1);
|
||||
this.ClientSize = new System.Drawing.Size(985, 773);
|
||||
this.Controls.Add(this.statusStrip1);
|
||||
this.Controls.Add(this.splitContainer3);
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.KeyPreview = true;
|
||||
this.MainMenuStrip = this.menuStrip1;
|
||||
this.Name = "Form1";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "OpenRA Editor";
|
||||
this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyUp);
|
||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.OnFormClosing);
|
||||
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);
|
||||
this.toolStripContainer1.ContentPanel.ResumeLayout(false);
|
||||
this.toolStripContainer1.TopToolStripPanel.ResumeLayout(false);
|
||||
this.toolStripContainer1.TopToolStripPanel.PerformLayout();
|
||||
this.toolStripContainer1.ResumeLayout(false);
|
||||
this.toolStripContainer1.PerformLayout();
|
||||
this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyUp);
|
||||
this.splitContainer1.Panel1.ResumeLayout(false);
|
||||
this.splitContainer1.Panel2.ResumeLayout(false);
|
||||
this.splitContainer1.ResumeLayout(false);
|
||||
this.splitContainer2.Panel1.ResumeLayout(false);
|
||||
this.splitContainer2.Panel2.ResumeLayout(false);
|
||||
this.splitContainer2.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.pmMiniMap)).EndInit();
|
||||
this.tabControl1.ResumeLayout(false);
|
||||
this.tabPage1.ResumeLayout(false);
|
||||
this.tabPage2.ResumeLayout(false);
|
||||
this.tabPage3.ResumeLayout(false);
|
||||
this.splitContainer3.Panel1.ResumeLayout(false);
|
||||
this.splitContainer3.Panel1.PerformLayout();
|
||||
this.splitContainer3.Panel2.ResumeLayout(false);
|
||||
this.splitContainer3.ResumeLayout(false);
|
||||
this.menuStrip1.ResumeLayout(false);
|
||||
this.menuStrip1.PerformLayout();
|
||||
this.statusStrip1.ResumeLayout(false);
|
||||
this.statusStrip1.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.ToolStripContainer toolStripContainer1;
|
||||
private System.Windows.Forms.SplitContainer splitContainer1;
|
||||
private System.Windows.Forms.ToolTip tt;
|
||||
private System.Windows.Forms.TabControl tabControl1;
|
||||
@@ -385,27 +529,39 @@
|
||||
private System.Windows.Forms.TabPage tabPage2;
|
||||
private System.Windows.Forms.FlowLayoutPanel actorPalette;
|
||||
private System.Windows.Forms.TabPage tabPage3;
|
||||
private System.Windows.Forms.FlowLayoutPanel resourcePalette;
|
||||
private System.Windows.Forms.FolderBrowserDialog folderBrowser;
|
||||
private System.Windows.Forms.FlowLayoutPanel resourcePalette;
|
||||
private Surface surface1;
|
||||
private System.Windows.Forms.PictureBox pmMiniMap;
|
||||
private System.Windows.Forms.SplitContainer splitContainer2;
|
||||
private System.Windows.Forms.SaveFileDialog saveFileDialog;
|
||||
private System.Windows.Forms.SplitContainer splitContainer3;
|
||||
private System.Windows.Forms.StatusStrip statusStrip1;
|
||||
private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabelMousePosition;
|
||||
private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabelFiller;
|
||||
private System.Windows.Forms.MenuStrip menuStrip1;
|
||||
private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem newToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem openToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
|
||||
private System.Windows.Forms.ToolStripMenuItem openToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem saveToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem saveAsToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator2;
|
||||
private System.Windows.Forms.ToolStripMenuItem exotToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem1;
|
||||
private System.Windows.Forms.ToolStripMenuItem cCRedAlertMapToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem bitmapToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuExport;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuMinimapToPNG;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator3;
|
||||
private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem mapToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem propertiesToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem resizeToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator4;
|
||||
private System.Windows.Forms.ToolStripMenuItem spawnpointsToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem toolsToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem layersFloaterToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripLabel toolStripLabel1;
|
||||
private System.Windows.Forms.ToolStripComboBox toolStripComboBox1;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
285
OpenRA.Editor/Form1.cs
Normal file → Executable file
285
OpenRA.Editor/Form1.cs
Normal file → Executable file
@@ -10,13 +10,11 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Editor
|
||||
@@ -30,20 +28,43 @@ namespace OpenRA.Editor
|
||||
|
||||
currentMod = mods.FirstOrDefault() ?? "ra";
|
||||
|
||||
Text = "OpenRA Editor (mod:{0})".F(currentMod);
|
||||
toolStripComboBox1.Items.AddRange(Mod.AllMods.Keys.ToArray());
|
||||
|
||||
toolStripComboBox1.SelectedIndexChanged += (_, e) =>
|
||||
{
|
||||
tilePalette.SuspendLayout();
|
||||
actorPalette.SuspendLayout();
|
||||
resourcePalette.SuspendLayout();
|
||||
tilePalette.Controls.Clear();
|
||||
actorPalette.Controls.Clear();
|
||||
resourcePalette.Controls.Clear();
|
||||
tilePalette.ResumeLayout();
|
||||
actorPalette.ResumeLayout();
|
||||
resourcePalette.ResumeLayout();
|
||||
surface1.Bind(null, null, null);
|
||||
pmMiniMap.Image = null;
|
||||
currentMod = toolStripComboBox1.SelectedItem as string;
|
||||
|
||||
Text = "OpenRA Editor (mod:{0})".F(currentMod);
|
||||
Game.modData = new ModData(currentMod);
|
||||
FileSystem.LoadFromManifest(Game.modData.Manifest);
|
||||
Rules.LoadRules(Game.modData.Manifest, new Map());
|
||||
loadedMapName = null;
|
||||
};
|
||||
|
||||
toolStripComboBox1.SelectedItem = currentMod;
|
||||
|
||||
surface1.AfterChange += OnMapChanged;
|
||||
surface1.MousePositionChanged += s => toolStripStatusLabelMousePosition.Text = s;
|
||||
}
|
||||
|
||||
Game.modData = new ModData( currentMod );
|
||||
|
||||
Rules.LoadRules(Game.modData.Manifest, new Map());
|
||||
|
||||
folderBrowser.SelectedPath = new string[] { Environment.CurrentDirectory, "mods", currentMod, "maps" }
|
||||
.Aggregate(Path.Combine);
|
||||
|
||||
surface1.AfterChange += MakeDirty;
|
||||
void OnMapChanged()
|
||||
{
|
||||
MakeDirty();
|
||||
pmMiniMap.Image = Minimap.AddStaticResources(surface1.Map, Minimap.TerrainBitmap(surface1.Map, true));
|
||||
}
|
||||
|
||||
void MakeDirty() { dirty = true; }
|
||||
|
||||
string loadedMapName;
|
||||
string currentMod = "ra";
|
||||
TileSet tileset;
|
||||
@@ -57,10 +78,8 @@ namespace OpenRA.Editor
|
||||
|
||||
loadedMapName = mapname;
|
||||
|
||||
Game.modData = new ModData( currentMod );
|
||||
|
||||
// load the map
|
||||
var map = new Map(new Folder(mapname));
|
||||
var map = new Map(mapname);
|
||||
|
||||
// upgrade maps that have no player definitions. editor doesnt care,
|
||||
// but this breaks the game pretty badly.
|
||||
@@ -80,32 +99,29 @@ namespace OpenRA.Editor
|
||||
resourcePalette.Controls.Clear();
|
||||
|
||||
loadedMapName = null;
|
||||
|
||||
Game.modData = new ModData( currentMod );
|
||||
|
||||
PrepareMapResources(Game.modData.Manifest, map);
|
||||
|
||||
MakeDirty();
|
||||
}
|
||||
|
||||
// this code is insanely stupid, and mostly my fault -- chrisf
|
||||
void PrepareMapResources(Manifest manifest, Map map)
|
||||
{
|
||||
Rules.LoadRules(manifest, map);
|
||||
tileset = Rules.TileSets[map.Theater];
|
||||
Rules.LoadRules(manifest, map);
|
||||
tileset = Rules.TileSets[map.Tileset];
|
||||
tileset.LoadTiles();
|
||||
var palette = new Palette(FileSystem.Open(tileset.Palette), true);
|
||||
|
||||
surface1.Bind(map, tileset, palette);
|
||||
|
||||
surface1.Bind(map, tileset, palette);
|
||||
// construct the palette of tiles
|
||||
var palettes = new[] { tilePalette, actorPalette, resourcePalette };
|
||||
foreach (var p in palettes) { p.Visible = false; p.SuspendLayout(); }
|
||||
|
||||
foreach (var t in tileset.Templates)
|
||||
{
|
||||
try
|
||||
{
|
||||
var bitmap = RenderTemplate(tileset, (ushort)t.Key, palette);
|
||||
var bitmap = RenderUtils.RenderTemplate(tileset, (ushort)t.Key, palette);
|
||||
var ibox = new PictureBox
|
||||
{
|
||||
Image = bitmap,
|
||||
@@ -115,11 +131,10 @@ namespace OpenRA.Editor
|
||||
};
|
||||
|
||||
var brushTemplate = new BrushTemplate { Bitmap = bitmap, N = t.Key };
|
||||
ibox.Click += (_, e) => surface1.SetBrush(brushTemplate);
|
||||
ibox.Click += (_, e) => surface1.SetTool(new BrushTool(brushTemplate));
|
||||
|
||||
var template = t.Value;
|
||||
tilePalette.Controls.Add(ibox);
|
||||
|
||||
tt.SetToolTip(ibox,
|
||||
"{1}:{0} ({2}x{3})".F(
|
||||
template.Image,
|
||||
@@ -137,17 +152,19 @@ namespace OpenRA.Editor
|
||||
try
|
||||
{
|
||||
var info = Rules.Info[a];
|
||||
if( !info.Traits.Contains<RenderSimpleInfo>() ) continue;
|
||||
var template = RenderActor(info, tileset, palette);
|
||||
if (!info.Traits.Contains<RenderSimpleInfo>()) continue;
|
||||
var template = RenderUtils.RenderActor(info, tileset, palette);
|
||||
var ibox = new PictureBox
|
||||
{
|
||||
Image = template.Bitmap,
|
||||
Width = template.Bitmap.Width / 2,
|
||||
Height = template.Bitmap.Height / 2,
|
||||
SizeMode = PictureBoxSizeMode.StretchImage
|
||||
Width = 32,
|
||||
Height = 32,
|
||||
SizeMode = PictureBoxSizeMode.Zoom,
|
||||
BorderStyle = BorderStyle.FixedSingle
|
||||
};
|
||||
|
||||
ibox.Click += (_, e) => surface1.SetActor(template);
|
||||
|
||||
ibox.Click += (_, e) => surface1.SetTool(new ActorTool(template));
|
||||
|
||||
actorPalette.Controls.Add(ibox);
|
||||
|
||||
@@ -168,16 +185,19 @@ namespace OpenRA.Editor
|
||||
{
|
||||
try
|
||||
{
|
||||
var template = RenderResourceType(a, tileset.Extensions, palette);
|
||||
var template = RenderUtils.RenderResourceType(a, tileset.Extensions, palette);
|
||||
var ibox = new PictureBox
|
||||
{
|
||||
Image = template.Bitmap,
|
||||
Width = template.Bitmap.Width,
|
||||
Height = template.Bitmap.Height,
|
||||
SizeMode = PictureBoxSizeMode.StretchImage
|
||||
Width = 32,
|
||||
Height = 32,
|
||||
SizeMode = PictureBoxSizeMode.Zoom,
|
||||
BorderStyle = BorderStyle.FixedSingle
|
||||
};
|
||||
|
||||
ibox.Click += (_, e) => surface1.SetResource(template);
|
||||
|
||||
|
||||
ibox.Click += (_, e) => surface1.SetTool(new ResourceTool(template));
|
||||
|
||||
resourcePalette.Controls.Add(ibox);
|
||||
|
||||
@@ -193,103 +213,20 @@ namespace OpenRA.Editor
|
||||
|
||||
surface1.BindResourceTemplates(resourceTemplates);
|
||||
|
||||
foreach (var p in palettes) { p.Visible = true; p.ResumeLayout(); }
|
||||
}
|
||||
|
||||
static Bitmap RenderTemplate(TileSet ts, ushort n, Palette p)
|
||||
{
|
||||
var template = ts.Templates[n];
|
||||
var tile = ts.Tiles[n];
|
||||
|
||||
var bitmap = new Bitmap(24 * template.Size.X, 24 * template.Size.Y);
|
||||
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
|
||||
|
||||
unsafe
|
||||
foreach (var p in palettes)
|
||||
{
|
||||
int* q = (int*)data.Scan0.ToPointer();
|
||||
var stride = data.Stride >> 2;
|
||||
|
||||
for (var u = 0; u < template.Size.X; u++)
|
||||
for (var v = 0; v < template.Size.Y; v++)
|
||||
if (tile.TileBitmapBytes[u + v * template.Size.X] != null)
|
||||
{
|
||||
var rawImage = tile.TileBitmapBytes[u + v * template.Size.X];
|
||||
for (var i = 0; i < 24; i++)
|
||||
for (var j = 0; j < 24; j++)
|
||||
q[(v * 24 + j) * stride + u * 24 + i] = p.GetColor(rawImage[i + 24 * j]).ToArgb();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < 24; i++)
|
||||
for (var j = 0; j < 24; j++)
|
||||
q[(v * 24 + j) * stride + u * 24 + i] = Color.Transparent.ToArgb();
|
||||
}
|
||||
p.Visible = true;
|
||||
p.ResumeLayout();
|
||||
}
|
||||
|
||||
bitmap.UnlockBits(data);
|
||||
return bitmap;
|
||||
}
|
||||
pmMiniMap.Image = Minimap.AddStaticResources(surface1.Map, Minimap.TerrainBitmap(surface1.Map, true));
|
||||
|
||||
static ActorTemplate RenderActor(ActorInfo info, TileSet tileset, Palette p)
|
||||
{
|
||||
var ri = info.Traits.Get<RenderSimpleInfo>();
|
||||
string image = null;
|
||||
if (ri.OverrideTheater != null)
|
||||
for (int i = 0; i < ri.OverrideTheater.Length; i++)
|
||||
if (ri.OverrideTheater[i] == tileset.Id)
|
||||
image = ri.OverrideImage[i];
|
||||
|
||||
image = image ?? ri.Image ?? info.Name;
|
||||
using (var s = FileSystem.OpenWithExts(image, tileset.Extensions))
|
||||
{
|
||||
var shp = new ShpReader(s);
|
||||
var frame = shp[0];
|
||||
|
||||
var bitmap = new Bitmap(shp.Width, shp.Height);
|
||||
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
|
||||
|
||||
unsafe
|
||||
{
|
||||
int* q = (int*)data.Scan0.ToPointer();
|
||||
var stride = data.Stride >> 2;
|
||||
|
||||
for (var i = 0; i < shp.Width; i++)
|
||||
for (var j = 0; j < shp.Height; j++)
|
||||
q[j * stride + i] = p.GetColor(frame.Image[i + shp.Width * j]).ToArgb();
|
||||
}
|
||||
|
||||
bitmap.UnlockBits(data);
|
||||
return new ActorTemplate { Bitmap = bitmap, Info = info, Centered = !info.Traits.Contains<BuildingInfo>() };
|
||||
}
|
||||
}
|
||||
|
||||
static ResourceTemplate RenderResourceType(ResourceTypeInfo info, string[] exts, Palette p)
|
||||
{
|
||||
var image = info.SpriteNames[0];
|
||||
using (var s = FileSystem.OpenWithExts(image, exts))
|
||||
{
|
||||
var shp = new ShpReader(s);
|
||||
var frame = shp[shp.ImageCount - 1];
|
||||
|
||||
var bitmap = new Bitmap(shp.Width, shp.Height);
|
||||
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
|
||||
|
||||
unsafe
|
||||
{
|
||||
int* q = (int*)data.Scan0.ToPointer();
|
||||
var stride = data.Stride >> 2;
|
||||
|
||||
for (var i = 0; i < shp.Width; i++)
|
||||
for (var j = 0; j < shp.Height; j++)
|
||||
q[j * stride + i] = p.GetColor(frame.Image[i + shp.Width * j]).ToArgb();
|
||||
}
|
||||
|
||||
bitmap.UnlockBits(data);
|
||||
return new ResourceTemplate { Bitmap = bitmap, Info = info, Value = shp.ImageCount - 1 };
|
||||
}
|
||||
propertiesToolStripMenuItem.Enabled = true;
|
||||
resizeToolStripMenuItem.Enabled = true;
|
||||
spawnpointsToolStripMenuItem.Enabled = true;
|
||||
saveToolStripMenuItem.Enabled = true;
|
||||
saveAsToolStripMenuItem.Enabled = true;
|
||||
mnuMinimapToPNG.Enabled = true; // todo: what is this VB naming bullshit doing here?
|
||||
}
|
||||
|
||||
void ResizeClicked(object sender, EventArgs e)
|
||||
@@ -298,16 +235,18 @@ namespace OpenRA.Editor
|
||||
{
|
||||
rd.width.Value = surface1.Map.MapSize.X;
|
||||
rd.height.Value = surface1.Map.MapSize.Y;
|
||||
rd.cordonLeft.Value = surface1.Map.TopLeft.X;
|
||||
rd.cordonTop.Value = surface1.Map.TopLeft.Y;
|
||||
rd.cordonRight.Value = surface1.Map.BottomRight.X;
|
||||
rd.cordonBottom.Value = surface1.Map.BottomRight.Y;
|
||||
rd.cordonLeft.Value = surface1.Map.Bounds.Left;
|
||||
rd.cordonTop.Value = surface1.Map.Bounds.Top;
|
||||
rd.cordonRight.Value = surface1.Map.Bounds.Right;
|
||||
rd.cordonBottom.Value = surface1.Map.Bounds.Bottom;
|
||||
|
||||
if (DialogResult.OK != rd.ShowDialog())
|
||||
return;
|
||||
|
||||
surface1.Map.TopLeft = new int2((int)rd.cordonLeft.Value, (int)rd.cordonTop.Value);
|
||||
surface1.Map.BottomRight = new int2((int)rd.cordonRight.Value, (int)rd.cordonBottom.Value);
|
||||
surface1.Map.ResizeCordon((int)rd.cordonLeft.Value,
|
||||
(int)rd.cordonTop.Value,
|
||||
(int)rd.cordonRight.Value,
|
||||
(int)rd.cordonBottom.Value);
|
||||
|
||||
if ((int)rd.width.Value != surface1.Map.MapSize.X || (int)rd.height.Value != surface1.Map.MapSize.Y)
|
||||
{
|
||||
@@ -318,7 +257,7 @@ namespace OpenRA.Editor
|
||||
surface1.Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SaveClicked(object sender, EventArgs e)
|
||||
{
|
||||
if (loadedMapName == null)
|
||||
@@ -326,30 +265,44 @@ namespace OpenRA.Editor
|
||||
else
|
||||
{
|
||||
surface1.Map.PlayerCount = surface1.Map.Waypoints.Count;
|
||||
surface1.Map.Package = new Folder(loadedMapName);
|
||||
surface1.Map.Save(loadedMapName);
|
||||
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SaveAsClicked(object sender, EventArgs e)
|
||||
{
|
||||
folderBrowser.ShowNewFolderButton = true;
|
||||
|
||||
if (DialogResult.OK == folderBrowser.ShowDialog())
|
||||
using (var nms = new MapSelect(currentMod))
|
||||
{
|
||||
loadedMapName = folderBrowser.SelectedPath;
|
||||
SaveClicked(sender, e);
|
||||
nms.txtNew.ReadOnly = false;
|
||||
nms.btnOk.Text = "Save";
|
||||
nms.txtNew.Text = "unnamed";
|
||||
nms.txtPathOut.ReadOnly = false;
|
||||
|
||||
if (DialogResult.OK == nms.ShowDialog())
|
||||
{
|
||||
if (nms.txtNew.Text == "")
|
||||
nms.txtNew.Text = "unnamed";
|
||||
|
||||
// TODO: Allow the user to choose map format (directory vs oramap)
|
||||
loadedMapName = Path.Combine(nms.MapFolderPath, nms.txtNew.Text + ".oramap");
|
||||
SaveClicked(sender, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OpenClicked(object sender, EventArgs e)
|
||||
{
|
||||
folderBrowser.ShowNewFolderButton = true;
|
||||
using (var nms = new MapSelect(currentMod))
|
||||
{
|
||||
nms.txtNew.ReadOnly = true;
|
||||
nms.txtPathOut.ReadOnly = true;
|
||||
nms.btnOk.Text = "Open";
|
||||
|
||||
if (DialogResult.OK == folderBrowser.ShowDialog())
|
||||
LoadMap(folderBrowser.SelectedPath);
|
||||
if (DialogResult.OK == nms.ShowDialog())
|
||||
LoadMap(nms.txtNew.Tag as string);
|
||||
}
|
||||
}
|
||||
|
||||
void NewClicked(object sender, EventArgs e)
|
||||
@@ -362,13 +315,11 @@ namespace OpenRA.Editor
|
||||
|
||||
if (DialogResult.OK == nmd.ShowDialog())
|
||||
{
|
||||
var map = new Map();
|
||||
var map = Map.FromTileset(nmd.theater.SelectedItem as string);
|
||||
|
||||
map.Resize((int)nmd.width.Value, (int)nmd.height.Value);
|
||||
|
||||
map.TopLeft = new int2((int)nmd.cordonLeft.Value, (int)nmd.cordonTop.Value);
|
||||
map.BottomRight = new int2((int)nmd.cordonRight.Value, (int)nmd.cordonBottom.Value);
|
||||
map.Tileset = nmd.theater.SelectedItem as string;
|
||||
map.ResizeCordon((int)nmd.cordonLeft.Value, (int)nmd.cordonTop.Value,
|
||||
(int)nmd.cordonRight.Value, (int)nmd.cordonBottom.Value);
|
||||
map.Players.Add("Neutral", new PlayerReference("Neutral", Rules.Info["world"].Traits.WithInterface<CountryInfo>().First().Race, true, true));
|
||||
NewMap(map);
|
||||
}
|
||||
@@ -383,6 +334,7 @@ namespace OpenRA.Editor
|
||||
pd.desc.Text = surface1.Map.Description;
|
||||
pd.author.Text = surface1.Map.Author;
|
||||
pd.selectable.Checked = surface1.Map.Selectable;
|
||||
pd.useAsShellmap.Checked = surface1.Map.UseAsShellmap;
|
||||
|
||||
if (DialogResult.OK != pd.ShowDialog())
|
||||
return;
|
||||
@@ -391,10 +343,11 @@ namespace OpenRA.Editor
|
||||
surface1.Map.Description = pd.desc.Text;
|
||||
surface1.Map.Author = pd.author.Text;
|
||||
surface1.Map.Selectable = pd.selectable.Checked;
|
||||
surface1.Map.UseAsShellmap = pd.useAsShellmap.Checked;
|
||||
}
|
||||
}
|
||||
|
||||
void SpawnPointsClicked(object sender, EventArgs e) { surface1.SetWaypoint(new WaypointTemplate()); }
|
||||
void SpawnPointsClicked(object sender, EventArgs e) { surface1.SetTool(new WaypointTool(new WaypointTemplate())); }
|
||||
void Form1_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Space) surface1.IsPanning = true; }
|
||||
void Form1_KeyUp(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Space) surface1.IsPanning = false; }
|
||||
|
||||
@@ -405,9 +358,11 @@ namespace OpenRA.Editor
|
||||
|
||||
void ImportLegacyMapClicked(object sender, EventArgs e)
|
||||
{
|
||||
var currentDirectory = Directory.GetCurrentDirectory();
|
||||
using (var ofd = new OpenFileDialog { Filter = "Legacy maps (*.ini;*.mpr)|*.ini;*.mpr" })
|
||||
if (DialogResult.OK == ofd.ShowDialog())
|
||||
{
|
||||
Directory.SetCurrentDirectory(currentDirectory);
|
||||
/* massive hack: we should be able to call NewMap() with the imported Map object,
|
||||
* but something's not right internally in it, unless loaded via the real maploader */
|
||||
|
||||
@@ -415,10 +370,9 @@ namespace OpenRA.Editor
|
||||
Directory.CreateDirectory(savePath);
|
||||
|
||||
var map = LegacyMapImporter.Import(ofd.FileName);
|
||||
map.Package = new Folder(savePath);
|
||||
map.Players.Add("Neutral", new PlayerReference("Neutral",
|
||||
map.Players.Add("Neutral", new PlayerReference("Neutral",
|
||||
Rules.Info["world"].Traits.WithInterface<CountryInfo>().First().Race, true, true));
|
||||
|
||||
|
||||
map.Save(savePath);
|
||||
LoadMap(savePath);
|
||||
loadedMapName = null; /* editor needs to think this hasnt been saved */
|
||||
@@ -432,7 +386,7 @@ namespace OpenRA.Editor
|
||||
{
|
||||
if (!dirty) return;
|
||||
|
||||
switch (MessageBox.Show("The map has been modified since it was last saved. Save changes now?",
|
||||
switch (MessageBox.Show("The map has been modified since it was last saved. " + "\r\n" + "Save changes now?",
|
||||
"Unsaved Changes", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation))
|
||||
{
|
||||
case DialogResult.Yes: SaveClicked(null, EventArgs.Empty); break;
|
||||
@@ -440,5 +394,20 @@ namespace OpenRA.Editor
|
||||
case DialogResult.Cancel: e.Cancel = true; break;
|
||||
}
|
||||
}
|
||||
|
||||
private void layersFloaterToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
var pb = new PaletteBox();
|
||||
pb.Show();
|
||||
}
|
||||
|
||||
void ExportMinimap(object sender, EventArgs e)
|
||||
{
|
||||
saveFileDialog.InitialDirectory = Path.Combine(Environment.CurrentDirectory, "maps");
|
||||
saveFileDialog.FileName = Path.ChangeExtension(loadedMapName, ".png");
|
||||
|
||||
if (DialogResult.OK == saveFileDialog.ShowDialog())
|
||||
pmMiniMap.Image.Save(saveFileDialog.FileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
270
OpenRA.Editor/Form1.resx
Normal file → Executable file
270
OpenRA.Editor/Form1.resx
Normal file → Executable file
@@ -117,8 +117,14 @@
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="tt.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<metadata name="saveFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>76, 17</value>
|
||||
</metadata>
|
||||
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>309, 17</value>
|
||||
<value>198, 17</value>
|
||||
</metadata>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="newToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
@@ -237,6 +243,23 @@
|
||||
z2ki+Wo1CWklROkMCiT8wEm0kXEsCTmrAiTbDtcEpTVdZOS1oDfWk5xZ6RPeQZeUR8zxK0Qe1BO65xjr
|
||||
t0YotXhjAEAeQ7It8ZSESUjkznIq2bYsTGYW29JZxIs2nFEdLOSdfwFwpvLxRKIY2AAAAABJRU5ErkJg
|
||||
gg==
|
||||
</value>
|
||||
</data>
|
||||
<data name="mnuMinimapToPNG.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
|
||||
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsMAAALDAE/QCLIAAACR0lE
|
||||
QVQ4T6WTXUiTARSGdxkRRBdB0IUREV1EKRFEYYuQAklL8sKQfphUoJSUWJbLxAVZWqyBio5WajorM1PL
|
||||
xExUlLQfbU5n0lygRerMP/qxOZ92vpjfCKLAi3P5Puc957xHA2gWUoo49147gWUqbSPrdjOXChrQm56S
|
||||
lFVFvKEcXaqV2OQiohMt7Esw+6Ro5gGeWfhbff0BY9NzDI3N0f/JS6fLy7rd6f8HcNsdOI6EYD8cjK3V
|
||||
roiLawdYu+vivwHSWcQM1THz/DQv96+ixeHlVvU71oQFAGTmP+37bdsPBf8WZ4fRFhVEXdcsBQ9srN6Z
|
||||
pjqQhQUCAmcW29JZxA8fvaWyY5YcawdBOy6oANm2H9A3MMypDLNS7b1flJnFtnQWcVmrB2NhMytD9SpA
|
||||
TiUA5+CYInQOjWPrH2V7RBzmijdo9x5VKr+yj6ImD9nmelZsS1UBcme/+OPIJIOfv/Gi201ZXQ/hMfFU
|
||||
Peuktqnbd3QN+U/cXM6tYfmW8ypAQiKdh91TTE7PYHNOYKl6z916F3m+eSNjT1B4vxHjzWoFYrhRwbLN
|
||||
51SAJOynx8vo5Ay9rimKHzu5XtJDpuU1WZY2Eg1WgrXRJOpNxKdcUyBLN6WoAInnyPh3XvW6KW/4MC9O
|
||||
z2ki+Wo1CWklROkMCiT8wEm0kXEsCTmrAiTbDtcEpTVdZOS1oDfWk5xZ6RPeQZeUR8zxK0Qe1BO65xjr
|
||||
t0YotXhjAEAeQ7It8ZSESUjkznIq2bYsTGYW29JZxIs2nFEdLOSdfwFwpvLxRKIY2AAAAABJRU5ErkJg
|
||||
gg==
|
||||
</value>
|
||||
</data>
|
||||
<data name="propertiesToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
@@ -288,10 +311,247 @@
|
||||
vP+uv56/AehVvkSccelEAAAAAElFTkSuQmCC
|
||||
</value>
|
||||
</data>
|
||||
<metadata name="tt.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>313, 17</value>
|
||||
</metadata>
|
||||
<metadata name="folderBrowser.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>182, 17</value>
|
||||
<metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>45</value>
|
||||
</metadata>
|
||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
AAABAAIAMDAAAAEAIACoJQAAJgAAACAgAAABACAAqBAAAM4lAAAoAAAAMAAAAGAAAAABACAAAAAAAAAk
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAQAAAAQAAAAJQAA
|
||||
ADcAAAA+AAAAOAAAACoAAAAYAAAACwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAUAAAApAAAAVAAAAGIBAQFNAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAASAAAAOgAA
|
||||
AFkAAAA6AAAAMQEBAUYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
|
||||
AAoAAAAkAAAAUQAAAHkAAACJAAAAhQAAAHMAAABTAAAAMAAAABUAAAAGAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAIAAAAkAAAAaQEBAZYCAgLaAAAAWgAAAAsAAAABAAAAAAAAAAAAAAAAAAAABwAA
|
||||
AB8AAABMAAAAfwAAAHkAAAA8AgIAwgEBAWkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAQAAAA8AAAA9AAAAgwAAALMAAADFHRcU3QAAAMMAAACgAAAAdwAAAEUAAAAeAAAABwAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASAAAAUgAAAJgDBATpAgIG/wEAAI8AAAAYAAAABAAA
|
||||
AAIAAAAOAAAALgAAAGIAAACVAAAApgEAAJUEBADsAwQK/wAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABYAAABPAAAAngAAAMx3YFX3jXZv/5RuY/9mT0X2GxENygcG
|
||||
BYsAAABKAAAAGgAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAKAAAAQAAAAJMBAQHRBApN/wQK
|
||||
U/8CAADQAQEARwAAACkAAABIAAAAeQAAAKMAAAC5AgAA1QQGJf8FC1v/AQEHrAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABwAAACEAAABcAAAApQICAtOFc2z8hnJt/5h6
|
||||
cf+hfXL/mHty/3VkXewZExGLAAAAOQAAAAwAAAABAAAAAQAAAAIAAAAFAAAACAAAABAAAAAqAAAAYwAA
|
||||
AKABAAC8AwAV+QUWxv8ED4P/BgcX/AEAALAAAACWAAAAsQAAAMkEBArzBAli/wMOtf8CCVD/AwIAbAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAEAAAADQAAAB1AAAAsgcE
|
||||
BNmHcGj8mYiB/6GMhf+lkIj/moiB/5qIgP9dTUfqAgICYAAAACAAAAAGAAAABAAAAAoAAAAZAAAAKgAA
|
||||
AEEAAABqAQEBmgEBAbkHCw7dBgcH+QEAi/8FHf//AgG0/wIABP8GFRntBiIw6wcYHf8BAET/AgR6/wMF
|
||||
X/8DACD5AAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAFAAAAGwAA
|
||||
AE8AAACXAAAAxQwLCuGSfHX9momC/5yLg/+cjIX/mYaA/5aGf/+MdWv/GhUSoQAAAEAAAAAXAAAAEAAA
|
||||
AB8AAAA+AAAAZgAAAIwAAACtCQkJx0A5N+UYdqT/JsXu/wgdZ/8AAIr/Cyx0/x6Rwf8luf3/Jbv//yCd
|
||||
3P8TYIj/FWaB/xdtjf8EDhfkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAEAAAAIAAAAKQAAAG4AAACxBwYD1HdiWPmcioL/mYiA/56Nhf+ejoX/lYV//5WGf/+Wgnv/U0M96AAA
|
||||
AHUAAAA4AAAALwAAAEYAAABzAAAApAAAAMIkGRHhIBkT6F1WVfYqPUb/KM3//yOt5f8NN0b/J8r+/ybE
|
||||
+P8ZfqT/G4ay/x6Tz/8hpej/IKTl/xuLwf8FExmmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAIAAAANAAAANwAAAIQAAAC+IhoW5Jt2av+Qfnf/no6G/5WHgP+vnpb/koJ7/5iG
|
||||
f/+Zh4D/k4B6/kU4M8UAAABvAAAAagAAAIcAAACsAAAAzAMDAt+FW0z8fV5R/VtQS/2PgHn/UUhH/yKV
|
||||
tf8z////I62//wcXX/8CBMz/AABw/w9HXv8muv3/Iq30/xh0p/8BAABfAAAABAAAAAIAAAABAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAYAAAAWAAAASAAAAJQAAADESzkz86CCd/+mlI3/rJyT/4Z5
|
||||
cf+djIX/m4qD/5CAef9xZF7/jHx1/3BiWe0GBQSzAAAAsAAAAMQBAQDWCgUE5U83KfaCa2D/lH11/3hp
|
||||
Y/+QgHn/noyF/xQODf8SU4X/CBuY/wUK//8BAOn/Cypv/yfC5v8luvf/IJvN/yKx+f8MKzrlAAAAIgAA
|
||||
ABAAAAAHAAAAAwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAwAAAAqAAAAZgAAAKgAAADMVEdA+LKg
|
||||
mP+pmZH/rp+U/4Z3b/9+cGr/joB5/4R3cf9zZ1//dmhi/4p5cv8fHRjlAAAA3AYEBOQgGhfzV0U4/pqA
|
||||
df+wnpX/no6F/4V1bv9yZF7/ERIX/wUNzf8AAJ//AgK+/wAA8v8LJlr/K9bh/y/w//8NO0r/EEh+/ynZ
|
||||
//8SVHj/AAAAywAAAEgAAAAnAAAAEgAAAAQAAAABAAAAAAAAAAAAAAABAAAABAAAABcAAABIAAAAjwAA
|
||||
AMAAAADZZlxV+rSkmv+4qZ//oZGJ/419dv+QgHn/eGlh/35waP+Nf3b/emxl/5KCe/9kVEr+GxQO+Ug9
|
||||
OP2Mf3j+loZ+/52LhP+qmpH/oZGI/15STf8ICTL/CB30/wUTzv8il4j/HYac/wgcRf8qz93/NP///xZg
|
||||
av8AAJb/D0W8/y3h/f8TWZ7/AQBY/wYEAPABAQCJAAAAQwAAAB0AAAAIAAAAAAAAAAAAAAABAAAACQAA
|
||||
ACgAAABoAAAArQAAANCCaV74pJSN/8i4rf+omY//koF6/4t7dP9+b2j/koB5/5uJgv+UhHz/iXlx/3Bh
|
||||
XP9lW1f/UEM8/4F0bf+jk4r/m4qC/52Nhf+gj4f/OjIs/wgUf/8KKv//AgDw/xlhU/87////L+b//y3g
|
||||
8P8w7v//F2N//wAAqP8BAP//E1SY/y7n//8PPn//AADr/wYWv/8GCCv/AQMEuQAAAEkAAAAWAAAAAAAA
|
||||
AAAAAAAEAAAAEQAAADwAAACCAAAAvCUbGOKhjoT+sKCW/7ionf+Yh4D/gHBp/3hoYP+KeHH/kYF4/5+P
|
||||
h/+Xhn//h3hx/3hoYf+XhoD/cF5V/5WEff+ejYX/nYyF/21hWv8LCQz/ChmV/wop//8IJPr/Ch/z/wcS
|
||||
of8eiZD/Nv///zP///8jrKD/AABe/wYZ//8CAJ3/H4+m/yrT/v8IGoz/BAzS/wUWy/8GFKX/BQYm/wUG
|
||||
BOUBAQFBAAAAAAAAAAEAAAAHAAAAHgAAAFUAAACbAAAAyUc/Ou6ejYX/pJOL/6WUjP+ejoX/iXpz/4t7
|
||||
cv+Xh37/mId//5+Ohv+pmI//koJ5/5GBeP+cjIP/dGNb/4t7dP+bioP/iHx2/zEtKf8hHyT/KipE/yYk
|
||||
Jv8lIiX/ISEp/xkSPP8REA7/Gnh5/zb//f86//D/IqGV/wAAlf8NMYr/Nv///xhkgf8eKzT/KDg//xca
|
||||
Hf8lLDP/ERUd/wYHCu0BAQFxAAAAAAAAAAEAAAAMAAAAMAAAAHQAAAC0AwMD1WleWfidjYT/pZSL/5yK
|
||||
g/+OfHX/hnly/5CBef+Pfnb/m4uA/6aTiP+di4P/moqC/5mJgf+VhX3/lIN7/5eFfv+gjof/nIqE/5iH
|
||||
gP+djYT/kIF4/5CAeP+Le3P/hnZv/4x9df+UhX3/SD04/xA6bf8XW6z/EESi/wYMPv8y+f//JKu7/1uA
|
||||
kv+Nx+P/kcvn/1d4jv9KVmr/LD9N/xIfKacAAAAUAAAAAAAAAAIAAAAQAAAARAAAAJMAAADGKSYj5KWV
|
||||
jP+woJb/pZSM/4V0b/+MfXb/nYyE/5iJgf+UhHv/pI+G/6GRh/+Qf3j/lYR9/6CRiv+ZiID/mYeA/5mI
|
||||
gf+ci4P/n46G/5iIf/+KenP/gXBo/31tZf+GdG3/iHdv/4d1b/+LhYP/WGRm/wYASP8AAP//BAmf/zHr
|
||||
4f8jrK3/WH6O/3y71P+JxeH/jcjj/4292f9FWWj+JC86+QkPE3EAAAANAAAAAAAAAAIAAAATAAAAUAAA
|
||||
AKIAAADNh3p0/K2dk/+snZL/no2F/4N0bf+RgXr/jXx1/5yLg/+YiID/mYiA/5ODfP+NfHX/mYiB/56M
|
||||
hf+Yh4D/nY2E/5CBeP+Sgnr/loZ+/5qJgf+nl47/nY2E/5SEe/+PfXb/e3Rx/1Zocv9fg5L/Pml+/x4s
|
||||
Pf8OKmv/Ip6E/xhrdf9kjqD/i8zm/4HC3P+Fwdz/iL7X/32xyv8xPkn/Hiw28wUIClcAAAAMAAAAAAAA
|
||||
AAIAAAARAAAATQAAAKEAAADWqZqR/6STi/+ikon/b2Nd/3xqZP9wYlr/fm5n/4p5cv+OfXb/i3t0/4V1
|
||||
bv+MfHX/loR9/5qJgf+WhX3/jn53/4h3b/+Id2//mYmA/6OSiv+hkYn/qJiP/5uNhP9zdnj/T2h6/0uO
|
||||
rf9UlbP/Z7LP/052hv8RMD3/CSPV/woMIf+GxOD/gsbf/3+/3P+Dvdf/erDJ/3epwv9jla//HTxM6wAD
|
||||
BEQAAAAFAAAAAAAAAAMAAAAQAAAASgAAAJ4AAADQopOK/56Mhf+gj4f/kX95/4NzbP+DdG3/fGxl/35u
|
||||
Z/96a2P/dGZf/4R0bf+Nfnb/i3pz/5B/d/+TgXj/nY2E/5+Ohv+di4T/o5KK/6CPiP+fjof/oJGJ/2Vw
|
||||
dv8/X3T/Y6XF/1WiyP9cosb/drzY/3e51P8JD3b/Ch/e/z1WXv9/wNr/gL3W/4C92v+GxN3/baK9/4G8
|
||||
1P9/wuH/ETJIlwAAABQAAAACAAAAAQAAAAYAAAAXAAAAUAAAAKIAAADMjoJ5/6iYj/+qmpH/oI+H/5GB
|
||||
ev+SgXr/lYN8/5GBev+RgXn/koF6/41+dv+Le3L/jXdt/4x6c/+XhX3/mYeA/5iHgP+ejYX/opKJ/5qK
|
||||
gf+NfnX/a3By/zhhdv9orsv/YKvP/0uZv/9krc3/c7zZ/3u72P8sP1P/Cg8t/2qbrv9zrsf/e7TN/4W/
|
||||
2P+FwNv/erbR/3Oiwv9pqsf/AwkOUgAAAAgAAAABAAAAAwAAAA0AAAAoAAAAZQAAAKwAAADQm4yE/7Sl
|
||||
mv+klIv/oI+H/5iGgP+Le3T/lIN8/5ODfP+Ug33/lIJ7/5iHf/+ch3//kX54/3JjXf+Ugnz/loV+/5WE
|
||||
ff+ai4L/jHx0/4NzbP+HhYP/R2p//1iny/+Iyeb/O3Wo/0+fwv9vvNv/eL/c/3m72P9LcH7/DAoA/4jG
|
||||
3v93uNH/fL3X/4zD2/9/udX/f8De/4y+1/87cJDxAQIDLgAAAAcAAAAAAAAABwAAABwAAABKAAAAiQAA
|
||||
AL4AAADap5iP/66elf+hkIj/oI+I/5SDfP+Qf3j/koB5/5KAef+aioL/lYR8/56Ohf+ci4T/mIZ//4Ry
|
||||
bP+RgXr/momC/458df97bmX/gGRU/4l2bP9Qh6b/XqrO/2Oozf9hp8v/Ya3O/2q72v94vdz/gcbi/3y9
|
||||
2/9nnbD/U3OB/4zN5/+Bw9z/gL7a/32zyf92sMn/iMfg/3251f8pUWjIAQEBIQAAAAIAAAAAAAAADQAA
|
||||
ADQAAAB1AAAAsAAAAM8pIyDsrJuS/56Nhf+ejIX/k4J7/4Z1bv+Pfnf/kYF6/4d1b/+cjIP/mouD/5qI
|
||||
gf+UhH3/i3pz/4t5cv+XhX7/koB5/2teVf94fH//dK/I/2e42P9RkL7/YrDR/1qoyf9eqsv/WqbJ/3bB
|
||||
3v97w9//fcTh/32+3P+DxN//g8Db/4TJ4/9/v93/gbzX/3Kmv/9qqMD/i7/b/1N/p/8ZLjp9AgQEFgAA
|
||||
AAAAAAAAAAAAGAAAAEwAAACWAAAAxickIemAcWj/loV+/4t5cv9/bmf/fW1m/3BjW/96aGL/bmBZ/31t
|
||||
Zv+Ne3X/koF6/4x8df+FdW7/i3t0/5SCe/+Qf3j/gnFq/2trav9rtdT/bLTU/2KjyP9tt9f/X6XI/2Ow
|
||||
zf9Zp8r/Z7DQ/3m/3v+Axd//fL3b/3/B3v+IzOb/h8nk/4rL5P+ExeP/hMXe/2qeuf92scb/oc7q/0yC
|
||||
pv8OHihoAQEBDQAAAAAAAAAAAAAAJwAAAGMAAACqBwYG03FjXvqTgnv/bl9Y/3dnYP91Z2D/d2dg/3Bg
|
||||
W/98bGX/gnNs/3trZP+BcGj/fGxk/3NlXv+EdG3/lIV9/6COh/+NfHX/ZF5a/0p5nP9ajar/WJO9/3K+
|
||||
2v9/vdz/YKPG/2muzv9cqcn/ZbHR/3K72P9+wN3/hcXi/4fI5P+Jy+T/f8Dc/4fF3/+NzOX/iMbf/3m3
|
||||
0f9nlrT/b5uz/yhVb+YFCw5KAAEBCQAAAAAAAAAAAAAAQAAAAIMAAAC7CAUF21BEPv5uYFj/hndw/4l6
|
||||
cv+KenT/momB/5KBev+RgXr/k4F6/5mJgv+Tgnr/iHdw/4p5c/+ThH3/m4yF/6CPiP+CdXH/TnKL/0tv
|
||||
k/8hITb/M0Zh/2OjyP90u9j/abHO/2etzf9cqMn/Z7HR/3e92f95u9j/eb7b/5PV8P+Mzeb/fsPd/3/D
|
||||
3f+Szeb/h8Lf/3/A3v+Mu9T/RnGF/hEiMcwAAABAAAAABwAAAAAAAAAAAAAAXgAAAKQAAADMKCUj6ZmH
|
||||
gP+ejIX/lIN8/5iHf/+YiH//mYeA/5OCe/+UhH3/hXRu/4x6dP+SgHn/mYeA/5qJgf+bioP/loV+/4h3
|
||||
cf9bXl//bLrc/3S/4P9LdJj/KiNI/z1ehf9mr9L/d77b/1uoy/9Vo8b/bLDN/3q/3P97vdr/hMrj/5LQ
|
||||
7P+Oz+v/iMzm/4TF3/+Gwdz/hMbh/4rO6P+Oxd7/PGyF/hocHNUCAwNeAAABEQAAAAEAAAAAAAAAdQAA
|
||||
ALUAAADekIB7/pODev+ejob/mIeA/6iXj/+jkor/mIZ//5KAef+RgHn/jn12/5qIgf+cioP/no2F/6OR
|
||||
iv+hkYj/iHdw/2JVTf9NfJX/YqrR/3O31/93weH/VoKj/2+y0f9ppM3/ebvb/1Kfxf9nsdD/YKPG/3G3
|
||||
1v96vNn/gsTg/4rL5/+FyuT/gsTh/4jK5v+Fw93/d7/b/5zT7/97r8//Y6vF/zVZaNwRGx5dAAABEgAA
|
||||
AAIAAAAAAAAAiQAAAL8jHxzoq5yR/56Nhf+hkIj/rJyT/6mZkP+qmpH/m4uD/5KBev+WhX3/kH55/5WD
|
||||
fP+VhH3/oo+J/6iXj/+cjIP/c2Ja/3xwaP9WncX/abLS/3O62f9qtNT/d8Hd/3vD4P+MxuP/Y6bM/1up
|
||||
yv9qtdT/ZK3M/3jA3f95wN//hMrl/4rM5/+Ky+X/hcbk/4rO6P98u9v/hMni/6zZ9f9km77/K1V37gkQ
|
||||
FGoBAQEHAAAAAAAAAAAAAAAAAAAAngAAAMlZUEzxoI+H/6uckv+omI//oZCJ/6STi/+ikIr/nImD/5aE
|
||||
ff+aiIH/j313/4x7dP+UhH3/m4mC/6SUi/+Ugnv/cVxO/3ymuv9KibL/dLnZ/3rB3v9fpsj/b73b/3G5
|
||||
1v99x+P/ZLLQ/02Xwf9rtNj/fMXh/3O52P91vt3/eb7b/37A3f+HyOL/js/p/4/Q6v+Dx+T/erPX/5XL
|
||||
5/9Jl7v+GjJBrgEBAQoAAAAAAAAAAAAAAAAAAAAAAAAApw0NDdaIeHD9kX95/6qbkf+unpX/j395/459
|
||||
dv+pmJD/n46H/56Ohf+gkIj/kH95/4x8dv+JeXL/kIB4/5WFfP9yZmH/b36H/2aqzv9nr8//esLe/3m/
|
||||
3v9rtdT/arbW/2iz0P9rvdr/UqbG/2q41P9gqs3/crjX/2Spzf+AyeT/f8Hd/3m+2/+Cx+H/k9Ht/4rH
|
||||
5P+Fx+T/mc7p/2amxP8nSF36AAAAawAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqBUSEN2Ug3r9lYV8/6OT
|
||||
iv+klIv/l4V+/4p6dP+omI//p5aO/56Ohf+WhX3/j394/3hoZP9uXFb/emtk/3NnXv9ydXn/bLXV/2Sp
|
||||
zv92vdz/fcbh/3zE4f9xu9v/Z67Q/16kx/9QnMD/Xq/O/2Wy0f94wN3/c7jV/3q83P9encj/gsrj/33C
|
||||
3v+CxN//jMjk/4bI4/+Lz+n/lM/q/0d+nf8sLiv3BQYHTwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArg8P
|
||||
DdqSgX38qZiQ/6WVjP+ci4P/lYR9/419d/+KeHH/opGJ/5WFfP91YlX/hGpX/2ZkY/9HUlj/OFVn/1eQ
|
||||
tf9fpcj/Y6jP/3W+3f96wt7/drrX/36/3f9+x+L/bbjV/2241f9hsc7/ZrTS/2u41P92udX/h83o/4fI
|
||||
5f97wd3/dr3a/3K72/+DxuL/hsfj/3jA3P+c0+//fLPT/2avyf5HfZLyHzI3SwAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAux0aGuGWhH39rp6V/6qbkf+Yh3//koB6/5B/ef+Rf3j/fWtk/4huXf+jrK//d7jX/2Ow
|
||||
1v9kstb/Up3I/2Wlyv9krdD/Y6/S/2y52f9ut9b/er3Z/4PG4v99wt7/f8Xh/3jE4P91wd7/bbrW/3W9
|
||||
2v99w97/hMnl/4jL5/+BxuD/i8/p/3m+3v+Izef/fbzc/4XK4/+s2fX/ZZ7C/y1dhOwTJzK9FxobTQAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAxzo0Muqbi4T/saKY/7Cgl/+fjYb/kIB6/49+d/+Bcmn/fGxg/3u7
|
||||
1P9sqc3/Z6vP/2Kny/9vuNf/abfW/3O72P95w9//cLjV/3C+2v9wuNX/gsTh/33A3/9wudb/db7b/2i1
|
||||
0v9uutf/cLzY/4HG4v+P0er/icvk/4XH4v+Ozej/itDr/43S7P+O0Ov/hcnm/3q02P+TyeX+SZu//yNH
|
||||
XKEHBwcnCgkITAAAAAEAAAAAAAAAAAAAAAAAAAABCwsNtZKEfPicjIX/sqKY/66elP+hj4n/opGJ/5GC
|
||||
ef+OfnP/icbj/1qdw/9ZmL//f8Xh/3fA3f91wd3/eb7d/4PL5f+EyuP/fsbg/3e+3f93vNv/gMHe/3u9
|
||||
3P9wt9T/dbnW/2m21f9rtNP/cbnW/3693f9dh7T/Ypa8/4bH4f9zp8f/gsLf/47M6P+R0On/jtDs/5jP
|
||||
6v9mp8X/GTJFrgAAACYCAgISAgMDEwYGBxAAAAAAAAAAAAAAAAAAAAABExMTgJCGffWdj4f/t6ee/6iX
|
||||
jv+tnJT/pZWM/5KBc/+WtML/ZqbL/2Gkyv9xvt3/fMXh/3rB3v93vdz/g8nl/37E4P90vdn/ecDd/3nA
|
||||
3f97vdz/d7jV/3a71/96wd7/fr/d/3G41f9zuNX/hcfk/1yMtP9Fa5n/LUd8/2yhxP9RcJj/cqPG/4nC
|
||||
3/+MyuP/hc3n/5PO6v9Hf5//AwUFYgAAAB8AAAAHBAMDCAsLDBoEBAQHAAAAAAAAAAAAAAAAAAAADwcH
|
||||
BzMPDg1MPTk2ro6EevKbjYT/o5SK/6GKev95vNn/aqrO/3O61/99xOP/esLe/37E3/96xd//e8Pf/3i9
|
||||
2v9qstL/a7bT/3W+2v9wtNH/dLnV/2+20/9yvdf/eLnW/36+2/+Mzur/i9Pt/16cxP85XpP/Q1mD/2CV
|
||||
vf9roMP/jMfi/4nF4f+DyOL/hMnm/2yfwv5lvNn/TImj2wAAABMAAAADAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAABAAAABgAAABYAAAA4FBIQlIKCgux4qsn3dKvM/H/A3f+Ky+j/i8nl/4HG
|
||||
4v94vdz/gsLf/4TI4v90u9j/dbva/3W51v9xuNf/bbXS/3O82f99vtz/ervZ/4jK5f+T1fL/iMvn/3m8
|
||||
3v98vt3/TnWg/1qQvP96ttf/h8jk/1aErf9qs9P/n9Tv/2ufv/8lUoL+ECQ0jwAAAAwAAAABAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAEAAAACgAAAB4OEBFRHiktejZN
|
||||
WKdagZTVaY2i4GiRpPF+ssv/kdPv/5DV8f+Fy+f/hMPf/4bI5P9/xuP/ebzb/3m92v94vNn/fMHd/4/Q
|
||||
6v+W1PD/l9jy/4fF4f9HcqH/aqHI/3Ot0f9Mf6v/h8Xi/3y93f8lTIL/iL/f/3Cx1P8mTG3QAAAAHwAA
|
||||
AAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAABAAAAAwAAAAcDBAQYBQYHJQYICTsNEhVlJTM8w1Buf/9Zeo7/i87q/4PE4P+SzOn/icbj/3e4
|
||||
1f97wt//isbi/5PR7f+b2PX/ldPp/4S72v9hmcL/ZqHI/1mMuv+Gw+D/aaPK/1CLuf9hibj/ic3n/kh4
|
||||
qf8OGCV2AAAADQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAFAAAADgAAADIAAAByJzlD0Xmz
|
||||
zvx/vNn/gb/e/3W20/+Exd//k8vn/5nU7/+V0Oz/mNTw/5/a8v9xrtL/UIW0/1WBsP80YJn/h8Pi/4fN
|
||||
6P9nmsb/SYqz/1+WsvIHCw4+AAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAQAAAAPAAAAHxAVGmwxSVajUHqN00Jkdsg8WWW2NlFewXOftfSc1PD/kc7r/4O72/9zrtH/bpzE/2OL
|
||||
u/9Zi73/ib3d/2WSvf9oiLf/TYCr/z9phdIDBQcsAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAMAAAAHAwQFFAEBARUAAAAUAAAAJQYHCFUyQkquUnmO7m+i
|
||||
yf9oosb/cKPC/1N4rP9ZgKz/isPg/2SXwv9Yibf/OnGf/xkoSawAAAAbAAAAAQAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAA
|
||||
AAcAAAAPAAAAGwUGB2UGBgiAIC40vHGbv/pnm8H+jcfg/1yJvf+Bt9f/T4Op+Q8bInUAAAANAAAAAQAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAALAAAAGgkLD1UfLDWMITVCrT1ced93pMf/c6bE/BMd
|
||||
IVUAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAIAAAAIAAAAFgID
|
||||
AysUHSFgHC02gQAAAAoAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AB/gfgP
|
||||
AAD8AD+AcA8AAPwAH8AADwAA/AAPgAAfAAD4AAAAAB8AAPgAAAAAHwAA8AAAAAA/AADwAAAAAD8AAPAA
|
||||
AAAABwAA4AAAAAABAADgAAAAAAAAAMAAAAAAAAAAwAAAAAAAAADAAAAAAAAAAIAAAAAAAAAAgAAAAAAA
|
||||
AACAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAEAAAAA
|
||||
AAAAAwAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAABAAAAAAAAAAEAAAAAAAAABwAAAAAAAAAP
|
||||
AAAAAAAAAB8AAAAAAAAAHwAAAAAAAAAfAAAAAAAAAB8AAAAAAAAADgAAAAAAAAAOAAAAAAAAAAcAAAAA
|
||||
AAAAPwAAwAAAAAA/AADwAAAAAH8AAP8AAAAA/wAA//gAAAD/AAD//wAAAP8AAP//wAAA/wAA///+AAD/
|
||||
AAD////wAf8AAP////wB/wAAKAAAACAAAABAAAAAAQAgAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAABAAAAEQAAADsAAABeAAAAXwAAAEIAAAAeAAAACAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAFQAAAF8CAgKIAAAAMAAAAAMAAAAAAAAAAAAAAAQAAAAhAAAAXQAAAFMBAQB6AQEBLAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAmAAAAgwAAALwdFxTdAAAAsgAAAHcAAAAyAAAABwAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAJAAAAUgICAsECAgb/AQAAVAAAAAQAAAAIAAAALgAAAHwAAACmAgIAwQME
|
||||
Cv8AAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABgAAADkAAACiQTYw5Yp0bv+ObWP9WkVA5SYg
|
||||
HJQAAAAqAAAABQAAAAEAAAACAAAABAAAABIAAABSAQEBsAQFMPwEC2f0BAQLogEAAG4AAACVAQECxgMF
|
||||
MeoEC2L/AwIEjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAQAAAAVQAAALJIOzbrmYiB/6OO
|
||||
h/+aiIH/fGtk9QICAmAAAAATAAAABAAAABIAAAAqAAAAVgEBAZoFBgjLBgcH+QMPxf8CAbT/BAsO9gYi
|
||||
MOsEDDH/AgR6/wMDP/wAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAACIAAACCAwICzWxd
|
||||
V/aaiYH/nY2F/5eGgP+UgXn/Ny0nxQAAAEIAAAAgAAAARgAAAIUJBgS4FBEO2DdQXvcnyff/DkGI/xl7
|
||||
uf8ho9f/IKHZ/x2Ox/8bhbP/DkZf4wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAANwAA
|
||||
AKEiGhbklnpx/56Ohv+ik4v/koJ7/5mHgP+TgHr+Ih0amgAAAGoAAACaAAAAzEQvJ+59XlH9dmlj/lFI
|
||||
R/8rytr/I62//wUOlv8AAHD/G4Gu/yKt9P8MOlSvAAAABAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAgAA
|
||||
ABUAAABXAAAAs09BOvaplIz/rZ6U/4p8dP+VhX7/f3Fq/4FybP9IQDrhAAAAxgoJB90wJh3yh29k/ZmG
|
||||
ff+AcWr/WE9O/wscgP8FD6v/BQzN/xuAqP8iqsr/GHKm/xqDq/kAAAB3AAAAIgAAAAsAAAACAAAAAAAA
|
||||
AAEAAAAEAAAAMAAAAI8AAADNZlxV+rannf+hkYn/j394/3hpYf+GeG//emxl/3trY/8bFA75a15Y/paG
|
||||
fv+kk4v/oZGI/zMuQP8IHfT/FFWr/x2GnP8ZdpH/NP///wswgP8PRbz/IJ3O/wEAWP8EAwC9AAAAQwAA
|
||||
ABMAAAAAAAAAAgAAAA0AAABUAAAAtVNGP+qqmpL/sKGX/4l5cv+Dc2z/koF5/5qJgf+IeXH/emtm/2BR
|
||||
Sf+Wh3//nIuE/25iXf8iJmH/CSPe/wYQ8v8ff6H/M/P//y3f5P8MMm//AwfR/xlyn/8chcL/Agbf/wYS
|
||||
l/8DBBXcAgICYgAAAAAAAAAEAAAAHgAAAHgAAADJcmZg96STi/+ikYn/iXpz/5GBeP+Yh3//pJOL/5KC
|
||||
ef+Xh37/dGNb/5ODfP+IfHb/KSYn/yoqRP8mIyb/ISEp/xURJf8aeHn/OP/3/yKhlf8HGZD/Nv///xtI
|
||||
W/8oOD//HiMo/xEVHf8DBQWvAAAAAAAAAAgAAAA6AAAAoRcVEt2XiH/+pZSM/49+eP+Sg3v/k4R7/6CN
|
||||
g/+ejIP/mIeA/5qKgv+XhX7/nIqD/56Mhf+Whn7/iXlw/4h4cP+Hd2//jX95/1BRT/8MJpn/Cieh/yOo
|
||||
s/8+laX/fLLL/4/K5f9deY//KTZD/AcMEE8AAAAAAAAACwAAAFAAAAC4h3p0/K2dk/+ejYX/int0/418
|
||||
df+aioL/mYiA/5CAef+ZiIH/m4qD/52NhP+Rgnn/loZ+/6GQiP+djYT/koF5/3t0cf9bdoL/Pml+/xYr
|
||||
VP8inoT/Pn2L/4vM5v+Dwtz/iL7X/1d4iv8eLDbzAwQFMgAAAAAAAAAKAAAATAAAALqml47/oZGI/4Bx
|
||||
a/99bWb/fW1m/4R0bf+AcWr/iXly/5F/eP+VhHz/loZ+/5OCev+ejoX/oZGJ/6SVjP9tdXr/WYeg/1Wa
|
||||
vP9vt9T/OFyE/woh2v9Teo//gcLb/4LA2/90qcP/d6/K/xc2S8EAAQEYAAAAAQAAAA8AAABQAAAAt46C
|
||||
ef+pmZD/oI+H/5KBev+Vg3z/kYF6/5KBev+MfXT/jXdt/5KAeP+Zh4D/m4qD/6KSif+UhHv/a3By/1CI
|
||||
of9gq8//WKPG/3O82f9UfZb/Cg8t/2+lu/97tM3/hcDa/3q20f9upsX/AwkOUgAAAAUAAAAFAAAAJwAA
|
||||
AHcAAADFoZKK/6qakf+gj4j/koF6/5OCe/+VhH7/lYN8/5yKgv+Vgnz/h3dw/5iHgP+Pf3f/hnBk/3l+
|
||||
gf9Tiqf/abDT/06Ru/9otdX/fcPf/2qiuf8wP0H/hMTd/36+2f+AuNH/hMTf/1uPqu4BAgIoAAAAAwAA
|
||||
AA0AAABVAAAAsBUREd6sm5L/no2F/5OCe/+LenP/kYF6/5KBef+ai4P/l4Z//4t6c/+Rf3j/koB5/3Jt
|
||||
av90r8j/XKTL/2Kw0f9cqcr/WqbJ/3nC3/99xOH/gMHe/4PA2/+CxOD/gbzX/26nwP+Lv9v/NlZxvgIE
|
||||
BBYAAAAAAAAAIAAAAHwDAgLNal9Z+YJya/9+bmf/empj/3ZmYP94amP/gnFq/4d3b/+Dc2z/kIB5/5WD
|
||||
fP9zaGL/X4qh/2Kkyf9xttb/YKTH/2GszP9msdH/e8Dd/4HB3/+GyeP/g8Xg/4nJ4/+Gxt//cKjC/4i1
|
||||
z/8iQFOmAQEBCwAAAAAAAABAAAAAnwgFBdtfUkv/hndw/4p6c/+aiYH/koF6/5OBev+Whn7/iHdw/49/
|
||||
eP+bjIX/kYJ9/05yi/82SGX/M0Zh/2yv0P9psc7/YqvL/2ex0f94vNn/eb7b/5DR6/9+w93/icji/4fC
|
||||
3/+Gvtn/RnGF/gkRGYYAAAAHAAAAAAAAAGoAAADBXVJO9JuKgv+WhX7/n4+G/5mHgP+Tgnv/inly/5WD
|
||||
ff+cioP/n46G/49+d/9lam3/Z7LX/2urzP9AU3b/X5m+/3i92/9bp8r/ZqrK/3m82v+Dx+L/jM7p/4XI
|
||||
5P+GxeD/fsPe/4zG4f9QjKb/GCUqnAAAARIAAAABAAAAiREQD9SrnJH/oI+H/6yck/+qmpH/m4uD/5SD
|
||||
fP+Qfnn/lYR9/6KPif+ikon/c2Ja/2mHl/9pstL/b7fX/3fB3f+ExeL/Y6bM/2Ovz/9krcz/ecDe/4TK
|
||||
5f+KzOb/hcbk/4PF4v+EyeL/iLra/ytVd+4FCQs5AAAAAAAAAAAAAACjPDYz5JmHgP+rnJL/mIiB/6CP
|
||||
h/+ejIX/nIuD/5B+eP+Ofnf/loV9/5CBef9wbWv/ZaPD/3e+3P9wt9b/bbrZ/3G82f9brMv/YazP/3e/
|
||||
3P9zu9r/fMDc/4HE3/+R0Ov/icrm/4rB4P9blLH+DRohjQEBAQMAAAAAAAAAAAAAAKhVSkbtlYV8/6SU
|
||||
i/+XhX7/mYmC/6eWjv+aioH/j394/3NiXf96a2T/c25s/2y11f9ts9X/fcbh/3fA3v9nrtD/V6DE/16v
|
||||
zv9vudf/c7jV/2yt0v+CyuP/gMPf/4zI5P+JzOb/lM/q/zlWY/sFBgdPAAAAAAAAAAAAAAAAAAAAtVZM
|
||||
SO2sm5P/oZGI/5SCfP+PfXf/kH53/46BeP9+kZf/Xoaa/0V5mP9gosb/Y6zR/3O82/94vNj/f8Tg/3a/
|
||||
2/9vvNn/arfU/3W92f+Gy+f/g8fj/4HG4v9+xOH/gsLg/5LO6f9xqcv/PG2F5xsmKUwAAAAAAAAAAAAA
|
||||
AAAAAADHa19a9bGimP+ol4//kIB6/4h4cP98bGD/dLLR/2erz/9psNH/abfW/3a/3P9wuNX/cLvY/4LE
|
||||
4f93vdv/db7b/2u41f9wvNj/iMzm/4nL5P+KyuX/itDr/47R7P+Fyeb/h7/f/0mbv/8VJzJkCgkITAAA
|
||||
AAEAAAAAAAAAARAQEJuXioL7taWb/6qZkP+kk4v/ko6J/3i21/9ipsv/fsXh/3jA3f9+xOH/f8bh/3zD
|
||||
3/95vt3/fL3a/3e82v96vNr/brfV/3vA3f9gj7j/SG+c/26gwf96s9P/jsrl/4rP6v92sc//DhwliAEB
|
||||
ARgDAwMOBgYGDQAAAAAAAAABAAAADwsLCkA9OTaulImA+aOUiv+No6r/aqrO/3i/3f96wt7/fMXf/3vD
|
||||
3/9xuNb/a7bT/3O51v90udX/cbrV/3i51v+FxuP/i9Pt/0x9rP9DWYP/ZpvA/4zH4v+Gx+L/hMnm/2mu
|
||||
zv9MiaPbAAAACwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAMAAAAVCgkIT0NPWJVJan27Zpas33mq
|
||||
xPB4ssz8isvn/4TJ5f99v93/e8De/3O51/95vdv/e77b/5HR7f+Q0u3/ca3Q/1yLtP9lncT/h8fj/1mR
|
||||
uP+Uyuf/Snuh9AgSGlcAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
|
||||
AAMCAgIQBQYHJQoND1AlMzzDVXSH/4vO6v+LyOX/icbj/3m92v+KxuL/l9Xx/5XT6f9zqs7/ZqHI/3Co
|
||||
zf9po8r/WYq5/4nN5/4rSGe7AAAADQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAcAAAAuFB0ieE9zhsNonLbpXo+k32SNo+CQxeD9ldHu/4K9
|
||||
3P9fkbz/Un6x/4jA4P9vocn/S4Wv/ypEU4wAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABQMEBRQBAQEVAAAAJRwl
|
||||
KoJSeY7ubKLI/3Cjwv9WfKz/isPg/16Qvf86cZ//DRQlZAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAEAAAABAAAABgAAAA4DAwQ+ERcaa0BccbdWfpDWZY+092GVtvsJDxE3AAAAAQAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABQAAABYLEBJGHC02gQAAAAYAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAADwD4MD8AeAA+AAAAfgAAAH4AAAD+AAAAPAAAAAgAAAAIAAAACAAAAAgAAAAIAA
|
||||
AACAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAAAAAAAAwAAAAMAAAAHAAAABwAAAAIAAAACAAAAD4AA
|
||||
AA/4AAAf/4AAH//wAB///gAf///wPw==
|
||||
</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -8,13 +8,13 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
namespace OpenRA.Traits.Activities
|
||||
{
|
||||
class Idle : IActivity
|
||||
{
|
||||
public IActivity NextActivity { get; set; }
|
||||
using SGraphics = System.Drawing.Graphics;
|
||||
|
||||
public IActivity Tick(Actor self) { return NextActivity; }
|
||||
public void Cancel(Actor self) {}
|
||||
namespace OpenRA.Editor
|
||||
{
|
||||
interface ITool
|
||||
{
|
||||
void Apply(Surface surface);
|
||||
void Preview(Surface surface, SGraphics g);
|
||||
}
|
||||
}
|
||||
@@ -10,13 +10,13 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using OpenRA;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Traits;
|
||||
using System.Drawing;
|
||||
|
||||
namespace OpenRA.Editor
|
||||
{
|
||||
@@ -82,6 +82,7 @@ namespace OpenRA.Editor
|
||||
// {"scrate","crate"},
|
||||
};
|
||||
|
||||
// todo: fix this -- will have bitrotted pretty badly.
|
||||
static Dictionary<string,Pair<Color,Color>> namedColorMapping = new Dictionary<string, Pair<Color, Color>>()
|
||||
{
|
||||
{"gold",Pair.New(Color.FromArgb(246,214,121),Color.FromArgb(40,32,8))},
|
||||
@@ -401,13 +402,13 @@ namespace OpenRA.Editor
|
||||
{
|
||||
new LocationInit(new int2(loc % MapSize, loc / MapSize)),
|
||||
new OwnerInit(parts[0]),
|
||||
new HealthInit(float.Parse(parts[2])/256),
|
||||
new HealthInit(float.Parse(parts[2], NumberFormatInfo.InvariantInfo)/256),
|
||||
new FacingInit((section == "INFANTRY") ? int.Parse(parts[6]) : int.Parse(parts[4])),
|
||||
new ActorStanceInit(stance),
|
||||
};
|
||||
|
||||
if (section == "INFANTRY")
|
||||
actor.Add(new SubcellInit(int.Parse(parts[4])));
|
||||
actor.Add(new SubCellInit(int.Parse(parts[4])));
|
||||
|
||||
Map.Actors.Add("Actor" + ActorCount++,actor);
|
||||
|
||||
|
||||
375
OpenRA.Editor/MapSelect.Designer.cs
generated
Normal file
375
OpenRA.Editor/MapSelect.Designer.cs
generated
Normal file
@@ -0,0 +1,375 @@
|
||||
namespace OpenRA.Editor
|
||||
{
|
||||
partial class MapSelect
|
||||
{
|
||||
/// <summary>
|
||||
/// TODO
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// TODO
|
||||
/// </summary>
|
||||
/// <param name="disposing">TODO</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Код, автоматически созданный конструктором форм Windows
|
||||
|
||||
/// <summary>
|
||||
/// TODO
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MapSelect));
|
||||
this.MapList = new System.Windows.Forms.ListView();
|
||||
this.colMapName = new System.Windows.Forms.ColumnHeader("(отсутствует)");
|
||||
this.MapIconsList = new System.Windows.Forms.ImageList(this.components);
|
||||
this.btnCancel = new System.Windows.Forms.Button();
|
||||
this.btnOk = new System.Windows.Forms.Button();
|
||||
this.lblNew = new System.Windows.Forms.Label();
|
||||
this.txtNew = new System.Windows.Forms.TextBox();
|
||||
this.pbMinimap = new System.Windows.Forms.PictureBox();
|
||||
this.pnlBottom = new System.Windows.Forms.Panel();
|
||||
this.txtPathOut = new System.Windows.Forms.TextBox();
|
||||
this.lblPathOut = new System.Windows.Forms.Label();
|
||||
this.lblPath = new System.Windows.Forms.Label();
|
||||
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
|
||||
this.lblMapList = new System.Windows.Forms.Label();
|
||||
this.txtDesc = new System.Windows.Forms.TextBox();
|
||||
this.lblDesc = new System.Windows.Forms.Label();
|
||||
this.txtTheater = new System.Windows.Forms.TextBox();
|
||||
this.lblTheater = new System.Windows.Forms.Label();
|
||||
this.txtAuthor = new System.Windows.Forms.TextBox();
|
||||
this.lblAuthor = new System.Windows.Forms.Label();
|
||||
this.txtTitle = new System.Windows.Forms.TextBox();
|
||||
this.lblMapName = new System.Windows.Forms.Label();
|
||||
this.lblMinimap = new System.Windows.Forms.Label();
|
||||
this.pictureBox1 = new System.Windows.Forms.PictureBox();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pbMinimap)).BeginInit();
|
||||
this.pnlBottom.SuspendLayout();
|
||||
this.splitContainer1.Panel1.SuspendLayout();
|
||||
this.splitContainer1.Panel2.SuspendLayout();
|
||||
this.splitContainer1.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// MapList
|
||||
//
|
||||
this.MapList.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||
this.MapList.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
|
||||
this.colMapName});
|
||||
this.MapList.FullRowSelect = true;
|
||||
this.MapList.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;
|
||||
this.MapList.LargeImageList = this.MapIconsList;
|
||||
this.MapList.Location = new System.Drawing.Point(15, 25);
|
||||
this.MapList.MultiSelect = false;
|
||||
this.MapList.Name = "MapList";
|
||||
this.MapList.Size = new System.Drawing.Size(273, 294);
|
||||
this.MapList.SmallImageList = this.MapIconsList;
|
||||
this.MapList.StateImageList = this.MapIconsList;
|
||||
this.MapList.TabIndex = 0;
|
||||
this.MapList.UseCompatibleStateImageBehavior = false;
|
||||
this.MapList.View = System.Windows.Forms.View.Details;
|
||||
this.MapList.SelectedIndexChanged += new System.EventHandler(this.MapList_SelectedIndexChanged);
|
||||
//
|
||||
// colMapName
|
||||
//
|
||||
this.colMapName.Text = "Map name";
|
||||
this.colMapName.Width = 240;
|
||||
//
|
||||
// MapIconsList
|
||||
//
|
||||
this.MapIconsList.ColorDepth = System.Windows.Forms.ColorDepth.Depth32Bit;
|
||||
this.MapIconsList.ImageSize = new System.Drawing.Size(24, 24);
|
||||
this.MapIconsList.TransparentColor = System.Drawing.Color.Transparent;
|
||||
//
|
||||
// btnCancel
|
||||
//
|
||||
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||
this.btnCancel.Location = new System.Drawing.Point(407, 35);
|
||||
this.btnCancel.Name = "btnCancel";
|
||||
this.btnCancel.Size = new System.Drawing.Size(75, 23);
|
||||
this.btnCancel.TabIndex = 3;
|
||||
this.btnCancel.Text = "Cancel";
|
||||
this.btnCancel.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// btnOk
|
||||
//
|
||||
this.btnOk.DialogResult = System.Windows.Forms.DialogResult.OK;
|
||||
this.btnOk.Location = new System.Drawing.Point(326, 35);
|
||||
this.btnOk.Name = "btnOk";
|
||||
this.btnOk.Size = new System.Drawing.Size(75, 23);
|
||||
this.btnOk.TabIndex = 2;
|
||||
this.btnOk.Text = "Open";
|
||||
this.btnOk.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// lblNew
|
||||
//
|
||||
this.lblNew.AutoSize = true;
|
||||
this.lblNew.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
|
||||
this.lblNew.Location = new System.Drawing.Point(12, 40);
|
||||
this.lblNew.Name = "lblNew";
|
||||
this.lblNew.Size = new System.Drawing.Size(69, 13);
|
||||
this.lblNew.TabIndex = 3;
|
||||
this.lblNew.Text = "Map name:";
|
||||
//
|
||||
// txtNew
|
||||
//
|
||||
this.txtNew.BackColor = System.Drawing.SystemColors.Window;
|
||||
this.txtNew.Location = new System.Drawing.Point(88, 37);
|
||||
this.txtNew.Name = "txtNew";
|
||||
this.txtNew.ReadOnly = true;
|
||||
this.txtNew.Size = new System.Drawing.Size(232, 20);
|
||||
this.txtNew.TabIndex = 1;
|
||||
//
|
||||
// pbMinimap
|
||||
//
|
||||
this.pbMinimap.BackColor = System.Drawing.Color.Black;
|
||||
this.pbMinimap.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
|
||||
this.pbMinimap.Location = new System.Drawing.Point(32, 25);
|
||||
this.pbMinimap.Name = "pbMinimap";
|
||||
this.pbMinimap.Size = new System.Drawing.Size(124, 124);
|
||||
this.pbMinimap.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
|
||||
this.pbMinimap.TabIndex = 5;
|
||||
this.pbMinimap.TabStop = false;
|
||||
//
|
||||
// pnlBottom
|
||||
//
|
||||
this.pnlBottom.Controls.Add(this.pictureBox1);
|
||||
this.pnlBottom.Controls.Add(this.txtPathOut);
|
||||
this.pnlBottom.Controls.Add(this.lblPathOut);
|
||||
this.pnlBottom.Controls.Add(this.lblPath);
|
||||
this.pnlBottom.Controls.Add(this.btnCancel);
|
||||
this.pnlBottom.Controls.Add(this.btnOk);
|
||||
this.pnlBottom.Controls.Add(this.txtNew);
|
||||
this.pnlBottom.Controls.Add(this.lblNew);
|
||||
this.pnlBottom.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||
this.pnlBottom.Location = new System.Drawing.Point(0, 332);
|
||||
this.pnlBottom.MaximumSize = new System.Drawing.Size(0, 70);
|
||||
this.pnlBottom.Name = "pnlBottom";
|
||||
this.pnlBottom.Size = new System.Drawing.Size(494, 70);
|
||||
this.pnlBottom.TabIndex = 6;
|
||||
//
|
||||
// txtPathOut
|
||||
//
|
||||
this.txtPathOut.BackColor = System.Drawing.SystemColors.Window;
|
||||
this.txtPathOut.Location = new System.Drawing.Point(55, 10);
|
||||
this.txtPathOut.Name = "txtPathOut";
|
||||
this.txtPathOut.ReadOnly = true;
|
||||
this.txtPathOut.Size = new System.Drawing.Size(265, 20);
|
||||
this.txtPathOut.TabIndex = 0;
|
||||
this.txtPathOut.TextChanged += new System.EventHandler(this.txtPathOut_TextChanged);
|
||||
//
|
||||
// lblPathOut
|
||||
//
|
||||
this.lblPathOut.AutoSize = true;
|
||||
this.lblPathOut.Location = new System.Drawing.Point(55, 13);
|
||||
this.lblPathOut.Name = "lblPathOut";
|
||||
this.lblPathOut.Size = new System.Drawing.Size(0, 13);
|
||||
this.lblPathOut.TabIndex = 6;
|
||||
//
|
||||
// lblPath
|
||||
//
|
||||
this.lblPath.AutoSize = true;
|
||||
this.lblPath.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
|
||||
this.lblPath.Location = new System.Drawing.Point(12, 13);
|
||||
this.lblPath.Name = "lblPath";
|
||||
this.lblPath.Size = new System.Drawing.Size(37, 13);
|
||||
this.lblPath.TabIndex = 5;
|
||||
this.lblPath.Text = "Path:";
|
||||
//
|
||||
// splitContainer1
|
||||
//
|
||||
this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.splitContainer1.Location = new System.Drawing.Point(0, 0);
|
||||
this.splitContainer1.Name = "splitContainer1";
|
||||
//
|
||||
// splitContainer1.Panel1
|
||||
//
|
||||
this.splitContainer1.Panel1.Controls.Add(this.lblMapList);
|
||||
this.splitContainer1.Panel1.Controls.Add(this.MapList);
|
||||
//
|
||||
// splitContainer1.Panel2
|
||||
//
|
||||
this.splitContainer1.Panel2.Controls.Add(this.txtDesc);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.lblDesc);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.txtTheater);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.lblTheater);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.txtAuthor);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.lblAuthor);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.txtTitle);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.lblMapName);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.lblMinimap);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.pbMinimap);
|
||||
this.splitContainer1.Size = new System.Drawing.Size(494, 332);
|
||||
this.splitContainer1.SplitterDistance = 300;
|
||||
this.splitContainer1.TabIndex = 7;
|
||||
//
|
||||
// lblMapList
|
||||
//
|
||||
this.lblMapList.AutoSize = true;
|
||||
this.lblMapList.Location = new System.Drawing.Point(12, 9);
|
||||
this.lblMapList.Name = "lblMapList";
|
||||
this.lblMapList.Size = new System.Drawing.Size(81, 13);
|
||||
this.lblMapList.TabIndex = 1;
|
||||
this.lblMapList.Text = "Available maps:";
|
||||
//
|
||||
// txtDesc
|
||||
//
|
||||
this.txtDesc.BackColor = System.Drawing.SystemColors.ButtonFace;
|
||||
this.txtDesc.Location = new System.Drawing.Point(16, 289);
|
||||
this.txtDesc.Name = "txtDesc";
|
||||
this.txtDesc.ReadOnly = true;
|
||||
this.txtDesc.Size = new System.Drawing.Size(162, 20);
|
||||
this.txtDesc.TabIndex = 14;
|
||||
//
|
||||
// lblDesc
|
||||
//
|
||||
this.lblDesc.AutoSize = true;
|
||||
this.lblDesc.Location = new System.Drawing.Point(13, 273);
|
||||
this.lblDesc.Name = "lblDesc";
|
||||
this.lblDesc.Size = new System.Drawing.Size(63, 13);
|
||||
this.lblDesc.TabIndex = 13;
|
||||
this.lblDesc.Text = "Description:";
|
||||
//
|
||||
// txtTheater
|
||||
//
|
||||
this.txtTheater.BackColor = System.Drawing.SystemColors.ButtonFace;
|
||||
this.txtTheater.Location = new System.Drawing.Point(16, 252);
|
||||
this.txtTheater.Name = "txtTheater";
|
||||
this.txtTheater.ReadOnly = true;
|
||||
this.txtTheater.Size = new System.Drawing.Size(162, 20);
|
||||
this.txtTheater.TabIndex = 12;
|
||||
//
|
||||
// lblTheater
|
||||
//
|
||||
this.lblTheater.AutoSize = true;
|
||||
this.lblTheater.Location = new System.Drawing.Point(13, 236);
|
||||
this.lblTheater.Name = "lblTheater";
|
||||
this.lblTheater.Size = new System.Drawing.Size(47, 13);
|
||||
this.lblTheater.TabIndex = 11;
|
||||
this.lblTheater.Text = "Tileset:";
|
||||
//
|
||||
// txtAuthor
|
||||
//
|
||||
this.txtAuthor.BackColor = System.Drawing.SystemColors.ButtonFace;
|
||||
this.txtAuthor.Location = new System.Drawing.Point(16, 214);
|
||||
this.txtAuthor.Name = "txtAuthor";
|
||||
this.txtAuthor.ReadOnly = true;
|
||||
this.txtAuthor.Size = new System.Drawing.Size(162, 20);
|
||||
this.txtAuthor.TabIndex = 10;
|
||||
//
|
||||
// lblAuthor
|
||||
//
|
||||
this.lblAuthor.AutoSize = true;
|
||||
this.lblAuthor.Location = new System.Drawing.Point(13, 198);
|
||||
this.lblAuthor.Name = "lblAuthor";
|
||||
this.lblAuthor.Size = new System.Drawing.Size(41, 13);
|
||||
this.lblAuthor.TabIndex = 9;
|
||||
this.lblAuthor.Text = "Author:";
|
||||
//
|
||||
// txtTitle
|
||||
//
|
||||
this.txtTitle.BackColor = System.Drawing.SystemColors.ButtonFace;
|
||||
this.txtTitle.Location = new System.Drawing.Point(16, 177);
|
||||
this.txtTitle.Name = "txtTitle";
|
||||
this.txtTitle.ReadOnly = true;
|
||||
this.txtTitle.Size = new System.Drawing.Size(162, 20);
|
||||
this.txtTitle.TabIndex = 8;
|
||||
//
|
||||
// lblMapName
|
||||
//
|
||||
this.lblMapName.AutoSize = true;
|
||||
this.lblMapName.Location = new System.Drawing.Point(13, 161);
|
||||
this.lblMapName.Name = "lblMapName";
|
||||
this.lblMapName.Size = new System.Drawing.Size(30, 13);
|
||||
this.lblMapName.TabIndex = 7;
|
||||
this.lblMapName.Text = "Title:";
|
||||
//
|
||||
// lblMinimap
|
||||
//
|
||||
this.lblMinimap.AutoSize = true;
|
||||
this.lblMinimap.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
|
||||
this.lblMinimap.Location = new System.Drawing.Point(29, 9);
|
||||
this.lblMinimap.Name = "lblMinimap";
|
||||
this.lblMinimap.Size = new System.Drawing.Size(71, 13);
|
||||
this.lblMinimap.TabIndex = 6;
|
||||
this.lblMinimap.Text = "Map preview:";
|
||||
//
|
||||
// pictureBox1
|
||||
//
|
||||
this.pictureBox1.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox1.Image")));
|
||||
this.pictureBox1.Location = new System.Drawing.Point(336, -9);
|
||||
this.pictureBox1.Name = "pictureBox1";
|
||||
this.pictureBox1.Size = new System.Drawing.Size(54, 35);
|
||||
this.pictureBox1.TabIndex = 7;
|
||||
this.pictureBox1.TabStop = false;
|
||||
this.pictureBox1.Visible = false;
|
||||
//
|
||||
// MapSelect
|
||||
//
|
||||
this.AcceptButton = this.btnOk;
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.CancelButton = this.btnCancel;
|
||||
this.ClientSize = new System.Drawing.Size(494, 402);
|
||||
this.Controls.Add(this.splitContainer1);
|
||||
this.Controls.Add(this.pnlBottom);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "MapSelect";
|
||||
this.ShowIcon = false;
|
||||
this.ShowInTaskbar = false;
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||
this.Text = "Select map";
|
||||
this.Load += new System.EventHandler(this.MapSelect_Load);
|
||||
((System.ComponentModel.ISupportInitialize)(this.pbMinimap)).EndInit();
|
||||
this.pnlBottom.ResumeLayout(false);
|
||||
this.pnlBottom.PerformLayout();
|
||||
this.splitContainer1.Panel1.ResumeLayout(false);
|
||||
this.splitContainer1.Panel1.PerformLayout();
|
||||
this.splitContainer1.Panel2.ResumeLayout(false);
|
||||
this.splitContainer1.Panel2.PerformLayout();
|
||||
this.splitContainer1.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public System.Windows.Forms.ListView MapList;
|
||||
public System.Windows.Forms.Button btnCancel;
|
||||
public System.Windows.Forms.Button btnOk;
|
||||
public System.Windows.Forms.Label lblNew;
|
||||
public System.Windows.Forms.TextBox txtNew;
|
||||
public System.Windows.Forms.ColumnHeader colMapName;
|
||||
public System.Windows.Forms.ImageList MapIconsList;
|
||||
public System.Windows.Forms.PictureBox pbMinimap;
|
||||
public System.Windows.Forms.Panel pnlBottom;
|
||||
public System.Windows.Forms.SplitContainer splitContainer1;
|
||||
public System.Windows.Forms.Label lblMinimap;
|
||||
public System.Windows.Forms.TextBox txtTheater;
|
||||
public System.Windows.Forms.Label lblTheater;
|
||||
public System.Windows.Forms.TextBox txtAuthor;
|
||||
public System.Windows.Forms.Label lblAuthor;
|
||||
public System.Windows.Forms.TextBox txtTitle;
|
||||
public System.Windows.Forms.Label lblMapName;
|
||||
public System.Windows.Forms.TextBox txtDesc;
|
||||
public System.Windows.Forms.Label lblDesc;
|
||||
public System.Windows.Forms.Label lblMapList;
|
||||
public System.Windows.Forms.Label lblPathOut;
|
||||
public System.Windows.Forms.Label lblPath;
|
||||
public System.Windows.Forms.TextBox txtPathOut;
|
||||
private System.Windows.Forms.PictureBox pictureBox1;
|
||||
}
|
||||
}
|
||||
74
OpenRA.Editor/MapSelect.cs
Normal file
74
OpenRA.Editor/MapSelect.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Graphics;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.Editor
|
||||
{
|
||||
public partial class MapSelect : Form
|
||||
{
|
||||
public string MapFolderPath;
|
||||
|
||||
public MapSelect(string currentMod)
|
||||
{
|
||||
MapFolderPath = new string[] { Environment.CurrentDirectory, "mods", currentMod, "maps" }
|
||||
.Aggregate(Path.Combine);
|
||||
|
||||
InitializeComponent();
|
||||
MapIconsList.Images.Add(pictureBox1.Image);
|
||||
}
|
||||
|
||||
void MapSelect_Load(object sender, EventArgs e)
|
||||
{
|
||||
MapList.Items.Clear();
|
||||
txtPathOut.Text = MapFolderPath;
|
||||
|
||||
foreach (var map in ModData.FindMapsIn(MapFolderPath))
|
||||
{
|
||||
ListViewItem map1 = new ListViewItem();
|
||||
map1.Tag = map;
|
||||
map1.Text = Path.GetFileNameWithoutExtension(map);
|
||||
map1.ImageIndex = 0;
|
||||
MapList.Items.Add(map1);
|
||||
}
|
||||
|
||||
// hack
|
||||
if (txtNew.Text != "unnamed")
|
||||
MapList.Items[0].Selected = true;
|
||||
}
|
||||
|
||||
void MapList_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (MapList.SelectedItems.Count == 1)
|
||||
{
|
||||
txtNew.Text = MapList.SelectedItems[0].Text;
|
||||
txtNew.Tag = MapList.SelectedItems[0].Tag;
|
||||
|
||||
var map = new Map(txtNew.Tag as string);
|
||||
txtTitle.Text = map.Title;
|
||||
txtAuthor.Text = map.Author;
|
||||
txtTheater.Text = map.Tileset;
|
||||
txtDesc.Text = map.Description;
|
||||
pbMinimap.Image = null;
|
||||
|
||||
try
|
||||
{
|
||||
pbMinimap.Image = Minimap.AddStaticResources(map, Minimap.TerrainBitmap(map, true));
|
||||
}
|
||||
catch (Exception ed)
|
||||
{
|
||||
Console.WriteLine("No map preview image found: {0}", ed.ToString());
|
||||
}
|
||||
finally { }
|
||||
}
|
||||
}
|
||||
|
||||
void txtPathOut_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
MapFolderPath = txtPathOut.Text;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
177
OpenRA.Editor/MapSelect.resx
Normal file
177
OpenRA.Editor/MapSelect.resx
Normal file
@@ -0,0 +1,177 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="MapIconsList.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="pictureBox1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAArjSURBVFhHrVcJUFRXFmVpkE0Wg0ZEMoIBl8RodGSMmVES
|
||||
R0NiChVxCyIIAmFfhe6maeh9AZodZHFpUFQWcQmKisiuLKLEKFFEcIuljtZMYmI5Uc/c14EZYyapmpq8
|
||||
qlP/9/+/373v3HPu+19P7/cf+jSlEWHCOEuzZfNn2Yvo3Pj3D/PTjCwYAwtgyeFwFk163Tos2tvtWJZw
|
||||
zeUjmYFP6vL9fhw31vRPI8/9LnmMrtCWZhtPcJ7hbC/W8DwfnS0LR0t5NKoFazHcqsaprE3YGbMQLrYW
|
||||
W/7fBAxogjGEd5wcXuPK4jxa60qD75VrfIbKMrYMD7VlPX/Ul49rp8RoyPbFIaEnhpuU6NRGoVa2HKuX
|
||||
zEj/X8vAVmlIsDY2Nna2sjBd+ee5b7Yq4tfgfm8a7pxNw60OFa6e4uFmhxr/uFSIexfz0VsZh7PaIJzb
|
||||
F42u8hAcV2/ANz3KF8Hub52kucb+Fv+jAccbm5quWOfxYX5y6Mcnq/IDh1oreX/vOcx9drdbjTudUgye
|
||||
Tsb1piT0H4/DACUw0JiEh33ZePhlFi7UxOCLtI1o2x6IW2cUqM/egLtdediV9MnjSTYm60bE+Ys8rMzN
|
||||
zd1c3/vLgVRV3lN1XjkqyzNoNaEUjIvrLXwMtQsw1JqEy/UxuHg0DJcp+KXj8bh0IobOucSGDA8vpqE6
|
||||
+VNINixBU0kQbp5JJ8jxDSXdeyAE5arlAxTZ/BfRra2tS8Tqwh9L9tQhq6gSabm7odLkoP8oF90V/rjR
|
||||
LsRgExc32oS40ZFCiQgw2Mgj+gW42pBI4OPSsUh6Jgn1mX4ojXJH865IXDzCx50uDe6fV+P8oQQ4Tx6r
|
||||
pOATmVteKgdjXu/Mhk1h328rO4TMwn3gp2YhmquEX7gAfYfjcb4qGH0HQ3D5WAiunU7ApfpofH0ymhIS
|
||||
UwkSqQRb6VoYvm6IZvXG7W4VBVbjwQU1/tanIQZkGDqtwOmSjzHXxXaLsZnZpy85QpdAnfunax/mllRD
|
||||
ma2FQJyHxORMJAqzwBVpUJgtRLF8E7bxlqKjzA991QEYaIijgFwMt6VggJK60hCFr46F4sqprbjbLaf6
|
||||
S0icIh1rwy1i3OvNQff+GEgj3r87/c1JLIGfjX1LP/F6KJDlIy1vN4SyQohVRdAU7IVIXQxuSiZ8/OOw
|
||||
JYyP8EiqfV04Lh2JoHIwMSbiwoFgtO1ah97aTSTMKGIjDl/WhONWl5jKlYrbZ9OJGRWVIg/+axf8SK5a
|
||||
8WoC5fPm//l2qqIIOaVVECm3QZG5C7L0HZCklYJLTCQKNUiWFYAnykJYRDRaywNxrTGRyhKNKyciiIEY
|
||||
dFd743z1ZioT6eJkHK41kXDbRFSKbHzTpcJwsxoHc71fTLGzyBix+L/zUFlaWX+VTcFZ4NzSamQXV1Lw
|
||||
EggkeeBRAsnSfKgyy6DKKcNnxEahIgRfHg5B/7EoDDYn4ma7FD0VAThfG4Cemi3EDI90IKWVq3GbHHKz
|
||||
nUpCbrh6QokEr5mPTEw4773MQij9aPZY5fNYrC6hEhRAnrkTjJEkcS5ieWokS/IhUZdCrtlJbGQiIjQQ
|
||||
/YeD0VMVhoTVbmgs8iVBctG11xtdlUHkDGpQpIN7velUAhmG2+W43spclI6K9JWY6TyxlGKOGxWjG53s
|
||||
5HBMBpZ7+iI6UY44vhoiVTH4ohxCLoTyArqu1OlBll6CZHE20mI9EOjuis3L5uFCbTh6D4Wgu8offYeC
|
||||
qSRccgcPD/qyMEiBb55VYahFgSuNckhjlr2YaGMqH2ntOiKmEAQGBgbnNviGPg2LFSM4UoiAUD78ghLo
|
||||
yEVojBhRiQqEx0nAI5sKiBH/z+OgVfuic7c/Lh+NwZndfughDfQdCtL1hKFmEW51ymn1EjpSAh1ytFCL
|
||||
Pl+nhKebY8XLTYn16DWEgzY2ttdzyI6yjB06+uP4acRANokvhzRRjBR5oe4aN4WupeYgNCIWZ2vj0b17
|
||||
I/UKf3Tt34jOis9otTyyILmkORUDTRKyqxj9DSI07Y0k26Yhes38Roo3YVQH7OVhGiGR0K7O0epEqCRB
|
||||
shKwRIQkQrZqMelAIM6ncihII9uQSCXZEi2HSMjDXvVqXKSGdTLbg6z6OVkwGcfLQvHB4jkYbJMS/UL0
|
||||
1aeSM6So1Hg/oljTR93AupEVYSXhGE+soZa8X+cIlgALzFhg5/HJ6YhIzACXVs9EKiHRMmckSfMQGx0G
|
||||
rXIldU4/dJSvJx3EoSDZC7OszHByTxTOfZGEq00y9B3lo70iElamhp4Ujy1eN8wIrEOd0BRW6DpiWEwq
|
||||
giKSdYiIl5IOUskRKh39AmKECZNP7Mg0O6Ci59Pzd4O/NQK7FBvQULyGOmMUpBsX4KqjGTL5qzHQIqJy
|
||||
iNG6Px5dtYlY7jqhmeKxvUE32C7FGKiP58uf5W6v0ekgPkmNrYIMor4YqcoinQBFdGQrl2ZsB4/cwBJR
|
||||
Zml/+k0sxcQnQZzgDWHIIni9NQHSHU5IS15EPSEN11ok6G9UQs1dh/lvv/GdkZHR3NEETOhkIUE7zvb1
|
||||
wRRFwYv0vD3UBTORJCEdSHMhydgFCXVHVnuWEGvZrDewjqmzKbHDNjHmFl5KBlasWokiFwtop5nhyL6p
|
||||
2JO/CN2HBdSgMpHJ88GH82c8s7b4T1vmUPA3CFxCp19QzBPdtpxdRqon2kkDKRSYXeOJcyBUFMI7IJ70
|
||||
kYsEgRLTXGbgrzNnwmWqC2Y4OsLZZjx43El4ggXI1zohy24MAFd4u9tj8YLpmD71DTiMtwGHY1A7ygB7
|
||||
52N29CLULV7qeT+HnFCoPairu87/RC9rTjE8JYJoY/p4lR8lVQAp7Rc+/pHY7OKE61NN8a21MbQpfwC+
|
||||
m4fbQ7MQNdcCfWMMsTPWDi2yyRgyNkDhOGPYGhpeo97jP5oAcwJjYQ4hk3DOyzvwn9v3HtUJjHXAzSFc
|
||||
RHHlCAznIyAsCZa2k56u3xT2gtHPmGHCdXtnHh47mKBqjS1K5Q7ITrCjlf8RqXPM0bDUCr3bp2C9nj70
|
||||
DDinKMYSwmujCbAjY4G9ZrN3tyMLP/D4IT1vP/J21CBeoKaa55MTUhAeK8J7i91v0DMdxqZmgw7Oc74N
|
||||
iFQ8T5YX6ZzisWI9Uiebo8rKCOcsjLAv1Z72BydUxE5ElcTuKf2P9RunEeGzmD8bTIzsI0I7wc7xdgyf
|
||||
NiayWVoueZ1qz7zPT8l5McnBqZieYZsYO/a4zF7yaKWP4HlASMKLj9xX4WrXWzhdMxUFlkaI1tPDAZE9
|
||||
Htc4wWuhOas5Y/oXgUezYDdZdmK2N6zzCfuB1V1GFkulNswT5cFllms73f+QMIWwjCDjGJnUW1rbfu2z
|
||||
wvXJk85pUH5gieNJdugvd8QV7RSc0TjgiMwevkvH3np1xa/+ZplZE9jecNh14UcPmO8VmnLyfzGr/feU
|
||||
mB/dY7VjybItdSZhrb6+fvEYY6PuMWOMn7ZbGeILfQNYmnN+mO1o/OBdCw74HAMsMjR8NjL/r+Yx+p3H
|
||||
XhjKZs93uxMZr4Z/uOb54qWf3bGf4pw3EpC1UPYsS3g0EU9K4uBsI86zYHPOY3MOp4zuRRLyDfT1O941
|
||||
Mrzvb86Bob4h+0r6zcEmdiFICA2vvT55kLFBYOJhnYt9or06TOmCJ7HTbGxgADpndmaJMU29QxAQKvTo
|
||||
vhnHkN1nX12/OlgCNoT3CZsIvgRWc9ao2IT/bTD3+BID7N1/zisBWCKOBB/CagKf8PboJP8CoUmu3yhA
|
||||
ga8AAAAASUVORK5CYII=
|
||||
</value>
|
||||
</data>
|
||||
</root>
|
||||
24
OpenRA.Editor/NewMapDialog.Designer.cs
generated
Normal file → Executable file
24
OpenRA.Editor/NewMapDialog.Designer.cs
generated
Normal file → Executable file
@@ -55,7 +55,7 @@
|
||||
this.button2.Location = new System.Drawing.Point(229, 160);
|
||||
this.button2.Name = "button2";
|
||||
this.button2.Size = new System.Drawing.Size(75, 23);
|
||||
this.button2.TabIndex = 12;
|
||||
this.button2.TabIndex = 7;
|
||||
this.button2.Text = "OK";
|
||||
this.button2.UseVisualStyleBackColor = true;
|
||||
//
|
||||
@@ -65,7 +65,7 @@
|
||||
this.button1.Location = new System.Drawing.Point(310, 160);
|
||||
this.button1.Name = "button1";
|
||||
this.button1.Size = new System.Drawing.Size(75, 23);
|
||||
this.button1.TabIndex = 13;
|
||||
this.button1.TabIndex = 8;
|
||||
this.button1.Text = "Cancel";
|
||||
this.button1.UseVisualStyleBackColor = true;
|
||||
//
|
||||
@@ -106,12 +106,13 @@
|
||||
0});
|
||||
this.cordonBottom.Name = "cordonBottom";
|
||||
this.cordonBottom.Size = new System.Drawing.Size(105, 20);
|
||||
this.cordonBottom.TabIndex = 8;
|
||||
this.cordonBottom.TabIndex = 5;
|
||||
this.cordonBottom.Value = new decimal(new int[] {
|
||||
112,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.cordonBottom.Enter += new System.EventHandler(this.SelectText);
|
||||
//
|
||||
// cordonTop
|
||||
//
|
||||
@@ -129,6 +130,7 @@
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.cordonTop.Enter += new System.EventHandler(this.SelectText);
|
||||
//
|
||||
// cordonRight
|
||||
//
|
||||
@@ -140,12 +142,13 @@
|
||||
0});
|
||||
this.cordonRight.Name = "cordonRight";
|
||||
this.cordonRight.Size = new System.Drawing.Size(105, 20);
|
||||
this.cordonRight.TabIndex = 5;
|
||||
this.cordonRight.TabIndex = 4;
|
||||
this.cordonRight.Value = new decimal(new int[] {
|
||||
112,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.cordonRight.Enter += new System.EventHandler(this.SelectText);
|
||||
//
|
||||
// cordonLeft
|
||||
//
|
||||
@@ -157,12 +160,13 @@
|
||||
0});
|
||||
this.cordonLeft.Name = "cordonLeft";
|
||||
this.cordonLeft.Size = new System.Drawing.Size(105, 20);
|
||||
this.cordonLeft.TabIndex = 7;
|
||||
this.cordonLeft.TabIndex = 2;
|
||||
this.cordonLeft.Value = new decimal(new int[] {
|
||||
16,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.cordonLeft.Enter += new System.EventHandler(this.SelectText);
|
||||
//
|
||||
// height
|
||||
//
|
||||
@@ -179,12 +183,13 @@
|
||||
0});
|
||||
this.height.Name = "height";
|
||||
this.height.Size = new System.Drawing.Size(105, 20);
|
||||
this.height.TabIndex = 6;
|
||||
this.height.TabIndex = 1;
|
||||
this.height.Value = new decimal(new int[] {
|
||||
128,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.height.Enter += new System.EventHandler(this.SelectText);
|
||||
//
|
||||
// width
|
||||
//
|
||||
@@ -201,12 +206,13 @@
|
||||
0});
|
||||
this.width.Name = "width";
|
||||
this.width.Size = new System.Drawing.Size(105, 20);
|
||||
this.width.TabIndex = 4;
|
||||
this.width.TabIndex = 0;
|
||||
this.width.Value = new decimal(new int[] {
|
||||
128,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.width.Enter += new System.EventHandler(this.SelectText);
|
||||
//
|
||||
// label4
|
||||
//
|
||||
@@ -215,7 +221,7 @@
|
||||
this.label4.Name = "label4";
|
||||
this.label4.Size = new System.Drawing.Size(44, 13);
|
||||
this.label4.TabIndex = 14;
|
||||
this.label4.Text = "Theater";
|
||||
this.label4.Text = "Tileset";
|
||||
//
|
||||
// theater
|
||||
//
|
||||
@@ -224,7 +230,7 @@
|
||||
this.theater.Location = new System.Drawing.Point(169, 121);
|
||||
this.theater.Name = "theater";
|
||||
this.theater.Size = new System.Drawing.Size(216, 21);
|
||||
this.theater.TabIndex = 15;
|
||||
this.theater.TabIndex = 6;
|
||||
//
|
||||
// NewMapDialog
|
||||
//
|
||||
|
||||
5
OpenRA.Editor/NewMapDialog.cs
Normal file → Executable file
5
OpenRA.Editor/NewMapDialog.cs
Normal file → Executable file
@@ -18,5 +18,10 @@ namespace OpenRA.Editor
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void SelectText(object sender, System.EventArgs e)
|
||||
{
|
||||
(sender as NumericUpDown).Select(0, (sender as NumericUpDown).ToString().Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BIN
OpenRA.Editor/OpenRA.Editor.Icon.ico
Normal file
BIN
OpenRA.Editor/OpenRA.Editor.Icon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
@@ -12,6 +12,7 @@
|
||||
<AssemblyName>OpenRA.Editor</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ApplicationIcon>OpenRA.Editor.Icon.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@@ -33,6 +34,7 @@
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
@@ -52,19 +54,34 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ActorTemplate.cs" />
|
||||
<Compile Include="ActorTool.cs" />
|
||||
<Compile Include="BrushTool.cs" />
|
||||
<Compile Include="Form1.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Form1.Designer.cs">
|
||||
<DependentUpon>Form1.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ITool.cs" />
|
||||
<Compile Include="LegacyMapImporter.cs" />
|
||||
<Compile Include="MapSelect.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MapSelect.Designer.cs">
|
||||
<DependentUpon>MapSelect.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="NewMapDialog.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="NewMapDialog.Designer.cs">
|
||||
<DependentUpon>NewMapDialog.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="PaletteBox.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="PaletteBox.Designer.cs">
|
||||
<DependentUpon>PaletteBox.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="PropertiesDialog.cs">
|
||||
<SubType>Form</SubType>
|
||||
@@ -76,9 +93,15 @@
|
||||
<EmbeddedResource Include="Form1.resx">
|
||||
<DependentUpon>Form1.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="MapSelect.resx">
|
||||
<DependentUpon>MapSelect.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="NewMapDialog.resx">
|
||||
<DependentUpon>NewMapDialog.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="PaletteBox.resx">
|
||||
<DependentUpon>PaletteBox.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="PropertiesDialog.resx">
|
||||
<DependentUpon>PropertiesDialog.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
@@ -103,15 +126,18 @@
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
<Compile Include="RenderUtils.cs" />
|
||||
<Compile Include="ResizeDialog.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="ResizeDialog.Designer.cs">
|
||||
<DependentUpon>ResizeDialog.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ResourceTool.cs" />
|
||||
<Compile Include="Surface.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="WaypointTool.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">
|
||||
@@ -123,6 +149,9 @@
|
||||
<Name>OpenRA.Game</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="OpenRA.Editor.Icon.ico" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
||||
165
OpenRA.Editor/PaletteBox.Designer.cs
generated
Normal file
165
OpenRA.Editor/PaletteBox.Designer.cs
generated
Normal file
@@ -0,0 +1,165 @@
|
||||
namespace OpenRA.Editor
|
||||
{
|
||||
partial class PaletteBox
|
||||
{
|
||||
/// <summary>
|
||||
/// Требуется переменная конструктора.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Освободить все используемые ресурсы.
|
||||
/// </summary>
|
||||
/// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Код, автоматически созданный конструктором форм Windows
|
||||
|
||||
/// <summary>
|
||||
/// Обязательный метод для поддержки конструктора - не изменяйте
|
||||
/// содержимое данного метода при помощи редактора кода.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.LayerBox = new System.Windows.Forms.ComboBox();
|
||||
this.tabControl1 = new System.Windows.Forms.TabControl();
|
||||
this.tabPage1 = new System.Windows.Forms.TabPage();
|
||||
this.pbtilePalette = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.tabPage2 = new System.Windows.Forms.TabPage();
|
||||
this.pbactorPalette = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.tabPage3 = new System.Windows.Forms.TabPage();
|
||||
this.pbresourcePalette = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.tabControl1.SuspendLayout();
|
||||
this.tabPage1.SuspendLayout();
|
||||
this.tabPage2.SuspendLayout();
|
||||
this.tabPage3.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// LayerBox
|
||||
//
|
||||
this.LayerBox.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.LayerBox.FormattingEnabled = true;
|
||||
this.LayerBox.Location = new System.Drawing.Point(0, 0);
|
||||
this.LayerBox.Name = "LayerBox";
|
||||
this.LayerBox.Size = new System.Drawing.Size(194, 21);
|
||||
this.LayerBox.TabIndex = 0;
|
||||
//
|
||||
// tabControl1
|
||||
//
|
||||
this.tabControl1.Controls.Add(this.tabPage1);
|
||||
this.tabControl1.Controls.Add(this.tabPage2);
|
||||
this.tabControl1.Controls.Add(this.tabPage3);
|
||||
this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tabControl1.Location = new System.Drawing.Point(0, 21);
|
||||
this.tabControl1.Margin = new System.Windows.Forms.Padding(3, 3, 3, 0);
|
||||
this.tabControl1.Multiline = true;
|
||||
this.tabControl1.Name = "tabControl1";
|
||||
this.tabControl1.SelectedIndex = 0;
|
||||
this.tabControl1.Size = new System.Drawing.Size(194, 357);
|
||||
this.tabControl1.TabIndex = 1;
|
||||
//
|
||||
// tabPage1
|
||||
//
|
||||
this.tabPage1.Controls.Add(this.pbtilePalette);
|
||||
this.tabPage1.Location = new System.Drawing.Point(4, 22);
|
||||
this.tabPage1.Name = "tabPage1";
|
||||
this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tabPage1.Size = new System.Drawing.Size(186, 331);
|
||||
this.tabPage1.TabIndex = 0;
|
||||
this.tabPage1.Text = "Templates";
|
||||
this.tabPage1.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// pbtilePalette
|
||||
//
|
||||
this.pbtilePalette.AutoScroll = true;
|
||||
this.pbtilePalette.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
this.pbtilePalette.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.pbtilePalette.Location = new System.Drawing.Point(3, 3);
|
||||
this.pbtilePalette.Name = "pbtilePalette";
|
||||
this.pbtilePalette.Size = new System.Drawing.Size(180, 325);
|
||||
this.pbtilePalette.TabIndex = 1;
|
||||
//
|
||||
// tabPage2
|
||||
//
|
||||
this.tabPage2.Controls.Add(this.pbactorPalette);
|
||||
this.tabPage2.Location = new System.Drawing.Point(4, 22);
|
||||
this.tabPage2.Name = "tabPage2";
|
||||
this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tabPage2.Size = new System.Drawing.Size(186, 331);
|
||||
this.tabPage2.TabIndex = 1;
|
||||
this.tabPage2.Text = "Actors";
|
||||
this.tabPage2.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// pbactorPalette
|
||||
//
|
||||
this.pbactorPalette.AutoScroll = true;
|
||||
this.pbactorPalette.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
this.pbactorPalette.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.pbactorPalette.Location = new System.Drawing.Point(3, 3);
|
||||
this.pbactorPalette.Name = "pbactorPalette";
|
||||
this.pbactorPalette.Size = new System.Drawing.Size(180, 325);
|
||||
this.pbactorPalette.TabIndex = 2;
|
||||
//
|
||||
// tabPage3
|
||||
//
|
||||
this.tabPage3.Controls.Add(this.pbresourcePalette);
|
||||
this.tabPage3.Location = new System.Drawing.Point(4, 22);
|
||||
this.tabPage3.Name = "tabPage3";
|
||||
this.tabPage3.Size = new System.Drawing.Size(186, 331);
|
||||
this.tabPage3.TabIndex = 2;
|
||||
this.tabPage3.Text = "Resources";
|
||||
this.tabPage3.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// pbresourcePalette
|
||||
//
|
||||
this.pbresourcePalette.AutoScroll = true;
|
||||
this.pbresourcePalette.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
this.pbresourcePalette.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.pbresourcePalette.Location = new System.Drawing.Point(0, 0);
|
||||
this.pbresourcePalette.Name = "pbresourcePalette";
|
||||
this.pbresourcePalette.Size = new System.Drawing.Size(186, 331);
|
||||
this.pbresourcePalette.TabIndex = 3;
|
||||
//
|
||||
// PaletteBox
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(194, 378);
|
||||
this.Controls.Add(this.tabControl1);
|
||||
this.Controls.Add(this.LayerBox);
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "PaletteBox";
|
||||
this.ShowIcon = false;
|
||||
this.ShowInTaskbar = false;
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||
this.Text = "Palette Box";
|
||||
this.TopMost = true;
|
||||
this.tabControl1.ResumeLayout(false);
|
||||
this.tabPage1.ResumeLayout(false);
|
||||
this.tabPage2.ResumeLayout(false);
|
||||
this.tabPage3.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public System.Windows.Forms.ComboBox LayerBox;
|
||||
public System.Windows.Forms.TabControl tabControl1;
|
||||
public System.Windows.Forms.TabPage tabPage1;
|
||||
public System.Windows.Forms.FlowLayoutPanel pbtilePalette;
|
||||
public System.Windows.Forms.TabPage tabPage2;
|
||||
public System.Windows.Forms.FlowLayoutPanel pbactorPalette;
|
||||
public System.Windows.Forms.TabPage tabPage3;
|
||||
public System.Windows.Forms.FlowLayoutPanel pbresourcePalette;
|
||||
|
||||
}
|
||||
}
|
||||
19
OpenRA.Editor/PaletteBox.cs
Normal file
19
OpenRA.Editor/PaletteBox.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace OpenRA.Editor
|
||||
{
|
||||
public partial class PaletteBox : Form
|
||||
{
|
||||
public PaletteBox()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
120
OpenRA.Editor/PaletteBox.resx
Normal file
120
OpenRA.Editor/PaletteBox.resx
Normal file
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@@ -11,6 +11,8 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Forms;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA.Editor
|
||||
{
|
||||
@@ -19,11 +21,32 @@ namespace OpenRA.Editor
|
||||
[STAThread]
|
||||
static void Main( string[] args )
|
||||
{
|
||||
if (args.Length >= 2 && args[0] == "--convert")
|
||||
{
|
||||
Game.modData = new ModData(args[1]);
|
||||
Rules.LoadRules(Game.modData.Manifest, new Map());
|
||||
UpgradeMaps(args[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
Application.CurrentCulture = CultureInfo.InvariantCulture;
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
|
||||
Application.Run(new Form1(args));
|
||||
}
|
||||
|
||||
static void UpgradeMaps(string mod)
|
||||
{
|
||||
var MapFolderPath = new string[] { Environment.CurrentDirectory, "mods", mod, "maps" }
|
||||
.Aggregate(Path.Combine);
|
||||
|
||||
foreach (var path in ModData.FindMapsIn(MapFolderPath))
|
||||
{
|
||||
var map = new Map(path);
|
||||
map.Save(path+".oramap");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
239
OpenRA.Editor/PropertiesDialog.Designer.cs
generated
239
OpenRA.Editor/PropertiesDialog.Designer.cs
generated
@@ -28,119 +28,131 @@
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.button2 = new System.Windows.Forms.Button();
|
||||
this.button1 = new System.Windows.Forms.Button();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.title = new System.Windows.Forms.TextBox();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.desc = new System.Windows.Forms.TextBox();
|
||||
this.selectable = new System.Windows.Forms.CheckBox();
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this.author = new System.Windows.Forms.TextBox();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// button2
|
||||
//
|
||||
this.button2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.button2.DialogResult = System.Windows.Forms.DialogResult.OK;
|
||||
this.button2.Location = new System.Drawing.Point(196, 193);
|
||||
this.button2.Name = "button2";
|
||||
this.button2.Size = new System.Drawing.Size(75, 23);
|
||||
this.button2.TabIndex = 14;
|
||||
this.button2.Text = "OK";
|
||||
this.button2.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// button1
|
||||
//
|
||||
this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.button1.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||
this.button1.Location = new System.Drawing.Point(277, 193);
|
||||
this.button1.Name = "button1";
|
||||
this.button1.Size = new System.Drawing.Size(75, 23);
|
||||
this.button1.TabIndex = 15;
|
||||
this.button1.Text = "Cancel";
|
||||
this.button1.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Location = new System.Drawing.Point(12, 50);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(27, 13);
|
||||
this.label1.TabIndex = 16;
|
||||
this.label1.Text = "Title";
|
||||
//
|
||||
// title
|
||||
//
|
||||
this.title.Location = new System.Drawing.Point(66, 47);
|
||||
this.title.Name = "title";
|
||||
this.title.Size = new System.Drawing.Size(286, 20);
|
||||
this.title.TabIndex = 17;
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.Location = new System.Drawing.Point(12, 76);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(32, 13);
|
||||
this.label2.TabIndex = 16;
|
||||
this.label2.Text = "Desc";
|
||||
//
|
||||
// desc
|
||||
//
|
||||
this.desc.Location = new System.Drawing.Point(66, 73);
|
||||
this.desc.Name = "desc";
|
||||
this.desc.Size = new System.Drawing.Size(286, 20);
|
||||
this.desc.TabIndex = 17;
|
||||
//
|
||||
// selectable
|
||||
//
|
||||
this.selectable.AutoSize = true;
|
||||
this.selectable.Location = new System.Drawing.Point(118, 138);
|
||||
this.selectable.Name = "selectable";
|
||||
this.selectable.Size = new System.Drawing.Size(130, 17);
|
||||
this.selectable.TabIndex = 18;
|
||||
this.selectable.Text = "Show in Map Chooser";
|
||||
this.selectable.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// label3
|
||||
//
|
||||
this.label3.AutoSize = true;
|
||||
this.label3.Location = new System.Drawing.Point(12, 102);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(38, 13);
|
||||
this.label3.TabIndex = 16;
|
||||
this.label3.Text = "Author";
|
||||
//
|
||||
// author
|
||||
//
|
||||
this.author.Location = new System.Drawing.Point(66, 99);
|
||||
this.author.Name = "author";
|
||||
this.author.Size = new System.Drawing.Size(286, 20);
|
||||
this.author.TabIndex = 17;
|
||||
//
|
||||
// PropertiesDialog
|
||||
//
|
||||
this.AcceptButton = this.button2;
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.CancelButton = this.button1;
|
||||
this.ClientSize = new System.Drawing.Size(370, 228);
|
||||
this.Controls.Add(this.selectable);
|
||||
this.Controls.Add(this.author);
|
||||
this.Controls.Add(this.label3);
|
||||
this.Controls.Add(this.desc);
|
||||
this.Controls.Add(this.label2);
|
||||
this.Controls.Add(this.title);
|
||||
this.Controls.Add(this.label1);
|
||||
this.Controls.Add(this.button2);
|
||||
this.Controls.Add(this.button1);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
|
||||
this.Name = "PropertiesDialog";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||
this.Text = "PropertiesDialog";
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
this.button2 = new System.Windows.Forms.Button();
|
||||
this.button1 = new System.Windows.Forms.Button();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.title = new System.Windows.Forms.TextBox();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.desc = new System.Windows.Forms.TextBox();
|
||||
this.selectable = new System.Windows.Forms.CheckBox();
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this.author = new System.Windows.Forms.TextBox();
|
||||
this.useAsShellmap = new System.Windows.Forms.CheckBox();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// button2
|
||||
//
|
||||
this.button2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.button2.DialogResult = System.Windows.Forms.DialogResult.OK;
|
||||
this.button2.Location = new System.Drawing.Point(196, 193);
|
||||
this.button2.Name = "button2";
|
||||
this.button2.Size = new System.Drawing.Size(75, 23);
|
||||
this.button2.TabIndex = 14;
|
||||
this.button2.Text = "OK";
|
||||
this.button2.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// button1
|
||||
//
|
||||
this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.button1.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||
this.button1.Location = new System.Drawing.Point(277, 193);
|
||||
this.button1.Name = "button1";
|
||||
this.button1.Size = new System.Drawing.Size(75, 23);
|
||||
this.button1.TabIndex = 15;
|
||||
this.button1.Text = "Cancel";
|
||||
this.button1.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Location = new System.Drawing.Point(12, 50);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(27, 13);
|
||||
this.label1.TabIndex = 16;
|
||||
this.label1.Text = "Title";
|
||||
//
|
||||
// title
|
||||
//
|
||||
this.title.Location = new System.Drawing.Point(66, 47);
|
||||
this.title.Name = "title";
|
||||
this.title.Size = new System.Drawing.Size(286, 20);
|
||||
this.title.TabIndex = 17;
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.Location = new System.Drawing.Point(12, 76);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(32, 13);
|
||||
this.label2.TabIndex = 16;
|
||||
this.label2.Text = "Desc";
|
||||
//
|
||||
// desc
|
||||
//
|
||||
this.desc.Location = new System.Drawing.Point(66, 73);
|
||||
this.desc.Name = "desc";
|
||||
this.desc.Size = new System.Drawing.Size(286, 20);
|
||||
this.desc.TabIndex = 17;
|
||||
//
|
||||
// selectable
|
||||
//
|
||||
this.selectable.AutoSize = true;
|
||||
this.selectable.Location = new System.Drawing.Point(118, 138);
|
||||
this.selectable.Name = "selectable";
|
||||
this.selectable.Size = new System.Drawing.Size(130, 17);
|
||||
this.selectable.TabIndex = 18;
|
||||
this.selectable.Text = "Show in Map Chooser";
|
||||
this.selectable.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// label3
|
||||
//
|
||||
this.label3.AutoSize = true;
|
||||
this.label3.Location = new System.Drawing.Point(12, 102);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(38, 13);
|
||||
this.label3.TabIndex = 16;
|
||||
this.label3.Text = "Author";
|
||||
//
|
||||
// author
|
||||
//
|
||||
this.author.Location = new System.Drawing.Point(66, 99);
|
||||
this.author.Name = "author";
|
||||
this.author.Size = new System.Drawing.Size(286, 20);
|
||||
this.author.TabIndex = 17;
|
||||
//
|
||||
// checkBox1
|
||||
//
|
||||
this.useAsShellmap.AutoSize = true;
|
||||
this.useAsShellmap.Location = new System.Drawing.Point(118, 161);
|
||||
this.useAsShellmap.Name = "checkBox1";
|
||||
this.useAsShellmap.Size = new System.Drawing.Size(105, 17);
|
||||
this.useAsShellmap.TabIndex = 18;
|
||||
this.useAsShellmap.Text = "Use as Shellmap";
|
||||
this.useAsShellmap.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// PropertiesDialog
|
||||
//
|
||||
this.AcceptButton = this.button2;
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.CancelButton = this.button1;
|
||||
this.ClientSize = new System.Drawing.Size(370, 228);
|
||||
this.Controls.Add(this.useAsShellmap);
|
||||
this.Controls.Add(this.selectable);
|
||||
this.Controls.Add(this.author);
|
||||
this.Controls.Add(this.label3);
|
||||
this.Controls.Add(this.desc);
|
||||
this.Controls.Add(this.label2);
|
||||
this.Controls.Add(this.title);
|
||||
this.Controls.Add(this.label1);
|
||||
this.Controls.Add(this.button2);
|
||||
this.Controls.Add(this.button1);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
|
||||
this.Name = "PropertiesDialog";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||
this.Text = "PropertiesDialog";
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
@@ -155,5 +167,6 @@
|
||||
public System.Windows.Forms.CheckBox selectable;
|
||||
private System.Windows.Forms.Label label3;
|
||||
public System.Windows.Forms.TextBox author;
|
||||
public System.Windows.Forms.CheckBox useAsShellmap;
|
||||
}
|
||||
}
|
||||
156
OpenRA.Editor/RenderUtils.cs
Normal file
156
OpenRA.Editor/RenderUtils.cs
Normal file
@@ -0,0 +1,156 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Editor
|
||||
{
|
||||
static class RenderUtils
|
||||
{
|
||||
public static ColorPalette MakeSystemPalette(Palette p)
|
||||
{
|
||||
ColorPalette pal;
|
||||
using (var b = new Bitmap(1, 1, PixelFormat.Format8bppIndexed))
|
||||
pal = b.Palette;
|
||||
|
||||
for (var i = 0; i < 256; i++)
|
||||
pal.Entries[i] = p.GetColor(i);
|
||||
return pal;
|
||||
}
|
||||
|
||||
public static Bitmap RenderTemplate(TileSet ts, ushort n, Palette p)
|
||||
{
|
||||
var template = ts.Templates[n];
|
||||
var tile = ts.Tiles[n];
|
||||
|
||||
var bitmap = new Bitmap(ts.TileSize * template.Size.X, ts.TileSize * template.Size.Y,
|
||||
PixelFormat.Format8bppIndexed);
|
||||
|
||||
bitmap.Palette = MakeSystemPalette(p);
|
||||
|
||||
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
|
||||
|
||||
unsafe
|
||||
{
|
||||
byte* q = (byte*)data.Scan0.ToPointer();
|
||||
var stride = data.Stride;
|
||||
|
||||
for (var u = 0; u < template.Size.X; u++)
|
||||
for (var v = 0; v < template.Size.Y; v++)
|
||||
if (tile.TileBitmapBytes[u + v * template.Size.X] != null)
|
||||
{
|
||||
var rawImage = tile.TileBitmapBytes[u + v * template.Size.X];
|
||||
for (var i = 0; i < ts.TileSize; i++)
|
||||
for (var j = 0; j < ts.TileSize; j++)
|
||||
q[(v * ts.TileSize + j) * stride + u * ts.TileSize + i] = rawImage[i + ts.TileSize * j];
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < ts.TileSize; i++)
|
||||
for (var j = 0; j < ts.TileSize; j++)
|
||||
q[(v * ts.TileSize + j) * stride + u * ts.TileSize + i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bitmap.UnlockBits(data);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
static Bitmap RenderShp(ShpReader shp, Palette p)
|
||||
{
|
||||
var frame = shp[0];
|
||||
|
||||
var bitmap = new Bitmap(shp.Width, shp.Height, PixelFormat.Format8bppIndexed);
|
||||
|
||||
bitmap.Palette = MakeSystemPalette(p);
|
||||
|
||||
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
|
||||
|
||||
unsafe
|
||||
{
|
||||
byte* q = (byte*)data.Scan0.ToPointer();
|
||||
var stride2 = data.Stride;
|
||||
|
||||
for (var i = 0; i < shp.Width; i++)
|
||||
for (var j = 0; j < shp.Height; j++)
|
||||
q[j * stride2 + i] = frame.Image[i + shp.Width * j];
|
||||
}
|
||||
|
||||
bitmap.UnlockBits(data);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
public static ActorTemplate RenderActor(ActorInfo info, TileSet tileset, Palette p)
|
||||
{
|
||||
var ri = info.Traits.Get<RenderSimpleInfo>();
|
||||
var image = RenderSimple.GetImage(info, tileset.Id);
|
||||
|
||||
using (var s = FileSystem.OpenWithExts(image, tileset.Extensions))
|
||||
{
|
||||
var shp = new ShpReader(s);
|
||||
var bitmap = RenderShp(shp, p);
|
||||
|
||||
try
|
||||
{
|
||||
using (var s2 = FileSystem.OpenWithExts(image + "2", tileset.Extensions))
|
||||
{
|
||||
var shp2 = new ShpReader(s2);
|
||||
var roofBitmap = RenderShp(shp2, p);
|
||||
|
||||
using (var g = System.Drawing.Graphics.FromImage(bitmap))
|
||||
g.DrawImage(roofBitmap, 0, 0);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
return new ActorTemplate
|
||||
{
|
||||
Bitmap = bitmap,
|
||||
Info = info,
|
||||
Appearance = info.Traits.GetOrDefault<EditorAppearanceInfo>()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public static ResourceTemplate RenderResourceType(ResourceTypeInfo info, string[] exts, Palette p)
|
||||
{
|
||||
var image = info.SpriteNames[0];
|
||||
using (var s = FileSystem.OpenWithExts(image, exts))
|
||||
{
|
||||
var shp = new ShpReader(s);
|
||||
var frame = shp[shp.ImageCount - 1];
|
||||
|
||||
var bitmap = new Bitmap(shp.Width, shp.Height, PixelFormat.Format8bppIndexed);
|
||||
bitmap.Palette = MakeSystemPalette(p);
|
||||
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
|
||||
|
||||
unsafe
|
||||
{
|
||||
byte* q = (byte*)data.Scan0.ToPointer();
|
||||
var stride = data.Stride;
|
||||
|
||||
for (var i = 0; i < shp.Width; i++)
|
||||
for (var j = 0; j < shp.Height; j++)
|
||||
q[j * stride + i] = frame.Image[i + shp.Width * j];
|
||||
}
|
||||
|
||||
bitmap.UnlockBits(data);
|
||||
return new ResourceTemplate { Bitmap = bitmap, Info = info, Value = shp.ImageCount - 1 };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
51
OpenRA.Editor/ResourceTool.cs
Normal file
51
OpenRA.Editor/ResourceTool.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
using SGraphics = System.Drawing.Graphics;
|
||||
|
||||
namespace OpenRA.Editor
|
||||
{
|
||||
class ResourceTool : ITool
|
||||
{
|
||||
ResourceTemplate Resource;
|
||||
|
||||
public ResourceTool(ResourceTemplate resource) { Resource = resource; }
|
||||
|
||||
public void Apply(Surface surface)
|
||||
{
|
||||
surface.Map.MapResources[surface.GetBrushLocation().X, surface.GetBrushLocation().Y]
|
||||
= new TileReference<byte, byte>
|
||||
{
|
||||
type = (byte)Resource.Info.ResourceType,
|
||||
index = (byte)random.Next(Resource.Info.SpriteNames.Length),
|
||||
image = (byte)Resource.Value
|
||||
};
|
||||
|
||||
var ch = new int2((surface.GetBrushLocation().X) / Surface.ChunkSize,
|
||||
(surface.GetBrushLocation().Y) / Surface.ChunkSize);
|
||||
|
||||
if (surface.Chunks.ContainsKey(ch))
|
||||
{
|
||||
surface.Chunks[ch].Dispose();
|
||||
surface.Chunks.Remove(ch);
|
||||
}
|
||||
}
|
||||
|
||||
public void Preview(Surface surface, SGraphics g)
|
||||
{
|
||||
surface.DrawImage(g, Resource.Bitmap, surface.GetBrushLocation(), false, null);
|
||||
}
|
||||
|
||||
Random random = new Random();
|
||||
}
|
||||
}
|
||||
386
OpenRA.Editor/Surface.cs
Normal file → Executable file
386
OpenRA.Editor/Surface.cs
Normal file → Executable file
@@ -15,6 +15,9 @@ using System.Drawing.Imaging;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Traits;
|
||||
|
||||
using SGraphics = System.Drawing.Graphics;
|
||||
|
||||
namespace OpenRA.Editor
|
||||
{
|
||||
@@ -23,32 +26,34 @@ namespace OpenRA.Editor
|
||||
public Map Map { get; private set; }
|
||||
public TileSet TileSet { get; private set; }
|
||||
public Palette Palette { get; private set; }
|
||||
int2 Offset;
|
||||
public int2 Offset;
|
||||
|
||||
BrushTemplate Brush;
|
||||
ActorTemplate Actor;
|
||||
ResourceTemplate Resource;
|
||||
WaypointTemplate Waypoint;
|
||||
public int2 GetOffset() { return Offset; }
|
||||
|
||||
public float Zoom = 1.0f;
|
||||
|
||||
ITool Tool;
|
||||
|
||||
public bool IsPanning;
|
||||
public event Action AfterChange = () => { };
|
||||
public event Action<string> MousePositionChanged = _ => { };
|
||||
|
||||
Dictionary<string, ActorTemplate> ActorTemplates = new Dictionary<string, ActorTemplate>();
|
||||
Dictionary<int, ResourceTemplate> ResourceTemplates = new Dictionary<int, ResourceTemplate>();
|
||||
|
||||
public Keys GetModifiers() { return ModifierKeys; }
|
||||
|
||||
public void Bind(Map m, TileSet ts, Palette p)
|
||||
{
|
||||
Map = m;
|
||||
TileSet = ts;
|
||||
Palette = p;
|
||||
Brush = null;
|
||||
PlayerPalettes = null;
|
||||
Chunks.Clear();
|
||||
Tool = null;
|
||||
}
|
||||
|
||||
public void SetBrush(BrushTemplate brush) { Actor = null; Brush = brush; Resource = null; Waypoint = null; }
|
||||
public void SetActor(ActorTemplate actor) { Brush = null; Actor = actor; Resource = null; Waypoint = null; }
|
||||
public void SetResource(ResourceTemplate resource) { Brush = null; Actor = null; Resource = resource; Waypoint = null; }
|
||||
public void SetWaypoint(WaypointTemplate waypoint) { Brush = null; Actor = null; Resource = null; Waypoint = waypoint; }
|
||||
public void SetTool(ITool tool) { Tool = tool; }
|
||||
|
||||
public void BindActorTemplates(IEnumerable<ActorTemplate> templates)
|
||||
{
|
||||
@@ -60,7 +65,7 @@ namespace OpenRA.Editor
|
||||
ResourceTemplates = templates.ToDictionary(a => a.Info.ResourceType);
|
||||
}
|
||||
|
||||
Dictionary<int2, Bitmap> Chunks = new Dictionary<int2, Bitmap>();
|
||||
public Dictionary<int2, Bitmap> Chunks = new Dictionary<int2, Bitmap>();
|
||||
|
||||
public Surface()
|
||||
: base()
|
||||
@@ -80,13 +85,45 @@ namespace OpenRA.Editor
|
||||
Offset -= dx;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
|
||||
protected override void OnMouseWheel(MouseEventArgs e)
|
||||
{
|
||||
base.OnMouseWheel(e);
|
||||
|
||||
if (Map == null) return;
|
||||
|
||||
Zoom *= e.Delta > 0 ? 4.0f / 3.0f : .75f;
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
protected override void OnMouseLeave(EventArgs e)
|
||||
{
|
||||
base.OnMouseLeave(e);
|
||||
|
||||
this.Parent.Focus();
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
protected override void OnMouseEnter(EventArgs e)
|
||||
{
|
||||
base.OnMouseLeave(e);
|
||||
|
||||
this.Focus();
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
protected override void OnMouseMove(MouseEventArgs e)
|
||||
{
|
||||
base.OnMouseMove(e);
|
||||
|
||||
if (Map == null) return;
|
||||
|
||||
var oldMousePos = MousePos;
|
||||
MousePos = new int2(e.Location);
|
||||
MousePositionChanged(GetBrushLocation().ToString());
|
||||
|
||||
if (e.Button == MouseButtons.Middle || (e.Button != MouseButtons.None && IsPanning))
|
||||
Scroll(oldMousePos - MousePos);
|
||||
@@ -96,130 +133,32 @@ namespace OpenRA.Editor
|
||||
Erase();
|
||||
|
||||
if (e.Button == MouseButtons.Left)
|
||||
Draw();
|
||||
Draw();
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void FloodFillWithBrush(int2 pos)
|
||||
{
|
||||
var queue = new Queue<int2>();
|
||||
var replace = Map.MapTiles[pos.X, pos.Y];
|
||||
|
||||
queue.Enqueue(pos);
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
var p = queue.Dequeue();
|
||||
if (!Map.MapTiles[p.X, p.Y].Equals(replace))
|
||||
continue;
|
||||
|
||||
var a = FindEdge(p, new int2(-1, 0), replace);
|
||||
var b = FindEdge(p, new int2(1, 0), replace);
|
||||
|
||||
for (var x = a.X; x <= b.X; x++)
|
||||
{
|
||||
Map.MapTiles[x, p.Y] = new TileReference<ushort, byte> { type = Brush.N, image = (byte)0, index = (byte)0 };
|
||||
if (Map.MapTiles[x, p.Y - 1].Equals(replace) && Map.IsInMap(x, p.Y - 1))
|
||||
queue.Enqueue(new int2(x, p.Y - 1));
|
||||
if (Map.MapTiles[x, p.Y + 1].Equals(replace) && Map.IsInMap(x, p.Y + 1))
|
||||
queue.Enqueue(new int2(x, p.Y + 1));
|
||||
}
|
||||
}
|
||||
|
||||
/* todo: optimize */
|
||||
foreach (var ch in Chunks.Values) ch.Dispose();
|
||||
Chunks.Clear();
|
||||
|
||||
AfterChange();
|
||||
}
|
||||
|
||||
int2 FindEdge(int2 p, int2 d, TileReference<ushort, byte> replace)
|
||||
{
|
||||
for (; ; )
|
||||
{
|
||||
var q = p+d;
|
||||
if (!Map.IsInMap(q)) return p;
|
||||
if (!Map.MapTiles[q.X, q.Y].Equals(replace)) return p;
|
||||
p = q;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawWithBrush()
|
||||
{
|
||||
// change the bits in the map
|
||||
var tile = TileSet.Tiles[Brush.N];
|
||||
var template = TileSet.Templates[Brush.N];
|
||||
var pos = GetBrushLocation();
|
||||
|
||||
if (ModifierKeys == Keys.Shift)
|
||||
{
|
||||
FloodFillWithBrush(pos);
|
||||
return;
|
||||
}
|
||||
|
||||
for (var u = 0; u < template.Size.X; u++)
|
||||
for (var v = 0; v < template.Size.Y; v++)
|
||||
{
|
||||
if (Map.IsInMap(new int2(u, v) + pos))
|
||||
{
|
||||
var z = u + v * template.Size.X;
|
||||
if (tile.TileBitmapBytes[z] != null)
|
||||
Map.MapTiles[u + pos.X, v + pos.Y] =
|
||||
new TileReference<ushort, byte>
|
||||
{
|
||||
type = Brush.N,
|
||||
index = template.PickAny ? byte.MaxValue : (byte)z,
|
||||
image = template.PickAny ? (byte)((u + pos.X) % 4 + ((v + pos.Y) % 4)*4) : (byte)z,
|
||||
};
|
||||
|
||||
var ch = new int2((pos.X + u) / ChunkSize, (pos.Y + v) / ChunkSize);
|
||||
if (Chunks.ContainsKey(ch))
|
||||
{
|
||||
Chunks[ch].Dispose();
|
||||
Chunks.Remove(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AfterChange();
|
||||
}
|
||||
|
||||
int wpid;
|
||||
string NextWpid()
|
||||
{
|
||||
for (; ; )
|
||||
{
|
||||
var a = "wp{0}".F(wpid++);
|
||||
if (!Map.Waypoints.ContainsKey(a))
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawWithWaypoint()
|
||||
{
|
||||
var k = Map.Waypoints.FirstOrDefault(a => a.Value == GetBrushLocation());
|
||||
if (k.Key != null) Map.Waypoints.Remove(k.Key);
|
||||
|
||||
Map.Waypoints.Add(NextWpid(), GetBrushLocation());
|
||||
|
||||
AfterChange();
|
||||
}
|
||||
|
||||
void Erase()
|
||||
{
|
||||
Actor = null;
|
||||
Brush = null;
|
||||
Resource = null;
|
||||
Waypoint = null;
|
||||
// Crash preventing
|
||||
var BrushLocation = GetBrushLocation();
|
||||
|
||||
var key = Map.Actors.FirstOrDefault(a => a.Value.Location() == GetBrushLocation());
|
||||
if (Map == null || BrushLocation.X >= Map.MapSize.X ||
|
||||
BrushLocation.Y >= Map.MapSize.Y ||
|
||||
BrushLocation.X < 0 ||
|
||||
BrushLocation.Y < 0)
|
||||
return;
|
||||
|
||||
Tool = null;
|
||||
|
||||
var key = Map.Actors.FirstOrDefault(a => a.Value.Location() == BrushLocation);
|
||||
if (key.Key != null) Map.Actors.Remove(key.Key);
|
||||
|
||||
if (Map.MapResources[GetBrushLocation().X, GetBrushLocation().Y].type != 0)
|
||||
if (Map.MapResources[BrushLocation.X, BrushLocation.Y].type != 0)
|
||||
{
|
||||
Map.MapResources[GetBrushLocation().X, GetBrushLocation().Y] = new TileReference<byte, byte>();
|
||||
var ch = new int2((GetBrushLocation().X) / ChunkSize, (GetBrushLocation().Y) / ChunkSize);
|
||||
Map.MapResources[BrushLocation.X, BrushLocation.Y] = new TileReference<byte, byte>();
|
||||
var ch = new int2((BrushLocation.X) / ChunkSize, (BrushLocation.Y) / ChunkSize);
|
||||
if (Chunks.ContainsKey(ch))
|
||||
{
|
||||
Chunks[ch].Dispose();
|
||||
@@ -227,7 +166,7 @@ namespace OpenRA.Editor
|
||||
}
|
||||
}
|
||||
|
||||
var k = Map.Waypoints.FirstOrDefault(a => a.Value == GetBrushLocation());
|
||||
var k = Map.Waypoints.FirstOrDefault(a => a.Value == BrushLocation);
|
||||
if (k.Key != null) Map.Waypoints.Remove(k.Key);
|
||||
|
||||
AfterChange();
|
||||
@@ -235,58 +174,7 @@ namespace OpenRA.Editor
|
||||
|
||||
void Draw()
|
||||
{
|
||||
if (Brush != null) DrawWithBrush();
|
||||
if (Actor != null) DrawWithActor();
|
||||
if (Resource != null) DrawWithResource();
|
||||
if (Waypoint != null) DrawWithWaypoint();
|
||||
|
||||
AfterChange();
|
||||
}
|
||||
|
||||
int id;
|
||||
string NextActorName()
|
||||
{
|
||||
for (; ; )
|
||||
{
|
||||
var possible = "Actor{0}".F(id++);
|
||||
if (!Map.Actors.ContainsKey(possible)) return possible;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawWithActor()
|
||||
{
|
||||
if (Map.Actors.Any(a => a.Value.Location() == GetBrushLocation()))
|
||||
return;
|
||||
|
||||
var owner = "Neutral";
|
||||
var id = NextActorName();
|
||||
Map.Actors[id] = new ActorReference(Actor.Info.Name.ToLowerInvariant())
|
||||
{
|
||||
new LocationInit( GetBrushLocation() ),
|
||||
new OwnerInit( owner)
|
||||
};
|
||||
|
||||
AfterChange();
|
||||
}
|
||||
|
||||
System.Random r = new System.Random();
|
||||
void DrawWithResource()
|
||||
{
|
||||
Map.MapResources[GetBrushLocation().X, GetBrushLocation().Y]
|
||||
= new TileReference<byte, byte>
|
||||
{
|
||||
type = (byte)Resource.Info.ResourceType,
|
||||
index = (byte)r.Next(Resource.Info.SpriteNames.Length),
|
||||
image = (byte)Resource.Value
|
||||
};
|
||||
|
||||
var ch = new int2((GetBrushLocation().X) / ChunkSize, (GetBrushLocation().Y) / ChunkSize);
|
||||
if (Chunks.ContainsKey(ch))
|
||||
{
|
||||
Chunks[ch].Dispose();
|
||||
Chunks.Remove(ch);
|
||||
}
|
||||
|
||||
if (Tool != null) Tool.Apply(this);
|
||||
AfterChange();
|
||||
}
|
||||
|
||||
@@ -294,6 +182,8 @@ namespace OpenRA.Editor
|
||||
{
|
||||
base.OnMouseDown(e);
|
||||
|
||||
if (Map == null) return;
|
||||
|
||||
if (!IsPanning)
|
||||
{
|
||||
if (e.Button == MouseButtons.Right) Erase();
|
||||
@@ -303,12 +193,12 @@ namespace OpenRA.Editor
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
const int ChunkSize = 8; // 8x8 chunks ==> 192x192 bitmaps.
|
||||
public const int ChunkSize = 8; // 8x8 chunks ==> 192x192 bitmaps.
|
||||
|
||||
Bitmap RenderChunk(int u, int v)
|
||||
{
|
||||
|
||||
var bitmap = new Bitmap(ChunkSize * 24, ChunkSize * 24);
|
||||
var bitmap = new Bitmap(ChunkSize * TileSet.TileSize, ChunkSize * TileSet.TileSize);
|
||||
bitmap.SetPixel(0, 0, Color.Green);
|
||||
|
||||
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
@@ -326,9 +216,9 @@ namespace OpenRA.Editor
|
||||
var tile = TileSet.Tiles[tr.type];
|
||||
var index = (tr.image < tile.TileBitmapBytes.Count) ? tr.image : (byte)0;
|
||||
var rawImage = tile.TileBitmapBytes[index];
|
||||
for (var x = 0; x < 24; x++)
|
||||
for (var y = 0; y < 24; y++)
|
||||
p[(j * 24 + y) * stride + i * 24 + x] = Palette.GetColor(rawImage[x + 24 * y]).ToArgb();
|
||||
for (var x = 0; x < TileSet.TileSize; x++)
|
||||
for (var y = 0; y < TileSet.TileSize; y++)
|
||||
p[(j * TileSet.TileSize + y) * stride + i * TileSet.TileSize + x] = Palette.GetColor(rawImage[x + TileSet.TileSize * y]).ToArgb();
|
||||
|
||||
if (Map.MapResources[u * ChunkSize + i, v * ChunkSize + j].type != 0)
|
||||
{
|
||||
@@ -339,12 +229,12 @@ namespace OpenRA.Editor
|
||||
int* q = (int*)srcdata.Scan0.ToPointer();
|
||||
var srcstride = srcdata.Stride >> 2;
|
||||
|
||||
for (var x = 0; x < 24; x++)
|
||||
for (var y = 0; y < 24; y++)
|
||||
for (var x = 0; x < TileSet.TileSize; x++)
|
||||
for (var y = 0; y < TileSet.TileSize; y++)
|
||||
{
|
||||
var c = q[y * srcstride + x];
|
||||
if ((c & 0xff000000) != 0) /* quick & dirty, i cbf doing real alpha */
|
||||
p[(j * 24 + y) * stride + i * 24 + x] = c;
|
||||
p[(j * TileSet.TileSize + y) * stride + i * TileSet.TileSize + x] = c;
|
||||
}
|
||||
|
||||
resourceImage.UnlockBits(srcdata);
|
||||
@@ -356,30 +246,73 @@ namespace OpenRA.Editor
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
int2 GetBrushLocation()
|
||||
public int2 GetBrushLocation()
|
||||
{
|
||||
var v = MousePos - Offset;
|
||||
return new int2(v.X / 24, v.Y / 24);
|
||||
var vX = (int)Math.Floor((MousePos.X - Offset.X) / Zoom);
|
||||
var vY = (int)Math.Floor((MousePos.Y - Offset.Y) / Zoom);
|
||||
return new int2(vX / TileSet.TileSize, vY / TileSet.TileSize);
|
||||
}
|
||||
|
||||
void DrawActor(System.Drawing.Graphics g, int2 p, ActorTemplate t)
|
||||
public void DrawActor(SGraphics g, int2 p, ActorTemplate t, ColorPalette cp)
|
||||
{
|
||||
g.DrawImage(t.Bitmap,
|
||||
((24 * p + Offset
|
||||
- (t.Centered
|
||||
? new int2(t.Bitmap.Width / 2 - 12, t.Bitmap.Height / 2 - 12)
|
||||
: int2.Zero)).ToPoint()));
|
||||
var centered = t.Appearance == null || !t.Appearance.RelativeToTopLeft;
|
||||
DrawImage(g, t.Bitmap, p, centered, cp);
|
||||
}
|
||||
|
||||
float2 GetDrawPosition(int2 location, Bitmap bmp, bool centered)
|
||||
{
|
||||
float OffsetX = centered ? bmp.Width / 2 - TileSet.TileSize / 2 : 0;
|
||||
float DrawX = TileSet.TileSize * location.X * Zoom + Offset.X - OffsetX;
|
||||
|
||||
float OffsetY = centered ? bmp.Height / 2 - TileSet.TileSize / 2 : 0;
|
||||
float DrawY = TileSet.TileSize * location.Y * Zoom + Offset.Y - OffsetY;
|
||||
|
||||
return new float2(DrawX, DrawY);
|
||||
}
|
||||
|
||||
public void DrawImage(SGraphics g, Bitmap bmp, int2 location, bool centered, ColorPalette cp)
|
||||
{
|
||||
var drawPos = GetDrawPosition(location, bmp, centered);
|
||||
|
||||
var sourceRect = new RectangleF(0, 0, bmp.Width, bmp.Height);
|
||||
var destRect = new RectangleF(drawPos.X, drawPos.Y, bmp.Width * Zoom, bmp.Height * Zoom);
|
||||
|
||||
var restorePalette = bmp.Palette;
|
||||
if (cp != null) bmp.Palette = cp;
|
||||
g.DrawImage(bmp, destRect, sourceRect, GraphicsUnit.Pixel);
|
||||
if (cp != null) bmp.Palette = restorePalette;
|
||||
}
|
||||
|
||||
void DrawActorBorder(System.Drawing.Graphics g, int2 p, ActorTemplate t)
|
||||
{
|
||||
var origin = (24 * p + Offset
|
||||
- (t.Centered
|
||||
? new int2(t.Bitmap.Width / 2 - 12, t.Bitmap.Height / 2 - 12)
|
||||
: int2.Zero)).ToPoint();
|
||||
var centered = t.Appearance == null || !t.Appearance.RelativeToTopLeft;
|
||||
var drawPos = GetDrawPosition(p, t.Bitmap, centered);
|
||||
|
||||
g.DrawRectangle(CordonPen,
|
||||
origin.X, origin.Y,
|
||||
t.Bitmap.Width, t.Bitmap.Height );
|
||||
drawPos.X, drawPos.Y,
|
||||
t.Bitmap.Width * Zoom, t.Bitmap.Height * Zoom);
|
||||
}
|
||||
|
||||
ColorPalette GetPaletteForPlayer(string name)
|
||||
{
|
||||
var pr = Map.Players[name];
|
||||
var pcpi = Rules.Info["player"].Traits.Get<PlayerColorPaletteInfo>();
|
||||
var remap = new PlayerColorRemap(pr.ColorRamp, pcpi.PaletteFormat);
|
||||
return RenderUtils.MakeSystemPalette(new Palette(Palette, remap));
|
||||
}
|
||||
|
||||
Cache<string, ColorPalette> PlayerPalettes;
|
||||
|
||||
ColorPalette GetPaletteForActor(ActorReference ar)
|
||||
{
|
||||
if (PlayerPalettes == null)
|
||||
PlayerPalettes = new Cache<string, ColorPalette>(GetPaletteForPlayer);
|
||||
|
||||
var ownerInit = ar.InitDict.GetOrDefault<OwnerInit>();
|
||||
if (ownerInit == null)
|
||||
return null;
|
||||
|
||||
return PlayerPalettes[ownerInit.PlayerName];
|
||||
}
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
@@ -387,44 +320,41 @@ namespace OpenRA.Editor
|
||||
if (Map == null) return;
|
||||
if (TileSet == null) return;
|
||||
|
||||
for( var u = 0; u < Map.MapSize.X; u += ChunkSize )
|
||||
for (var u = 0; u < Map.MapSize.X; u += ChunkSize)
|
||||
for (var v = 0; v < Map.MapSize.Y; v += ChunkSize)
|
||||
{
|
||||
var x = new int2(u/ChunkSize,v/ChunkSize);
|
||||
var x = new int2(u / ChunkSize, v / ChunkSize);
|
||||
if (!Chunks.ContainsKey(x)) Chunks[x] = RenderChunk(u / ChunkSize, v / ChunkSize);
|
||||
e.Graphics.DrawImage(Chunks[x], (24 * ChunkSize * x + Offset).ToPoint());
|
||||
|
||||
Bitmap bmp = Chunks[x];
|
||||
|
||||
float DrawX = TileSet.TileSize * (float)ChunkSize * (float)x.X * Zoom + Offset.X;
|
||||
float DrawY = TileSet.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);
|
||||
e.Graphics.DrawImage(bmp, destRect, sourceRect, GraphicsUnit.Pixel);
|
||||
}
|
||||
|
||||
e.Graphics.DrawRectangle(CordonPen,
|
||||
new Rectangle(Map.XOffset * 24 + Offset.X, Map.YOffset * 24 + Offset.Y, Map.Width * 24, Map.Height * 24));
|
||||
Map.Bounds.Left * TileSet.TileSize * Zoom + Offset.X,
|
||||
Map.Bounds.Top * TileSet.TileSize * Zoom + Offset.Y,
|
||||
Map.Bounds.Width * TileSet.TileSize * Zoom,
|
||||
Map.Bounds.Height * TileSet.TileSize * Zoom);
|
||||
|
||||
foreach (var ar in Map.Actors)
|
||||
DrawActor(e.Graphics, ar.Value.Location(), ActorTemplates[ar.Value.Type]);
|
||||
DrawActor(e.Graphics, ar.Value.Location(), ActorTemplates[ar.Value.Type],
|
||||
GetPaletteForActor(ar.Value));
|
||||
|
||||
foreach (var wp in Map.Waypoints)
|
||||
e.Graphics.DrawRectangle(Pens.LimeGreen, new Rectangle(
|
||||
24 * wp.Value.X + Offset.X + 4,
|
||||
24 * wp.Value.Y + Offset.Y + 4,
|
||||
16, 16));
|
||||
e.Graphics.DrawRectangle(Pens.LimeGreen,
|
||||
TileSet.TileSize * wp.Value.X * Zoom + Offset.X + 4,
|
||||
TileSet.TileSize * wp.Value.Y * Zoom + Offset.Y + 4,
|
||||
(TileSet.TileSize - 8) * Zoom, (TileSet.TileSize - 8) * Zoom);
|
||||
|
||||
if (Brush != null)
|
||||
e.Graphics.DrawImage(Brush.Bitmap,
|
||||
(24 * GetBrushLocation() + Offset).ToPoint());
|
||||
|
||||
if (Actor != null)
|
||||
DrawActor(e.Graphics, GetBrushLocation(), Actor);
|
||||
|
||||
if (Resource != null)
|
||||
e.Graphics.DrawImage(Resource.Bitmap,
|
||||
(24 * GetBrushLocation() + Offset).ToPoint());
|
||||
|
||||
if (Waypoint != null)
|
||||
e.Graphics.DrawRectangle(Pens.LimeGreen, new Rectangle(
|
||||
24 * GetBrushLocation().X + Offset.X + 4,
|
||||
24 * GetBrushLocation().Y + Offset.Y + 4,
|
||||
16, 16));
|
||||
|
||||
if (Brush == null && Actor == null && Resource == null)
|
||||
if (Tool != null)
|
||||
Tool.Preview(this, e.Graphics);
|
||||
|
||||
if (Tool == null)
|
||||
{
|
||||
var x = Map.Actors.FirstOrDefault(a => a.Value.Location() == GetBrushLocation());
|
||||
if (x.Key != null)
|
||||
|
||||
51
OpenRA.Editor/WaypointTool.cs
Normal file
51
OpenRA.Editor/WaypointTool.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
|
||||
using SGraphics = System.Drawing.Graphics;
|
||||
|
||||
namespace OpenRA.Editor
|
||||
{
|
||||
class WaypointTool : ITool
|
||||
{
|
||||
WaypointTemplate Waypoint;
|
||||
|
||||
public WaypointTool(WaypointTemplate waypoint) { Waypoint = waypoint; }
|
||||
|
||||
public void Apply(Surface surface)
|
||||
{
|
||||
var k = surface.Map.Waypoints.FirstOrDefault(a => a.Value == surface.GetBrushLocation());
|
||||
if (k.Key != null) surface.Map.Waypoints.Remove(k.Key);
|
||||
|
||||
surface.Map.Waypoints.Add(NextWpid(surface), surface.GetBrushLocation());
|
||||
}
|
||||
|
||||
public void Preview(Surface surface, SGraphics g)
|
||||
{
|
||||
g.DrawRectangle(Pens.LimeGreen,
|
||||
surface.TileSet.TileSize * surface.GetBrushLocation().X * surface.Zoom + surface.GetOffset().X + 4,
|
||||
surface.TileSet.TileSize * surface.GetBrushLocation().Y * surface.Zoom + surface.GetOffset().Y + 4,
|
||||
(surface.TileSet.TileSize - 8) * surface.Zoom, (surface.TileSet.TileSize - 8) * surface.Zoom);
|
||||
}
|
||||
|
||||
public string NextWpid(Surface surface)
|
||||
{
|
||||
int wpid = 0;
|
||||
for (; ; )
|
||||
{
|
||||
var a = "wp{0}".F(wpid++);
|
||||
if (!surface.Map.Waypoints.ContainsKey(a))
|
||||
return a;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
64
OpenRA.FileFormats/ColorHSLR.cs
Normal file
64
OpenRA.FileFormats/ColorHSLR.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Drawing;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public struct ColorRamp
|
||||
{
|
||||
public byte H,S,L,R;
|
||||
|
||||
public ColorRamp(byte h, byte s, byte l, byte r)
|
||||
{
|
||||
H = h; S = s; L = l; R = r;
|
||||
}
|
||||
|
||||
/* returns a color along the Lum ramp */
|
||||
public Color GetColor( float t )
|
||||
{
|
||||
return ColorFromHSL( H / 255f, S / 255f, float2.Lerp( L / 255f, L*R / (255f * 255f), t ) );
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "{0},{1},{2},{3}".F(H, S, L, R);
|
||||
}
|
||||
|
||||
// hk is hue in the range [0,1] instead of [0,360]
|
||||
public static Color ColorFromHSL(float hk, float s, float l)
|
||||
{
|
||||
// Convert from HSL to RGB
|
||||
var q = (l < 0.5f) ? l * (1 + s) : l + s - (l * s);
|
||||
var p = 2 * l - q;
|
||||
|
||||
float[] trgb = { hk + 1 / 3.0f,
|
||||
hk,
|
||||
hk - 1/3.0f };
|
||||
float[] rgb = { 0, 0, 0 };
|
||||
|
||||
for (int k = 0; k < 3; k++)
|
||||
{
|
||||
while (trgb[k] < 0) trgb[k] += 1.0f;
|
||||
while (trgb[k] > 1) trgb[k] -= 1.0f;
|
||||
}
|
||||
|
||||
for (int k = 0; k < 3; k++)
|
||||
{
|
||||
if (trgb[k] < 1 / 6.0f) { rgb[k] = (p + ((q - p) * 6 * trgb[k])); }
|
||||
else if (trgb[k] >= 1 / 6.0f && trgb[k] < 0.5) { rgb[k] = q; }
|
||||
else if (trgb[k] >= 0.5f && trgb[k] < 2.0f / 3) { rgb[k] = (p + ((q - p) * 6 * (2.0f / 3 - trgb[k]))); }
|
||||
else { rgb[k] = p; }
|
||||
}
|
||||
|
||||
return Color.FromArgb((int)(rgb[0] * 255), (int)(rgb[1] * 255), (int)(rgb[2] * 255));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Packaging;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class CompressedPackage : IFolder
|
||||
{
|
||||
readonly uint[] hashes;
|
||||
readonly Stream s;
|
||||
readonly ZipPackage pkg;
|
||||
|
||||
public CompressedPackage(string filename)
|
||||
{
|
||||
s = FileSystem.Open(filename);
|
||||
pkg = (ZipPackage)ZipPackage.Open(s, FileMode.Open);
|
||||
hashes = pkg.GetParts()
|
||||
.Select(p => PackageEntry.HashFilename(p.Uri.LocalPath)).ToArray();
|
||||
}
|
||||
|
||||
public Stream GetContent(string filename)
|
||||
{
|
||||
return pkg.GetPart(new Uri(filename)).GetStream(FileMode.Open);
|
||||
}
|
||||
|
||||
public IEnumerable<uint> AllFileHashes() { return hashes; }
|
||||
|
||||
public bool Exists(string filename)
|
||||
{
|
||||
return hashes.Contains(PackageEntry.HashFilename(filename));
|
||||
}
|
||||
}
|
||||
}
|
||||
39
OpenRA.FileFormats/Exts.cs
Normal file → Executable file
39
OpenRA.FileFormats/Exts.cs
Normal file → Executable file
@@ -10,6 +10,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
@@ -23,10 +24,10 @@ namespace OpenRA
|
||||
return string.Format(fmt, args);
|
||||
}
|
||||
|
||||
public static void Do<T>( this IEnumerable<T> e, Action<T> fn )
|
||||
public static void Do<T>(this IEnumerable<T> e, Action<T> fn)
|
||||
{
|
||||
foreach( var ee in e )
|
||||
fn( ee );
|
||||
foreach (var ee in e)
|
||||
fn(ee);
|
||||
}
|
||||
|
||||
public static IEnumerable<string> GetNamespaces(this Assembly a)
|
||||
@@ -73,5 +74,37 @@ namespace OpenRA
|
||||
{
|
||||
return mi.GetCustomAttributes(typeof(T), true).Length != 0;
|
||||
}
|
||||
|
||||
public static T[] GetCustomAttributes<T>(this MemberInfo mi, bool inherit)
|
||||
where T : class
|
||||
{
|
||||
return (T[])mi.GetCustomAttributes(typeof(T), inherit);
|
||||
}
|
||||
|
||||
public static T[] GetCustomAttributes<T>(this ParameterInfo mi)
|
||||
where T : class
|
||||
{
|
||||
return (T[])mi.GetCustomAttributes(typeof(T), true);
|
||||
}
|
||||
|
||||
public static T Clamp<T>(this T val, T min, T max) where T : IComparable<T>
|
||||
{
|
||||
if (val.CompareTo(min) < 0)
|
||||
return min;
|
||||
else if (val.CompareTo(max) > 0)
|
||||
return max;
|
||||
else
|
||||
return val;
|
||||
}
|
||||
|
||||
public static bool Contains(this Rectangle r, int2 p)
|
||||
{
|
||||
return r.Contains(p.ToPoint());
|
||||
}
|
||||
|
||||
public static bool Contains(this RectangleF r, int2 p)
|
||||
{
|
||||
return r.Contains(p.ToPointF());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
105
OpenRA.FileFormats/FieldLoader.cs
Normal file → Executable file
105
OpenRA.FileFormats/FieldLoader.cs
Normal file → Executable file
@@ -13,6 +13,7 @@ using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Globalization;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
@@ -99,11 +100,19 @@ namespace OpenRA.FileFormats
|
||||
else if (fieldType == typeof(float))
|
||||
{
|
||||
float res;
|
||||
if (float.TryParse(x.Replace("%",""), out res))
|
||||
if (float.TryParse(x.Replace("%",""), System.Globalization.NumberStyles.Any, NumberFormatInfo.InvariantInfo, out res))
|
||||
return res * (x.Contains( '%' ) ? 0.01f : 1f);
|
||||
return InvalidValueAction(x,fieldType, field);
|
||||
}
|
||||
|
||||
else if (fieldType == typeof(decimal))
|
||||
{
|
||||
decimal res;
|
||||
if (decimal.TryParse(x.Replace("%",""), System.Globalization.NumberStyles.Any, NumberFormatInfo.InvariantInfo, out res))
|
||||
return res * (x.Contains( '%' ) ? 0.01m : 1m);
|
||||
return InvalidValueAction(x,fieldType, field);
|
||||
}
|
||||
|
||||
else if (fieldType == typeof(string))
|
||||
return x;
|
||||
|
||||
@@ -111,39 +120,64 @@ namespace OpenRA.FileFormats
|
||||
{
|
||||
var parts = x.Split(',');
|
||||
if (parts.Length == 3)
|
||||
return Color.FromArgb(int.Parse(parts[0]), int.Parse(parts[1]), int.Parse(parts[2]));
|
||||
return Color.FromArgb(int.Parse(parts[0]).Clamp(0, 255), int.Parse(parts[1]).Clamp(0, 255), int.Parse(parts[2]).Clamp(0, 255));
|
||||
if (parts.Length == 4)
|
||||
return Color.FromArgb(int.Parse(parts[0]), int.Parse(parts[1]), int.Parse(parts[2]), int.Parse(parts[3]));
|
||||
return Color.FromArgb(int.Parse(parts[0]).Clamp(0, 255), int.Parse(parts[1]).Clamp(0, 255), int.Parse(parts[2]).Clamp(0, 255), int.Parse(parts[3]).Clamp(0, 255));
|
||||
return InvalidValueAction(x,fieldType, field);
|
||||
}
|
||||
|
||||
else if (fieldType.IsEnum)
|
||||
{
|
||||
if (!Enum.GetNames(fieldType).Select(a => a.ToLower()).Contains(x.ToLower()))
|
||||
return InvalidValueAction(x,fieldType, field);
|
||||
return Enum.Parse(fieldType, x, true);
|
||||
}
|
||||
else if (fieldType == typeof(ColorRamp))
|
||||
{
|
||||
var parts = x.Split(',');
|
||||
if (parts.Length == 4)
|
||||
return new ColorRamp(
|
||||
(byte)int.Parse(parts[0]).Clamp(0, 255),
|
||||
(byte)int.Parse(parts[1]).Clamp(0, 255),
|
||||
(byte)int.Parse(parts[2]).Clamp(0, 255),
|
||||
(byte)int.Parse(parts[3]).Clamp(0, 255));
|
||||
|
||||
else if (fieldType == typeof(bool))
|
||||
return ParseYesNo(x, fieldType, field);
|
||||
return InvalidValueAction(x, fieldType, field);
|
||||
}
|
||||
|
||||
else if (fieldType.IsArray)
|
||||
{
|
||||
if (x == null)
|
||||
return Array.CreateInstance(fieldType.GetElementType(), 0);
|
||||
else if (fieldType.IsEnum)
|
||||
{
|
||||
if (!Enum.GetNames(fieldType).Select(a => a.ToLower()).Contains(x.ToLower()))
|
||||
return InvalidValueAction(x, fieldType, field);
|
||||
return Enum.Parse(fieldType, x, true);
|
||||
}
|
||||
|
||||
var parts = x.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
else if (fieldType == typeof(bool))
|
||||
return ParseYesNo(x, fieldType, field);
|
||||
|
||||
var ret = Array.CreateInstance(fieldType.GetElementType(), parts.Length);
|
||||
for (int i = 0; i < parts.Length; i++)
|
||||
ret.SetValue(GetValue(field, fieldType.GetElementType(), parts[i].Trim()), i);
|
||||
return ret;
|
||||
}
|
||||
else if (fieldType == typeof(int2))
|
||||
{
|
||||
var parts = x.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
return new int2(int.Parse(parts[0]), int.Parse(parts[1]));
|
||||
}
|
||||
else if (fieldType.IsArray)
|
||||
{
|
||||
if (x == null)
|
||||
return Array.CreateInstance(fieldType.GetElementType(), 0);
|
||||
|
||||
var parts = x.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
var ret = Array.CreateInstance(fieldType.GetElementType(), parts.Length);
|
||||
for (int i = 0; i < parts.Length; i++)
|
||||
ret.SetValue(GetValue(field, fieldType.GetElementType(), parts[i].Trim()), i);
|
||||
return ret;
|
||||
}
|
||||
else if (fieldType == typeof(int2))
|
||||
{
|
||||
var parts = x.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
return new int2(int.Parse(parts[0]), int.Parse(parts[1]));
|
||||
}
|
||||
else if (fieldType == typeof(float2))
|
||||
{
|
||||
var parts = x.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
float xx = 0;
|
||||
float yy = 0;
|
||||
float res;
|
||||
if (float.TryParse(parts[0].Replace("%", ""), out res))
|
||||
xx = res * (parts[0].Contains('%') ? 0.01f : 1f);
|
||||
if (float.TryParse(parts[1].Replace("%", ""), out res))
|
||||
yy = res * (parts[1].Contains('%') ? 0.01f : 1f);
|
||||
return new float2(xx, yy);
|
||||
}
|
||||
|
||||
UnknownFieldAction("[Type] {0}".F(x),fieldType);
|
||||
return null;
|
||||
@@ -165,11 +199,12 @@ namespace OpenRA.FileFormats
|
||||
{
|
||||
var ret = new Dictionary<FieldInfo, Func<string, Type, MiniYaml, object>>();
|
||||
|
||||
foreach( var field in type.GetFields() )
|
||||
foreach( var ff in type.GetFields() )
|
||||
{
|
||||
var load = (LoadAttribute[])field.GetCustomAttributes( typeof( LoadAttribute ), false );
|
||||
var loadUsing = (LoadUsingAttribute[])field.GetCustomAttributes( typeof( LoadUsingAttribute ), false );
|
||||
var fromYamlKey = (FieldFromYamlKeyAttribute[])field.GetCustomAttributes( typeof( FieldFromYamlKeyAttribute ), false );
|
||||
var field = ff;
|
||||
var load = field.GetCustomAttributes<LoadAttribute>( false );
|
||||
var loadUsing = field.GetCustomAttributes<LoadUsingAttribute>( false );
|
||||
var fromYamlKey = field.GetCustomAttributes<FieldFromYamlKeyAttribute>( false );
|
||||
if( loadUsing.Length != 0 )
|
||||
ret[ field ] = ( _1, fieldType, yaml ) => loadUsing[ 0 ].LoaderFunc( field )( yaml );
|
||||
else if( fromYamlKey.Length != 0 )
|
||||
@@ -240,6 +275,11 @@ namespace OpenRA.FileFormats
|
||||
FormatValue( o, f ) ) ).ToList() );
|
||||
}
|
||||
|
||||
public static MiniYamlNode SaveField(object o, string field)
|
||||
{
|
||||
return new MiniYamlNode(field, FieldSaver.FormatValue( o, o.GetType().GetField(field) ));
|
||||
}
|
||||
|
||||
public static string FormatValue(object o, FieldInfo f)
|
||||
{
|
||||
var v = f.GetValue(o);
|
||||
@@ -250,7 +290,10 @@ namespace OpenRA.FileFormats
|
||||
if (f.FieldType == typeof(Color))
|
||||
{
|
||||
var c = (Color)v;
|
||||
return "{0},{1},{2},{3}".F(c.A,c.R,c.G,c.B);
|
||||
return "{0},{1},{2},{3}".F(((int)c.A).Clamp(0, 255),
|
||||
((int)c.R).Clamp(0, 255),
|
||||
((int)c.G).Clamp(0, 255),
|
||||
((int)c.B).Clamp(0, 255));
|
||||
}
|
||||
|
||||
return f.FieldType.IsArray
|
||||
|
||||
@@ -102,6 +102,20 @@ namespace OpenRA.FileFormats
|
||||
return output;
|
||||
}
|
||||
|
||||
public static float SoundLength(Stream s)
|
||||
{
|
||||
var br = new BinaryReader(s);
|
||||
var sampleRate = br.ReadUInt16();
|
||||
/*var dataSize = */ br.ReadInt32();
|
||||
var outputSize = br.ReadInt32();
|
||||
var flags = (SoundFlags) br.ReadByte();
|
||||
|
||||
var samples = outputSize;
|
||||
if (0 != (flags & SoundFlags.Stereo)) samples /= 2;
|
||||
if (0 != (flags & SoundFlags._16Bit)) samples /= 2;
|
||||
return samples / sampleRate;
|
||||
}
|
||||
|
||||
public static byte[] LoadSound(Stream s)
|
||||
{
|
||||
var br = new BinaryReader(s);
|
||||
|
||||
274
OpenRA.FileFormats/FileFormats/Blast.cs
Normal file
274
OpenRA.FileFormats/FileFormats/Blast.cs
Normal file
@@ -0,0 +1,274 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*
|
||||
* This file is based on the blast routines (version 1.1 by Mark Adler)
|
||||
* included in zlib/contrib
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public static class Blast
|
||||
{
|
||||
public static readonly int MAXBITS = 13; // maximum code length
|
||||
public static readonly int MAXWIN = 4096; // maximum window size
|
||||
|
||||
static byte[] litlen = new byte[] {
|
||||
11, 124, 8, 7, 28, 7, 188, 13, 76, 4,
|
||||
10, 8, 12, 10, 12, 10, 8, 23, 8, 9,
|
||||
7, 6, 7, 8, 7, 6, 55, 8, 23, 24,
|
||||
12, 11, 7, 9, 11, 12, 6, 7, 22, 5,
|
||||
7, 24, 6, 11, 9, 6, 7, 22, 7, 11,
|
||||
38, 7, 9, 8, 25, 11, 8, 11, 9, 12,
|
||||
8, 12, 5, 38, 5, 38, 5, 11, 7, 5,
|
||||
6, 21, 6, 10, 53, 8, 7, 24, 10, 27,
|
||||
44, 253, 253, 253, 252, 252, 252, 13, 12, 45,
|
||||
12, 45, 12, 61, 12, 45, 44, 173
|
||||
};
|
||||
|
||||
// bit lengths of length codes 0..15
|
||||
static byte[] lenlen = new byte[] { 2, 35, 36, 53, 38, 23 };
|
||||
|
||||
// bit lengths of distance codes 0..63
|
||||
static byte[] distlen = new byte[] { 2, 20, 53, 230, 247, 151, 248 };
|
||||
|
||||
// base for length codes
|
||||
static short[] lengthbase = new short[] {
|
||||
3, 2, 4, 5, 6, 7, 8, 9, 10, 12,
|
||||
16, 24, 40, 72, 136, 264
|
||||
};
|
||||
|
||||
// extra bits for length codes
|
||||
static byte[] extra = new byte[] {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 2,
|
||||
3, 4, 5, 6, 7, 8
|
||||
};
|
||||
|
||||
static Huffman litcode = new Huffman(litlen, litlen.Length, 256);
|
||||
static Huffman lencode = new Huffman(lenlen, lenlen.Length, 16);
|
||||
static Huffman distcode = new Huffman(distlen, distlen.Length, 64);
|
||||
|
||||
// Decode PKWare Compression Library stream.
|
||||
public static byte[] Decompress(byte[] src)
|
||||
{
|
||||
BitReader br = new BitReader(src);
|
||||
|
||||
// Are literals coded?
|
||||
int coded = br.ReadBits(8);
|
||||
|
||||
if (coded < 0 || coded > 1)
|
||||
throw new NotImplementedException("Invalid datastream");
|
||||
bool EncodedLiterals = (coded == 1);
|
||||
|
||||
// log2(dictionary size) - 6
|
||||
int dict = br.ReadBits(8);
|
||||
if (dict < 4 || dict > 6)
|
||||
throw new InvalidDataException("Invalid dictionary size");
|
||||
|
||||
// output state
|
||||
ushort next = 0; // index of next write location in out[]
|
||||
bool first = true; // true to check distances (for first 4K)
|
||||
byte[] outBuffer = new byte[MAXWIN]; // output buffer and sliding window
|
||||
var ms = new MemoryStream();
|
||||
|
||||
// decode literals and length/distance pairs
|
||||
do
|
||||
{
|
||||
// length/distance pair
|
||||
if (br.ReadBits(1) == 1)
|
||||
{
|
||||
// Length
|
||||
int symbol = Decode(lencode, br);
|
||||
int len = lengthbase[symbol] + br.ReadBits(extra[symbol]);
|
||||
if (len == 519) // Magic number for "done"
|
||||
{
|
||||
for (int i = 0; i < next; i++)
|
||||
ms.WriteByte(outBuffer[i]);
|
||||
break;
|
||||
}
|
||||
|
||||
// Distance
|
||||
symbol = len == 2 ? 2 : dict;
|
||||
int dist = Decode(distcode, br) << symbol;
|
||||
dist += br.ReadBits(symbol);
|
||||
dist++;
|
||||
|
||||
if (first && dist > next)
|
||||
throw new InvalidDataException("Attempt to jump before data");
|
||||
|
||||
// copy length bytes from distance bytes back
|
||||
do
|
||||
{
|
||||
int dest = next;
|
||||
int source = dest - dist;
|
||||
|
||||
int copy = MAXWIN;
|
||||
if (next < dist)
|
||||
{
|
||||
source += copy;
|
||||
copy = dist;
|
||||
}
|
||||
|
||||
copy -= next;
|
||||
if (copy > len)
|
||||
copy = len;
|
||||
|
||||
len -= copy;
|
||||
next += (ushort)copy;
|
||||
Array.Copy(outBuffer, source, outBuffer, dest, copy);
|
||||
|
||||
// Flush window to outstream
|
||||
if (next == MAXWIN)
|
||||
{
|
||||
for (int i = 0; i < next; i++)
|
||||
ms.WriteByte(outBuffer[i]);
|
||||
next = 0;
|
||||
first = false;
|
||||
}
|
||||
} while (len != 0);
|
||||
}
|
||||
else // literal value
|
||||
{
|
||||
int symbol = EncodedLiterals ? Decode(litcode, br) : br.ReadBits(8);
|
||||
outBuffer[next++] = (byte)symbol;
|
||||
if (next == MAXWIN)
|
||||
{
|
||||
for (int i = 0; i < next; i++)
|
||||
ms.WriteByte(outBuffer[i]);
|
||||
next = 0;
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
} while (true);
|
||||
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
// Decode a code using huffman table h.
|
||||
private static int Decode(Huffman h, BitReader br)
|
||||
{
|
||||
int code = 0; // len bits being decoded
|
||||
int first = 0; // first code of length len
|
||||
int index = 0; // index of first code of length len in symbol table
|
||||
short next = 1;
|
||||
while (true)
|
||||
{
|
||||
code |= br.ReadBits(1) ^ 1; // invert code
|
||||
int count = h.Count[next++];
|
||||
if (code < first + count)
|
||||
return h.Symbol[index + (code - first)];
|
||||
|
||||
index += count;
|
||||
first += count;
|
||||
first <<= 1;
|
||||
code <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class BitReader
|
||||
{
|
||||
readonly byte[] src;
|
||||
int offset = 0;
|
||||
int bitBuffer = 0;
|
||||
int bitCount = 0;
|
||||
|
||||
public BitReader(byte[] src)
|
||||
{
|
||||
this.src = src;
|
||||
}
|
||||
|
||||
public int ReadBits(int count)
|
||||
{
|
||||
int ret = 0;
|
||||
int filled = 0;
|
||||
while (filled < count)
|
||||
{
|
||||
if (bitCount == 0)
|
||||
{
|
||||
bitBuffer = src[offset++];
|
||||
bitCount = 8;
|
||||
}
|
||||
|
||||
ret |= (bitBuffer & 1) << filled;
|
||||
bitBuffer >>= 1;
|
||||
bitCount--;
|
||||
filled++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a list of repeated code lengths rep[0..n-1], where each byte is a
|
||||
* count (high four bits + 1) and a code length (low four bits), generate the
|
||||
* list of code lengths. This compaction reduces the size of the object code.
|
||||
* Then given the list of code lengths length[0..n-1] representing a canonical
|
||||
* Huffman code for n symbols, construct the tables required to decode those
|
||||
* codes. Those tables are the number of codes of each length, and the symbols
|
||||
* sorted by length, retaining their original order within each length.
|
||||
*/
|
||||
class Huffman
|
||||
{
|
||||
public short[] Count; // number of symbols of each length
|
||||
public short[] Symbol; // canonically ordered symbols
|
||||
|
||||
public Huffman(byte[] rep, int n, short SymbolCount)
|
||||
{
|
||||
short[] length = new short[256]; // code lengths
|
||||
int s = 0; // current symbol
|
||||
|
||||
// convert compact repeat counts into symbol bit length list
|
||||
foreach (byte code in rep)
|
||||
{
|
||||
int num = (code >> 4) + 1; // Number of codes (top four bits plus 1)
|
||||
byte len = (byte)(code & 15); // Code length (low four bits)
|
||||
do
|
||||
{
|
||||
length[s++] = len;
|
||||
} while (--num > 0);
|
||||
}
|
||||
n = s;
|
||||
|
||||
// count number of codes of each length
|
||||
Count = new short[Blast.MAXBITS + 1];
|
||||
for (int i = 0; i < n; i++)
|
||||
Count[length[i]]++;
|
||||
|
||||
// no codes!
|
||||
if (Count[0] == n)
|
||||
return;
|
||||
|
||||
// check for an over-subscribed or incomplete set of lengths
|
||||
int left = 1; // one possible code of zero length
|
||||
for (int len = 1; len <= Blast.MAXBITS; len++)
|
||||
{
|
||||
left <<= 1;
|
||||
// one more bit, double codes left
|
||||
left -= Count[len];
|
||||
// deduct count from possible codes
|
||||
if (left < 0)
|
||||
throw new InvalidDataException ("over subscribed code set");
|
||||
}
|
||||
|
||||
// generate offsets into symbol table for each length for sorting
|
||||
short[] offs = new short[Blast.MAXBITS + 1];
|
||||
for (int len = 1; len < Blast.MAXBITS; len++)
|
||||
offs[len + 1] = (short)(offs[len] + Count[len]);
|
||||
|
||||
// put symbols in table sorted by length, by symbol order within each length
|
||||
Symbol = new short[SymbolCount];
|
||||
for (short i = 0; i < n; i++)
|
||||
if (length[i] != 0)
|
||||
Symbol[offs[length[i]]++] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
@@ -35,6 +36,8 @@ namespace OpenRA.FileFormats
|
||||
Array.Copy(src, this.offset, dest, offset, count);
|
||||
this.offset += count;
|
||||
}
|
||||
|
||||
public int Remaining() { return src.Length - offset; }
|
||||
}
|
||||
|
||||
public static class Format80
|
||||
@@ -121,5 +124,27 @@ namespace OpenRA.FileFormats
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
var len = Math.Min(ctx.Remaining(), 0x3F);
|
||||
ms.WriteByte((byte)(0x80 | len));
|
||||
while (len-- > 0)
|
||||
ms.WriteByte(ctx.ReadByte());
|
||||
}
|
||||
while (!ctx.Done());
|
||||
|
||||
ms.WriteByte(0x80); // terminator -- 0-length run.
|
||||
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,12 +12,14 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public static class FileSystem
|
||||
{
|
||||
static List<IFolder> mountedFolders = new List<IFolder>();
|
||||
public static string SpecialPackageRoot = "";
|
||||
|
||||
static Cache<uint, List<IFolder>> allFiles = new Cache<uint, List<IFolder>>( _ => new List<IFolder>() );
|
||||
|
||||
@@ -33,22 +35,50 @@ namespace OpenRA.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
static int order = 0;
|
||||
|
||||
static IFolder OpenPackage(string filename)
|
||||
{
|
||||
if (filename.EndsWith(".mix"))
|
||||
return new Package(filename);
|
||||
else if (filename.EndsWith(".zip"))
|
||||
return new CompressedPackage(filename);
|
||||
else
|
||||
return new Folder(filename);
|
||||
return OpenPackage(filename, order++);
|
||||
}
|
||||
|
||||
public static IFolder CreatePackage(string filename, int order, Dictionary<string, byte[]> content)
|
||||
{
|
||||
if (filename.EndsWith(".mix", StringComparison.InvariantCultureIgnoreCase))
|
||||
return new MixFile(filename, order, content);
|
||||
else if (filename.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase))
|
||||
return new ZipFile(filename, order, content);
|
||||
else if (filename.EndsWith(".oramap", StringComparison.InvariantCultureIgnoreCase))
|
||||
return new ZipFile(filename, order, content);
|
||||
else if (filename.EndsWith(".Z", StringComparison.InvariantCultureIgnoreCase))
|
||||
throw new NotImplementedException("Creating .Z archives is unsupported");
|
||||
else
|
||||
return new Folder(filename, order, content);
|
||||
}
|
||||
|
||||
public static IFolder OpenPackage(string filename, int order)
|
||||
{
|
||||
if (filename.EndsWith(".mix", StringComparison.InvariantCultureIgnoreCase))
|
||||
return new MixFile(filename, order);
|
||||
else if (filename.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase))
|
||||
return new ZipFile(filename, order);
|
||||
else if (filename.EndsWith(".oramap", StringComparison.InvariantCultureIgnoreCase))
|
||||
return new ZipFile(filename, order);
|
||||
else if (filename.EndsWith(".Z", StringComparison.InvariantCultureIgnoreCase))
|
||||
return new InstallShieldPackage(filename, order);
|
||||
else
|
||||
return new Folder(filename, order);
|
||||
}
|
||||
|
||||
public static void Mount(string name)
|
||||
{
|
||||
name = name.ToLowerInvariant();
|
||||
var optional = name.StartsWith("~");
|
||||
if (optional) name = name.Substring(1);
|
||||
|
||||
|
||||
// paths starting with $ are relative to SpecialPackageRoot
|
||||
if (name.StartsWith("$"))
|
||||
name = SpecialPackageRoot+name.Substring(1);
|
||||
|
||||
var a = (Action)(() => FileSystem.MountInner(OpenPackage(name)));
|
||||
|
||||
if (optional)
|
||||
@@ -64,6 +94,16 @@ namespace OpenRA.FileFormats
|
||||
allFiles = new Cache<uint, List<IFolder>>( _ => new List<IFolder>() );
|
||||
}
|
||||
|
||||
public static bool Unmount(IFolder mount)
|
||||
{
|
||||
return (mountedFolders.RemoveAll(f => f == mount) > 0);
|
||||
}
|
||||
|
||||
public static void Mount(IFolder mount)
|
||||
{
|
||||
if (!mountedFolders.Contains(mount)) mountedFolders.Add(mount);
|
||||
}
|
||||
|
||||
public static void LoadFromManifest( Manifest manifest )
|
||||
{
|
||||
UnmountAll();
|
||||
@@ -73,9 +113,14 @@ namespace OpenRA.FileFormats
|
||||
|
||||
static Stream GetFromCache( Cache<uint, List<IFolder>> index, string filename )
|
||||
{
|
||||
foreach( var folder in index[ PackageEntry.HashFilename( filename ) ] )
|
||||
if (folder.Exists(filename))
|
||||
return folder.GetContent(filename);
|
||||
var folder = index[PackageEntry.HashFilename(filename)]
|
||||
.Where(x => x.Exists(filename))
|
||||
.OrderBy(x => x.Priority)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (folder != null)
|
||||
return folder.GetContent(filename);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -88,11 +133,13 @@ namespace OpenRA.FileFormats
|
||||
return ret;
|
||||
}
|
||||
|
||||
foreach( IFolder folder in mountedFolders )
|
||||
{
|
||||
if (folder.Exists(filename))
|
||||
return folder.GetContent(filename);
|
||||
}
|
||||
var folder = mountedFolders
|
||||
.Where(x => x.Exists(filename))
|
||||
.OrderByDescending(x => x.Priority)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (folder != null)
|
||||
return folder.GetContent(filename);
|
||||
|
||||
throw new FileNotFoundException( string.Format( "File not found: {0}", filename ), filename );
|
||||
}
|
||||
73
OpenRA.FileFormats/Filesystem/Folder.cs
Normal file
73
OpenRA.FileFormats/Filesystem/Folder.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class Folder : IFolder
|
||||
{
|
||||
readonly string path;
|
||||
|
||||
int priority;
|
||||
|
||||
// Create a new folder package
|
||||
public Folder(string path, int priority, Dictionary<string, byte[]> contents)
|
||||
{
|
||||
this.path = path;
|
||||
this.priority = priority;
|
||||
if (Directory.Exists(path))
|
||||
Directory.Delete(path);
|
||||
|
||||
Write(contents);
|
||||
}
|
||||
|
||||
public Folder(string path, int priority)
|
||||
{
|
||||
this.path = path;
|
||||
this.priority = priority;
|
||||
if (!Directory.Exists(path))
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
|
||||
public Stream GetContent(string filename)
|
||||
{
|
||||
try { return File.OpenRead( Path.Combine( path, filename ) ); }
|
||||
catch { return null; }
|
||||
}
|
||||
|
||||
public IEnumerable<uint> AllFileHashes()
|
||||
{
|
||||
foreach( var filename in Directory.GetFiles( path, "*", SearchOption.TopDirectoryOnly ) )
|
||||
yield return PackageEntry.HashFilename( Path.GetFileName(filename) );
|
||||
}
|
||||
|
||||
public bool Exists(string filename)
|
||||
{
|
||||
return File.Exists(Path.Combine(path,filename));
|
||||
}
|
||||
|
||||
|
||||
public int Priority
|
||||
{
|
||||
get { return priority; }
|
||||
}
|
||||
|
||||
public void Write(Dictionary<string, byte[]> contents)
|
||||
{
|
||||
foreach (var file in contents)
|
||||
using (var dataStream = File.Create(Path.Combine(path, file.Key)))
|
||||
using (var writer = new BinaryWriter(dataStream))
|
||||
writer.Write(file.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
126
OpenRA.FileFormats/Filesystem/InstallShieldPackage.cs
Normal file
126
OpenRA.FileFormats/Filesystem/InstallShieldPackage.cs
Normal file
@@ -0,0 +1,126 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class InstallShieldPackage : IFolder
|
||||
{
|
||||
readonly Dictionary<uint, PackageEntry> index = new Dictionary<uint, PackageEntry>();
|
||||
readonly Stream s;
|
||||
readonly long dataStart = 255;
|
||||
int priority;
|
||||
|
||||
public InstallShieldPackage(string filename, int priority)
|
||||
{
|
||||
this.priority = priority;
|
||||
s = FileSystem.Open(filename);
|
||||
|
||||
// Parse package header
|
||||
BinaryReader reader = new BinaryReader(s);
|
||||
uint signature = reader.ReadUInt32();
|
||||
if (signature != 0x8C655D13)
|
||||
throw new InvalidDataException("Not an Installshield package");
|
||||
|
||||
reader.ReadBytes(8);
|
||||
/*var FileCount = */reader.ReadUInt16();
|
||||
reader.ReadBytes(4);
|
||||
/*var ArchiveSize = */reader.ReadUInt32();
|
||||
reader.ReadBytes(19);
|
||||
var TOCAddress = reader.ReadInt32();
|
||||
reader.ReadBytes(4);
|
||||
var DirCount = reader.ReadUInt16();
|
||||
|
||||
// Parse the directory list
|
||||
s.Seek(TOCAddress, SeekOrigin.Begin);
|
||||
BinaryReader TOCreader = new BinaryReader(s);
|
||||
for (var i = 0; i < DirCount; i++)
|
||||
ParseDirectory(TOCreader);
|
||||
}
|
||||
|
||||
void ParseDirectory(BinaryReader reader)
|
||||
{
|
||||
// Parse directory header
|
||||
var FileCount = reader.ReadUInt16();
|
||||
var ChunkSize = reader.ReadUInt16();
|
||||
var NameLength = reader.ReadUInt16();
|
||||
reader.ReadChars(NameLength); //var DirName = new String(reader.ReadChars(NameLength));
|
||||
|
||||
// Skip to the end of the chunk
|
||||
reader.ReadBytes(ChunkSize - NameLength - 6);
|
||||
|
||||
// Parse files
|
||||
for (var i = 0; i < FileCount; i++)
|
||||
ParseFile(reader);
|
||||
}
|
||||
|
||||
uint AccumulatedData = 0;
|
||||
void ParseFile(BinaryReader reader)
|
||||
{
|
||||
reader.ReadBytes(7);
|
||||
var CompressedSize = reader.ReadUInt32();
|
||||
reader.ReadBytes(12);
|
||||
var ChunkSize = reader.ReadUInt16();
|
||||
reader.ReadBytes(4);
|
||||
var NameLength = reader.ReadByte();
|
||||
var FileName = new String(reader.ReadChars(NameLength));
|
||||
|
||||
var hash = PackageEntry.HashFilename(FileName);
|
||||
index.Add(hash, new PackageEntry(hash,AccumulatedData, CompressedSize));
|
||||
AccumulatedData += CompressedSize;
|
||||
|
||||
// Skip to the end of the chunk
|
||||
reader.ReadBytes(ChunkSize - NameLength - 30);
|
||||
}
|
||||
|
||||
public Stream GetContent(uint hash)
|
||||
{
|
||||
PackageEntry e;
|
||||
if (!index.TryGetValue(hash, out e))
|
||||
return null;
|
||||
|
||||
s.Seek( dataStart + e.Offset, SeekOrigin.Begin );
|
||||
byte[] data = new byte[ e.Length ];
|
||||
s.Read( data, 0, (int)e.Length );
|
||||
|
||||
return new MemoryStream(Blast.Decompress(data));
|
||||
}
|
||||
|
||||
public Stream GetContent(string filename)
|
||||
{
|
||||
return GetContent(PackageEntry.HashFilename(filename));
|
||||
}
|
||||
|
||||
public IEnumerable<uint> AllFileHashes()
|
||||
{
|
||||
return index.Keys;
|
||||
}
|
||||
|
||||
public bool Exists(string filename)
|
||||
{
|
||||
return index.ContainsKey(PackageEntry.HashFilename(filename));
|
||||
}
|
||||
|
||||
|
||||
public int Priority
|
||||
{
|
||||
get { return 2000 + priority; }
|
||||
}
|
||||
|
||||
public void Write(Dictionary<string, byte[]> contents)
|
||||
{
|
||||
throw new NotImplementedException("Cannot save InstallShieldPackages.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,17 +20,32 @@ namespace OpenRA.FileFormats
|
||||
Stream GetContent(string filename);
|
||||
bool Exists(string filename);
|
||||
IEnumerable<uint> AllFileHashes();
|
||||
void Write(Dictionary<string, byte[]> contents);
|
||||
int Priority { get; }
|
||||
}
|
||||
|
||||
public class Package : IFolder
|
||||
public class MixFile : IFolder
|
||||
{
|
||||
readonly Dictionary<uint, PackageEntry> index;
|
||||
readonly bool isRmix, isEncrypted;
|
||||
readonly long dataStart;
|
||||
readonly Stream s;
|
||||
|
||||
public Package(string filename)
|
||||
int priority;
|
||||
|
||||
// Create a new MixFile
|
||||
public MixFile(string filename, int priority, Dictionary<string, byte[]> contents)
|
||||
{
|
||||
this.priority = priority;
|
||||
if (File.Exists(filename))
|
||||
File.Delete(filename);
|
||||
|
||||
s = File.Create(filename);
|
||||
Write(contents);
|
||||
}
|
||||
|
||||
public MixFile(string filename, int priority)
|
||||
{
|
||||
this.priority = priority;
|
||||
s = FileSystem.Open(filename);
|
||||
|
||||
BinaryReader reader = new BinaryReader(s);
|
||||
@@ -149,6 +164,51 @@ namespace OpenRA.FileFormats
|
||||
{
|
||||
return index.ContainsKey(PackageEntry.HashFilename(filename));
|
||||
}
|
||||
|
||||
|
||||
public int Priority
|
||||
{
|
||||
get { return 1000 + priority; }
|
||||
}
|
||||
|
||||
public void Write(Dictionary<string, byte[]> contents)
|
||||
{
|
||||
// Cannot modify existing mixfile - rename existing file and
|
||||
// create a new one with original content plus modifications
|
||||
FileSystem.Unmount(this);
|
||||
|
||||
// TODO: Add existing data to the contents list
|
||||
if (index.Count > 0)
|
||||
throw new NotImplementedException("Updating mix files unfinished");
|
||||
|
||||
// Construct a list of entries for the file header
|
||||
uint dataSize = 0;
|
||||
var items = new List<PackageEntry>();
|
||||
foreach (var kv in contents)
|
||||
{
|
||||
uint length = (uint)kv.Value.Length;
|
||||
uint hash = PackageEntry.HashFilename(Path.GetFileName(kv.Key));
|
||||
items.Add(new PackageEntry(hash, dataSize, length));
|
||||
dataSize += length;
|
||||
}
|
||||
|
||||
// Write the new file
|
||||
s.Seek(0,SeekOrigin.Begin);
|
||||
using (var writer = new BinaryWriter(s))
|
||||
{
|
||||
// Write file header
|
||||
writer.Write((ushort)items.Count);
|
||||
writer.Write(dataSize);
|
||||
foreach (var item in items)
|
||||
item.Write(writer);
|
||||
|
||||
writer.Flush();
|
||||
|
||||
// Copy file data
|
||||
foreach (var file in contents)
|
||||
s.Write(file.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
117
OpenRA.FileFormats/Filesystem/ZipFile.cs
Normal file
117
OpenRA.FileFormats/Filesystem/ZipFile.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using ICSharpCode.SharpZipLib.Zip;
|
||||
using SZipFile = ICSharpCode.SharpZipLib.Zip.ZipFile;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class ZipFile : IFolder
|
||||
{
|
||||
string filename;
|
||||
SZipFile pkg;
|
||||
int priority;
|
||||
|
||||
public ZipFile(string filename, int priority)
|
||||
{
|
||||
this.filename = filename;
|
||||
this.priority = priority;
|
||||
try
|
||||
{
|
||||
// pull the file into memory, dont keep it open.
|
||||
pkg = new SZipFile(new MemoryStream(File.ReadAllBytes(filename)));
|
||||
}
|
||||
catch (ZipException e)
|
||||
{
|
||||
Log.Write("debug", "Couldn't load zip file: {0}", e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new zip with the specified contents
|
||||
public ZipFile(string filename, int priority, Dictionary<string, byte[]> contents)
|
||||
{
|
||||
this.priority = priority;
|
||||
this.filename = filename;
|
||||
|
||||
if (File.Exists(filename))
|
||||
File.Delete(filename);
|
||||
|
||||
pkg = SZipFile.Create(filename);
|
||||
Write(contents);
|
||||
}
|
||||
|
||||
public Stream GetContent(string filename)
|
||||
{
|
||||
|
||||
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);
|
||||
|
||||
ms.Seek(0, SeekOrigin.Begin);
|
||||
return ms;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<uint> AllFileHashes()
|
||||
{
|
||||
foreach(ZipEntry entry in pkg)
|
||||
yield return PackageEntry.HashFilename(entry.Name);
|
||||
}
|
||||
|
||||
public bool Exists(string filename)
|
||||
{
|
||||
return pkg.GetEntry(filename) != null;
|
||||
}
|
||||
|
||||
public int Priority
|
||||
{
|
||||
get { return 500 + priority; }
|
||||
}
|
||||
|
||||
public void Write(Dictionary<string, byte[]> contents)
|
||||
{
|
||||
pkg.Close();
|
||||
|
||||
pkg = SZipFile.Create(filename);
|
||||
|
||||
pkg.BeginUpdate();
|
||||
// TODO: Clear existing content?
|
||||
|
||||
foreach (var kvp in contents)
|
||||
pkg.Add(new StaticMemoryDataSource(kvp.Value), kvp.Key);
|
||||
|
||||
pkg.CommitUpdate();
|
||||
|
||||
pkg.Close();
|
||||
|
||||
pkg = new SZipFile(new MemoryStream(File.ReadAllBytes(filename)));
|
||||
}
|
||||
}
|
||||
|
||||
class StaticMemoryDataSource : IStaticDataSource
|
||||
{
|
||||
byte[] data;
|
||||
public StaticMemoryDataSource (byte[] data)
|
||||
{
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public Stream GetSource()
|
||||
{
|
||||
return new MemoryStream(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class Folder : IFolder
|
||||
{
|
||||
readonly string path;
|
||||
|
||||
public Folder(string path) { this.path = path; }
|
||||
|
||||
public Stream GetContent(string filename)
|
||||
{
|
||||
try { return File.OpenRead( Path.Combine( path, filename ) ); }
|
||||
catch { return null; }
|
||||
}
|
||||
|
||||
public IEnumerable<uint> AllFileHashes()
|
||||
{
|
||||
foreach( var filename in Directory.GetFiles( path, "*", SearchOption.TopDirectoryOnly ) )
|
||||
yield return PackageEntry.HashFilename( filename );
|
||||
}
|
||||
|
||||
public bool Exists(string filename)
|
||||
{
|
||||
return File.Exists(Path.Combine(path,filename));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,14 +33,12 @@ namespace OpenRA.FileFormats.Graphics
|
||||
IIndexBuffer CreateIndexBuffer( int length );
|
||||
ITexture CreateTexture( Bitmap bitmap );
|
||||
ITexture CreateTexture();
|
||||
IShader CreateShader( Stream stream );
|
||||
IShader CreateShader( string name );
|
||||
|
||||
Size WindowSize { get; }
|
||||
|
||||
void Begin();
|
||||
void End();
|
||||
void Clear( Color color );
|
||||
void Present();
|
||||
void Present( IInputHandler inputHandler );
|
||||
|
||||
void DrawIndexedPrimitives( PrimitiveType type, Range<int> vertexRange, Range<int> indexRange );
|
||||
void DrawIndexedPrimitives( PrimitiveType type, int vertexPool, int numPrimitives );
|
||||
@@ -52,13 +50,13 @@ namespace OpenRA.FileFormats.Graphics
|
||||
public interface IVertexBuffer<T>
|
||||
{
|
||||
void Bind();
|
||||
void SetData( T[] vertices );
|
||||
void SetData( T[] vertices, int length );
|
||||
}
|
||||
|
||||
public interface IIndexBuffer
|
||||
{
|
||||
void Bind();
|
||||
void SetData( ushort[] indices );
|
||||
void SetData( ushort[] indices, int length );
|
||||
}
|
||||
|
||||
public interface IShader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#region Copyright & License Information
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
@@ -9,16 +9,32 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public interface IInputHandler
|
||||
{
|
||||
void ModifierKeys( Modifiers mods );
|
||||
void OnKeyInput( KeyInput input );
|
||||
void OnMouseInput( MouseInput input );
|
||||
}
|
||||
|
||||
public struct MouseInput
|
||||
{
|
||||
public MouseInputEvent Event;
|
||||
public int2 Location;
|
||||
public MouseButton Button;
|
||||
public int2 Location;
|
||||
public Modifiers Modifiers;
|
||||
|
||||
public MouseInput( MouseInputEvent ev, MouseButton button, int2 location, Modifiers mods )
|
||||
{
|
||||
this.Event = ev;
|
||||
this.Button = button;
|
||||
this.Location = location;
|
||||
this.Modifiers = mods;
|
||||
}
|
||||
}
|
||||
|
||||
public enum MouseInputEvent { Down, Move, Up };
|
||||
@@ -26,19 +42,21 @@ namespace OpenRA
|
||||
[Flags]
|
||||
public enum MouseButton
|
||||
{
|
||||
None = (int)MouseButtons.None,
|
||||
Left = (int)MouseButtons.Left,
|
||||
Right = (int)MouseButtons.Right,
|
||||
Middle = (int)MouseButtons.Middle,
|
||||
None = 0,
|
||||
Left = 1,
|
||||
Right = 2,
|
||||
Middle = 4,
|
||||
WheelDown = 8,
|
||||
WheelUp = 16
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum Modifiers
|
||||
{
|
||||
None = (int)Keys.None,
|
||||
Shift = (int)Keys.Shift,
|
||||
Alt = (int)Keys.Alt,
|
||||
Ctrl = (int)Keys.Control,
|
||||
None = 0,
|
||||
Shift = 1,
|
||||
Alt = 2,
|
||||
Ctrl = 4,
|
||||
}
|
||||
|
||||
public enum KeyInputEvent { Down, Up };
|
||||
@@ -26,6 +26,8 @@ namespace OpenRA.FileFormats
|
||||
|
||||
public byte[] Image;
|
||||
|
||||
public ImageHeader() { }
|
||||
|
||||
public ImageHeader( BinaryReader reader )
|
||||
{
|
||||
Offset = reader.ReadUInt32();
|
||||
@@ -35,6 +37,15 @@ namespace OpenRA.FileFormats
|
||||
RefOffset = reader.ReadUInt16();
|
||||
RefFormat = (Format)reader.ReadUInt16();
|
||||
}
|
||||
|
||||
public static readonly int SizeOnDisk = 8;
|
||||
|
||||
public void WriteTo(BinaryWriter writer)
|
||||
{
|
||||
writer.Write(Offset | ((uint)Format << 24));
|
||||
writer.Write((ushort)RefOffset);
|
||||
writer.Write((ushort)RefFormat);
|
||||
}
|
||||
}
|
||||
|
||||
public enum Format
|
||||
|
||||
46
OpenRA.FileFormats/Graphics/ShpWriter.cs
Normal file
46
OpenRA.FileFormats/Graphics/ShpWriter.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.FileFormats.Graphics
|
||||
{
|
||||
// format80-only SHP writer
|
||||
|
||||
public static class ShpWriter
|
||||
{
|
||||
public static void Write(Stream s, int width, int height, IEnumerable<byte[]> frames)
|
||||
{
|
||||
var compressedFrames = frames.Select(f => Format80.Encode(f)).ToArray();
|
||||
|
||||
// note: end-of-file and all-zeroes headers
|
||||
var dataOffset = 14 + (compressedFrames.Length + 2) * ImageHeader.SizeOnDisk;
|
||||
|
||||
using (var bw = new BinaryWriter(s))
|
||||
{
|
||||
bw.Write((ushort)compressedFrames.Length);
|
||||
bw.Write((ushort)0); // unused
|
||||
bw.Write((ushort)0); // unused
|
||||
bw.Write((ushort)width);
|
||||
bw.Write((ushort)height);
|
||||
bw.Write((uint)0); // unused
|
||||
|
||||
foreach (var f in compressedFrames)
|
||||
{
|
||||
var ih = new ImageHeader { Format = Format.Format80, Offset = (uint)dataOffset };
|
||||
dataOffset += f.Length;
|
||||
|
||||
ih.WriteTo(bw);
|
||||
}
|
||||
|
||||
var eof = new ImageHeader { Offset = (uint)dataOffset };
|
||||
eof.WriteTo(bw);
|
||||
|
||||
var allZeroes = new ImageHeader { };
|
||||
allZeroes.WriteTo(bw);
|
||||
|
||||
foreach (var f in compressedFrames)
|
||||
bw.Write(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
97
OpenRA.FileFormats/HttpUtil.cs
Normal file
97
OpenRA.FileFormats/HttpUtil.cs
Normal file
@@ -0,0 +1,97 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public static class HttpUtil
|
||||
{
|
||||
public static byte[] DownloadData(string url, Action<int, int> f, int chunkSize)
|
||||
{
|
||||
var uri = new Uri(url);
|
||||
var ip = Dns.GetHostEntry(uri.DnsSafeHost).AddressList[0];
|
||||
|
||||
using (var s = new TcpClient())
|
||||
{
|
||||
s.Connect(new IPEndPoint(ip, uri.Port));
|
||||
var ns = s.GetStream();
|
||||
var sw = new StreamWriter(ns);
|
||||
|
||||
sw.Write("GET {0} HTTP/1.0\r\nHost:{1}\r\n\r\n", uri.PathAndQuery, uri.Host);
|
||||
sw.Flush();
|
||||
|
||||
var br = new BinaryReader(ns);
|
||||
var contentLength = 0;
|
||||
var offset = 0;
|
||||
for (; ; )
|
||||
{
|
||||
var result = br.ReadLine();
|
||||
var kv = result.Split(new string[] { ": " }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if (result == "")
|
||||
{
|
||||
/* data follows the blank line */
|
||||
|
||||
if (contentLength > 0)
|
||||
{
|
||||
if (f != null)
|
||||
f(offset, contentLength);
|
||||
|
||||
var data = new byte[contentLength];
|
||||
while (offset < contentLength)
|
||||
{
|
||||
var thisChunk = Math.Min(contentLength - offset, chunkSize);
|
||||
br.Read(data, offset, thisChunk);
|
||||
offset += thisChunk;
|
||||
if (f != null)
|
||||
f(offset, contentLength);
|
||||
}
|
||||
s.Close();
|
||||
return data;
|
||||
}
|
||||
else
|
||||
{
|
||||
s.Close();
|
||||
return new byte[] { };
|
||||
}
|
||||
}
|
||||
else if (kv[0] == "Content-Length")
|
||||
contentLength = int.Parse(kv[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] DownloadData(string url, Action<int, int> f)
|
||||
{
|
||||
return DownloadData(url, f, 4096);
|
||||
}
|
||||
|
||||
public static byte[] DownloadData(string url)
|
||||
{
|
||||
return DownloadData(url, null);
|
||||
}
|
||||
|
||||
static string ReadLine(this BinaryReader br)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
char c;
|
||||
while ((c = br.ReadChar()) != '\n')
|
||||
if (c != '\r' && c != '\n')
|
||||
sb.Append(c);
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,22 +18,26 @@ namespace OpenRA.FileFormats
|
||||
public class Manifest
|
||||
{
|
||||
public readonly string[]
|
||||
Folders, Packages, Rules,
|
||||
Sequences, Chrome, Assemblies, ChromeLayout,
|
||||
Mods, Folders, Packages, Rules, ServerTraits,
|
||||
Sequences, Cursors, Chrome, Assemblies, ChromeLayout,
|
||||
Weapons, Voices, Music, Movies, TileSets;
|
||||
|
||||
public readonly string ShellmapUid, LoadScreen;
|
||||
public readonly string LoadScreen;
|
||||
public readonly int TileSize = 24;
|
||||
|
||||
public Manifest(string[] mods)
|
||||
{
|
||||
Mods = mods;
|
||||
var yaml = mods
|
||||
.Select(m => MiniYaml.FromFile("mods/" + m + "/mod.yaml"))
|
||||
.Aggregate(MiniYaml.Merge);
|
||||
|
||||
|
||||
// Todo: Use fieldloader
|
||||
Folders = YamlList(yaml, "Folders");
|
||||
Packages = YamlList(yaml, "Packages");
|
||||
Rules = YamlList(yaml, "Rules");
|
||||
ServerTraits = YamlList(yaml, "ServerTraits");
|
||||
Sequences = YamlList(yaml, "Sequences");
|
||||
Cursors = YamlList(yaml, "Cursors");
|
||||
Chrome = YamlList(yaml, "Chrome");
|
||||
Assemblies = YamlList(yaml, "Assemblies");
|
||||
ChromeLayout = YamlList(yaml, "ChromeLayout");
|
||||
@@ -43,8 +47,10 @@ namespace OpenRA.FileFormats
|
||||
Movies = YamlList(yaml, "Movies");
|
||||
TileSets = YamlList(yaml, "TileSets");
|
||||
|
||||
ShellmapUid = yaml.First( x => x.Key == "ShellmapUid" ).Value.Value;
|
||||
LoadScreen = yaml.First( x => x.Key == "LoadScreen" ).Value.Value;
|
||||
|
||||
if (yaml.FirstOrDefault( x => x.Key == "TileSize" ) != null)
|
||||
TileSize = int.Parse(yaml.First( x => x.Key == "TileSize" ).Value.Value);
|
||||
}
|
||||
|
||||
static string[] YamlList(List<MiniYamlNode> ys, string key)
|
||||
|
||||
@@ -12,18 +12,22 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class MapStub
|
||||
{
|
||||
public readonly IFolder Package;
|
||||
protected IFolder Container;
|
||||
public string Path {get; protected set;}
|
||||
|
||||
// Yaml map data
|
||||
public readonly string Uid;
|
||||
[FieldLoader.Load] public bool Selectable;
|
||||
public string Uid { get; protected set; }
|
||||
[FieldLoader.Load] public bool Selectable;
|
||||
[FieldLoader.Load] public bool UseAsShellmap;
|
||||
|
||||
[FieldLoader.Load] public string Title;
|
||||
[FieldLoader.Load] public string Type = "Conquest";
|
||||
[FieldLoader.Load] public string Description;
|
||||
[FieldLoader.Load] public string Author;
|
||||
[FieldLoader.Load] public int PlayerCount;
|
||||
@@ -35,18 +39,33 @@ namespace OpenRA.FileFormats
|
||||
|
||||
[FieldLoader.Load] public int2 TopLeft;
|
||||
[FieldLoader.Load] public int2 BottomRight;
|
||||
public int Width { get { return BottomRight.X - TopLeft.X; } }
|
||||
public int Height { get { return BottomRight.Y - TopLeft.Y; } }
|
||||
|
||||
public MapStub(IFolder package)
|
||||
public Rectangle Bounds;
|
||||
|
||||
public MapStub() {} // Hack for the editor - not used for anything important
|
||||
|
||||
public MapStub(string path)
|
||||
{
|
||||
Package = package;
|
||||
var yaml = MiniYaml.FromStream(Package.GetContent("map.yaml"));
|
||||
Path = path;
|
||||
Container = FileSystem.OpenPackage(path, int.MaxValue);
|
||||
var yaml = MiniYaml.FromStream(Container.GetContent("map.yaml"));
|
||||
FieldLoader.Load( this, new MiniYaml( null, yaml ) );
|
||||
|
||||
Uid = Package.GetContent("map.uid").ReadAllText();
|
||||
|
||||
Bounds = Rectangle.FromLTRB(TopLeft.X, TopLeft.Y, BottomRight.X, BottomRight.Y);
|
||||
Uid = ComputeHash();
|
||||
}
|
||||
|
||||
string ComputeHash()
|
||||
{
|
||||
// UID is calculated by taking an SHA1 of the yaml and binary data
|
||||
// Read the relevant data into a buffer
|
||||
var data = Container.GetContent("map.yaml").ReadAllBytes()
|
||||
.Concat(Container.GetContent("map.bin").ReadAllBytes()).ToArray();
|
||||
|
||||
// Take the SHA1
|
||||
using (var csp = SHA1.Create())
|
||||
return new string(csp.ComputeHash(data).SelectMany(a => a.ToString("x2")).ToArray());
|
||||
}
|
||||
|
||||
static object LoadWaypoints( MiniYaml y )
|
||||
{
|
||||
var ret = new Dictionary<string, int2>();
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Drawing;
|
||||
using System.Drawing;
|
||||
using System;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
@@ -16,13 +17,19 @@ namespace OpenRA.FileFormats
|
||||
{
|
||||
public string Name;
|
||||
public string Palette;
|
||||
public string Race;
|
||||
public bool OwnsWorld = false;
|
||||
public bool NonCombatant = false;
|
||||
public bool Playable = false;
|
||||
public bool DefaultStartingUnits = false;
|
||||
public bool AllowBots = true;
|
||||
|
||||
public bool LockRace = false;
|
||||
public string Race;
|
||||
|
||||
public bool LockColor = false;
|
||||
public Color Color = Color.FromArgb(238,238,238);
|
||||
public Color Color2 = Color.FromArgb(44,28,24);
|
||||
public ColorRamp ColorRamp = new ColorRamp(75, 255, 180, 25);
|
||||
|
||||
public int InitialCash = 0;
|
||||
public string[] Allies = {};
|
||||
|
||||
@@ -17,15 +17,15 @@ namespace OpenRA.FileFormats
|
||||
{
|
||||
public readonly List<byte[]> TileBitmapBytes = new List<byte[]>();
|
||||
|
||||
public Terrain( Stream stream )
|
||||
public Terrain( Stream stream, int size )
|
||||
{
|
||||
// Try loading as a cnc .tem
|
||||
BinaryReader reader = new BinaryReader( stream );
|
||||
int Width = reader.ReadUInt16();
|
||||
int Height = reader.ReadUInt16();
|
||||
|
||||
if( Width != 24 || Height != 24 )
|
||||
throw new InvalidDataException( string.Format( "{0}x{1}", Width, Height ) );
|
||||
|
||||
if( Width != size || Height != size )
|
||||
throw new InvalidDataException( "{0}x{1} != {2}x{2}".F(Width, Height, size ) );
|
||||
|
||||
/*NumTiles = */reader.ReadUInt16();
|
||||
/*Zero1 = */reader.ReadUInt16();
|
||||
@@ -46,9 +46,7 @@ namespace OpenRA.FileFormats
|
||||
reader = new BinaryReader( stream );
|
||||
Width = reader.ReadUInt16();
|
||||
Height = reader.ReadUInt16();
|
||||
if( Width != 24 || Height != 24 )
|
||||
throw new InvalidDataException( string.Format( "{0}x{1}", Width, Height ) );
|
||||
|
||||
|
||||
/*NumTiles = */reader.ReadUInt16();
|
||||
reader.ReadUInt16();
|
||||
/*XDim = */reader.ReadUInt16();
|
||||
@@ -67,8 +65,8 @@ namespace OpenRA.FileFormats
|
||||
{
|
||||
if (b != 255)
|
||||
{
|
||||
stream.Position = ImgStart + b * 24 * 24;
|
||||
TileBitmapBytes.Add(new BinaryReader(stream).ReadBytes(24 * 24));
|
||||
stream.Position = ImgStart + b * size * size;
|
||||
TileBitmapBytes.Add(new BinaryReader(stream).ReadBytes(size * size));
|
||||
}
|
||||
else
|
||||
TileBitmapBytes.Add(null);
|
||||
|
||||
@@ -74,11 +74,12 @@ namespace OpenRA.FileFormats
|
||||
public string Name;
|
||||
public string Id;
|
||||
public string Palette;
|
||||
public int TileSize = 24;
|
||||
public string[] Extensions;
|
||||
public Dictionary<string, TerrainTypeInfo> Terrain = new Dictionary<string, TerrainTypeInfo>();
|
||||
public Dictionary<ushort, Terrain> Tiles = new Dictionary<ushort, Terrain>();
|
||||
public Dictionary<ushort, TileTemplate> Templates = new Dictionary<ushort, TileTemplate>();
|
||||
static List<string> fields = new List<string>() {"Name", "Id", "Palette", "Extensions"};
|
||||
static List<string> fields = new List<string>() {"Name", "TileSize", "Id", "Palette", "Extensions"};
|
||||
|
||||
public TileSet() {}
|
||||
public TileSet( string filepath )
|
||||
@@ -103,20 +104,13 @@ namespace OpenRA.FileFormats
|
||||
using( Stream s = FileSystem.OpenWithExts(t.Value.Image, Extensions) )
|
||||
{
|
||||
if( !Tiles.ContainsKey( t.Key ) )
|
||||
Tiles.Add( t.Key, new Terrain( s ) );
|
||||
Tiles.Add( t.Key, new Terrain( s, TileSize ) );
|
||||
}
|
||||
}
|
||||
|
||||
public void Save(string filepath)
|
||||
{
|
||||
var root = new List<MiniYamlNode>();
|
||||
foreach (var field in fields)
|
||||
{
|
||||
FieldInfo f = this.GetType().GetField(field);
|
||||
if (f.GetValue(this) == null) continue;
|
||||
root.Add( new MiniYamlNode( field, FieldSaver.FormatValue( this, f ) ) );
|
||||
}
|
||||
|
||||
var gen = new List<MiniYamlNode>();
|
||||
foreach (var field in fields)
|
||||
{
|
||||
@@ -144,7 +138,7 @@ namespace OpenRA.FileFormats
|
||||
if( Tiles.TryGetValue( r.type, out tile ) )
|
||||
return tile.TileBitmapBytes[ r.image ];
|
||||
|
||||
byte[] missingTile = new byte[ 24 * 24 ];
|
||||
byte[] missingTile = new byte[ TileSize * TileSize ];
|
||||
for( int i = 0 ; i < missingTile.Length ; i++ )
|
||||
missingTile[ i ] = 0x36;
|
||||
|
||||
|
||||
@@ -225,7 +225,7 @@ namespace OpenRA.FileFormats
|
||||
{
|
||||
return string.Join("\n", y.ToLines(true).Select(x => x.TrimEnd()).ToArray());
|
||||
}
|
||||
|
||||
|
||||
public static IEnumerable<string> ToLines(this MiniYamlNodes y, bool lowest)
|
||||
{
|
||||
foreach (var kv in y)
|
||||
|
||||
37
OpenRA.FileFormats/Mod.cs
Normal file
37
OpenRA.FileFormats/Mod.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class Mod
|
||||
{
|
||||
public string Title;
|
||||
public string Description;
|
||||
public string Version;
|
||||
public string Author;
|
||||
public string Requires;
|
||||
public bool Standalone = false;
|
||||
|
||||
public static readonly Dictionary<string, Mod> AllMods = ValidateMods(Directory.GetDirectories("mods").Select(x => x.Substring(5)).ToArray());
|
||||
|
||||
public static Dictionary<string, Mod> ValidateMods(string[] mods)
|
||||
{
|
||||
var ret = new Dictionary<string, Mod>();
|
||||
foreach (var m in mods)
|
||||
{
|
||||
if (!File.Exists("mods" + Path.DirectorySeparatorChar + m + Path.DirectorySeparatorChar + "mod.yaml"))
|
||||
continue;
|
||||
|
||||
var yaml = new MiniYaml(null, MiniYaml.FromFile("mods" + Path.DirectorySeparatorChar + m + Path.DirectorySeparatorChar + "mod.yaml"));
|
||||
if (!yaml.NodesDict.ContainsKey("Metadata"))
|
||||
continue;
|
||||
|
||||
ret.Add(m, FieldLoader.Load<Mod>(yaml.NodesDict["Metadata"]));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,7 @@
|
||||
</Reference>
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Tao.Sdl, Version=1.2.13.0, Culture=neutral, PublicKeyToken=9c7a200e36c0094e">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
@@ -53,22 +54,28 @@
|
||||
<Reference Include="WindowsBase">
|
||||
<RequiredTargetFramework>3.0</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\thirdparty\ICSharpCode.SharpZipLib.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ColorHSLR.cs" />
|
||||
<Compile Include="Evaluator.cs" />
|
||||
<Compile Include="Exts.cs" />
|
||||
<Compile Include="FieldLoader.cs" />
|
||||
<Compile Include="FileSystem.cs" />
|
||||
<Compile Include="Folder.cs" />
|
||||
<Compile Include="Graphics\IGraphicsDevice.cs" />
|
||||
<Compile Include="Graphics\IInputHandler.cs" />
|
||||
<Compile Include="Graphics\ShpWriter.cs" />
|
||||
<Compile Include="Graphics\Vertex.cs" />
|
||||
<Compile Include="HttpUtil.cs" />
|
||||
<Compile Include="Manifest.cs" />
|
||||
<Compile Include="MiniYaml.cs" />
|
||||
<Compile Include="Mod.cs" />
|
||||
<Compile Include="PackageEntry.cs" />
|
||||
<Compile Include="Package.cs" />
|
||||
<Compile Include="PackageWriter.cs" />
|
||||
<Compile Include="Palette.cs" />
|
||||
<Compile Include="PlayerColorRemap.cs" />
|
||||
<Compile Include="Primitives\ActionQueue.cs" />
|
||||
<Compile Include="Primitives\DisposableAction.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Thirdparty\Random.cs" />
|
||||
@@ -98,8 +105,13 @@
|
||||
<Compile Include="Map\MapStub.cs" />
|
||||
<Compile Include="Map\SmudgeReference.cs" />
|
||||
<Compile Include="Map\PlayerReference.cs" />
|
||||
<Compile Include="CompressedPackage.cs" />
|
||||
<Compile Include="Graphics\VqaReader.cs" />
|
||||
<Compile Include="Filesystem\MixFile.cs" />
|
||||
<Compile Include="Filesystem\FileSystem.cs" />
|
||||
<Compile Include="Filesystem\Folder.cs" />
|
||||
<Compile Include="Filesystem\InstallShieldPackage.cs" />
|
||||
<Compile Include="FileFormats\Blast.cs" />
|
||||
<Compile Include="Filesystem\ZipFile.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public static class PackageWriter
|
||||
{
|
||||
public static void CreateMix(string filename, List<string> contents)
|
||||
{
|
||||
// Construct a list of entries for the file header
|
||||
uint dataSize = 0;
|
||||
var items = new List<PackageEntry>();
|
||||
foreach (var file in contents)
|
||||
{
|
||||
uint length = (uint)new FileInfo(file).Length;
|
||||
uint hash = PackageEntry.HashFilename(Path.GetFileName(file));
|
||||
items.Add(new PackageEntry(hash, dataSize, length));
|
||||
dataSize += length;
|
||||
}
|
||||
|
||||
using (var s = File.Create(filename))
|
||||
using (var writer = new BinaryWriter(s))
|
||||
{
|
||||
// Write file header
|
||||
writer.Write((ushort)items.Count);
|
||||
writer.Write(dataSize);
|
||||
foreach (var item in items)
|
||||
item.Write(writer);
|
||||
|
||||
writer.Flush();
|
||||
|
||||
// Copy file data
|
||||
foreach (var file in contents)
|
||||
s.Write(File.ReadAllBytes(file));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,11 +8,8 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
@@ -57,6 +54,7 @@ namespace OpenRA.FileFormats
|
||||
colors[0] = 0;
|
||||
if (remapTransparent)
|
||||
{
|
||||
colors[1] = 178u << 24; // Hack for d2k; may have side effects
|
||||
colors[3] = 178u << 24;
|
||||
colors[4] = 140u << 24;
|
||||
}
|
||||
|
||||
12
OpenRA.FileFormats/PlayerColorRemap.cs
Normal file → Executable file
12
OpenRA.FileFormats/PlayerColorRemap.cs
Normal file → Executable file
@@ -15,15 +15,19 @@ using System.Linq;
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
// TODO: ship this out of here.
|
||||
public enum PaletteFormat { ra, cnc, d2k }
|
||||
|
||||
public class PlayerColorRemap : IPaletteRemap
|
||||
{
|
||||
Dictionary<int, Color> remapColors;
|
||||
|
||||
public PlayerColorRemap(Color c1, Color c2, bool useSplitRamp)
|
||||
public PlayerColorRemap(ColorRamp c, PaletteFormat fmt)
|
||||
{
|
||||
var baseIndex = useSplitRamp ? 0xb0 : 80;
|
||||
var ramp = useSplitRamp
|
||||
var c1 = c.GetColor(0);
|
||||
var c2 = c.GetColor(1); /* temptemp: this can be expressed better */
|
||||
|
||||
var baseIndex = (fmt == PaletteFormat.cnc) ? 0xb0 : (fmt == PaletteFormat.d2k) ? 240 : 80;
|
||||
var ramp = (fmt == PaletteFormat.cnc)
|
||||
? new[] { 0, 2, 4, 6, 8, 10, 13, 15, 1, 3, 5, 7, 9, 11, 12, 14 }
|
||||
: new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
|
||||
|
||||
@@ -31,7 +35,7 @@ namespace OpenRA.FileFormats
|
||||
.ToDictionary(u => u.First, u => u.Second);
|
||||
}
|
||||
|
||||
static Color ColorLerp(float t, Color c1, Color c2)
|
||||
public static Color ColorLerp(float t, Color c1, Color c2)
|
||||
{
|
||||
return Color.FromArgb(255,
|
||||
(int)(t * c2.R + (1 - t) * c1.R),
|
||||
|
||||
40
OpenRA.FileFormats/Primitives/ActionQueue.cs
Normal file
40
OpenRA.FileFormats/Primitives/ActionQueue.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
/// <summary>
|
||||
/// A thread-safe action queue, suitable for passing units of work between threads.
|
||||
/// </summary>
|
||||
public class ActionQueue
|
||||
{
|
||||
object syncRoot = new object();
|
||||
Action actions = () => { };
|
||||
|
||||
public void Add(Action a)
|
||||
{
|
||||
lock (syncRoot)
|
||||
actions += a;
|
||||
}
|
||||
|
||||
public void PerformActions()
|
||||
{
|
||||
Action a;
|
||||
lock (syncRoot)
|
||||
{
|
||||
a = actions;
|
||||
actions = () => { };
|
||||
}
|
||||
a();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -56,6 +56,11 @@ namespace OpenRA.FileFormats
|
||||
public static U AsSecond(Pair<T, U> p) { return p.Second; }
|
||||
|
||||
public Pair<U, T> Swap() { return Pair.New(Second, First); }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "({0},{1})".F(First, Second);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Pair
|
||||
|
||||
@@ -62,7 +62,8 @@ namespace OpenRA
|
||||
Constrain(Y, min.Y, max.Y));
|
||||
}
|
||||
|
||||
public static float2 operator *(float a, float2 b) { return new float2(a * b.X, a * b.Y); }
|
||||
public static float2 operator *(float a, float2 b) { return new float2(a * b.X, a * b.Y); }
|
||||
public static float2 operator *(float2 b, float a) { return new float2(a * b.X, a * b.Y); }
|
||||
public static float2 operator *( float2 a, float2 b ) { return new float2( a.X * b.X, a.Y * b.Y ); }
|
||||
public static float2 operator /( float2 a, float2 b ) { return new float2( a.X / b.X, a.Y / b.Y ); }
|
||||
|
||||
|
||||
@@ -25,6 +25,9 @@ namespace OpenRA
|
||||
public static int2 operator -(int2 a, int2 b) { return new int2(a.X - b.X, a.Y - b.Y); }
|
||||
public static int2 operator *(int a, int2 b) { return new int2(a * b.X, a * b.Y); }
|
||||
public static int2 operator *(int2 b, int a) { return new int2(a * b.X, a * b.Y); }
|
||||
public static int2 operator /(int2 a, int b) { return new int2(a.X / b, a.Y / b); }
|
||||
|
||||
public static int2 operator -(int2 a) { return new int2(-a.X, -a.Y); }
|
||||
|
||||
public static bool operator ==(int2 me, int2 other) { return (me.X == other.X && me.Y == other.Y); }
|
||||
public static bool operator !=(int2 me, int2 other) { return !(me == other); }
|
||||
@@ -59,5 +62,24 @@ namespace OpenRA
|
||||
{
|
||||
return (uint)((orig & 0xff000000) >> 24) | ((orig & 0x00ff0000) >> 8) | ((orig & 0x0000ff00) << 8) | ((orig & 0x000000ff) << 24);
|
||||
}
|
||||
|
||||
public static int Lerp( int a, int b, int mul, int div )
|
||||
{
|
||||
return a + ( b - a ) * mul / div;
|
||||
}
|
||||
|
||||
public static int2 Lerp( int2 a, int2 b, int mul, int div )
|
||||
{
|
||||
return a + ( b - a ) * mul / div;
|
||||
}
|
||||
|
||||
public int2 Clamp(Rectangle r)
|
||||
{
|
||||
return new int2(Math.Min(r.Right, Math.Max(X, r.Left)),
|
||||
Math.Min(r.Bottom, Math.Max(Y, r.Top)));
|
||||
}
|
||||
|
||||
public static int Dot(int2 a, int2 b) { return a.X * b.X + a.Y * b.Y; }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
5
OpenRA.FileFormats/Thirdparty/Random.cs
vendored
5
OpenRA.FileFormats/Thirdparty/Random.cs
vendored
@@ -18,6 +18,8 @@ namespace OpenRA.Thirdparty
|
||||
{
|
||||
uint[] mt = new uint[624];
|
||||
int index = 0;
|
||||
|
||||
public int Last;
|
||||
|
||||
public Random() : this(Environment.TickCount) { }
|
||||
|
||||
@@ -39,7 +41,8 @@ namespace OpenRA.Thirdparty
|
||||
y ^= y >> 18;
|
||||
|
||||
index = (index + 1) % 624;
|
||||
return (int)(y % int.MaxValue);
|
||||
Last = (int)(y % int.MaxValue);
|
||||
return Last;
|
||||
}
|
||||
|
||||
public int Next(int low, int high) { return low + Next() % (high - low); }
|
||||
|
||||
@@ -6,15 +6,15 @@
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.Traits;
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Support;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Traits.Activities;
|
||||
|
||||
namespace OpenRA
|
||||
@@ -26,11 +26,12 @@ namespace OpenRA
|
||||
public readonly World World;
|
||||
public readonly uint ActorID;
|
||||
|
||||
public int2 Location { get { return Trait<IOccupySpace>().TopLeft; } }
|
||||
public int2 Location { get { return Trait<IOccupySpace>().TopLeft; } }
|
||||
public int2 CenterLocation { get { return Trait<IHasLocation>().PxPosition; } }
|
||||
[Sync]
|
||||
public Player Owner;
|
||||
|
||||
IActivity currentActivity;
|
||||
private IActivity currentActivity;
|
||||
public Group Group;
|
||||
|
||||
internal Actor(World world, string name, TypeDictionary initDict )
|
||||
@@ -52,9 +53,6 @@ namespace OpenRA
|
||||
AddTrait(trait.Create(init));
|
||||
}
|
||||
|
||||
if( CenterLocation == float2.Zero && HasTrait<IOccupySpace>() )
|
||||
CenterLocation = Traits.Util.CenterOfCell(Location);
|
||||
|
||||
Size = Lazy.New(() =>
|
||||
{
|
||||
var si = Info.Traits.GetOrDefault<SelectableInfo>();
|
||||
@@ -63,39 +61,25 @@ namespace OpenRA
|
||||
|
||||
// auto size from render
|
||||
var firstSprite = TraitsImplementing<IRender>().SelectMany(x => x.Render(this)).FirstOrDefault();
|
||||
if (firstSprite.Sprite == null) return float2.Zero;
|
||||
return firstSprite.Sprite.size;
|
||||
if (firstSprite.Sprite == null) return float2.Zero;
|
||||
return firstSprite.Sprite.size * firstSprite.Scale;
|
||||
});
|
||||
}
|
||||
|
||||
public void Tick()
|
||||
{
|
||||
var wasIdle = currentActivity is Idle;
|
||||
while (currentActivity != null)
|
||||
{
|
||||
var a = currentActivity;
|
||||
currentActivity = a.Tick(this) ?? new Idle();
|
||||
if (currentActivity == null)
|
||||
foreach (var ni in TraitsImplementing<INotifyIdle>())
|
||||
ni.TickIdle(this);
|
||||
|
||||
if (a == currentActivity) break;
|
||||
|
||||
if (currentActivity is Idle)
|
||||
{
|
||||
if (!wasIdle)
|
||||
foreach (var ni in TraitsImplementing<INotifyIdle>())
|
||||
ni.Idle(this);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
currentActivity = Util.RunActivity( this, currentActivity );
|
||||
}
|
||||
|
||||
public bool IsIdle
|
||||
{
|
||||
get { return currentActivity == null || currentActivity is Idle; }
|
||||
get { return currentActivity == null; }
|
||||
}
|
||||
|
||||
public float2 CenterLocation;
|
||||
|
||||
OpenRA.FileFormats.Lazy<float2> Size;
|
||||
|
||||
public IEnumerable<Renderable> Render()
|
||||
@@ -104,62 +88,46 @@ namespace OpenRA
|
||||
var sprites = TraitsImplementing<IRender>().SelectMany(x => x.Render(this));
|
||||
return mods.Aggregate(sprites, (m, p) => p.ModifyRender(this, m));
|
||||
}
|
||||
|
||||
public Order Order( int2 xy, MouseInput mi )
|
||||
{
|
||||
if (Owner != World.LocalPlayer)
|
||||
return null;
|
||||
|
||||
if (!World.Map.IsInMap(xy.X, xy.Y))
|
||||
return null;
|
||||
|
||||
if (Destroyed)
|
||||
return null;
|
||||
|
||||
var underCursor = World.FindUnitsAtMouse(mi.Location)
|
||||
.Where(a => a.Info.Traits.Contains<TargetableInfo>())
|
||||
.OrderByDescending(a => a.Info.Traits.Contains<SelectableInfo>() ? a.Info.Traits.Get<SelectableInfo>().Priority : int.MinValue)
|
||||
.FirstOrDefault();
|
||||
|
||||
return TraitsImplementing<IIssueOrder>()
|
||||
.Select( x => x.IssueOrder( this, xy, mi, underCursor ) )
|
||||
.FirstOrDefault( x => x != null );
|
||||
}
|
||||
|
||||
|
||||
// When useAltitude = true, the bounding box is extended
|
||||
// vertically to altitude = 0 to support FindUnitsInCircle queries
|
||||
// When false, the bounding box is given for the actor
|
||||
// at its current altitude
|
||||
public RectangleF GetBounds(bool useAltitude)
|
||||
{
|
||||
var si = Info.Traits.GetOrDefault<SelectableInfo>();
|
||||
|
||||
var size = Size.Value;
|
||||
var loc = CenterLocation - 0.5f * size;
|
||||
var loc = CenterLocation - 0.5f * size;
|
||||
|
||||
var si = Info.Traits.GetOrDefault<SelectableInfo>();
|
||||
if (si != null && si.Bounds != null && si.Bounds.Length > 2)
|
||||
loc += new float2(si.Bounds[2], si.Bounds[3]);
|
||||
|
||||
if (useAltitude)
|
||||
{
|
||||
var move = TraitOrDefault<IMove>();
|
||||
if (move != null) loc -= new float2(0, move.Altitude);
|
||||
var move = TraitOrDefault<IMove>();
|
||||
if (move != null)
|
||||
{
|
||||
loc -= new float2(0, move.Altitude);
|
||||
if (useAltitude)
|
||||
size = new float2(size.X, size.Y + move.Altitude);
|
||||
}
|
||||
|
||||
|
||||
return new RectangleF(loc.X, loc.Y, size.X, size.Y);
|
||||
}
|
||||
|
||||
public bool IsInWorld { get; internal set; }
|
||||
public bool IsInWorld { get; internal set; }
|
||||
|
||||
public void QueueActivity( bool queued, IActivity nextActivity )
|
||||
{
|
||||
if( !queued )
|
||||
CancelActivity();
|
||||
QueueActivity( nextActivity );
|
||||
}
|
||||
|
||||
public void QueueActivity( IActivity nextActivity )
|
||||
{
|
||||
if( currentActivity == null )
|
||||
{
|
||||
currentActivity = nextActivity;
|
||||
return;
|
||||
}
|
||||
var act = currentActivity;
|
||||
while( act.NextActivity != null )
|
||||
{
|
||||
act = act.NextActivity;
|
||||
}
|
||||
act.NextActivity = nextActivity;
|
||||
else
|
||||
currentActivity.Queue( nextActivity );
|
||||
}
|
||||
|
||||
public void CancelActivity()
|
||||
@@ -168,7 +136,6 @@ namespace OpenRA
|
||||
currentActivity.Cancel( this );
|
||||
}
|
||||
|
||||
// For pathdebug, et al
|
||||
public IActivity GetCurrentActivity()
|
||||
{
|
||||
return currentActivity;
|
||||
@@ -221,10 +188,24 @@ namespace OpenRA
|
||||
{
|
||||
World.AddFrameEndTask( w =>
|
||||
{
|
||||
if (Destroyed) return;
|
||||
|
||||
World.Remove( this );
|
||||
World.traitDict.RemoveActor( this );
|
||||
Destroyed = true;
|
||||
} );
|
||||
}
|
||||
|
||||
// todo: move elsewhere.
|
||||
public void ChangeOwner(Player newOwner)
|
||||
{
|
||||
World.AddFrameEndTask(w =>
|
||||
{
|
||||
// momentarily remove from world so the ownership queries don't get confused
|
||||
w.Remove(this);
|
||||
Owner = newOwner;
|
||||
w.Add(this);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
@@ -23,9 +23,6 @@ namespace OpenRA.FileFormats
|
||||
|
||||
public ActorReference( string type, Dictionary<string, MiniYaml> inits )
|
||||
{
|
||||
if (Rules.Info != null && !Rules.Info.ContainsKey(type))
|
||||
throw new InvalidDataException("Unknown actor: `{0}'".F(type));
|
||||
|
||||
Type = type;
|
||||
InitDict = new TypeDictionary();
|
||||
foreach( var i in inits )
|
||||
@@ -45,7 +42,7 @@ namespace OpenRA.FileFormats
|
||||
foreach( var init in InitDict )
|
||||
{
|
||||
var initName = init.GetType().Name;
|
||||
ret.NodesDict.Add( 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;
|
||||
}
|
||||
|
||||
@@ -17,12 +17,12 @@ namespace OpenRA
|
||||
CursorSequence sequence;
|
||||
public Cursor(string cursor)
|
||||
{
|
||||
sequence = SequenceProvider.GetCursorSequence(cursor);
|
||||
sequence = CursorProvider.GetCursorSequence(cursor);
|
||||
}
|
||||
|
||||
public void Draw(int frame, float2 pos)
|
||||
{
|
||||
Game.Renderer.SpriteRenderer.DrawSprite(sequence.GetSprite(frame), pos - sequence.Hotspot, sequence.Palette);
|
||||
sequence.GetSprite(frame).DrawAt(pos - sequence.Hotspot, Game.modData.Palette.GetPaletteIndex(sequence.Palette));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Effects
|
||||
{
|
||||
public class MoveFlash : IEffect
|
||||
{
|
||||
Animation anim = new Animation("moveflsh");
|
||||
float2 pos;
|
||||
|
||||
|
||||
public MoveFlash( World world, int2 cell )
|
||||
{
|
||||
this.pos = Game.CellSize * (cell + new float2(0.5f, 0.5f));
|
||||
anim.PlayThen( "idle",
|
||||
() => world.AddFrameEndTask(
|
||||
w => w.Remove( this ) ) );
|
||||
}
|
||||
|
||||
public MoveFlash( World world, float2 pos )
|
||||
{
|
||||
this.pos = pos;
|
||||
anim.PlayThen( "idle",
|
||||
() => world.AddFrameEndTask(
|
||||
w => w.Remove( this ) ) );
|
||||
}
|
||||
|
||||
public void Tick( World world ) { anim.Tick(); }
|
||||
|
||||
public IEnumerable<Renderable> Render()
|
||||
{
|
||||
yield return new Renderable(anim.Image, pos - .5f * anim.Image.size, "shadow");
|
||||
}
|
||||
}
|
||||
}
|
||||
23
OpenRA.Game/Exts.cs
Normal file → Executable file
23
OpenRA.Game/Exts.cs
Normal file → Executable file
@@ -12,7 +12,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Support;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
@@ -34,17 +33,17 @@ namespace OpenRA
|
||||
return xs.Aggregate(1f, (a, x) => a * x);
|
||||
}
|
||||
|
||||
public static V GetOrAdd<K, V>( this Dictionary<K, V> d, K k )
|
||||
public static V GetOrAdd<K, V>(this Dictionary<K, V> d, K k)
|
||||
where V : new()
|
||||
{
|
||||
return d.GetOrAdd( k, _ => new V() );
|
||||
return d.GetOrAdd(k, _ => new V());
|
||||
}
|
||||
|
||||
public static V GetOrAdd<K, V>( this Dictionary<K, V> d, K k, Func<K, V> createFn )
|
||||
public static V GetOrAdd<K, V>(this Dictionary<K, V> d, K k, Func<K, V> createFn)
|
||||
{
|
||||
V ret;
|
||||
if( !d.TryGetValue( k, out ret ) )
|
||||
d.Add( k, ret = createFn( k ) );
|
||||
if (!d.TryGetValue(k, out ret))
|
||||
d.Add(k, ret = createFn(k));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -54,18 +53,18 @@ namespace OpenRA
|
||||
return xs[r.Next(xs.Length)];
|
||||
}
|
||||
|
||||
public static void DoTimed<T>( this IEnumerable<T> e, Action<T> a, string text, double time )
|
||||
public static void DoTimed<T>(this IEnumerable<T> e, Action<T> a, string text, double time)
|
||||
{
|
||||
var sw = new Stopwatch();
|
||||
|
||||
e.Do( x =>
|
||||
e.Do(x =>
|
||||
{
|
||||
var t = sw.ElapsedTime();
|
||||
a( x );
|
||||
a(x);
|
||||
var dt = sw.ElapsedTime() - t;
|
||||
if( dt > time )
|
||||
Log.Write("perf", text, x, dt * 1000);
|
||||
} );
|
||||
if (dt > time)
|
||||
Log.Write("perf", text, x, dt * 1000, Game.LocalTick);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
451
OpenRA.Game/Game.cs
Normal file → Executable file
451
OpenRA.Game/Game.cs
Normal file → Executable file
@@ -6,335 +6,364 @@
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using System.Net;
|
||||
using System.Windows.Forms;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Network;
|
||||
using OpenRA.Server;
|
||||
using OpenRA.Support;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
using Timer = OpenRA.Support.Timer;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Network;
|
||||
using OpenRA.Server;
|
||||
using OpenRA.Support;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
using XRandom = OpenRA.Thirdparty.Random;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public static class Game
|
||||
{
|
||||
public static readonly int CellSize = 24;
|
||||
public static Utilities Utilities;
|
||||
|
||||
public static int CellSize { get { return modData.Manifest.TileSize; } }
|
||||
|
||||
public static ModData modData;
|
||||
public static World world;
|
||||
private static WorldRenderer worldRenderer;
|
||||
|
||||
public static Viewport viewport;
|
||||
public static Settings Settings;
|
||||
|
||||
internal static OrderManager orderManager;
|
||||
static Server.Server server;
|
||||
|
||||
public static XRandom CosmeticRandom = new XRandom(); // not synced
|
||||
|
||||
public static Renderer Renderer;
|
||||
public static Session LobbyInfo = new Session();
|
||||
public static bool HasInputFocus = false;
|
||||
|
||||
static void LoadMap(string uid)
|
||||
{
|
||||
var map = modData.PrepareMap(uid);
|
||||
|
||||
viewport = new Viewport(new float2(Renderer.Resolution), map.TopLeft, map.BottomRight, Renderer);
|
||||
world = null; // trying to access the old world will NRE, rather than silently doing it wrong.
|
||||
Timer.Time("viewport: {0}");
|
||||
world = new World(modData.Manifest, map);
|
||||
Timer.Time("world: {0}");
|
||||
}
|
||||
|
||||
public static void MoveViewport(int2 loc)
|
||||
public static void MoveViewport(float2 loc)
|
||||
{
|
||||
viewport.Center(loc);
|
||||
}
|
||||
|
||||
internal static string CurrentHost = "";
|
||||
internal static int CurrentPort = 0;
|
||||
|
||||
internal static void JoinServer(string host, int port)
|
||||
public static void JoinServer(string host, int port)
|
||||
{
|
||||
if (orderManager != null) orderManager.Dispose();
|
||||
var replayFilename = ChooseReplayFilename();
|
||||
string path = Path.Combine( Game.SupportDir, "Replays" );
|
||||
if( !Directory.Exists( path ) ) Directory.CreateDirectory( path );
|
||||
var replayFile = File.Create( Path.Combine( path, replayFilename ) );
|
||||
|
||||
CurrentHost = host;
|
||||
CurrentPort = port;
|
||||
|
||||
lastConnectionState = ConnectionState.PreConnecting;
|
||||
ConnectionStateChanged();
|
||||
|
||||
orderManager = new OrderManager(new NetworkConnection(host, port), ChooseReplayFilename());
|
||||
}
|
||||
JoinInner(new OrderManager(host, port,
|
||||
new ReplayRecorderConnection(new NetworkConnection(host, port), replayFile)));
|
||||
}
|
||||
|
||||
static string ChooseReplayFilename()
|
||||
{
|
||||
return DateTime.UtcNow.ToString("OpenRA-yyyy-MM-ddThhmmssZ.rep");
|
||||
return DateTime.UtcNow.ToString("OpenRA-yyyy-MM-ddTHHmmssZ.rep");
|
||||
}
|
||||
|
||||
static void JoinInner(OrderManager om)
|
||||
{
|
||||
if (orderManager != null) orderManager.Dispose();
|
||||
orderManager = om;
|
||||
lastConnectionState = ConnectionState.PreConnecting;
|
||||
ConnectionStateChanged(orderManager);
|
||||
}
|
||||
|
||||
public static void JoinReplay(string replayFile)
|
||||
{
|
||||
JoinInner(new OrderManager("<no server>", -1, new ReplayConnection(replayFile)));
|
||||
}
|
||||
|
||||
static void JoinLocal()
|
||||
{
|
||||
lastConnectionState = ConnectionState.PreConnecting;
|
||||
ConnectionStateChanged();
|
||||
|
||||
if (orderManager != null) orderManager.Dispose();
|
||||
orderManager = new OrderManager(new EchoConnection());
|
||||
JoinInner(new OrderManager("<no server>", -1, new EchoConnection()));
|
||||
}
|
||||
|
||||
static int lastTime = Environment.TickCount;
|
||||
|
||||
static void ResetTimer()
|
||||
{
|
||||
lastTime = Environment.TickCount;
|
||||
}
|
||||
|
||||
internal static int RenderFrame = 0;
|
||||
internal static int LocalTick = 0;
|
||||
public static int RenderFrame = 0;
|
||||
public static int NetFrameNumber { get { return orderManager.NetFrameNumber; } }
|
||||
public static int LocalTick { get { return orderManager.LocalFrameNumber; } }
|
||||
const int NetTickScale = 3; // 120ms net tick for 40ms local tick
|
||||
|
||||
public static event Action ConnectionStateChanged = () => { };
|
||||
static ConnectionState lastConnectionState = ConnectionState.PreConnecting;
|
||||
|
||||
public static event Action<OrderManager> ConnectionStateChanged = _ => { };
|
||||
static ConnectionState lastConnectionState = ConnectionState.PreConnecting;
|
||||
public static int LocalClientId { get { return orderManager.Connection.LocalClientId; } }
|
||||
|
||||
static void Tick()
|
||||
|
||||
|
||||
// Hacky workaround for orderManager visibility
|
||||
public static Widget OpenWindow(World world, string widget)
|
||||
{
|
||||
if (orderManager.Connection.ConnectionState != lastConnectionState)
|
||||
{
|
||||
lastConnectionState = orderManager.Connection.ConnectionState;
|
||||
ConnectionStateChanged();
|
||||
}
|
||||
return Widget.OpenWindow(widget, new Dictionary<string,object>{{ "world", world }, { "orderManager", orderManager }, { "worldRenderer", worldRenderer }});
|
||||
}
|
||||
|
||||
int t = Environment.TickCount;
|
||||
int dt = t - lastTime;
|
||||
if (dt >= Settings.Game.Timestep)
|
||||
static ActionQueue afterTickActions = new ActionQueue();
|
||||
public static void RunAfterTick(Action a) { afterTickActions.Add(a); }
|
||||
|
||||
static void Tick( OrderManager orderManager, Viewport viewPort )
|
||||
{
|
||||
if (orderManager.Connection.ConnectionState != lastConnectionState)
|
||||
{
|
||||
using (new PerfSample("tick_time"))
|
||||
{
|
||||
lastTime += Settings.Game.Timestep;
|
||||
Widget.DoTick(world);
|
||||
|
||||
orderManager.TickImmediate(world);
|
||||
|
||||
var isNetTick = LocalTick % NetTickScale == 0;
|
||||
|
||||
if (!isNetTick || orderManager.IsReadyForNextFrame)
|
||||
{
|
||||
++LocalTick;
|
||||
|
||||
if (isNetTick) orderManager.Tick(world);
|
||||
|
||||
world.OrderGenerator.Tick(world);
|
||||
world.Selection.Tick(world);
|
||||
world.Tick();
|
||||
|
||||
PerfHistory.Tick();
|
||||
}
|
||||
else
|
||||
if (orderManager.FrameNumber == 0)
|
||||
lastTime = Environment.TickCount;
|
||||
}
|
||||
lastConnectionState = orderManager.Connection.ConnectionState;
|
||||
ConnectionStateChanged( orderManager );
|
||||
}
|
||||
|
||||
Tick( orderManager );
|
||||
if( worldRenderer != null && orderManager.world != worldRenderer.world )
|
||||
Tick( worldRenderer.world.orderManager );
|
||||
|
||||
using (new PerfSample("render"))
|
||||
{
|
||||
++RenderFrame;
|
||||
viewport.DrawRegions(world);
|
||||
viewport.DrawRegions(worldRenderer, new DefaultInputHandler( orderManager.world ));
|
||||
Sound.SetListenerPosition(viewport.Location + .5f * new float2(viewport.Width, viewport.Height));
|
||||
}
|
||||
|
||||
PerfHistory.items["render"].Tick();
|
||||
PerfHistory.items["batches"].Tick();
|
||||
PerfHistory.items["text"].Tick();
|
||||
PerfHistory.items["cursor"].Tick();
|
||||
|
||||
MasterServerQuery.Tick();
|
||||
|
||||
afterTickActions.PerformActions();
|
||||
}
|
||||
|
||||
internal static event Action LobbyInfoChanged = () => { };
|
||||
|
||||
internal static void SyncLobbyInfo(string data)
|
||||
private static void Tick( OrderManager orderManager )
|
||||
{
|
||||
LobbyInfo = Session.Deserialize(data);
|
||||
int t = Environment.TickCount;
|
||||
int dt = t - orderManager.LastTickTime;
|
||||
if (dt >= Settings.Game.Timestep)
|
||||
using( new PerfSample( "tick_time" ) )
|
||||
{
|
||||
orderManager.LastTickTime += Settings.Game.Timestep;
|
||||
Widget.DoTick();
|
||||
var world = orderManager.world;
|
||||
if( orderManager.GameStarted && world.LocalPlayer != null )
|
||||
++Viewport.TicksSinceLastMove;
|
||||
Sound.Tick();
|
||||
Sync.CheckSyncUnchanged( world, () => { orderManager.TickImmediate(); } );
|
||||
|
||||
if( !world.GameHasStarted )
|
||||
world.SharedRandom = new XRandom( LobbyInfo.GlobalSettings.RandomSeed );
|
||||
if (world != null)
|
||||
{
|
||||
var isNetTick = LocalTick % NetTickScale == 0;
|
||||
|
||||
if (orderManager.Connection.ConnectionState == ConnectionState.Connected)
|
||||
world.SetLocalPlayer(orderManager.Connection.LocalClientId);
|
||||
if (!isNetTick || orderManager.IsReadyForNextFrame)
|
||||
{
|
||||
++orderManager.LocalFrameNumber;
|
||||
|
||||
if (orderManager.FramesAhead != LobbyInfo.GlobalSettings.OrderLatency
|
||||
&& !orderManager.GameStarted)
|
||||
{
|
||||
orderManager.FramesAhead = LobbyInfo.GlobalSettings.OrderLatency;
|
||||
Debug("Order lag is now {0} frames.".F(LobbyInfo.GlobalSettings.OrderLatency));
|
||||
}
|
||||
Log.Write("debug", "--Tick: {0} ({1})", LocalTick, isNetTick ? "net" : "local");
|
||||
|
||||
if (isNetTick) orderManager.Tick();
|
||||
|
||||
|
||||
Sync.CheckSyncUnchanged(world, () =>
|
||||
{
|
||||
world.OrderGenerator.Tick(world);
|
||||
world.Selection.Tick(world);
|
||||
});
|
||||
|
||||
world.Tick();
|
||||
|
||||
PerfHistory.Tick();
|
||||
}
|
||||
else
|
||||
if (orderManager.NetFrameNumber == 0)
|
||||
orderManager.LastTickTime = Environment.TickCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static event Action LobbyInfoChanged = () => { };
|
||||
|
||||
internal static void SyncLobbyInfo()
|
||||
{
|
||||
LobbyInfoChanged();
|
||||
}
|
||||
|
||||
public static void IssueOrder(Order o) { orderManager.IssueOrder(o); } /* avoid exposing the OM to mod code */
|
||||
|
||||
|
||||
public static event Action AfterGameStart = () => {};
|
||||
public static event Action<World> AfterGameStart = _ => {};
|
||||
public static event Action BeforeGameStart = () => {};
|
||||
internal static void StartGame(string map)
|
||||
internal static void StartGame(string mapUID)
|
||||
{
|
||||
BeforeGameStart();
|
||||
LoadMap(map);
|
||||
|
||||
var map = modData.PrepareMap(mapUID);
|
||||
viewport = new Viewport(new int2(Renderer.Resolution), map.Bounds, Renderer);
|
||||
orderManager.world = new World(modData.Manifest, map, orderManager);
|
||||
worldRenderer = new WorldRenderer(orderManager.world);
|
||||
|
||||
if (orderManager.GameStarted) return;
|
||||
Widget.SelectedWidget = null;
|
||||
Widget.SelectedWidget = null;
|
||||
|
||||
orderManager.StartGame();
|
||||
viewport.RefreshPalette();
|
||||
AfterGameStart();
|
||||
}
|
||||
|
||||
public static void DispatchMouseInput(MouseInputEvent ev, MouseEventArgs e, Modifiers modifierKeys)
|
||||
{
|
||||
if (world == null)
|
||||
return;
|
||||
|
||||
int sync = world.SyncHash();
|
||||
var initialWorld = world;
|
||||
|
||||
var mi = new MouseInput
|
||||
{
|
||||
Button = (MouseButton)(int)e.Button,
|
||||
Event = ev,
|
||||
Location = new int2(e.Location),
|
||||
Modifiers = modifierKeys,
|
||||
};
|
||||
Widget.HandleInput(world, mi);
|
||||
|
||||
if (sync != world.SyncHash() && world == initialWorld)
|
||||
throw new InvalidOperationException("Desync in DispatchMouseInput");
|
||||
orderManager.LocalFrameNumber = 0;
|
||||
orderManager.StartGame();
|
||||
worldRenderer.RefreshPalette();
|
||||
AfterGameStart( orderManager.world );
|
||||
}
|
||||
|
||||
public static bool IsHost
|
||||
{
|
||||
get { return orderManager.Connection.LocalClientId == 0; }
|
||||
}
|
||||
|
||||
internal static Session.Client LocalClient
|
||||
|
||||
public static Dictionary<String, Mod> CurrentMods
|
||||
{
|
||||
get { return LobbyInfo.Clients.FirstOrDefault(c => c.Index == orderManager.Connection.LocalClientId); }
|
||||
}
|
||||
|
||||
public static void HandleKeyEvent(KeyInput e)
|
||||
{
|
||||
if (world == null)
|
||||
return;
|
||||
|
||||
int sync = world.SyncHash();
|
||||
|
||||
if (Widget.HandleKeyPress(e))
|
||||
return;
|
||||
|
||||
if (sync != Game.world.SyncHash())
|
||||
throw new InvalidOperationException("Desync in OnKeyPress");
|
||||
get { return Mod.AllMods.Where( k => orderManager.LobbyInfo.GlobalSettings.Mods.Contains( k.Key )).ToDictionary( k => k.Key, k => k.Value ); }
|
||||
}
|
||||
|
||||
static Modifiers modifiers;
|
||||
public static Modifiers GetModifierKeys() { return modifiers; }
|
||||
public static void HandleModifierKeys(Modifiers mods) { modifiers = mods; }
|
||||
internal static void HandleModifierKeys(Modifiers mods) { modifiers = mods; }
|
||||
|
||||
internal static void Initialize(Arguments args)
|
||||
{
|
||||
AppDomain.CurrentDomain.AssemblyResolve += FileSystem.ResolveAssembly;
|
||||
|
||||
var defaultSupport = Environment.GetFolderPath(Environment.SpecialFolder.Personal)
|
||||
+ Path.DirectorySeparatorChar + "OpenRA";
|
||||
|
||||
SupportDir = args.GetValue("SupportDir", defaultSupport);
|
||||
Settings = new Settings(SupportDir + "settings.yaml", args);
|
||||
|
||||
Log.LogPath = SupportDir + "Logs" + Path.DirectorySeparatorChar;
|
||||
Log.AddChannel("perf", "perf.log");
|
||||
Log.AddChannel("debug", "debug.log");
|
||||
Log.AddChannel("sync", "syncreport.log");
|
||||
AppDomain.CurrentDomain.AssemblyResolve += FileSystem.ResolveAssembly;
|
||||
|
||||
var defaultSupport = Environment.GetFolderPath(Environment.SpecialFolder.Personal)
|
||||
+ Path.DirectorySeparatorChar + "OpenRA";
|
||||
|
||||
SupportDir = args.GetValue("SupportDir", defaultSupport);
|
||||
FileSystem.SpecialPackageRoot = args.GetValue("SpecialPackageRoot", "");
|
||||
|
||||
Utilities = new Utilities(args.GetValue("UtilityPath", "OpenRA.Utility.exe"));
|
||||
|
||||
Settings = new Settings(SupportDir + "settings.yaml", args);
|
||||
Settings.Save();
|
||||
|
||||
Log.LogPath = SupportDir + "Logs" + Path.DirectorySeparatorChar;
|
||||
Log.AddChannel("perf", "perf.log");
|
||||
Log.AddChannel("debug", "debug.log");
|
||||
Log.AddChannel("sync", "syncreport.log");
|
||||
|
||||
FileSystem.Mount("."); // Needed to access shaders
|
||||
Renderer.Initialize( Game.Settings.Graphics.Mode );
|
||||
Renderer.SheetSize = Settings.Game.SheetSize;
|
||||
Renderer = new Renderer();
|
||||
|
||||
LobbyInfo.GlobalSettings.Mods = Settings.Game.Mods;
|
||||
modData = new ModData( LobbyInfo.GlobalSettings.Mods );
|
||||
Console.WriteLine("Available mods:");
|
||||
foreach(var mod in Mod.AllMods)
|
||||
Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Title, mod.Value.Version);
|
||||
|
||||
Sound.Create();
|
||||
InitializeWithMods(Settings.Game.Mods);
|
||||
}
|
||||
|
||||
public static void InitializeWithMods(string[] mods)
|
||||
{
|
||||
// Clear static state if we have switched mods
|
||||
LobbyInfoChanged = () => {};
|
||||
AddChatLine = (a,b,c) => {};
|
||||
worldRenderer = null;
|
||||
if (server != null)
|
||||
server.Shutdown();
|
||||
if (orderManager != null)
|
||||
orderManager.Dispose();
|
||||
|
||||
// Discard any invalid mods
|
||||
var mm = mods.Where( m => Mod.AllMods.ContainsKey( m ) ).ToArray();
|
||||
Console.WriteLine("Loading mods: {0}",string.Join(",",mm));
|
||||
Settings.Game.Mods = mm;
|
||||
Settings.Save();
|
||||
|
||||
Sound.Initialize();
|
||||
|
||||
modData = new ModData( mm );
|
||||
modData.LoadInitialAssets();
|
||||
|
||||
|
||||
PerfHistory.items["render"].hasNormalTick = false;
|
||||
PerfHistory.items["batches"].hasNormalTick = false;
|
||||
PerfHistory.items["text"].hasNormalTick = false;
|
||||
PerfHistory.items["cursor"].hasNormalTick = false;
|
||||
|
||||
|
||||
JoinLocal();
|
||||
|
||||
|
||||
JoinLocal();
|
||||
viewport = new Viewport(new int2(Renderer.Resolution), Rectangle.Empty, Renderer);
|
||||
|
||||
Widget.RootWidget.RemoveChildren();
|
||||
modData.WidgetLoader.LoadWidget( new Dictionary<string,object>(), Widget.RootWidget, "INIT_SETUP" );
|
||||
}
|
||||
|
||||
public static void LoadShellMap()
|
||||
{
|
||||
StartGame(ChooseShellmap());
|
||||
Game.orderManager.LastTickTime = Environment.TickCount;
|
||||
}
|
||||
|
||||
static string ChooseShellmap()
|
||||
{
|
||||
var shellmaps = modData.AvailableMaps
|
||||
.Where(m => m.Value.UseAsShellmap);
|
||||
|
||||
if (shellmaps.Count() == 0)
|
||||
throw new InvalidDataException("No valid shellmaps available");
|
||||
|
||||
return shellmaps.Random(CosmeticRandom).Key;
|
||||
}
|
||||
|
||||
static bool quit;
|
||||
public static event Action OnQuit = () => {};
|
||||
internal static void Run()
|
||||
{
|
||||
while (!quit)
|
||||
{
|
||||
{
|
||||
Tick( orderManager, viewport );
|
||||
Application.DoEvents();
|
||||
}
|
||||
OnQuit();
|
||||
}
|
||||
|
||||
|
||||
public static void Exit() { quit = true; }
|
||||
public static void Exit() { quit = true; }
|
||||
|
||||
public static Action<Color,string,string> AddChatLine = (c,n,s) => {};
|
||||
|
||||
|
||||
public static void Debug(string s)
|
||||
{
|
||||
public static void Debug(string s, params object[] args)
|
||||
{
|
||||
AddChatLine(Color.White, "Debug", String.Format(s,args));
|
||||
}
|
||||
|
||||
public static void Disconnect()
|
||||
{
|
||||
if (IsHost && server != null)
|
||||
server.Shutdown();
|
||||
|
||||
orderManager.Dispose();
|
||||
orderManager.Dispose();
|
||||
var shellmap = modData.Manifest.ShellmapUid;
|
||||
LobbyInfo = new Session();
|
||||
var shellmap = ChooseShellmap();
|
||||
JoinLocal();
|
||||
StartGame(shellmap);
|
||||
|
||||
|
||||
Widget.RootWidget.CloseWindow();
|
||||
Widget.RootWidget.OpenWindow("MAINMENU_BG");
|
||||
}
|
||||
|
||||
static string baseSupportDir = null;
|
||||
public static string SupportDir
|
||||
{
|
||||
set
|
||||
{
|
||||
var dir = value;
|
||||
|
||||
// Expand paths relative to the personal directory
|
||||
if (dir.ElementAt(0) == '~')
|
||||
dir = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + dir.Substring(1);
|
||||
|
||||
if (!Directory.Exists(dir))
|
||||
Directory.CreateDirectory(dir);
|
||||
|
||||
Widget.CloseWindow();
|
||||
Widget.OpenWindow("MAINMENU_BG");
|
||||
}
|
||||
|
||||
static string baseSupportDir = null;
|
||||
public static string SupportDir
|
||||
{
|
||||
set
|
||||
{
|
||||
var dir = value;
|
||||
|
||||
// Expand paths relative to the personal directory
|
||||
if (dir.ElementAt(0) == '~')
|
||||
dir = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + dir.Substring(1);
|
||||
|
||||
if (!Directory.Exists(dir))
|
||||
Directory.CreateDirectory(dir);
|
||||
|
||||
baseSupportDir = dir + Path.DirectorySeparatorChar;
|
||||
}
|
||||
}
|
||||
get { return baseSupportDir; }
|
||||
}
|
||||
|
||||
public static T CreateObject<T>( string name )
|
||||
{
|
||||
return modData.ObjectCreator.CreateObject<T>( name );
|
||||
}
|
||||
|
||||
public static void CreateAndJoinServer(Settings settings, string map)
|
||||
{
|
||||
server = new Server.Server(modData, settings, map);
|
||||
JoinServer(IPAddress.Loopback.ToString(), settings.Server.ListenPort);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,21 +66,21 @@ namespace OpenRA
|
||||
var ret = new List<ITraitInfo>();
|
||||
var t = Traits.WithInterface<ITraitInfo>().ToList();
|
||||
int index = 0;
|
||||
while( t.Count != 0 )
|
||||
while (t.Count != 0)
|
||||
{
|
||||
if( index >= t.Count )
|
||||
throw new InvalidOperationException( "Trait prerequisites not satisfied (or prerequisite loop) Actor={0} Unresolved={1}".F(
|
||||
Name, string.Join( ",", t.Select( x => x.GetType().Name ).ToArray())));
|
||||
|
||||
var prereqs = PrerequisitesOf( t[ index ] );
|
||||
if( prereqs.Count == 0 || prereqs.All( n => ret.Any( x => x.GetType() == n || x.GetType().IsSubclassOf( n ) ) ) )
|
||||
var prereqs = PrerequisitesOf(t[index]);
|
||||
var unsatisfied = prereqs.Where(n => !ret.Any(x => x.GetType() == n || x.GetType().IsSubclassOf(n)));
|
||||
if (!unsatisfied.Any())
|
||||
{
|
||||
ret.Add( t[ index ] );
|
||||
t.RemoveAt( index );
|
||||
ret.Add(t[index]);
|
||||
t.RemoveAt(index);
|
||||
index = 0;
|
||||
}
|
||||
else
|
||||
++index;
|
||||
else if (++index >= t.Count)
|
||||
throw new InvalidOperationException("Trait prerequisites not satisfied (or prerequisite loop) Actor={0} Unresolved={1} Missing={2}".F(
|
||||
Name,
|
||||
string.Join(",", t.Select(x => x.GetType().Name).ToArray()),
|
||||
string.Join(",", unsatisfied.Select(x => x.Name).ToArray())));
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -14,15 +14,21 @@ namespace OpenRA.GameRules
|
||||
{
|
||||
public class MusicInfo
|
||||
{
|
||||
[FieldLoader.Load] public readonly string Filename = null;
|
||||
[FieldLoader.Load] public readonly string Title = null;
|
||||
[FieldLoader.Load] public readonly int Length = 0; // seconds
|
||||
public readonly string Filename = null;
|
||||
public readonly string Title = null;
|
||||
public readonly int Length = 0; // seconds
|
||||
public readonly bool Exists = false;
|
||||
|
||||
public MusicInfo( string key, MiniYaml value )
|
||||
{
|
||||
FieldLoader.Load(this, value);
|
||||
if (Filename == null)
|
||||
Filename = key+".aud";
|
||||
Filename = key+".aud";
|
||||
Title = value.Value;
|
||||
|
||||
if (!FileSystem.Exists(Filename))
|
||||
return;
|
||||
|
||||
Exists = true;
|
||||
Length = (int)AudLoader.SoundLength(FileSystem.Open(Filename));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,6 @@ namespace OpenRA
|
||||
{
|
||||
public static class Rules
|
||||
{
|
||||
public static TechTree TechTree;
|
||||
|
||||
public static Dictionary<string, ActorInfo> Info;
|
||||
public static Dictionary<string, WeaponInfo> Weapons;
|
||||
public static Dictionary<string, VoiceInfo> Voices;
|
||||
@@ -29,9 +27,10 @@ namespace OpenRA
|
||||
|
||||
public static void LoadRules(Manifest m, Map map)
|
||||
{
|
||||
// Added support to extend the list of rules (add it to m.LocalRules)
|
||||
Info = LoadYamlRules(m.Rules, map.Rules, (k, y) => new ActorInfo(k.Key.ToLowerInvariant(), k.Value, y));
|
||||
Weapons = LoadYamlRules(m.Weapons, new List<MiniYamlNode>(), (k, _) => new WeaponInfo(k.Key.ToLowerInvariant(), k.Value));
|
||||
Voices = LoadYamlRules(m.Voices, new List<MiniYamlNode>(), (k, _) => new VoiceInfo(k.Value));
|
||||
Weapons = LoadYamlRules(m.Weapons, map.Weapons, (k, _) => new WeaponInfo(k.Key.ToLowerInvariant(), k.Value));
|
||||
Voices = LoadYamlRules(m.Voices, map.Voices, (k, _) => new VoiceInfo(k.Value));
|
||||
Music = LoadYamlRules(m.Music, new List<MiniYamlNode>(), (k, _) => new MusicInfo(k.Key, k.Value));
|
||||
Movies = LoadYamlRules(m.Movies, new List<MiniYamlNode>(), (k, v) => k.Value.Value);
|
||||
|
||||
@@ -41,8 +40,6 @@ namespace OpenRA
|
||||
var t = new TileSet(file);
|
||||
TileSets.Add(t.Id,t);
|
||||
}
|
||||
|
||||
TechTree = new TechTree();
|
||||
}
|
||||
|
||||
static Dictionary<string, T> LoadYamlRules<T>(string[] files, List<MiniYamlNode> dict, Func<MiniYamlNode, Dictionary<string, MiniYaml>, T> f)
|
||||
|
||||
@@ -8,13 +8,14 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.FileFormats.Graphics;
|
||||
using System;
|
||||
using OpenRA.Server;
|
||||
|
||||
namespace OpenRA.GameRules
|
||||
{
|
||||
@@ -24,22 +25,24 @@ namespace OpenRA.GameRules
|
||||
public int ListenPort = 1234;
|
||||
public int ExternalPort = 1234;
|
||||
public bool AdvertiseOnline = true;
|
||||
public string MasterServer = "http://open-ra.org/master/";
|
||||
public string MasterServer = "http://master.open-ra.org/";
|
||||
public bool AllowCheats = false;
|
||||
}
|
||||
|
||||
public class DebugSettings
|
||||
{
|
||||
public bool BotDebug = false;
|
||||
public bool PerfGraph = false;
|
||||
public bool RecordSyncReports = true;
|
||||
public bool ShowCollisions = false;
|
||||
public float LongTickThreshold = 0.001f;
|
||||
public bool SanityCheckUnsyncedCode = false;
|
||||
}
|
||||
|
||||
|
||||
public class GraphicSettings
|
||||
{
|
||||
public string Renderer = "Gl";
|
||||
public WindowMode Mode = WindowMode.PseudoFullscreen;
|
||||
public int2 FullscreenSize = new int2(Screen.PrimaryScreen.Bounds.Width,Screen.PrimaryScreen.Bounds.Height);
|
||||
public int2 WindowedSize = new int2(1024,768);
|
||||
public int2 FullscreenSize = new int2(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
|
||||
public int2 WindowedSize = new int2(1024, 768);
|
||||
public readonly int2 MinResolution = new int2(800, 600);
|
||||
}
|
||||
|
||||
@@ -48,13 +51,16 @@ namespace OpenRA.GameRules
|
||||
public float SoundVolume = 0.5f;
|
||||
public float MusicVolume = 0.5f;
|
||||
public float VideoVolume = 0.5f;
|
||||
public bool Shuffle = false;
|
||||
public bool Repeat = false;
|
||||
}
|
||||
|
||||
public class PlayerSettings
|
||||
{
|
||||
public string Name = "Newbie";
|
||||
public Color Color1 = Color.FromArgb(255,160,238);
|
||||
public Color Color2 = Color.FromArgb(68,0,56);
|
||||
[Obsolete] public Color Color1 = Color.FromArgb(255,160,238);
|
||||
[Obsolete] public Color Color2 = Color.FromArgb(68,0,56);
|
||||
public ColorRamp ColorRamp = new ColorRamp(75, 255, 180, 25);
|
||||
public string LastServer = "localhost:1234";
|
||||
}
|
||||
|
||||
@@ -63,9 +69,13 @@ namespace OpenRA.GameRules
|
||||
public string[] Mods = { "ra" };
|
||||
public bool MatchTimer = true;
|
||||
|
||||
// Chat settings
|
||||
public bool TeamChatToggle = false;
|
||||
|
||||
// Behaviour settings
|
||||
public bool ViewportEdgeScroll = true;
|
||||
public bool InverseDragScroll = false;
|
||||
public float ViewportEdgeScrollStep = 10f;
|
||||
|
||||
// Internal game settings
|
||||
public int Timestep = 40;
|
||||
@@ -83,7 +93,7 @@ namespace OpenRA.GameRules
|
||||
public ServerSettings Server = new ServerSettings();
|
||||
public DebugSettings Debug = new DebugSettings();
|
||||
|
||||
Dictionary<string, object> Sections;
|
||||
public Dictionary<string, object> Sections;
|
||||
public Settings(string file, Arguments args)
|
||||
{
|
||||
SettingsFile = file;
|
||||
@@ -97,18 +107,19 @@ namespace OpenRA.GameRules
|
||||
{"Debug", Debug}
|
||||
};
|
||||
|
||||
|
||||
// Override fieldloader to ignore invalid entries
|
||||
var err1 = FieldLoader.UnknownFieldAction;
|
||||
var err2 = FieldLoader.InvalidValueAction;
|
||||
|
||||
FieldLoader.UnknownFieldAction = (s,f) =>
|
||||
{
|
||||
System.Console.WriteLine( "Ignoring unknown field `{0}` on `{1}`".F( s, f.Name ) );
|
||||
Console.WriteLine( "Ignoring unknown field `{0}` on `{1}`".F( s, f.Name ) );
|
||||
};
|
||||
|
||||
if (File.Exists(SettingsFile))
|
||||
{
|
||||
System.Console.WriteLine("Loading settings file {0}",SettingsFile);
|
||||
//Console.WriteLine("Loading settings file {0}",SettingsFile);
|
||||
var yaml = MiniYaml.DictFromFile(SettingsFile);
|
||||
|
||||
foreach (var kv in Sections)
|
||||
@@ -120,7 +131,7 @@ namespace OpenRA.GameRules
|
||||
foreach (var kv in Sections)
|
||||
foreach (var f in kv.Value.GetType().GetFields())
|
||||
if (args.Contains(kv.Key+"."+f.Name))
|
||||
OpenRA.FileFormats.FieldLoader.LoadField( kv.Value, f.Name, args.GetValue(kv.Key+"."+f.Name, "") );
|
||||
FieldLoader.LoadField( kv.Value, f.Name, args.GetValue(kv.Key+"."+f.Name, "") );
|
||||
|
||||
FieldLoader.UnknownFieldAction = err1;
|
||||
FieldLoader.InvalidValueAction = err2;
|
||||
@@ -130,16 +141,11 @@ namespace OpenRA.GameRules
|
||||
{
|
||||
var root = new List<MiniYamlNode>();
|
||||
foreach( var kv in Sections )
|
||||
root.Add( new MiniYamlNode( kv.Key, SectionYaml( kv.Value ) ) );
|
||||
root.Add( new MiniYamlNode( kv.Key, FieldSaver.SaveDifferences(kv.Value, Activator.CreateInstance(kv.Value.GetType())) ) );
|
||||
|
||||
root.WriteToFile(SettingsFile);
|
||||
}
|
||||
|
||||
MiniYaml SectionYaml(object section)
|
||||
{
|
||||
return FieldSaver.SaveDifferences(section, Activator.CreateInstance(section.GetType()));
|
||||
}
|
||||
|
||||
void LoadSectionYaml(MiniYaml yaml, object section)
|
||||
{
|
||||
object defaults = Activator.CreateInstance(section.GetType());
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.GameRules
|
||||
{
|
||||
public class TechTree
|
||||
{
|
||||
readonly Cache<string, List<ActorInfo>> producesIndex = new Cache<string, List<ActorInfo>>(x => new List<ActorInfo>());
|
||||
|
||||
public TechTree()
|
||||
{
|
||||
foreach( var info in Rules.Info.Values )
|
||||
{
|
||||
var pi = info.Traits.GetOrDefault<ProductionInfo>();
|
||||
if (pi != null)
|
||||
foreach( var p in pi.Produces )
|
||||
producesIndex[ p ].Add( info );
|
||||
}
|
||||
}
|
||||
|
||||
public Cache<string, List<Actor>> GatherBuildings( Player player )
|
||||
{
|
||||
var ret = new Cache<string, List<Actor>>( x => new List<Actor>() );
|
||||
if (player == null)
|
||||
return ret;
|
||||
|
||||
foreach( var b in player.World.Queries.OwnedBy[player].Where( x=>x.Info.Traits.Contains<BuildingInfo>() ) )
|
||||
{
|
||||
ret[ b.Info.Name ].Add( b );
|
||||
var tt = b.Info.Traits.GetOrDefault<TooltipInfo>();
|
||||
if( tt != null )
|
||||
foreach( var alt in tt.AlternateName )
|
||||
ret[ alt ].Add( b );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool CanBuild( ActorInfo info, Player player, Cache<string, List<Actor>> playerBuildings )
|
||||
{
|
||||
if (player == null)
|
||||
return false;
|
||||
|
||||
var bi = info.Traits.GetOrDefault<BuildableInfo>();
|
||||
if( bi == null ) return false;
|
||||
|
||||
if( !bi.Owner.Contains( player.Country.Race ) )
|
||||
return false;
|
||||
|
||||
foreach( var p in bi.Prerequisites )
|
||||
if( playerBuildings[ p ].Count == 0 )
|
||||
return false;
|
||||
|
||||
if( producesIndex[ bi.Queue ].All( x => playerBuildings[ x.Name ].Count == 0 ) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public IEnumerable<string> BuildableItems( Player player, params string[] categories )
|
||||
{
|
||||
if (player == null)
|
||||
yield break;
|
||||
|
||||
var playerBuildings = GatherBuildings( player );
|
||||
foreach (var unit in AllBuildables(categories))
|
||||
if( CanBuild( unit, player, playerBuildings ) )
|
||||
yield return unit.Name;
|
||||
}
|
||||
|
||||
public IEnumerable<ActorInfo> AllBuildables(params string[] categories)
|
||||
{
|
||||
return Rules.Info.Values
|
||||
.Where( x => x.Name[ 0 ] != '^' )
|
||||
.Where( x => x.Traits.Contains<BuildableInfo>() )
|
||||
.Where( x => categories.Contains(x.Traits.Get<BuildableInfo>().Queue) );
|
||||
}
|
||||
|
||||
public IEnumerable<ActorInfo> UnitBuiltAt( ActorInfo info )
|
||||
{
|
||||
var bi = info.Traits.Get<BuildableInfo>();
|
||||
var builtAt = bi.BuiltAt;
|
||||
if( builtAt.Length != 0 )
|
||||
return builtAt.Select( x => Rules.Info[ x.ToLowerInvariant() ] );
|
||||
else
|
||||
return producesIndex[ bi.Queue ];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ namespace OpenRA.GameRules
|
||||
: new Dictionary<string, string[]>();
|
||||
}
|
||||
|
||||
public readonly Lazy<Dictionary<string, VoicePool>> Pools;
|
||||
public readonly OpenRA.FileFormats.Lazy<Dictionary<string, VoicePool>> Pools;
|
||||
|
||||
public VoiceInfo( MiniYaml y )
|
||||
{
|
||||
@@ -41,6 +41,9 @@ namespace OpenRA.GameRules
|
||||
|
||||
if (!Voices.ContainsKey("Attack"))
|
||||
Voices.Add("Attack", Voices["Move"]);
|
||||
|
||||
if (!Voices.ContainsKey("AttackMove"))
|
||||
Voices.Add("AttackMove", Voices["Move"]);
|
||||
|
||||
Pools = Lazy.New(() => Voices.ToDictionary( a => a.Key, a => new VoicePool(a.Value) ));
|
||||
}
|
||||
|
||||
@@ -12,47 +12,55 @@ using System.Collections.Generic;
|
||||
using OpenRA.Effects;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Traits;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.GameRules
|
||||
{
|
||||
public class WarheadInfo
|
||||
{
|
||||
public readonly int Spread = 1; // distance (in pixels) from the explosion center at which damage is 1/2.
|
||||
public readonly float[] Verses = { 1, 1, 1, 1, 1 }; // damage vs each armortype
|
||||
public readonly bool Ore = false; // can this damage ore?
|
||||
public readonly string Explosion = null; // explosion effect to use
|
||||
public readonly string WaterExplosion = null; // explosion effect on hitting water (usually a splash)
|
||||
public readonly string SmudgeType = null; // type of smudge to apply
|
||||
public readonly int[] Size = { 0, 0 }; // size of the explosion. provide 2 values for a ring effect (outer/inner)
|
||||
public readonly int InfDeath = 0; // infantry death animation to use
|
||||
public readonly string ImpactSound = null; // sound to play on impact
|
||||
public readonly string WaterImpactSound = null; // sound to play on impact with water
|
||||
public readonly int Damage = 0; // how much (raw) damage to deal
|
||||
public readonly int Delay = 0; // delay in ticks before dealing the damage. 0=instant (old model)
|
||||
public readonly DamageModel DamageModel = DamageModel.Normal; // which damage model to use
|
||||
[FieldLoader.Load] public readonly int Spread = 1; // distance (in pixels) from the explosion center at which damage is 1/2.
|
||||
[FieldLoader.LoadUsing( "LoadVersus" )]
|
||||
public readonly Dictionary<string, float> Versus; // damage vs each armortype
|
||||
[FieldLoader.Load] public readonly bool Ore = false; // can this damage ore?
|
||||
[FieldLoader.Load] public readonly string Explosion = null; // explosion effect to use
|
||||
[FieldLoader.Load] public readonly string WaterExplosion = null; // explosion effect on hitting water (usually a splash)
|
||||
[FieldLoader.Load] public readonly string SmudgeType = null; // type of smudge to apply
|
||||
[FieldLoader.Load] public readonly int[] Size = { 0, 0 }; // size of the explosion. provide 2 values for a ring effect (outer/inner)
|
||||
[FieldLoader.Load] public readonly int InfDeath = 0; // infantry death animation to use
|
||||
[FieldLoader.Load] public readonly string ImpactSound = null; // sound to play on impact
|
||||
[FieldLoader.Load] public readonly string WaterImpactSound = null; // sound to play on impact with water
|
||||
[FieldLoader.Load] public readonly int Damage = 0; // how much (raw) damage to deal
|
||||
[FieldLoader.Load] public readonly int Delay = 0; // delay in ticks before dealing the damage. 0=instant (old model)
|
||||
[FieldLoader.Load] public readonly DamageModel DamageModel = DamageModel.Normal; // which damage model to use
|
||||
[FieldLoader.Load] public readonly bool PreventProne = false; // whether we should prevent prone response in infantry.
|
||||
|
||||
public float EffectivenessAgainst(Actor self)
|
||||
{
|
||||
var health = self.Info.Traits.GetOrDefault<HealthInfo>();
|
||||
if (health == null) return 0f;
|
||||
var armor = self.Info.Traits.GetOrDefault<ArmorInfo>();
|
||||
if (armor == null || armor.Type == null) return 1;
|
||||
|
||||
return Verses[(int)(health.Armor)];
|
||||
float versus;
|
||||
return Versus.TryGetValue(armor.Type, out versus) ? versus : 1;
|
||||
}
|
||||
|
||||
public WarheadInfo( MiniYaml yaml )
|
||||
{
|
||||
FieldLoader.Load( this, yaml );
|
||||
}
|
||||
|
||||
static object LoadVersus( MiniYaml y )
|
||||
{
|
||||
return y.NodesDict.ContainsKey( "Versus" )
|
||||
? y.NodesDict[ "Versus" ].NodesDict.ToDictionary(
|
||||
a => a.Key,
|
||||
a => (float)FieldLoader.GetValue( "(value)", typeof( float ), a.Value.Value ) )
|
||||
: new Dictionary<string, float>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public enum ArmorType
|
||||
{
|
||||
none = 0,
|
||||
wood = 1,
|
||||
light = 2,
|
||||
heavy = 3,
|
||||
concrete = 4,
|
||||
}
|
||||
|
||||
public enum DamageModel
|
||||
{
|
||||
@@ -85,6 +93,7 @@ namespace OpenRA.GameRules
|
||||
[FieldLoader.Load] public readonly bool Underwater = false;
|
||||
[FieldLoader.Load] public readonly string[] ValidTargets = { "Ground" };
|
||||
[FieldLoader.Load] public readonly int BurstDelay = 5;
|
||||
[FieldLoader.Load] public readonly float MinRange = 0;
|
||||
|
||||
[FieldLoader.LoadUsing( "LoadProjectile" )] public IProjectileInfo Projectile;
|
||||
[FieldLoader.LoadUsing( "LoadWarheads" )] public List<WarheadInfo> Warheads;
|
||||
|
||||
@@ -56,13 +56,14 @@ namespace OpenRA.Graphics
|
||||
PlayThen( sequenceName, () => PlayRepeating( CurrentSequence.Name ) );
|
||||
}
|
||||
|
||||
public void ReplaceAnim(string sequenceName)
|
||||
public bool ReplaceAnim(string sequenceName)
|
||||
{
|
||||
if (!HasSequence(sequenceName))
|
||||
return;
|
||||
return false;
|
||||
|
||||
CurrentSequence = SequenceProvider.GetSequence(name, sequenceName);
|
||||
frame %= CurrentSequence.Length;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void PlayThen( string sequenceName, Action after )
|
||||
@@ -124,14 +125,15 @@ namespace OpenRA.Graphics
|
||||
}
|
||||
}
|
||||
|
||||
public void ChangeImage(string newImage)
|
||||
public void ChangeImage(string newImage, string newAnimIfMissing)
|
||||
{
|
||||
newImage = newImage.ToLowerInvariant();
|
||||
|
||||
if (name != newImage)
|
||||
{
|
||||
name = newImage.ToLowerInvariant();
|
||||
ReplaceAnim(CurrentSequence.Name);
|
||||
if (!ReplaceAnim(CurrentSequence.Name))
|
||||
ReplaceAnim(newAnimIfMissing);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
59
OpenRA.Game/Graphics/CursorProvider.cs
Normal file
59
OpenRA.Game/Graphics/CursorProvider.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
public static class CursorProvider
|
||||
{
|
||||
static Dictionary<string, CursorSequence> cursors;
|
||||
|
||||
public static void Initialize(string[] sequenceFiles)
|
||||
{
|
||||
cursors = new Dictionary<string, CursorSequence>();
|
||||
var sequences = new MiniYaml(null, sequenceFiles.Select(s => MiniYaml.FromFile(s)).Aggregate(MiniYaml.Merge));
|
||||
|
||||
foreach (var s in sequences.NodesDict["Palettes"].Nodes)
|
||||
Game.modData.Palette.AddPalette(s.Key, new Palette(FileSystem.Open(s.Value.Value), false));
|
||||
|
||||
foreach (var s in sequences.NodesDict["Cursors"].Nodes)
|
||||
LoadSequencesForCursor(s.Key, s.Value);
|
||||
}
|
||||
|
||||
static void LoadSequencesForCursor(string cursorSrc, MiniYaml cursor)
|
||||
{
|
||||
Game.modData.LoadScreen.Display();
|
||||
|
||||
foreach (var sequence in cursor.Nodes)
|
||||
cursors.Add(sequence.Key, new CursorSequence(cursorSrc, cursor.Value, sequence.Value));
|
||||
}
|
||||
|
||||
public static bool HasCursorSequence(string cursor)
|
||||
{
|
||||
return cursors.ContainsKey(cursor);
|
||||
}
|
||||
|
||||
public static CursorSequence GetCursorSequence(string cursor)
|
||||
{
|
||||
try { return cursors[cursor]; }
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Cursor does not have a sequence `{0}`".F(cursor));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
#endregion
|
||||
|
||||
using System.Xml;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
@@ -25,24 +26,27 @@ namespace OpenRA.Graphics
|
||||
|
||||
Sprite[] sprites;
|
||||
|
||||
public CursorSequence(string cursorSrc, string palette, XmlElement e)
|
||||
public CursorSequence(string cursorSrc, string palette, MiniYaml info)
|
||||
{
|
||||
sprites = Game.modData.CursorSheetBuilder.LoadAllSprites(cursorSrc);
|
||||
var d = info.NodesDict;
|
||||
|
||||
start = int.Parse(e.GetAttribute("start"));
|
||||
start = int.Parse(d["start"].Value);
|
||||
this.palette = palette;
|
||||
|
||||
if (e.GetAttribute("length") == "*" || e.GetAttribute("end") == "*")
|
||||
if ((d.ContainsKey("length") && d["length"].Value == "*") || (d.ContainsKey("end") && d["end"].Value == "*"))
|
||||
length = sprites.Length - start;
|
||||
else if (e.HasAttribute("length"))
|
||||
length = int.Parse(e.GetAttribute("length"));
|
||||
else if (e.HasAttribute("end"))
|
||||
length = int.Parse(e.GetAttribute("end")) - start;
|
||||
else if (d.ContainsKey("length"))
|
||||
length = int.Parse(d["length"].Value);
|
||||
else if (d.ContainsKey("end"))
|
||||
length = int.Parse(d["end"].Value) - start;
|
||||
else
|
||||
length = 1;
|
||||
|
||||
int.TryParse( e.GetAttribute("x"), out Hotspot.X );
|
||||
int.TryParse( e.GetAttribute("y"), out Hotspot.Y );
|
||||
|
||||
if (d.ContainsKey("x"))
|
||||
int.TryParse(d["x"].Value, out Hotspot.X );
|
||||
if (d.ContainsKey("y"))
|
||||
int.TryParse(d["y"].Value, out Hotspot.Y );
|
||||
}
|
||||
|
||||
public Sprite GetSprite(int frame)
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace OpenRA.Graphics
|
||||
}
|
||||
|
||||
Sprite[] LoadCursors(string filename)
|
||||
{
|
||||
{
|
||||
try
|
||||
{
|
||||
var shp = new Dune2ShpReader(FileSystem.OpenWithExts(filename, exts));
|
||||
|
||||
@@ -17,7 +17,7 @@ using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
class HardwarePalette
|
||||
public class HardwarePalette
|
||||
{
|
||||
public const int MaxPalettes = 64;
|
||||
int allocated = 0;
|
||||
@@ -26,7 +26,7 @@ namespace OpenRA.Graphics
|
||||
Dictionary<string, Palette> palettes;
|
||||
Dictionary<string, int> indices;
|
||||
|
||||
public HardwarePalette(Map map)
|
||||
public HardwarePalette()
|
||||
{
|
||||
palettes = new Dictionary<string, Palette>();
|
||||
indices = new Dictionary<string, int>();
|
||||
@@ -51,6 +51,9 @@ namespace OpenRA.Graphics
|
||||
|
||||
public void AddPalette(string name, Palette p)
|
||||
{
|
||||
if (palettes.ContainsKey(name))
|
||||
throw new InvalidOperationException("Palette {0} has already been defined".F(name));
|
||||
|
||||
palettes.Add(name, p);
|
||||
indices.Add(name, allocated++);
|
||||
}
|
||||
|
||||
@@ -13,45 +13,46 @@ using OpenRA.FileFormats.Graphics;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
public class LineRenderer
|
||||
public class LineRenderer : Renderer.IBatchRenderer
|
||||
{
|
||||
Renderer renderer;
|
||||
IVertexBuffer<Vertex> vertexBuffer;
|
||||
IIndexBuffer indexBuffer; /* kindof a waste of space, but the GPU likes indexing, oh well */
|
||||
|
||||
const int linesPerBatch = 1024;
|
||||
|
||||
Vertex[] vertices = new Vertex[ 2 * linesPerBatch ];
|
||||
ushort[] indices = new ushort[ 2 * linesPerBatch ];
|
||||
int lines = 0;
|
||||
Vertex[] vertices = new Vertex[ Renderer.TempBufferSize ];
|
||||
ushort[] indices = new ushort[ Renderer.TempBufferSize ];
|
||||
int nv = 0, ni = 0;
|
||||
|
||||
public LineRenderer( Renderer renderer )
|
||||
{
|
||||
this.renderer = renderer;
|
||||
vertexBuffer = renderer.Device.CreateVertexBuffer(vertices.Length );
|
||||
indexBuffer = renderer.Device.CreateIndexBuffer( indices.Length );
|
||||
}
|
||||
|
||||
public void Flush()
|
||||
{
|
||||
if( lines > 0 )
|
||||
if( ni > 0 )
|
||||
{
|
||||
renderer.LineShader.Render( () =>
|
||||
{
|
||||
vertexBuffer.SetData( vertices );
|
||||
indexBuffer.SetData( indices );
|
||||
renderer.DrawBatch( vertexBuffer, indexBuffer,
|
||||
var vb = renderer.GetTempVertexBuffer();
|
||||
var ib = renderer.GetTempIndexBuffer();
|
||||
vb.SetData( vertices, nv );
|
||||
ib.SetData( indices, ni );
|
||||
renderer.DrawBatch( vb, ib,
|
||||
nv, ni / 2, PrimitiveType.LineList );
|
||||
} );
|
||||
|
||||
nv = 0; ni = 0;
|
||||
lines = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawLine( float2 start, float2 end, Color startColor, Color endColor )
|
||||
{
|
||||
Renderer.CurrentBatchRenderer = this;
|
||||
|
||||
if( ni + 2 > Renderer.TempBufferSize )
|
||||
Flush();
|
||||
if( nv + 2 > Renderer.TempBufferSize )
|
||||
Flush();
|
||||
|
||||
indices[ ni++ ] = (ushort)nv;
|
||||
|
||||
vertices[ nv++ ] = new Vertex( start,
|
||||
@@ -63,9 +64,6 @@ namespace OpenRA.Graphics
|
||||
vertices[ nv++ ] = new Vertex( end,
|
||||
new float2( endColor.R / 255.0f, endColor.G / 255.0f ),
|
||||
new float2( endColor.B / 255.0f, endColor.A / 255.0f ) );
|
||||
|
||||
if( ++lines >= linesPerBatch )
|
||||
Flush();
|
||||
}
|
||||
|
||||
public void FillRect( RectangleF r, Color color )
|
||||
|
||||
@@ -14,16 +14,29 @@ using System.Drawing.Imaging;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Traits;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
public class Minimap
|
||||
{
|
||||
public static Bitmap TerrainBitmap(Map map)
|
||||
{
|
||||
return TerrainBitmap(map, false);
|
||||
}
|
||||
|
||||
public static Bitmap TerrainBitmap(Map map, bool actualSize)
|
||||
{
|
||||
var tileset = Rules.TileSets[map.Tileset];
|
||||
var size = Util.NextPowerOf2(Math.Max(map.Width, map.Height));
|
||||
Bitmap terrain = new Bitmap(size, size);
|
||||
var width = map.Bounds.Width;
|
||||
var height = map.Bounds.Height;
|
||||
|
||||
if (!actualSize)
|
||||
{
|
||||
width = height = Util.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height));
|
||||
}
|
||||
|
||||
Bitmap terrain = new Bitmap(width, height);
|
||||
|
||||
var bitmapData = terrain.LockBits(new Rectangle(0, 0, terrain.Width, terrain.Height),
|
||||
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||
@@ -32,12 +45,15 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
int* c = (int*)bitmapData.Scan0;
|
||||
|
||||
for (var x = 0; x < map.Width; x++)
|
||||
for (var y = 0; y < map.Height; y++)
|
||||
for (var x = 0; x < map.Bounds.Width; x++)
|
||||
for (var y = 0; y < map.Bounds.Height; y++)
|
||||
{
|
||||
var mapX = x + map.TopLeft.X;
|
||||
var mapY = y + map.TopLeft.Y;
|
||||
var mapX = x + map.Bounds.Left;
|
||||
var mapY = y + map.Bounds.Top;
|
||||
var type = tileset.GetTerrainType(map.MapTiles[mapX, mapY]);
|
||||
if (!tileset.Terrain.ContainsKey(type))
|
||||
throw new InvalidDataException("Tileset {0} lacks terraintype {1}".F(tileset.Id, type));
|
||||
|
||||
*(c + (y * bitmapData.Stride >> 2) + x) = tileset.Terrain[type].Color.ToArgb();
|
||||
}
|
||||
}
|
||||
@@ -59,11 +75,11 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
int* c = (int*)bitmapData.Scan0;
|
||||
|
||||
for (var x = 0; x < map.Width; x++)
|
||||
for (var y = 0; y < map.Height; y++)
|
||||
for (var x = 0; x < map.Bounds.Width; x++)
|
||||
for (var y = 0; y < map.Bounds.Height; y++)
|
||||
{
|
||||
var mapX = x + map.TopLeft.X;
|
||||
var mapY = y + map.TopLeft.Y;
|
||||
var mapX = x + map.Bounds.Left;
|
||||
var mapY = y + map.Bounds.Top;
|
||||
if (map.MapResources[mapX, mapY].type == 0)
|
||||
continue;
|
||||
|
||||
@@ -84,7 +100,7 @@ namespace OpenRA.Graphics
|
||||
public static Bitmap CustomTerrainBitmap(World world)
|
||||
{
|
||||
var map = world.Map;
|
||||
var size = Util.NextPowerOf2(Math.Max(map.Width, map.Height));
|
||||
var size = Util.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height));
|
||||
Bitmap bitmap = new Bitmap(size, size);
|
||||
var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||
@@ -93,11 +109,11 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
int* c = (int*)bitmapData.Scan0;
|
||||
|
||||
for (var x = 0; x < map.Width; x++)
|
||||
for (var y = 0; y < map.Height; y++)
|
||||
for (var x = 0; x < map.Bounds.Width; x++)
|
||||
for (var y = 0; y < map.Bounds.Height; y++)
|
||||
{
|
||||
var mapX = x + map.TopLeft.X;
|
||||
var mapY = y + map.TopLeft.Y;
|
||||
var mapX = x + map.Bounds.Left;
|
||||
var mapY = y + map.Bounds.Top;
|
||||
var custom = map.CustomTerrain[mapX,mapY];
|
||||
if (custom == null)
|
||||
continue;
|
||||
@@ -111,7 +127,7 @@ namespace OpenRA.Graphics
|
||||
public static Bitmap ActorsBitmap(World world)
|
||||
{
|
||||
var map = world.Map;
|
||||
var size = Util.NextPowerOf2(Math.Max(map.Width, map.Height));
|
||||
var size = Util.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height));
|
||||
Bitmap bitmap = new Bitmap(size, size);
|
||||
var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||
@@ -119,16 +135,16 @@ namespace OpenRA.Graphics
|
||||
unsafe
|
||||
{
|
||||
int* c = (int*)bitmapData.Scan0;
|
||||
|
||||
foreach (var t in world.Queries.WithTraitMultiple<IRadarSignature>())
|
||||
|
||||
foreach (var t in world.Queries.WithTrait<IRadarSignature>())
|
||||
{
|
||||
if (!t.Actor.IsVisible(world.LocalPlayer))
|
||||
if (!world.LocalShroud.IsVisible(t.Actor))
|
||||
continue;
|
||||
|
||||
var color = t.Trait.RadarSignatureColor(t.Actor);
|
||||
foreach (var cell in t.Trait.RadarSignatureCells(t.Actor))
|
||||
if (world.Map.IsInMap(cell))
|
||||
*(c + ((cell.Y - world.Map.TopLeft.Y) * bitmapData.Stride >> 2) + cell.X - world.Map.TopLeft.X) = color.ToArgb();
|
||||
*(c + ((cell.Y - world.Map.Bounds.Top) * bitmapData.Stride >> 2) + cell.X - world.Map.Bounds.Left) = color.ToArgb();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,26 +155,29 @@ namespace OpenRA.Graphics
|
||||
public static Bitmap ShroudBitmap(World world)
|
||||
{
|
||||
var map = world.Map;
|
||||
var size = Util.NextPowerOf2(Math.Max(map.Width, map.Height));
|
||||
var size = Util.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height));
|
||||
Bitmap bitmap = new Bitmap(size, size);
|
||||
if (world.LocalShroud.Disabled)
|
||||
return bitmap;
|
||||
|
||||
var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||
|
||||
var shroud = Color.Black.ToArgb();
|
||||
var fog = Color.FromArgb(128, Color.Black).ToArgb();
|
||||
|
||||
|
||||
unsafe
|
||||
{
|
||||
int* c = (int*)bitmapData.Scan0;
|
||||
|
||||
for (var x = 0; x < map.Width; x++)
|
||||
for (var y = 0; y < map.Height; y++)
|
||||
for (var x = 0; x < map.Bounds.Width; x++)
|
||||
for (var y = 0; y < map.Bounds.Height; y++)
|
||||
{
|
||||
var mapX = x + map.TopLeft.X;
|
||||
var mapY = y + map.TopLeft.Y;
|
||||
if (!world.LocalPlayer.Shroud.IsExplored(mapX, mapY))
|
||||
var mapX = x + map.Bounds.Left;
|
||||
var mapY = y + map.Bounds.Top;
|
||||
if (!world.LocalShroud.IsExplored(mapX, mapY))
|
||||
*(c + (y * bitmapData.Stride >> 2) + x) = shroud;
|
||||
else if (!world.LocalPlayer.Shroud.IsVisible(mapX,mapY))
|
||||
else if (!world.LocalShroud.IsVisible(mapX,mapY))
|
||||
*(c + (y * bitmapData.Stride >> 2) + x) = fog;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using OpenRA.FileFormats;
|
||||
using System.Windows.Forms;
|
||||
using OpenRA.FileFormats.Graphics;
|
||||
using OpenRA.Support;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
@@ -23,10 +23,10 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
internal static int SheetSize;
|
||||
|
||||
public IShader SpriteShader { get; private set; } /* note: shared shader params */
|
||||
public IShader LineShader { get; private set; }
|
||||
public IShader RgbaSpriteShader { get; private set; }
|
||||
public IShader WorldSpriteShader { get; private set; }
|
||||
internal IShader SpriteShader { get; private set; } /* note: shared shader params */
|
||||
internal IShader LineShader { get; private set; }
|
||||
internal IShader RgbaSpriteShader { get; private set; }
|
||||
internal IShader WorldSpriteShader { get; private set; }
|
||||
|
||||
public SpriteRenderer SpriteRenderer { get; private set; }
|
||||
public SpriteRenderer RgbaSpriteRenderer { get; private set; }
|
||||
@@ -35,14 +35,20 @@ namespace OpenRA.Graphics
|
||||
|
||||
public ITexture PaletteTexture;
|
||||
|
||||
public readonly SpriteFont RegularFont, BoldFont, TitleFont;
|
||||
public readonly SpriteFont RegularFont, BoldFont, TitleFont, TinyFont;
|
||||
|
||||
internal const int TempBufferSize = 8192;
|
||||
const int TempBufferCount = 8;
|
||||
|
||||
Queue<IVertexBuffer<Vertex>> tempBuffersV = new Queue<IVertexBuffer<Vertex>>();
|
||||
Queue<IIndexBuffer> tempBuffersI = new Queue<IIndexBuffer>();
|
||||
|
||||
public Renderer()
|
||||
{
|
||||
SpriteShader = device.CreateShader(FileSystem.Open("shaders/world-shp.fx"));
|
||||
LineShader = device.CreateShader(FileSystem.Open("shaders/line.fx"));
|
||||
RgbaSpriteShader = device.CreateShader(FileSystem.Open("shaders/chrome-rgba.fx"));
|
||||
WorldSpriteShader = device.CreateShader(FileSystem.Open("shaders/chrome-shp.fx"));
|
||||
SpriteShader = device.CreateShader("world-shp");
|
||||
LineShader = device.CreateShader("world-line");
|
||||
RgbaSpriteShader = device.CreateShader("chrome-rgba");
|
||||
WorldSpriteShader = device.CreateShader("chrome-shp");
|
||||
|
||||
SpriteRenderer = new SpriteRenderer( this, SpriteShader );
|
||||
RgbaSpriteRenderer = new SpriteRenderer( this, RgbaSpriteShader );
|
||||
@@ -52,13 +58,19 @@ namespace OpenRA.Graphics
|
||||
RegularFont = new SpriteFont("FreeSans.ttf", 14);
|
||||
BoldFont = new SpriteFont("FreeSansBold.ttf", 14);
|
||||
TitleFont = new SpriteFont("titles.ttf", 48);
|
||||
TinyFont = new SpriteFont("FreeSans.ttf", 10);
|
||||
|
||||
for( int i = 0 ; i < TempBufferCount ; i++ )
|
||||
{
|
||||
tempBuffersV.Enqueue( device.CreateVertexBuffer( TempBufferSize ) );
|
||||
tempBuffersI.Enqueue( device.CreateIndexBuffer( TempBufferSize ) );
|
||||
}
|
||||
}
|
||||
|
||||
public IGraphicsDevice Device { get { return device; } }
|
||||
internal IGraphicsDevice Device { get { return device; } }
|
||||
|
||||
public void BeginFrame(float2 scroll)
|
||||
{
|
||||
device.Begin();
|
||||
device.Clear(Color.Black);
|
||||
|
||||
float2 r1 = new float2(2f/Resolution.Width, -2f/Resolution.Height);
|
||||
@@ -73,16 +85,16 @@ namespace OpenRA.Graphics
|
||||
private void SetShaderParams( IShader s, float2 r1, float2 r2, float2 scroll )
|
||||
{
|
||||
s.SetValue( "Palette", PaletteTexture );
|
||||
s.SetValue( "Scroll", scroll.X, scroll.Y );
|
||||
s.SetValue( "Scroll", (int) scroll.X, (int) scroll.Y );
|
||||
s.SetValue( "r1", r1.X, r1.Y );
|
||||
s.SetValue( "r2", r2.X, r2.Y );
|
||||
s.Commit();
|
||||
}
|
||||
|
||||
public void EndFrame()
|
||||
public void EndFrame( IInputHandler inputHandler )
|
||||
{
|
||||
device.End();
|
||||
device.Present();
|
||||
Flush();
|
||||
device.Present( inputHandler );
|
||||
}
|
||||
|
||||
public void DrawBatch<T>(IVertexBuffer<T> vertices, IIndexBuffer indices,
|
||||
@@ -111,15 +123,9 @@ namespace OpenRA.Graphics
|
||||
|
||||
public void Flush()
|
||||
{
|
||||
WorldSpriteRenderer.Flush();
|
||||
RgbaSpriteRenderer.Flush();
|
||||
LineRenderer.Flush();
|
||||
CurrentBatchRenderer = null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static IGraphicsDevice device;
|
||||
|
||||
public static Size Resolution { get { return device.WindowSize; } }
|
||||
@@ -127,14 +133,14 @@ namespace OpenRA.Graphics
|
||||
internal static void Initialize( OpenRA.FileFormats.Graphics.WindowMode windowMode )
|
||||
{
|
||||
var resolution = GetResolution( windowMode );
|
||||
device = CreateDevice( Assembly.LoadFile( Path.GetFullPath( "OpenRA.Gl.dll" ) ), resolution.Width, resolution.Height, windowMode, false );
|
||||
device = CreateDevice( Assembly.LoadFile( Path.GetFullPath( "OpenRA.Renderer.{0}.dll".F(Game.Settings.Graphics.Renderer) ) ), resolution.Width, resolution.Height, windowMode, false );
|
||||
}
|
||||
|
||||
static Size GetResolution(WindowMode windowmode)
|
||||
{
|
||||
var desktopResolution = Screen.PrimaryScreen.Bounds.Size;
|
||||
var desktopResolution = Screen.PrimaryScreen.Bounds.Size;
|
||||
var customSize = (windowmode == WindowMode.Windowed) ? Game.Settings.Graphics.WindowedSize : Game.Settings.Graphics.FullscreenSize;
|
||||
|
||||
|
||||
if (customSize.X > 0 && customSize.Y > 0)
|
||||
{
|
||||
desktopResolution.Width = customSize.X;
|
||||
@@ -154,5 +160,49 @@ namespace OpenRA.Graphics
|
||||
}
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal IVertexBuffer<Vertex> GetTempVertexBuffer()
|
||||
{
|
||||
var ret = tempBuffersV.Dequeue();
|
||||
tempBuffersV.Enqueue( ret );
|
||||
return ret;
|
||||
}
|
||||
|
||||
internal IIndexBuffer GetTempIndexBuffer()
|
||||
{
|
||||
var ret = tempBuffersI.Dequeue();
|
||||
tempBuffersI.Enqueue( ret );
|
||||
return ret;
|
||||
}
|
||||
|
||||
public interface IBatchRenderer
|
||||
{
|
||||
void Flush();
|
||||
}
|
||||
|
||||
static IBatchRenderer currentBatchRenderer;
|
||||
public static IBatchRenderer CurrentBatchRenderer
|
||||
{
|
||||
get { return currentBatchRenderer; }
|
||||
set
|
||||
{
|
||||
if( currentBatchRenderer == value ) return;
|
||||
if( currentBatchRenderer != null )
|
||||
currentBatchRenderer.Flush();
|
||||
currentBatchRenderer = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void EnableScissor(int left, int top, int width, int height)
|
||||
{
|
||||
Flush();
|
||||
Device.EnableScissor( left, top, width, height );
|
||||
}
|
||||
|
||||
public void DisableScissor()
|
||||
{
|
||||
Flush();
|
||||
Device.DisableScissor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#endregion
|
||||
|
||||
using System.Xml;
|
||||
using OpenRA.FileFormats;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
@@ -24,34 +26,55 @@ namespace OpenRA.Graphics
|
||||
public int Facings { get { return facings; } }
|
||||
public int Tick { get { return tick; } }
|
||||
|
||||
public Sequence(string unit, XmlElement e)
|
||||
string srcOverride;
|
||||
public Sequence(string unit, string name, MiniYaml info)
|
||||
{
|
||||
string srcOverride = e.GetAttribute("src");
|
||||
Name = e.GetAttribute("name");
|
||||
srcOverride = info.Value;
|
||||
Name = name;
|
||||
var d = info.NodesDict;
|
||||
|
||||
sprites = Game.modData.SpriteLoader.LoadAllSprites(string.IsNullOrEmpty(srcOverride) ? unit : srcOverride );
|
||||
start = int.Parse(d["Start"].Value);
|
||||
|
||||
sprites = SpriteSheetBuilder.LoadAllSprites(string.IsNullOrEmpty(srcOverride) ? unit : srcOverride );
|
||||
start = int.Parse(e.GetAttribute("start"));
|
||||
|
||||
if (e.GetAttribute("length") == "*" || e.GetAttribute("end") == "*")
|
||||
length = sprites.Length - Start;
|
||||
else if (e.HasAttribute("length"))
|
||||
length = int.Parse(e.GetAttribute("length"));
|
||||
else if (e.HasAttribute("end"))
|
||||
length = int.Parse(e.GetAttribute("end")) - int.Parse(e.GetAttribute("start"));
|
||||
else
|
||||
if (!d.ContainsKey("Length"))
|
||||
length = 1;
|
||||
else if (d["Length"].Value == "*")
|
||||
length = sprites.Length - Start;
|
||||
else
|
||||
length = int.Parse(d["Length"].Value);
|
||||
|
||||
if( e.HasAttribute( "facings" ) )
|
||||
facings = int.Parse( e.GetAttribute( "facings" ) );
|
||||
|
||||
if(d.ContainsKey("Facings"))
|
||||
facings = int.Parse(d["Facings"].Value);
|
||||
else
|
||||
facings = 1;
|
||||
|
||||
if (e.HasAttribute("tick"))
|
||||
tick = int.Parse(e.GetAttribute("tick"));
|
||||
if(d.ContainsKey("Tick"))
|
||||
tick = int.Parse(d["Tick"].Value);
|
||||
else
|
||||
tick = 40;
|
||||
}
|
||||
|
||||
|
||||
public MiniYaml Save()
|
||||
{
|
||||
var root = new List<MiniYamlNode>();
|
||||
|
||||
root.Add(new MiniYamlNode("Start", start.ToString()));
|
||||
|
||||
if (length > 1 && (start != 0 || length != sprites.Length - start))
|
||||
root.Add(new MiniYamlNode("Length", length.ToString()));
|
||||
else if (length > 1 && length == sprites.Length - start)
|
||||
root.Add(new MiniYamlNode("Length", "*"));
|
||||
|
||||
if (facings > 1)
|
||||
root.Add(new MiniYamlNode("Facings", facings.ToString()));
|
||||
|
||||
if (tick != 40)
|
||||
root.Add(new MiniYamlNode("Tick", tick.ToString()));
|
||||
|
||||
return new MiniYaml(srcOverride, root);
|
||||
}
|
||||
|
||||
public Sprite GetSprite( int frame )
|
||||
{
|
||||
return GetSprite( frame, 0 );
|
||||
|
||||
@@ -12,7 +12,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
@@ -20,60 +19,48 @@ namespace OpenRA.Graphics
|
||||
public static class SequenceProvider
|
||||
{
|
||||
static Dictionary<string, Dictionary<string, Sequence>> units;
|
||||
static Dictionary<string, CursorSequence> cursors;
|
||||
|
||||
public static void Initialize(string[] sequenceFiles)
|
||||
public static void Initialize(string[] sequenceFiles, List<MiniYamlNode> sequenceNodes)
|
||||
{
|
||||
units = new Dictionary<string, Dictionary<string, Sequence>>();
|
||||
cursors = new Dictionary<string, CursorSequence>();
|
||||
|
||||
foreach (var f in sequenceFiles)
|
||||
LoadSequenceSource(f);
|
||||
if (sequenceFiles.Length == 0)
|
||||
return;
|
||||
|
||||
var sequences = sequenceFiles.Select(s => MiniYaml.FromFile(s)).Aggregate(sequenceNodes, MiniYaml.Merge);
|
||||
|
||||
foreach (var s in sequences)
|
||||
LoadSequencesForUnit(s.Key, s.Value);
|
||||
}
|
||||
|
||||
static void LoadSequenceSource(string filename)
|
||||
{
|
||||
XmlDocument document = new XmlDocument();
|
||||
document.Load(FileSystem.Open(filename));
|
||||
|
||||
foreach (XmlElement eUnit in document.SelectNodes("/sequences/unit"))
|
||||
LoadSequencesForUnit(eUnit);
|
||||
|
||||
foreach (XmlElement eCursor in document.SelectNodes("/sequences/cursor"))
|
||||
LoadSequencesForCursor(eCursor);
|
||||
}
|
||||
|
||||
static void LoadSequencesForCursor(XmlElement eCursor)
|
||||
static void LoadSequencesForUnit(string unit, MiniYaml sequences)
|
||||
{
|
||||
Game.modData.LoadScreen.Display();
|
||||
string cursorSrc = eCursor.GetAttribute("src");
|
||||
string palette = eCursor.GetAttribute("palette");
|
||||
|
||||
foreach (XmlElement eSequence in eCursor.SelectNodes("./sequence"))
|
||||
cursors.Add(eSequence.GetAttribute("name"), new CursorSequence(cursorSrc, palette, eSequence));
|
||||
|
||||
}
|
||||
|
||||
static void LoadSequencesForUnit(XmlElement eUnit)
|
||||
{
|
||||
Game.modData.LoadScreen.Display();
|
||||
string unitName = eUnit.GetAttribute("name");
|
||||
try {
|
||||
var sequences = eUnit.SelectNodes("./sequence").OfType<XmlElement>()
|
||||
.Select(e => new Sequence(unitName, e))
|
||||
.ToDictionary(s => s.Name);
|
||||
|
||||
units.Add(unitName, sequences);
|
||||
var seq = sequences.NodesDict.ToDictionary(x => x.Key, x => new Sequence(unit,x.Key,x.Value));
|
||||
units.Add(unit, seq);
|
||||
} catch (FileNotFoundException) {} // Do nothing; we can crash later if we actually wanted art
|
||||
}
|
||||
|
||||
public static MiniYaml SaveSequencesForUnit(string unitname)
|
||||
{
|
||||
var ret = new List<MiniYamlNode>();
|
||||
foreach (var s in units[unitname])
|
||||
ret.Add(new MiniYamlNode(s.Key, s.Value.Save()));
|
||||
|
||||
return new MiniYaml(null, ret);
|
||||
}
|
||||
|
||||
public static Sequence GetSequence(string unitName, string sequenceName)
|
||||
{
|
||||
try { return units[unitName][sequenceName]; }
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Unit `{0}` does not have a sequence `{1}`".F(unitName, sequenceName));
|
||||
if (units.ContainsKey(unitName))
|
||||
throw new InvalidOperationException(
|
||||
"Unit `{0}` does not have a sequence `{1}`".F(unitName, sequenceName));
|
||||
else
|
||||
throw new InvalidOperationException(
|
||||
"Unit `{0}` does not have any sequences defined.".F(unitName));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,20 +68,5 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
return units[unit].ContainsKey(seq);
|
||||
}
|
||||
|
||||
public static bool HasCursorSequence(string cursor)
|
||||
{
|
||||
return cursors.ContainsKey(cursor);
|
||||
}
|
||||
|
||||
public static CursorSequence GetCursorSequence(string cursor)
|
||||
{
|
||||
try { return cursors[cursor]; }
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Cursor does not have a sequence `{0}`".F(cursor));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
161
OpenRA.Game/Graphics/ShroudRenderer.cs
Normal file
161
OpenRA.Game/Graphics/ShroudRenderer.cs
Normal file
@@ -0,0 +1,161 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Drawing;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
public class ShroudRenderer
|
||||
{
|
||||
Traits.Shroud shroud;
|
||||
Sprite[] shadowBits = Game.modData.SpriteLoader.LoadAllSprites("shadow");
|
||||
Sprite[,] sprites, fogSprites;
|
||||
|
||||
bool dirty = true;
|
||||
Map map;
|
||||
|
||||
public ShroudRenderer(World world)
|
||||
{
|
||||
this.shroud = world.LocalShroud;
|
||||
this.map = world.Map;
|
||||
|
||||
sprites = new Sprite[map.MapSize.X, map.MapSize.Y];
|
||||
fogSprites = new Sprite[map.MapSize.X, map.MapSize.Y];
|
||||
shroud.Dirty += () => dirty = true;
|
||||
}
|
||||
|
||||
static readonly byte[][] SpecialShroudTiles =
|
||||
{
|
||||
new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
|
||||
new byte[] { 32, 32, 25, 25, 19, 19, 20, 20 },
|
||||
new byte[] { 33, 33, 33, 33, 26, 26, 26, 26, 21, 21, 21, 21, 23, 23, 23, 23 },
|
||||
new byte[] { 36, 36, 36, 36, 30, 30, 30, 30 },
|
||||
new byte[] { 34, 16, 34, 16, 34, 16, 34, 16, 27, 22, 27, 22, 27, 22, 27, 22 },
|
||||
new byte[] { 44 },
|
||||
new byte[] { 37, 37, 37, 37, 37, 37, 37, 37, 31, 31, 31, 31, 31, 31, 31, 31 },
|
||||
new byte[] { 40 },
|
||||
new byte[] { 35, 24, 17, 18 },
|
||||
new byte[] { 39, 39, 29, 29 },
|
||||
new byte[] { 45 },
|
||||
new byte[] { 43 },
|
||||
new byte[] { 38, 28 },
|
||||
new byte[] { 42 },
|
||||
new byte[] { 41 },
|
||||
new byte[] { 46 },
|
||||
};
|
||||
|
||||
Sprite ChooseShroud(int i, int j)
|
||||
{
|
||||
if( !shroud.IsExplored( i, j ) ) return shadowBits[ 0xf ];
|
||||
|
||||
// bits are for unexploredness: up, right, down, left
|
||||
var v = 0;
|
||||
// bits are for unexploredness: TL, TR, BR, BL
|
||||
var u = 0;
|
||||
|
||||
if( !shroud.IsExplored( i, j - 1 ) ) { v |= 1; u |= 3; }
|
||||
if( !shroud.IsExplored( i + 1, j ) ) { v |= 2; u |= 6; }
|
||||
if( !shroud.IsExplored( i, j + 1 ) ) { v |= 4; u |= 12; }
|
||||
if( !shroud.IsExplored( i - 1, j ) ) { v |= 8; u |= 9; }
|
||||
|
||||
var uSides = u;
|
||||
|
||||
if( !shroud.IsExplored( i - 1, j - 1 ) ) u |= 1;
|
||||
if( !shroud.IsExplored( i + 1, j - 1 ) ) u |= 2;
|
||||
if( !shroud.IsExplored( i + 1, j + 1 ) ) u |= 4;
|
||||
if( !shroud.IsExplored( i - 1, j + 1 ) ) u |= 8;
|
||||
|
||||
return shadowBits[ SpecialShroudTiles[ u ^ uSides ][ v ] ];
|
||||
}
|
||||
|
||||
Sprite ChooseFog(int i, int j)
|
||||
{
|
||||
if (!shroud.IsVisible(i,j)) return shadowBits[0xf];
|
||||
if (!shroud.IsExplored(i, j)) return shadowBits[0xf];
|
||||
|
||||
// bits are for unexploredness: up, right, down, left
|
||||
var v = 0;
|
||||
// bits are for unexploredness: TL, TR, BR, BL
|
||||
var u = 0;
|
||||
|
||||
if (!shroud.IsVisible(i, j - 1)) { v |= 1; u |= 3; }
|
||||
if (!shroud.IsVisible(i + 1, j)) { v |= 2; u |= 6; }
|
||||
if (!shroud.IsVisible(i, j + 1)) { v |= 4; u |= 12; }
|
||||
if (!shroud.IsVisible(i - 1, j)) { v |= 8; u |= 9; }
|
||||
|
||||
var uSides = u;
|
||||
|
||||
if (!shroud.IsVisible(i - 1, j - 1)) u |= 1;
|
||||
if (!shroud.IsVisible(i + 1, j - 1)) u |= 2;
|
||||
if (!shroud.IsVisible(i + 1, j + 1)) u |= 4;
|
||||
if (!shroud.IsVisible(i - 1, j + 1)) u |= 8;
|
||||
|
||||
return shadowBits[SpecialShroudTiles[u ^ uSides][v]];
|
||||
}
|
||||
|
||||
internal void Draw( WorldRenderer wr )
|
||||
{
|
||||
if (dirty)
|
||||
{
|
||||
dirty = false;
|
||||
for (int i = map.Bounds.Left; i < map.Bounds.Right; i++)
|
||||
for (int j = map.Bounds.Top; j < map.Bounds.Bottom; j++)
|
||||
sprites[i, j] = ChooseShroud(i, j);
|
||||
|
||||
for (int i = map.Bounds.Left; i < map.Bounds.Right; i++)
|
||||
for (int j = map.Bounds.Top; j < map.Bounds.Bottom; j++)
|
||||
fogSprites[i, j] = ChooseFog(i, j);
|
||||
}
|
||||
|
||||
var clipRect = Game.viewport.WorldBounds(wr.world);
|
||||
DrawShroud( wr, clipRect, fogSprites, "fog" );
|
||||
DrawShroud( wr, clipRect, sprites, "shroud" );
|
||||
}
|
||||
|
||||
void DrawShroud( WorldRenderer wr, Rectangle clip, Sprite[,] s, string pal )
|
||||
{
|
||||
var shroudPalette = wr.GetPaletteIndex(pal);
|
||||
|
||||
for (var j = clip.Top; j < clip.Bottom; j++)
|
||||
{
|
||||
var starti = clip.Left;
|
||||
var last = shadowBits[0x0f];
|
||||
for (var i = clip.Left; i < clip.Right; i++)
|
||||
{
|
||||
if ((s[i, j] == shadowBits[0x0f] && last == shadowBits[0x0f])
|
||||
|| (s[i, j] == shadowBits[0] && last == shadowBits[0]))
|
||||
continue;
|
||||
|
||||
if (starti != i)
|
||||
{
|
||||
s[starti, j].DrawAt(
|
||||
Game.CellSize * new float2(starti, j),
|
||||
shroudPalette,
|
||||
new float2(Game.CellSize * (i - starti), Game.CellSize));
|
||||
starti = i + 1;
|
||||
}
|
||||
|
||||
s[i, j].DrawAt(
|
||||
Game.CellSize * new float2(i, j),
|
||||
shroudPalette);
|
||||
starti = i + 1;
|
||||
last = s[i, j];
|
||||
}
|
||||
|
||||
if (starti < clip.Right)
|
||||
s[starti, j].DrawAt(
|
||||
Game.CellSize * new float2(starti, j),
|
||||
shroudPalette,
|
||||
new float2(Game.CellSize * (clip.Right - starti), Game.CellSize));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,26 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
return uvhax[ k ];
|
||||
}
|
||||
|
||||
public void DrawAt( WorldRenderer wr, float2 location, string palette )
|
||||
{
|
||||
Game.Renderer.SpriteRenderer.DrawSprite( this, location, wr, palette, this.size );
|
||||
}
|
||||
|
||||
public void DrawAt( float2 location, int paletteIndex )
|
||||
{
|
||||
Game.Renderer.SpriteRenderer.DrawSprite( this, location, paletteIndex, this.size );
|
||||
}
|
||||
|
||||
public void DrawAt(float2 location, int paletteIndex, float scale)
|
||||
{
|
||||
Game.Renderer.SpriteRenderer.DrawSprite(this, location, paletteIndex, this.size * scale);
|
||||
}
|
||||
|
||||
public void DrawAt( float2 location, int paletteIndex, float2 size )
|
||||
{
|
||||
Game.Renderer.SpriteRenderer.DrawSprite( this, location, paletteIndex, size );
|
||||
}
|
||||
}
|
||||
|
||||
public enum TextureChannel
|
||||
|
||||
@@ -69,6 +69,19 @@ namespace OpenRA.Graphics
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawTextWithContrast(string text, float2 location, Color fg, Color bg, int offset)
|
||||
{
|
||||
if (offset > 0)
|
||||
{
|
||||
DrawText(text, location + new float2(-offset, 0), bg);
|
||||
DrawText(text, location + new float2(offset, 0), bg);
|
||||
DrawText(text, location + new float2(0, -offset), bg);
|
||||
DrawText(text, location + new float2(0, offset), bg);
|
||||
}
|
||||
|
||||
DrawText(text, location, fg);
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -80,17 +93,20 @@ namespace OpenRA.Graphics
|
||||
GlyphInfo CreateGlyph(Pair<char,Color> c)
|
||||
{
|
||||
var index = FT.FT_Get_Char_Index(face, (uint)c.First);
|
||||
FT.FT_Load_Glyph(face, index, FT.FT_LOAD_RENDER);
|
||||
if (0 != FT.FT_Load_Glyph(face, index, FT.FT_LOAD_RENDER))
|
||||
throw new InvalidOperationException( "FT_Load_Glyph failed." );
|
||||
|
||||
var _face = (FT_FaceRec)Marshal.PtrToStructure(face, typeof(FT_FaceRec));
|
||||
var _glyph = (FT_GlyphSlotRec)Marshal.PtrToStructure(_face.glyph, typeof(FT_GlyphSlotRec));
|
||||
|
||||
var s = builder.Allocate(new Size(_glyph.metrics.width >> 6, _glyph.metrics.height >> 6));
|
||||
var s = builder.Allocate(
|
||||
new Size(_glyph.metrics.width.ToInt32() >> 6,
|
||||
_glyph.metrics.height.ToInt32() >> 6));
|
||||
|
||||
var g = new GlyphInfo
|
||||
{
|
||||
Sprite = s,
|
||||
Advance = _glyph.metrics.horiAdvance / 64f,
|
||||
Advance = _glyph.metrics.horiAdvance.ToInt32() / 64f,
|
||||
Offset = { X = _glyph.bitmap_left, Y = -_glyph.bitmap_top }
|
||||
};
|
||||
|
||||
|
||||
@@ -13,23 +13,25 @@ using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
public static class SpriteSheetBuilder
|
||||
public class SpriteLoader
|
||||
{
|
||||
public static void Initialize( TileSet tileset )
|
||||
public SpriteLoader( string[] exts, SheetBuilder sheetBuilder )
|
||||
{
|
||||
exts = tileset.Extensions;
|
||||
SheetBuilder = sheetBuilder;
|
||||
this.exts = exts;
|
||||
sprites = new Cache<string, Sprite[]>( LoadSprites );
|
||||
}
|
||||
|
||||
static Cache<string, Sprite[]> sprites;
|
||||
static string[] exts;
|
||||
readonly SheetBuilder SheetBuilder;
|
||||
readonly Cache<string, Sprite[]> sprites;
|
||||
readonly string[] exts;
|
||||
|
||||
static Sprite[] LoadSprites(string filename)
|
||||
Sprite[] LoadSprites(string filename)
|
||||
{
|
||||
var shp = new ShpReader(FileSystem.OpenWithExts(filename, exts));
|
||||
return shp.Select(a => Game.modData.SheetBuilder.Add(a.Image, shp.Size)).ToArray();
|
||||
return shp.Select(a => SheetBuilder.Add(a.Image, shp.Size)).ToArray();
|
||||
}
|
||||
|
||||
public static Sprite[] LoadAllSprites(string filename) { return sprites[filename]; }
|
||||
public Sprite[] LoadAllSprites(string filename) { return sprites[filename]; }
|
||||
}
|
||||
}
|
||||
@@ -12,28 +12,20 @@ using OpenRA.FileFormats.Graphics;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
public class SpriteRenderer
|
||||
public class SpriteRenderer : Renderer.IBatchRenderer
|
||||
{
|
||||
IVertexBuffer<Vertex> vertexBuffer;
|
||||
IIndexBuffer indexBuffer;
|
||||
Renderer renderer;
|
||||
IShader shader;
|
||||
|
||||
const int spritesPerBatch = 1024;
|
||||
|
||||
Vertex[] vertices = new Vertex[4 * spritesPerBatch];
|
||||
ushort[] indices = new ushort[6 * spritesPerBatch];
|
||||
Vertex[] vertices = new Vertex[Renderer.TempBufferSize];
|
||||
ushort[] indices = new ushort[Renderer.TempBufferSize];
|
||||
Sheet currentSheet = null;
|
||||
int sprites = 0;
|
||||
int nv = 0, ni = 0;
|
||||
|
||||
public SpriteRenderer(Renderer renderer, IShader shader)
|
||||
{
|
||||
this.renderer = renderer;
|
||||
this.shader = shader;
|
||||
|
||||
vertexBuffer = renderer.Device.CreateVertexBuffer( vertices.Length );
|
||||
indexBuffer = renderer.Device.CreateIndexBuffer( indices.Length );
|
||||
}
|
||||
|
||||
public SpriteRenderer(Renderer renderer)
|
||||
@@ -41,14 +33,16 @@ namespace OpenRA.Graphics
|
||||
|
||||
public void Flush()
|
||||
{
|
||||
if (sprites > 0)
|
||||
if (ni > 0)
|
||||
{
|
||||
shader.SetValue( "DiffuseTexture", currentSheet.Texture );
|
||||
shader.Render(() =>
|
||||
{
|
||||
vertexBuffer.SetData(vertices);
|
||||
indexBuffer.SetData(indices);
|
||||
renderer.DrawBatch(vertexBuffer, indexBuffer,
|
||||
var vb = renderer.GetTempVertexBuffer();
|
||||
var ib = renderer.GetTempIndexBuffer();
|
||||
vb.SetData(vertices, nv);
|
||||
ib.SetData(indices, ni);
|
||||
renderer.DrawBatch(vb, ib,
|
||||
new Range<int>(0, nv),
|
||||
new Range<int>(0, ni),
|
||||
PrimitiveType.TriangleList,
|
||||
@@ -57,30 +51,34 @@ namespace OpenRA.Graphics
|
||||
|
||||
nv = 0; ni = 0;
|
||||
currentSheet = null;
|
||||
sprites = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawSprite(Sprite s, float2 location, string palette)
|
||||
public void DrawSprite(Sprite s, float2 location, WorldRenderer wr, string palette)
|
||||
{
|
||||
DrawSprite(s, location, Game.world.WorldRenderer.GetPaletteIndex(palette), s.size);
|
||||
DrawSprite(s, location, wr.GetPaletteIndex(palette), s.size);
|
||||
}
|
||||
|
||||
public void DrawSprite(Sprite s, float2 location, string palette, float2 size)
|
||||
public void DrawSprite(Sprite s, float2 location, WorldRenderer wr, string palette, float2 size)
|
||||
{
|
||||
DrawSprite(s, location, Game.world.WorldRenderer.GetPaletteIndex(palette), size);
|
||||
DrawSprite(s, location, wr.GetPaletteIndex(palette), size);
|
||||
}
|
||||
|
||||
public void DrawSprite(Sprite s, float2 location, int paletteIndex, float2 size)
|
||||
{
|
||||
Renderer.CurrentBatchRenderer = this;
|
||||
|
||||
if (s.sheet != currentSheet)
|
||||
Flush();
|
||||
|
||||
if( nv + 4 > Renderer.TempBufferSize )
|
||||
Flush();
|
||||
if( ni + 6 > Renderer.TempBufferSize )
|
||||
Flush();
|
||||
|
||||
currentSheet = s.sheet;
|
||||
Util.FastCreateQuad(vertices, indices, location.ToInt2(), s, paletteIndex, nv, ni, size);
|
||||
nv += 4; ni += 6;
|
||||
if (++sprites >= spritesPerBatch)
|
||||
Flush();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -31,24 +31,24 @@ namespace OpenRA.Graphics
|
||||
this.map = world.Map;
|
||||
|
||||
Size tileSize = new Size( Game.CellSize, Game.CellSize );
|
||||
|
||||
var tileMapping = new Cache<TileReference<ushort,byte>, Sprite>(
|
||||
x => Game.modData.SheetBuilder.Add(world.TileSet.GetBytes(x), tileSize));
|
||||
|
||||
Vertex[] vertices = new Vertex[4 * map.Height * map.Width];
|
||||
ushort[] indices = new ushort[6 * map.Height * map.Width];
|
||||
Vertex[] vertices = new Vertex[4 * map.Bounds.Height * map.Bounds.Width];
|
||||
ushort[] indices = new ushort[6 * map.Bounds.Height * map.Bounds.Width];
|
||||
|
||||
terrainSheet = tileMapping[map.MapTiles[map.TopLeft.X, map.TopLeft.Y]].sheet;
|
||||
terrainSheet = tileMapping[map.MapTiles[map.Bounds.Left, map.Bounds.Top]].sheet;
|
||||
|
||||
int nv = 0;
|
||||
int ni = 0;
|
||||
for( int j = map.TopLeft.Y ; j < map.BottomRight.Y; j++ )
|
||||
for( int i = map.TopLeft.X ; i < map.BottomRight.X; i++ )
|
||||
|
||||
for( int j = map.Bounds.Top; j < map.Bounds.Bottom; j++ )
|
||||
for( int i = map.Bounds.Left; i < map.Bounds.Right; i++ )
|
||||
{
|
||||
Sprite tile = tileMapping[map.MapTiles[i, j]];
|
||||
// TODO: The zero below should explicitly refer to the terrain palette, but this code is called
|
||||
// before the palettes are created
|
||||
Util.FastCreateQuad(vertices, indices, Game.CellSize * new float2(i, j), tile, 0, nv, ni, tile.size);
|
||||
// before the palettes are created. Therefore assumes that "terrain" is the first palette to be defined
|
||||
Util.FastCreateQuad(vertices, indices, Game.CellSize * new float2(i, j), tile, Game.modData.Palette.GetPaletteIndex("terrain"), nv, ni, tile.size);
|
||||
nv += 4;
|
||||
ni += 6;
|
||||
|
||||
@@ -57,36 +57,36 @@ namespace OpenRA.Graphics
|
||||
}
|
||||
|
||||
vertexBuffer = Game.Renderer.Device.CreateVertexBuffer( vertices.Length );
|
||||
vertexBuffer.SetData( vertices );
|
||||
vertexBuffer.SetData( vertices, nv );
|
||||
|
||||
indexBuffer = Game.Renderer.Device.CreateIndexBuffer( indices.Length );
|
||||
indexBuffer.SetData( indices );
|
||||
indexBuffer.SetData( indices, ni );
|
||||
}
|
||||
|
||||
public void Draw( Viewport viewport )
|
||||
public void Draw( WorldRenderer wr, Viewport viewport )
|
||||
{
|
||||
int indicesPerRow = map.Width * 6;
|
||||
int verticesPerRow = map.Width * 4;
|
||||
int indicesPerRow = map.Bounds.Width * 6;
|
||||
int verticesPerRow = map.Bounds.Width * 4;
|
||||
|
||||
int visibleRows = (int)(viewport.Height / 24.0f + 2);
|
||||
int visibleRows = (int)(viewport.Height * 1f / Game.CellSize + 2);
|
||||
|
||||
int firstRow = (int)((viewport.Location.Y) / 24.0f - map.YOffset);
|
||||
int firstRow = (int)(viewport.Location.Y * 1f / Game.CellSize - map.Bounds.Top);
|
||||
int lastRow = firstRow + visibleRows;
|
||||
|
||||
if (lastRow < 0 || firstRow > map.Height)
|
||||
if (lastRow < 0 || firstRow > map.Bounds.Height)
|
||||
return;
|
||||
|
||||
if (firstRow < 0) firstRow = 0;
|
||||
if (lastRow > map.Height) lastRow = map.Height;
|
||||
if (lastRow > map.Bounds.Height) lastRow = map.Bounds.Height;
|
||||
|
||||
if (world.LocalPlayer != null && !world.LocalPlayer.Shroud.Disabled && world.LocalPlayer.Shroud.Bounds.HasValue)
|
||||
if (world.LocalPlayer != null && !world.LocalShroud.Disabled && world.LocalShroud.Bounds.HasValue)
|
||||
{
|
||||
var r = world.LocalPlayer.Shroud.Bounds.Value;
|
||||
if (firstRow < r.Top - map.YOffset)
|
||||
firstRow = r.Top - map.YOffset;
|
||||
var r = world.LocalShroud.Bounds.Value;
|
||||
if (firstRow < r.Top - map.Bounds.Top)
|
||||
firstRow = r.Top - map.Bounds.Top;
|
||||
|
||||
if (firstRow > r.Bottom - map.YOffset)
|
||||
firstRow = r.Bottom - map.YOffset;
|
||||
if (firstRow > r.Bottom - map.Bounds.Top)
|
||||
firstRow = r.Bottom - map.Bounds.Top;
|
||||
}
|
||||
|
||||
if( lastRow < firstRow ) lastRow = firstRow;
|
||||
@@ -99,7 +99,7 @@ namespace OpenRA.Graphics
|
||||
PrimitiveType.TriangleList, Game.Renderer.SpriteShader));
|
||||
|
||||
foreach (var r in world.WorldActor.TraitsImplementing<IRenderOverlay>())
|
||||
r.Render();
|
||||
r.Render( wr );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
133
OpenRA.Game/Graphics/Viewport.cs
Normal file → Executable file
133
OpenRA.Game/Graphics/Viewport.cs
Normal file → Executable file
@@ -11,22 +11,21 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.Support;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
public class Viewport
|
||||
{
|
||||
readonly float2 screenSize;
|
||||
float2 scrollPosition;
|
||||
readonly int2 screenSize;
|
||||
int2 scrollPosition;
|
||||
readonly Renderer renderer;
|
||||
readonly Rectangle adjustedMapBounds;
|
||||
|
||||
public float2 Location { get { return scrollPosition; } }
|
||||
|
||||
public int Width { get { return (int)screenSize.X; } }
|
||||
public int Height { get { return (int)screenSize.Y; } }
|
||||
public int Width { get { return screenSize.X; } }
|
||||
public int Height { get { return screenSize.Y; } }
|
||||
|
||||
float cursorFrame = 0f;
|
||||
|
||||
@@ -35,51 +34,67 @@ namespace OpenRA.Graphics
|
||||
|
||||
public void Scroll(float2 delta)
|
||||
{
|
||||
scrollPosition = scrollPosition + delta;
|
||||
this.Scroll(delta, false);
|
||||
}
|
||||
|
||||
public void Scroll(float2 delta, bool ignoreBorders)
|
||||
{
|
||||
var d = delta.ToInt2();
|
||||
var newScrollPosition = scrollPosition + d;
|
||||
|
||||
if(!ignoreBorders)
|
||||
newScrollPosition = this.NormalizeScrollPosition(newScrollPosition);
|
||||
|
||||
scrollPosition = newScrollPosition;
|
||||
}
|
||||
|
||||
private int2 NormalizeScrollPosition(int2 newScrollPosition)
|
||||
{
|
||||
return newScrollPosition.Clamp(adjustedMapBounds);
|
||||
}
|
||||
|
||||
public ScrollDirection GetBlockedDirections()
|
||||
{
|
||||
ScrollDirection blockedDirections = ScrollDirection.None;
|
||||
if(scrollPosition.Y <= adjustedMapBounds.Top)
|
||||
blockedDirections = blockedDirections.Set(ScrollDirection.Up, true);
|
||||
if(scrollPosition.X <= adjustedMapBounds.Left)
|
||||
blockedDirections = blockedDirections.Set(ScrollDirection.Left, true);
|
||||
if(scrollPosition.Y >= adjustedMapBounds.Bottom)
|
||||
blockedDirections = blockedDirections.Set(ScrollDirection.Down, true);
|
||||
if(scrollPosition.X >= adjustedMapBounds.Right)
|
||||
blockedDirections = blockedDirections.Set(ScrollDirection.Right, true);
|
||||
|
||||
return blockedDirections;
|
||||
}
|
||||
|
||||
public Viewport(float2 screenSize, int2 mapStart, int2 mapEnd, Renderer renderer)
|
||||
public Viewport(int2 screenSize, Rectangle mapBounds, Renderer renderer)
|
||||
{
|
||||
this.screenSize = screenSize;
|
||||
this.renderer = renderer;
|
||||
|
||||
this.scrollPosition = Game.CellSize* mapStart;
|
||||
this.adjustedMapBounds = new Rectangle(Game.CellSize*mapBounds.X - screenSize.X/2,
|
||||
Game.CellSize*mapBounds.Y - screenSize.Y/2,
|
||||
Game.CellSize*mapBounds.Width,
|
||||
Game.CellSize*mapBounds.Height);
|
||||
this.scrollPosition = new int2(adjustedMapBounds.Location) + new int2(adjustedMapBounds.Size)/2;
|
||||
}
|
||||
|
||||
public void DrawRegions( World world )
|
||||
public void DrawRegions( WorldRenderer wr, IInputHandler inputHandler )
|
||||
{
|
||||
Timer.Time( "DrawRegions start" );
|
||||
|
||||
renderer.BeginFrame(scrollPosition);
|
||||
world.WorldRenderer.Draw();
|
||||
Timer.Time( "worldRenderer: {0}" );
|
||||
|
||||
Widget.DoDraw(world);
|
||||
Timer.Time( "widgets: {0}" );
|
||||
|
||||
if (wr != null)
|
||||
wr.Draw();
|
||||
|
||||
Widget.DoDraw();
|
||||
var cursorName = Widget.RootWidget.GetCursorOuter(Viewport.LastMousePos) ?? "default";
|
||||
var c = new Cursor(cursorName);
|
||||
c.Draw((int)cursorFrame, Viewport.LastMousePos + Location);
|
||||
Timer.Time( "cursors: {0}" );
|
||||
new Cursor(cursorName).Draw((int)cursorFrame, Viewport.LastMousePos + Location);
|
||||
|
||||
renderer.RgbaSpriteRenderer.Flush();
|
||||
renderer.SpriteRenderer.Flush();
|
||||
renderer.WorldSpriteRenderer.Flush();
|
||||
|
||||
renderer.EndFrame();
|
||||
Timer.Time( "endFrame: {0}" );
|
||||
}
|
||||
|
||||
public void RefreshPalette()
|
||||
{
|
||||
Game.world.WorldRenderer.palette.Update(
|
||||
Game.world.WorldActor.TraitsImplementing<IPaletteModifier>());
|
||||
renderer.EndFrame( inputHandler );
|
||||
}
|
||||
|
||||
public void Tick()
|
||||
{
|
||||
cursorFrame += 0.5f;
|
||||
RefreshPalette();
|
||||
}
|
||||
|
||||
public float2 ViewToWorld(int2 loc)
|
||||
@@ -91,28 +106,52 @@ namespace OpenRA.Graphics
|
||||
return ViewToWorld(mi.Location);
|
||||
}
|
||||
|
||||
public void Center(int2 loc)
|
||||
public void Center(float2 loc)
|
||||
{
|
||||
scrollPosition = (Game.CellSize*loc - .5f * new float2(Width, Height));
|
||||
scrollPosition = this.NormalizeScrollPosition((Game.CellSize*loc - screenSize / 2).ToInt2());
|
||||
}
|
||||
|
||||
public void Center(IEnumerable<Actor> actors)
|
||||
{
|
||||
if (!actors.Any()) return;
|
||||
|
||||
var avgPos = (1f / actors.Count()) * actors
|
||||
var avgPos = actors
|
||||
.Select(a => a.CenterLocation)
|
||||
.Aggregate((a, b) => a + b);
|
||||
|
||||
scrollPosition = (avgPos - .5f * new float2(Width, Height));
|
||||
.Aggregate((a, b) => a + b) / actors.Count();
|
||||
scrollPosition = this.NormalizeScrollPosition((avgPos - screenSize / 2));
|
||||
}
|
||||
|
||||
public Rectangle ViewBounds(World world)
|
||||
{
|
||||
var r = WorldBounds(world);
|
||||
var left = (int)(Game.CellSize * r.Left - Game.viewport.Location.X);
|
||||
var top = (int)(Game.CellSize * r.Top - Game.viewport.Location.Y);
|
||||
var right = left + (int)(Game.CellSize * r.Width);
|
||||
var bottom = top + (int)(Game.CellSize * r.Height);
|
||||
|
||||
if (left < 0) left = 0;
|
||||
if (top < 0) top = 0;
|
||||
if (right > Game.viewport.Width) right = Game.viewport.Width;
|
||||
if (bottom > Game.viewport.Height) bottom = Game.viewport.Height;
|
||||
return new Rectangle(left, top, right - left, bottom - top);
|
||||
}
|
||||
|
||||
public Rectangle? ShroudBounds()
|
||||
int2 cachedScroll = new int2(int.MaxValue, int.MaxValue);
|
||||
Rectangle cachedRect;
|
||||
|
||||
public Rectangle WorldBounds(World world)
|
||||
{
|
||||
var localPlayer = Game.world.LocalPlayer;
|
||||
if (localPlayer == null) return null;
|
||||
if (localPlayer.Shroud.Disabled) return null;
|
||||
return localPlayer.Shroud.Bounds;
|
||||
if (cachedScroll != scrollPosition)
|
||||
{
|
||||
int2 boundary = new int2(1,1); // Add a curtain of cells around the viewport to account for rounding errors
|
||||
var tl = ViewToWorld(int2.Zero).ToInt2() - boundary;
|
||||
var br = ViewToWorld(new int2(Width, Height)).ToInt2() + boundary;
|
||||
cachedRect = Rectangle.Intersect(Rectangle.FromLTRB(tl.X, tl.Y, br.X, br.Y), world.Map.Bounds);
|
||||
cachedScroll = scrollPosition;
|
||||
}
|
||||
|
||||
var b = world.LocalShroud.Bounds;
|
||||
return (b.HasValue) ? Rectangle.Intersect(cachedRect, b.Value) : cachedRect;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,18 +19,23 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
public class WorldRenderer
|
||||
{
|
||||
readonly World world;
|
||||
public readonly World world;
|
||||
internal readonly TerrainRenderer terrainRenderer;
|
||||
internal readonly UiOverlay uiOverlay;
|
||||
internal readonly ShroudRenderer shroudRenderer;
|
||||
|
||||
public readonly UiOverlay uiOverlay;
|
||||
internal readonly HardwarePalette palette;
|
||||
|
||||
internal WorldRenderer(World world)
|
||||
{
|
||||
this.world = world;
|
||||
|
||||
this.palette = Game.modData.Palette;
|
||||
foreach( var pal in world.traitDict.ActorsWithTraitMultiple<IPalette>( world ) )
|
||||
pal.Trait.InitPalette( this );
|
||||
|
||||
terrainRenderer = new TerrainRenderer(world, this);
|
||||
shroudRenderer = new ShroudRenderer(world);
|
||||
uiOverlay = new UiOverlay();
|
||||
palette = new HardwarePalette(world.Map);
|
||||
}
|
||||
|
||||
public int GetPaletteIndex(string name) { return palette.GetPaletteIndex(name); }
|
||||
@@ -41,40 +46,13 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
public int Compare(Renderable x, Renderable y)
|
||||
{
|
||||
var result = x.ZOffset.CompareTo(y.ZOffset);
|
||||
if (result == 0)
|
||||
result = x.Pos.Y.CompareTo(y.Pos.Y);
|
||||
|
||||
return result;
|
||||
return (x.Z + x.ZOffset).CompareTo(y.Z + y.ZOffset);
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle GetBoundsRect()
|
||||
IEnumerable<Renderable> SpritesToRender()
|
||||
{
|
||||
if (world.LocalPlayer != null && !world.LocalPlayer.Shroud.Disabled && world.LocalPlayer.Shroud.Bounds.HasValue)
|
||||
{
|
||||
var r = world.LocalPlayer.Shroud.Bounds.Value;
|
||||
|
||||
var left = (int)(Game.CellSize * r.Left - Game.viewport.Location.X);
|
||||
var top = (int)(Game.CellSize * r.Top - Game.viewport.Location.Y);
|
||||
var right = left + (int)(Game.CellSize * r.Width);
|
||||
var bottom = top + (int)(Game.CellSize * r.Height);
|
||||
|
||||
if (left < 0) left = 0;
|
||||
if (top < 0) top = 0;
|
||||
if (right > Game.viewport.Width) right = Game.viewport.Width;
|
||||
if (bottom > Game.viewport.Height) bottom = Game.viewport.Height;
|
||||
|
||||
return new Rectangle(left, top, right - left, bottom - top);
|
||||
}
|
||||
else
|
||||
return new Rectangle(0, 0, Game.viewport.Width, Game.viewport.Height);
|
||||
}
|
||||
|
||||
Renderable[] worldSprites = { };
|
||||
public void Tick()
|
||||
{
|
||||
var bounds = GetBoundsRect();
|
||||
var bounds = Game.viewport.ViewBounds(world);
|
||||
var comparer = new SpriteComparer();
|
||||
|
||||
bounds.Offset((int)Game.viewport.Location.X, (int)Game.viewport.Location.Y);
|
||||
@@ -88,38 +66,52 @@ namespace OpenRA.Graphics
|
||||
|
||||
var effects = world.Effects.SelectMany(e => e.Render());
|
||||
|
||||
worldSprites = renderables.Concat(effects).ToArray();
|
||||
return renderables.Concat(effects);
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
var bounds = GetBoundsRect();
|
||||
Game.Renderer.Device.EnableScissor(bounds.Left, bounds.Top, bounds.Width, bounds.Height);
|
||||
RefreshPalette();
|
||||
var bounds = Game.viewport.ViewBounds(world);
|
||||
Game.Renderer.EnableScissor(bounds.Left, bounds.Top, bounds.Width, bounds.Height);
|
||||
|
||||
terrainRenderer.Draw(Game.viewport);
|
||||
terrainRenderer.Draw(this, Game.viewport);
|
||||
foreach (var a in world.traitDict.ActorsWithTraitMultiple<IRenderAsTerrain>(world))
|
||||
foreach (var r in a.Trait.RenderAsTerrain(a.Actor))
|
||||
r.Sprite.DrawAt(r.Pos, this.GetPaletteIndex(r.Palette), r.Scale);
|
||||
|
||||
foreach (var a in world.Selection.Actors)
|
||||
if (!a.Destroyed)
|
||||
foreach (var t in a.TraitsImplementing<IPreRenderSelection>())
|
||||
t.RenderBeforeWorld(this, a);
|
||||
|
||||
Game.Renderer.Flush();
|
||||
|
||||
if (world.OrderGenerator != null)
|
||||
world.OrderGenerator.RenderBeforeWorld(this, world);
|
||||
|
||||
foreach (var image in SpritesToRender() )
|
||||
image.Sprite.DrawAt(image.Pos, this.GetPaletteIndex(image.Palette), image.Scale);
|
||||
uiOverlay.Draw(this, world);
|
||||
|
||||
// added for contrails
|
||||
foreach (var a in world.Actors)
|
||||
if (!a.Destroyed)
|
||||
foreach (var t in a.TraitsImplementing<IPostRender>())
|
||||
t.RenderAfterWorld(this, a);
|
||||
|
||||
if (world.OrderGenerator != null)
|
||||
world.OrderGenerator.RenderBeforeWorld(world);
|
||||
world.OrderGenerator.RenderAfterWorld(this, world);
|
||||
|
||||
Game.Renderer.SpriteRenderer.Flush();
|
||||
Game.Renderer.LineRenderer.Flush();
|
||||
shroudRenderer.Draw( this );
|
||||
Game.Renderer.DisableScissor();
|
||||
|
||||
foreach (var a in world.Selection.Actors)
|
||||
if (!a.Destroyed)
|
||||
foreach (var t in a.TraitsImplementing<IPostRenderSelection>())
|
||||
t.RenderAfterWorld(this, a);
|
||||
|
||||
foreach (var image in worldSprites)
|
||||
Game.Renderer.SpriteRenderer.DrawSprite(image.Sprite, image.Pos, image.Palette);
|
||||
uiOverlay.Draw(world);
|
||||
Game.Renderer.SpriteRenderer.Flush();
|
||||
|
||||
if (world.OrderGenerator != null)
|
||||
world.OrderGenerator.RenderAfterWorld(world);
|
||||
|
||||
if (world.LocalPlayer != null)
|
||||
world.LocalPlayer.Shroud.Draw();
|
||||
|
||||
Game.Renderer.SpriteRenderer.Flush();
|
||||
|
||||
Game.Renderer.Device.DisableScissor();
|
||||
|
||||
Game.Renderer.LineRenderer.Flush();
|
||||
Game.Renderer.Flush();
|
||||
}
|
||||
|
||||
void DrawBox(RectangleF r, Color color)
|
||||
@@ -133,23 +125,9 @@ namespace OpenRA.Graphics
|
||||
Game.Renderer.LineRenderer.DrawLine(a, a + c, color, color);
|
||||
}
|
||||
|
||||
void DrawBins(RectangleF bounds)
|
||||
{
|
||||
DrawBox(bounds, Color.Red);
|
||||
if (world.LocalPlayer != null)
|
||||
DrawBox(world.LocalPlayer.Shroud.Bounds.Value, Color.Blue);
|
||||
|
||||
for (var j = 0; j < world.Map.MapSize.Y;
|
||||
j += world.WorldActor.Info.Traits.Get<SpatialBinsInfo>().BinSize)
|
||||
{
|
||||
Game.Renderer.LineRenderer.DrawLine(new float2(0, j * 24), new float2(world.Map.MapSize.X * 24, j * 24), Color.Black, Color.Black);
|
||||
Game.Renderer.LineRenderer.DrawLine(new float2(j * 24, 0), new float2(j * 24, world.Map.MapSize.Y * 24), Color.Black, Color.Black);
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawSelectionBox(Actor selectedUnit, Color c)
|
||||
{
|
||||
var bounds = selectedUnit.GetBounds(true);
|
||||
var bounds = selectedUnit.GetBounds(false);
|
||||
|
||||
var xy = new float2(bounds.Left, bounds.Top);
|
||||
var Xy = new float2(bounds.Right, bounds.Top);
|
||||
@@ -187,7 +165,7 @@ namespace OpenRA.Graphics
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawRangeCircle(Color c, float2 location, int range)
|
||||
public void DrawRangeCircle(Color c, float2 location, float range)
|
||||
{
|
||||
var prev = location + Game.CellSize * range * float2.FromAngle(0);
|
||||
for (var i = 1; i <= 32; i++)
|
||||
@@ -197,5 +175,10 @@ namespace OpenRA.Graphics
|
||||
prev = pos;
|
||||
}
|
||||
}
|
||||
|
||||
public void RefreshPalette()
|
||||
{
|
||||
palette.Update( world.WorldActor.TraitsImplementing<IPaletteModifier>() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
52
OpenRA.Game/InputHandler.cs
Executable file
52
OpenRA.Game/InputHandler.cs
Executable file
@@ -0,0 +1,52 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using OpenRA.Widgets;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public class NullInputHandler : IInputHandler
|
||||
{
|
||||
// ignore all input
|
||||
public void ModifierKeys( Modifiers mods ) { }
|
||||
public void OnKeyInput( KeyInput input ) { }
|
||||
public void OnMouseInput( MouseInput input ) { }
|
||||
}
|
||||
|
||||
public class DefaultInputHandler : IInputHandler
|
||||
{
|
||||
readonly World world;
|
||||
public DefaultInputHandler( World world )
|
||||
{
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
public void ModifierKeys( Modifiers mods )
|
||||
{
|
||||
Game.HandleModifierKeys( mods );
|
||||
}
|
||||
|
||||
public void OnKeyInput( KeyInput input )
|
||||
{
|
||||
Sync.CheckSyncUnchanged( world, () =>
|
||||
{
|
||||
Widget.HandleKeyPress( input );
|
||||
} );
|
||||
}
|
||||
|
||||
public void OnMouseInput( MouseInput input )
|
||||
{
|
||||
Sync.CheckSyncUnchanged( world, () =>
|
||||
{
|
||||
Widget.HandleInput( input );
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
193
OpenRA.Game/Map.cs
Executable file → Normal file
193
OpenRA.Game/Map.cs
Executable file → Normal file
@@ -16,68 +16,65 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography;
|
||||
using OpenRA.FileFormats;
|
||||
using System.Text;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public class Map
|
||||
public class Map : MapStub
|
||||
{
|
||||
public IFolder Package;
|
||||
public string Uid;
|
||||
|
||||
// Yaml map data
|
||||
[FieldLoader.Load] public bool Selectable = true;
|
||||
[FieldLoader.Load] public int MapFormat;
|
||||
[FieldLoader.Load] public string Title;
|
||||
[FieldLoader.Load] public string Description;
|
||||
[FieldLoader.Load] public string Author;
|
||||
[FieldLoader.Load] public int PlayerCount;
|
||||
[FieldLoader.Load] public string Tileset;
|
||||
|
||||
public Dictionary<string, PlayerReference> Players = new Dictionary<string, PlayerReference>();
|
||||
public Dictionary<string, ActorReference> Actors = new Dictionary<string, ActorReference>();
|
||||
public List<SmudgeReference> Smudges = new List<SmudgeReference>();
|
||||
public Dictionary<string, int2> Waypoints = new Dictionary<string, int2>();
|
||||
|
||||
// Rules overrides
|
||||
|
||||
// Rules overrides
|
||||
public List<MiniYamlNode> Rules = new List<MiniYamlNode>();
|
||||
|
||||
// Sequences overrides
|
||||
public List<MiniYamlNode> Sequences = new List<MiniYamlNode>();
|
||||
|
||||
// Weapon overrides
|
||||
public List<MiniYamlNode> Weapons = new List<MiniYamlNode>();
|
||||
|
||||
// Voices overrides
|
||||
public List<MiniYamlNode> Voices = new List<MiniYamlNode>();
|
||||
|
||||
// Binary map data
|
||||
public byte TileFormat = 1;
|
||||
[FieldLoader.Load] public int2 MapSize;
|
||||
|
||||
[FieldLoader.Load] public int2 TopLeft;
|
||||
[FieldLoader.Load] public int2 BottomRight;
|
||||
|
||||
public TileReference<ushort, byte>[,] MapTiles;
|
||||
public TileReference<byte, byte>[,] MapResources;
|
||||
public string [,] CustomTerrain;
|
||||
|
||||
// Temporary compat hacks
|
||||
public int XOffset { get { return TopLeft.X; } }
|
||||
public int YOffset { get { return TopLeft.Y; } }
|
||||
public int Width { get { return BottomRight.X - TopLeft.X; } }
|
||||
public int Height { get { return BottomRight.Y - TopLeft.Y; } }
|
||||
public string Theater { get { return Tileset; } }
|
||||
public IEnumerable<int2> SpawnPoints { get { return Waypoints.Select(kv => kv.Value); } }
|
||||
public Rectangle Bounds { get { return Rectangle.FromLTRB(TopLeft.X, TopLeft.Y, BottomRight.X, BottomRight.Y); } }
|
||||
|
||||
public Map()
|
||||
{
|
||||
MapSize = new int2(1, 1);
|
||||
MapResources = new TileReference<byte, byte>[1, 1];
|
||||
MapTiles = new TileReference<ushort, byte>[1, 1]
|
||||
{ { new TileReference<ushort, byte> {
|
||||
type = (ushort)0xffffu,
|
||||
image = (byte)0xffu,
|
||||
index = (byte)0xffu } } };
|
||||
|
||||
PlayerCount = 0;
|
||||
TopLeft = new int2(0, 0);
|
||||
BottomRight = new int2(0, 0);
|
||||
|
||||
Title = "Name your map here";
|
||||
Description = "Describe your map here";
|
||||
Author = "Your name here";
|
||||
// Do nothing; not a valid map (editor hack)
|
||||
}
|
||||
|
||||
public static Map FromTileset(string tileset)
|
||||
{
|
||||
var tile = OpenRA.Rules.TileSets[tileset].Templates.First();
|
||||
Map map = new Map()
|
||||
{
|
||||
Title = "Name your map here",
|
||||
Description = "Describe your map here",
|
||||
Author = "Your name here",
|
||||
MapSize = new int2(1, 1),
|
||||
PlayerCount = 0,
|
||||
Tileset = tileset,
|
||||
MapResources = new TileReference<byte, byte>[1, 1],
|
||||
MapTiles = new TileReference<ushort, byte>[1, 1]
|
||||
{ { new TileReference<ushort, byte> {
|
||||
type = tile.Key,
|
||||
image = (byte)(tile.Value.PickAny ? 0xffu : 0),
|
||||
index = (byte)(tile.Value.PickAny ? 0xffu : 0) }
|
||||
} },
|
||||
};
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
class Format2ActorReference
|
||||
@@ -87,21 +84,15 @@ namespace OpenRA
|
||||
public int2 Location = int2.Zero;
|
||||
public string Owner = null;
|
||||
}
|
||||
|
||||
public Map(IFolder package)
|
||||
|
||||
public Map(string path)
|
||||
: base(path)
|
||||
{
|
||||
Package = package;
|
||||
var yaml = new MiniYaml( null, MiniYaml.FromStream( Package.GetContent( "map.yaml" ) ) );
|
||||
var yaml = new MiniYaml( null, MiniYaml.FromStream( Container.GetContent( "map.yaml" ) ) );
|
||||
|
||||
// 'Simple' metadata
|
||||
FieldLoader.Load( this, yaml );
|
||||
|
||||
// Waypoints
|
||||
foreach (var wp in yaml.NodesDict["Waypoints"].NodesDict)
|
||||
{
|
||||
string[] loc = wp.Value.Value.Split(',');
|
||||
Waypoints.Add(wp.Key, new int2(int.Parse(loc[0]), int.Parse(loc[1])));
|
||||
}
|
||||
|
||||
// Players & Actors -- this has changed several times.
|
||||
// - Be backwards compatible wherever possible.
|
||||
@@ -148,6 +139,7 @@ namespace OpenRA
|
||||
} break;
|
||||
|
||||
case 3:
|
||||
case 4:
|
||||
{
|
||||
foreach (var kv in yaml.NodesDict["Players"].NodesDict)
|
||||
{
|
||||
@@ -177,7 +169,16 @@ namespace OpenRA
|
||||
};
|
||||
Players.Add(p.Name, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Color1/Color2 -> ColorRamp
|
||||
if (MapFormat == 3)
|
||||
foreach (var mp in Players)
|
||||
mp.Value.ColorRamp = new ColorRamp(
|
||||
(byte)((mp.Value.Color.GetHue() / 360.0f) * 255),
|
||||
(byte)(mp.Value.Color.GetSaturation() * 255),
|
||||
(byte)(mp.Value.Color.GetBrightness() * 255),
|
||||
(byte)(mp.Value.Color2.GetBrightness() * 255));
|
||||
|
||||
// Smudges
|
||||
foreach (var kv in yaml.NodesDict["Smudges"].NodesDict)
|
||||
@@ -190,19 +191,29 @@ namespace OpenRA
|
||||
// Rules
|
||||
Rules = yaml.NodesDict["Rules"].Nodes;
|
||||
|
||||
// Sequences
|
||||
Sequences = (yaml.NodesDict.ContainsKey("Sequences")) ? yaml.NodesDict["Sequences"].Nodes : new List<MiniYamlNode>();
|
||||
|
||||
// Weapons
|
||||
Weapons = (yaml.NodesDict.ContainsKey("Weapons")) ? yaml.NodesDict["Weapons"].Nodes : new List<MiniYamlNode>();
|
||||
|
||||
// Voices
|
||||
Voices = (yaml.NodesDict.ContainsKey("Voices")) ? yaml.NodesDict["Voices"].Nodes : new List<MiniYamlNode>();
|
||||
|
||||
CustomTerrain = new string[MapSize.X, MapSize.Y];
|
||||
LoadUid();
|
||||
LoadBinaryData();
|
||||
}
|
||||
|
||||
public void Save(string filepath)
|
||||
{
|
||||
MapFormat = 3;
|
||||
public void Save(string toPath)
|
||||
{
|
||||
Console.WriteLine("Saving map to path {0}",toPath);
|
||||
// Todo: save to a zip file in the support dir by default
|
||||
MapFormat = 4;
|
||||
|
||||
var root = new List<MiniYamlNode>();
|
||||
foreach (var field in new string[] {"Selectable", "MapFormat", "Title", "Description", "Author", "PlayerCount", "Tileset", "MapSize", "TopLeft", "BottomRight"})
|
||||
foreach (var field in new string[] {"Selectable", "MapFormat", "Title", "Description", "Author", "PlayerCount", "Tileset", "MapSize", "TopLeft", "BottomRight", "UseAsShellmap", "Type"})
|
||||
{
|
||||
FieldInfo f = this.GetType().GetField(field);
|
||||
var f = this.GetType().GetField(field);
|
||||
if (f.GetValue(this) == null) continue;
|
||||
root.Add( new MiniYamlNode( field, FieldSaver.FormatValue( this, f ) ) );
|
||||
}
|
||||
@@ -217,13 +228,30 @@ namespace OpenRA
|
||||
x.Key,
|
||||
x.Value.Save() ) ).ToList() ) );
|
||||
|
||||
root.Add( new MiniYamlNode( "Waypoints", MiniYaml.FromDictionary<string, int2>( Waypoints ) ) );
|
||||
root.Add( new MiniYamlNode( "Smudges", MiniYaml.FromList<SmudgeReference>( Smudges ) ) );
|
||||
root.Add( new MiniYamlNode( "Rules", null, Rules ) );
|
||||
|
||||
SaveBinaryData(Path.Combine(filepath, "map.bin"));
|
||||
root.WriteToFile(Path.Combine(filepath, "map.yaml"));
|
||||
SaveUid(Path.Combine(filepath, "map.uid"));
|
||||
root.Add(new MiniYamlNode("Waypoints", MiniYaml.FromDictionary<string, int2>( Waypoints )));
|
||||
root.Add(new MiniYamlNode("Smudges", MiniYaml.FromList<SmudgeReference>( Smudges )));
|
||||
root.Add(new MiniYamlNode("Rules", null, Rules));
|
||||
root.Add(new MiniYamlNode("Sequences", null, Sequences));
|
||||
root.Add(new MiniYamlNode("Weapons", null, Weapons));
|
||||
root.Add(new MiniYamlNode("Voices", null, Voices));
|
||||
|
||||
Dictionary<string, byte[]> entries = new Dictionary<string, byte[]>();
|
||||
entries.Add("map.bin", SaveBinaryData());
|
||||
var s = root.WriteToString();
|
||||
entries.Add("map.yaml", Encoding.UTF8.GetBytes(s));
|
||||
|
||||
// Saving the map to a new location
|
||||
if (toPath != Path)
|
||||
{
|
||||
Path = toPath;
|
||||
|
||||
// Create a new map package
|
||||
// TODO: Add other files (resources, rules) to the entries list
|
||||
Container = FileSystem.CreatePackage(Path, int.MaxValue, entries);
|
||||
}
|
||||
|
||||
// Update existing package
|
||||
Container.Write(entries);
|
||||
}
|
||||
|
||||
static byte ReadByte(Stream s)
|
||||
@@ -244,7 +272,7 @@ namespace OpenRA
|
||||
|
||||
public void LoadBinaryData()
|
||||
{
|
||||
using (var dataStream = Package.GetContent("map.bin"))
|
||||
using (var dataStream = Container.GetContent("map.bin"))
|
||||
{
|
||||
if (ReadByte(dataStream) != 1)
|
||||
throw new InvalidDataException("Unknown binary map format");
|
||||
@@ -276,9 +304,9 @@ namespace OpenRA
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveBinaryData(string filepath)
|
||||
public byte[] SaveBinaryData()
|
||||
{
|
||||
using (var dataStream = File.Create(filepath + ".tmp"))
|
||||
MemoryStream dataStream = new MemoryStream();
|
||||
using (var writer = new BinaryWriter(dataStream))
|
||||
{
|
||||
// File header consists of a version byte, followed by 2 ushorts for width and height
|
||||
@@ -302,27 +330,7 @@ namespace OpenRA
|
||||
writer.Write(MapResources[i, j].index);
|
||||
}
|
||||
}
|
||||
File.Delete(filepath);
|
||||
File.Move(filepath + ".tmp", filepath);
|
||||
}
|
||||
|
||||
public void LoadUid()
|
||||
{
|
||||
Uid = Package.GetContent("map.uid").ReadAllText();
|
||||
}
|
||||
|
||||
public void SaveUid(string filename)
|
||||
{
|
||||
// UID is calculated by taking an SHA1 of the yaml and binary data
|
||||
// Read the relevant data into a buffer
|
||||
var data = Package.GetContent("map.yaml").ReadAllBytes()
|
||||
.Concat(Package.GetContent("map.bin").ReadAllBytes()).ToArray();
|
||||
|
||||
// Take the SHA1
|
||||
using (var csp = SHA1.Create())
|
||||
Uid = new string(csp.ComputeHash(data).SelectMany(a => a.ToString("x2")).ToArray());
|
||||
|
||||
File.WriteAllText(filename, Uid);
|
||||
return dataStream.ToArray();
|
||||
}
|
||||
|
||||
public bool IsInMap(int2 xy)
|
||||
@@ -332,7 +340,7 @@ namespace OpenRA
|
||||
|
||||
public bool IsInMap(int x, int y)
|
||||
{
|
||||
return (x >= TopLeft.X && y >= TopLeft.Y && x < BottomRight.X && y < BottomRight.Y);
|
||||
return Bounds.Contains(x,y);
|
||||
}
|
||||
|
||||
static T[,] ResizeArray<T>(T[,] ts, T t, int width, int height)
|
||||
@@ -351,5 +359,12 @@ namespace OpenRA
|
||||
MapResources = ResizeArray(MapResources, MapResources[0, 0], width, height);
|
||||
MapSize = new int2(width, height);
|
||||
}
|
||||
|
||||
public void ResizeCordon(int left, int top, int right, int bottom)
|
||||
{
|
||||
TopLeft = new int2(left, top);
|
||||
BottomRight = new int2(right, bottom);
|
||||
Bounds = Rectangle.FromLTRB(TopLeft.X, TopLeft.Y, BottomRight.X, BottomRight.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,82 +1,122 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Support;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public class ModData
|
||||
{
|
||||
public readonly Manifest Manifest;
|
||||
public readonly ObjectCreator ObjectCreator;
|
||||
public readonly SheetBuilder SheetBuilder;
|
||||
public readonly CursorSheetBuilder CursorSheetBuilder;
|
||||
public readonly Dictionary<string, MapStub> AvailableMaps;
|
||||
public ILoadScreen LoadScreen = null;
|
||||
|
||||
public ModData( params string[] mods )
|
||||
{
|
||||
Manifest = new Manifest( mods );
|
||||
ObjectCreator = new ObjectCreator( Manifest );
|
||||
LoadScreen = ObjectCreator.CreateObject<ILoadScreen>(Manifest.LoadScreen);
|
||||
LoadScreen.Init();
|
||||
LoadScreen.Display();
|
||||
|
||||
FileSystem.LoadFromManifest( Manifest );
|
||||
ChromeProvider.Initialize( Manifest.Chrome );
|
||||
SheetBuilder = new SheetBuilder( TextureChannel.Red );
|
||||
CursorSheetBuilder = new CursorSheetBuilder( this );
|
||||
AvailableMaps = FindMaps( mods );
|
||||
}
|
||||
|
||||
// TODO: Do this nicer
|
||||
Dictionary<string, MapStub> FindMaps(string[] mods)
|
||||
{
|
||||
var paths = new[] { "maps/" }.Concat(mods.Select(m => "mods/" + m + "/maps/"))
|
||||
.Where(p => Directory.Exists(p))
|
||||
.SelectMany(p => Directory.GetDirectories(p)).ToList();
|
||||
|
||||
return paths.Select(p => new MapStub(new Folder(p))).ToDictionary(m => m.Uid);
|
||||
}
|
||||
|
||||
string cachedTheatre = null;
|
||||
public Map PrepareMap(string uid)
|
||||
{
|
||||
LoadScreen.Display();
|
||||
|
||||
if (!AvailableMaps.ContainsKey(uid))
|
||||
throw new InvalidDataException("Invalid map uid: {0}".F(uid));
|
||||
|
||||
Timer.Time("----PrepareMap");
|
||||
var map = new Map(AvailableMaps[uid].Package);
|
||||
Timer.Time( "Map: {0}" );
|
||||
|
||||
Rules.LoadRules(Manifest, map);
|
||||
Timer.Time( "Rules: {0}" );
|
||||
|
||||
if (map.Theater != cachedTheatre)
|
||||
{
|
||||
SpriteSheetBuilder.Initialize( Rules.TileSets[map.Tileset] );
|
||||
SequenceProvider.Initialize(Manifest.Sequences);
|
||||
Timer.Time("SSB, SeqProv: {0}");
|
||||
cachedTheatre = map.Theater;
|
||||
}
|
||||
Timer.Time("----end PrepareMap");
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
public interface ILoadScreen { void Display(); void Init(); }
|
||||
}
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public class ModData
|
||||
{
|
||||
public readonly Manifest Manifest;
|
||||
public readonly ObjectCreator ObjectCreator;
|
||||
public Dictionary<string, MapStub> AvailableMaps {get; private set;}
|
||||
public readonly WidgetLoader WidgetLoader;
|
||||
public ILoadScreen LoadScreen = null;
|
||||
public SheetBuilder SheetBuilder;
|
||||
public CursorSheetBuilder CursorSheetBuilder;
|
||||
public SpriteLoader SpriteLoader;
|
||||
public HardwarePalette Palette { get; private set; }
|
||||
IFolder previousMapMount = null;
|
||||
|
||||
public ModData( params string[] mods )
|
||||
{
|
||||
Manifest = new Manifest( mods );
|
||||
ObjectCreator = new ObjectCreator( Manifest );
|
||||
LoadScreen = ObjectCreator.CreateObject<ILoadScreen>(Manifest.LoadScreen);
|
||||
LoadScreen.Init();
|
||||
LoadScreen.Display();
|
||||
WidgetLoader = new WidgetLoader( this );
|
||||
}
|
||||
|
||||
public void ReloadMaps()
|
||||
{
|
||||
AvailableMaps = FindMaps( Manifest.Mods );
|
||||
}
|
||||
|
||||
public void LoadInitialAssets()
|
||||
{
|
||||
// all this manipulation of static crap here is nasty and breaks
|
||||
// horribly when you use ModData in unexpected ways.
|
||||
FileSystem.UnmountAll();
|
||||
foreach (var dir in Manifest.Folders)
|
||||
FileSystem.Mount(dir);
|
||||
|
||||
ReloadMaps();
|
||||
Palette = new HardwarePalette();
|
||||
ChromeProvider.Initialize( Manifest.Chrome );
|
||||
SheetBuilder = new SheetBuilder( TextureChannel.Red );
|
||||
CursorSheetBuilder = new CursorSheetBuilder( this );
|
||||
CursorProvider.Initialize(Manifest.Cursors);
|
||||
Palette.Update(new IPaletteModifier[]{});
|
||||
}
|
||||
|
||||
public Map PrepareMap(string uid)
|
||||
{
|
||||
LoadScreen.Display();
|
||||
if (!AvailableMaps.ContainsKey(uid))
|
||||
throw new InvalidDataException("Invalid map uid: {0}".F(uid));
|
||||
var map = new Map(AvailableMaps[uid].Path);
|
||||
|
||||
// Maps may contain custom assets
|
||||
// TODO: why are they lowest priority? they should be highest.
|
||||
if (previousMapMount != null) FileSystem.Unmount(previousMapMount);
|
||||
previousMapMount = FileSystem.OpenPackage(map.Path, int.MaxValue);
|
||||
FileSystem.Mount(previousMapMount);
|
||||
|
||||
// Reinit all our assets
|
||||
LoadInitialAssets();
|
||||
foreach (var pkg in Manifest.Packages)
|
||||
FileSystem.Mount(pkg);
|
||||
|
||||
Rules.LoadRules(Manifest, map);
|
||||
SpriteLoader = new SpriteLoader( Rules.TileSets[map.Tileset].Extensions, SheetBuilder );
|
||||
SequenceProvider.Initialize(Manifest.Sequences, map.Sequences);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
public static IEnumerable<string> FindMapsIn(string dir)
|
||||
{
|
||||
string[] NoMaps = { };
|
||||
|
||||
if (!Directory.Exists(dir))
|
||||
return NoMaps;
|
||||
|
||||
return Directory.GetDirectories(dir)
|
||||
.Concat(Directory.GetFiles(dir, "*.zip"))
|
||||
.Concat(Directory.GetFiles(dir, "*.oramap"));
|
||||
}
|
||||
|
||||
Dictionary<string, MapStub> FindMaps(string[] mods)
|
||||
{
|
||||
var paths = mods.SelectMany(p => FindMapsIn("mods{0}{1}{0}maps{0}".F(Path.DirectorySeparatorChar, p)))
|
||||
.Concat(mods.SelectMany(p => FindMapsIn("{1}maps{0}{2}{0}".F(Path.DirectorySeparatorChar, Game.SupportDir, p))));
|
||||
|
||||
Dictionary<string, MapStub> ret = new Dictionary<string, MapStub>();
|
||||
foreach (var path in paths)
|
||||
{
|
||||
var map = new MapStub(path);
|
||||
if (ret.ContainsKey(map.Uid))
|
||||
System.Console.WriteLine("Ignoring duplicate map: {0}", path);
|
||||
else
|
||||
ret.Add(map.Uid, map);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public interface ILoadScreen { void Display(); void Init(); }
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ using OpenRA.Support;
|
||||
|
||||
namespace OpenRA.Network
|
||||
{
|
||||
enum ConnectionState
|
||||
public enum ConnectionState
|
||||
{
|
||||
PreConnecting,
|
||||
NotConnected,
|
||||
@@ -26,11 +26,13 @@ namespace OpenRA.Network
|
||||
Connected,
|
||||
}
|
||||
|
||||
interface IConnection
|
||||
public interface IConnection : IDisposable
|
||||
{
|
||||
int LocalClientId { get; }
|
||||
ConnectionState ConnectionState { get; }
|
||||
void Send( byte[] packet );
|
||||
void Send( int frame, List<byte[]> orders );
|
||||
void SendImmediate( List<byte[]> orders );
|
||||
void SendSync( int frame, byte[] syncData );
|
||||
void Receive( Action<int, byte[]> packetFn );
|
||||
}
|
||||
|
||||
@@ -53,7 +55,33 @@ namespace OpenRA.Network
|
||||
get { return ConnectionState.PreConnecting; }
|
||||
}
|
||||
|
||||
public virtual void Send( byte[] packet )
|
||||
public virtual void Send( int frame, List<byte[]> orders )
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
ms.Write( BitConverter.GetBytes( frame ) );
|
||||
foreach( var o in orders )
|
||||
ms.Write( o );
|
||||
Send( ms.ToArray() );
|
||||
}
|
||||
|
||||
public virtual void SendImmediate( List<byte[]> orders )
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
ms.Write( BitConverter.GetBytes( (int)0 ) );
|
||||
foreach( var o in orders )
|
||||
ms.Write( o );
|
||||
Send( ms.ToArray() );
|
||||
}
|
||||
|
||||
public virtual void SendSync( int frame, byte[] syncData )
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
ms.Write( BitConverter.GetBytes( frame ) );
|
||||
ms.Write( syncData );
|
||||
Send( ms.ToArray() );
|
||||
}
|
||||
|
||||
protected virtual void Send( byte[] packet )
|
||||
{
|
||||
if( packet.Length == 0 )
|
||||
throw new NotImplementedException();
|
||||
@@ -73,9 +101,11 @@ namespace OpenRA.Network
|
||||
foreach( var p in packets )
|
||||
packetFn( p.FromClient, p.Data );
|
||||
}
|
||||
|
||||
public virtual void Dispose() { }
|
||||
}
|
||||
|
||||
class NetworkConnection : EchoConnection, IDisposable
|
||||
class NetworkConnection : EchoConnection
|
||||
{
|
||||
TcpClient socket;
|
||||
int clientId;
|
||||
@@ -112,12 +142,13 @@ namespace OpenRA.Network
|
||||
receivedPackets.Add( new ReceivedPacket { FromClient = client, Data = buf } );
|
||||
}
|
||||
}
|
||||
catch( SocketException )
|
||||
catch { }
|
||||
finally
|
||||
{
|
||||
connectionState = ConnectionState.NotConnected;
|
||||
if( socket != null )
|
||||
socket.Close();
|
||||
}
|
||||
catch ( IOException ) { socket.Close(); }
|
||||
catch (ThreadAbortException ) { socket.Close(); }
|
||||
}
|
||||
) { IsBackground = true };
|
||||
t.Start();
|
||||
@@ -126,23 +157,42 @@ namespace OpenRA.Network
|
||||
public override int LocalClientId { get { return clientId; } }
|
||||
public override ConnectionState ConnectionState { get { return connectionState; } }
|
||||
|
||||
public override void Send( byte[] packet )
|
||||
List<byte[]> queuedSyncPackets = new List<byte[]>();
|
||||
|
||||
public override void SendSync( int frame, byte[] syncData )
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
ms.Write( BitConverter.GetBytes( frame ) );
|
||||
ms.Write( syncData );
|
||||
queuedSyncPackets.Add( ms.ToArray() );
|
||||
}
|
||||
|
||||
protected override void Send( byte[] packet )
|
||||
{
|
||||
base.Send( packet );
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
var ms = new MemoryStream();
|
||||
ms.Write(BitConverter.GetBytes((int)packet.Length));
|
||||
ms.Write(packet);
|
||||
foreach( var q in queuedSyncPackets )
|
||||
{
|
||||
ms.Write( BitConverter.GetBytes( (int)q.Length ) );
|
||||
ms.Write( q );
|
||||
base.Send( q );
|
||||
}
|
||||
queuedSyncPackets.Clear();
|
||||
ms.WriteTo(socket.GetStream());
|
||||
|
||||
}
|
||||
catch (SocketException) { /* drop this on the floor; we'll pick up the disconnect from the reader thread */ }
|
||||
catch (ObjectDisposedException) { /* ditto */ }
|
||||
catch (InvalidOperationException) { /* ditto */ }
|
||||
}
|
||||
|
||||
bool disposed = false;
|
||||
public void Dispose ()
|
||||
|
||||
public override void Dispose ()
|
||||
{
|
||||
if (disposed) return;
|
||||
disposed = true;
|
||||
@@ -157,48 +207,4 @@ namespace OpenRA.Network
|
||||
|
||||
~NetworkConnection() { Dispose(); }
|
||||
}
|
||||
|
||||
class ReplayConnection : IConnection
|
||||
{
|
||||
//uint nextFrame = 1;
|
||||
FileStream replayStream;
|
||||
|
||||
public ReplayConnection( string replayFilename )
|
||||
{
|
||||
replayStream = File.OpenRead( replayFilename );
|
||||
}
|
||||
|
||||
public int LocalClientId
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
|
||||
public ConnectionState ConnectionState
|
||||
{
|
||||
get { return ConnectionState.Connected; }
|
||||
}
|
||||
|
||||
public void Send( byte[] packet )
|
||||
{
|
||||
// do nothing; ignore locally generated orders
|
||||
}
|
||||
|
||||
public void Receive( Action<int, byte[]> packetFn )
|
||||
{
|
||||
if( replayStream == null ) return;
|
||||
|
||||
var reader = new BinaryReader( replayStream );
|
||||
while( replayStream.Position < replayStream.Length )
|
||||
{
|
||||
var client = reader.ReadInt32();
|
||||
var packetLen = reader.ReadInt32();
|
||||
var packet = reader.ReadBytes( packetLen );
|
||||
packetFn( client, packet );
|
||||
|
||||
if( !Game.orderManager.GameStarted )
|
||||
return;
|
||||
}
|
||||
replayStream = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user