Compare commits
538 Commits
playtest-2
...
playtest-2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b35a7d9f8d | ||
|
|
67fa079658 | ||
|
|
c9edbd8a80 | ||
|
|
4b49bf03dc | ||
|
|
6cfad6f2ab | ||
|
|
c0c4e7299b | ||
|
|
afda1647fd | ||
|
|
aff6889995 | ||
|
|
65515d54af | ||
|
|
c5b7c43d23 | ||
|
|
dba5adc91c | ||
|
|
0073a03ca4 | ||
|
|
5509d0d2e9 | ||
|
|
fe52e3722e | ||
|
|
3ddd1581f1 | ||
|
|
56efc3930b | ||
|
|
2f8d81a0f7 | ||
|
|
46486073ab | ||
|
|
3dc11eaa05 | ||
|
|
b62ee4d37c | ||
|
|
532afc3ff8 | ||
|
|
9ddb2beced | ||
|
|
1e758ec3e0 | ||
|
|
aa1d44428d | ||
|
|
23da8a24bd | ||
|
|
fef291a27e | ||
|
|
f49e56d660 | ||
|
|
927ab00f4d | ||
|
|
3f870e7e48 | ||
|
|
f2a321186f | ||
|
|
410daecab6 | ||
|
|
966e3bb71a | ||
|
|
652f06f604 | ||
|
|
2a10af2007 | ||
|
|
4cb26c0e3c | ||
|
|
8455dadb3c | ||
|
|
3c19b3df73 | ||
|
|
c796e155e7 | ||
|
|
ce9caec291 | ||
|
|
0330ef2b9e | ||
|
|
872a304714 | ||
|
|
59cc50df4c | ||
|
|
a1fd84fb15 | ||
|
|
317007f7ce | ||
|
|
387212d9ea | ||
|
|
c9ca5e207b | ||
|
|
ce78944a9e | ||
|
|
1fb336b7da | ||
|
|
e4d05407d9 | ||
|
|
f7eca1157e | ||
|
|
a64245fc10 | ||
|
|
ad8038867d | ||
|
|
fb90400524 | ||
|
|
08b25d10c1 | ||
|
|
ba09bbba8e | ||
|
|
0d2e1d7de5 | ||
|
|
22861fca5a | ||
|
|
692ef539f9 | ||
|
|
d07b0e4400 | ||
|
|
9848d1f403 | ||
|
|
83eae029b7 | ||
|
|
99e225c279 | ||
|
|
1785c4e4a8 | ||
|
|
69753f8a08 | ||
|
|
5593b9ffdd | ||
|
|
1b66635670 | ||
|
|
f1b1f3bd52 | ||
|
|
ff611dac32 | ||
|
|
e0a4cb4763 | ||
|
|
a3246866fb | ||
|
|
b94c2fc7c4 | ||
|
|
d530cf22da | ||
|
|
94e5b02a39 | ||
|
|
40533a50c1 | ||
|
|
d4182b1929 | ||
|
|
482129499d | ||
|
|
366cd02761 | ||
|
|
f549e7e5a8 | ||
|
|
4cab7c7fc4 | ||
|
|
e3939d4805 | ||
|
|
2ae6983bc2 | ||
|
|
ad00193a17 | ||
|
|
810667abbc | ||
|
|
a66efd56f2 | ||
|
|
36ba15e7f9 | ||
|
|
d809fb1e7b | ||
|
|
d0bc834a57 | ||
|
|
483ca8cc4c | ||
|
|
06aba5da46 | ||
|
|
106fbcd5af | ||
|
|
f456e41a45 | ||
|
|
7dc3aee4a2 | ||
|
|
c91bee8091 | ||
|
|
82875e15f9 | ||
|
|
d6f8b7d850 | ||
|
|
72fe873b26 | ||
|
|
e9f34b1e21 | ||
|
|
d15ab79370 | ||
|
|
303613b052 | ||
|
|
051c451867 | ||
|
|
ac8a3526a4 | ||
|
|
be47fb55e8 | ||
|
|
5b8fc75d4a | ||
|
|
629e73ac29 | ||
|
|
7e5b861caf | ||
|
|
f3dcc14fca | ||
|
|
fee68d0231 | ||
|
|
83f56d152f | ||
|
|
a04ea789f5 | ||
|
|
94becc3ddc | ||
|
|
8452e1bdf0 | ||
|
|
5a513bc69d | ||
|
|
5a173a2bd3 | ||
|
|
d29b068d59 | ||
|
|
8dbbaca8da | ||
|
|
10a1f7ec1e | ||
|
|
8286dba919 | ||
|
|
bd735059d0 | ||
|
|
147acbf096 | ||
|
|
91aa5302a8 | ||
|
|
2b6328f0ee | ||
|
|
1bc2136771 | ||
|
|
4ad0a52104 | ||
|
|
b9450b0f63 | ||
|
|
03bb74ea84 | ||
|
|
8b4551c605 | ||
|
|
f645049054 | ||
|
|
aa832244fb | ||
|
|
190311c68c | ||
|
|
b8ed9d7da5 | ||
|
|
ca32d51375 | ||
|
|
b0e5bb3718 | ||
|
|
96ebbfe75c | ||
|
|
5c6a6ee350 | ||
|
|
bbf2d68e9d | ||
|
|
59cf76b4ae | ||
|
|
e97440819d | ||
|
|
87cd37a30b | ||
|
|
f406dfa277 | ||
|
|
24039f593c | ||
|
|
cceb4401aa | ||
|
|
f9445cb282 | ||
|
|
706adb6d0b | ||
|
|
dd7e578fe6 | ||
|
|
83d1df19ba | ||
|
|
975fa28f62 | ||
|
|
452f7f7bff | ||
|
|
626db661ab | ||
|
|
9ea3a404a3 | ||
|
|
55c3e9d5bb | ||
|
|
f616a527ee | ||
|
|
a594e9f830 | ||
|
|
45d712d390 | ||
|
|
dbbdc171d2 | ||
|
|
befe22e170 | ||
|
|
b284e82aa7 | ||
|
|
ed5a3338fe | ||
|
|
68dcec87c7 | ||
|
|
39d7e54e7f | ||
|
|
404a4ad578 | ||
|
|
c9d0a7a301 | ||
|
|
54ffdc51b4 | ||
|
|
9e53774299 | ||
|
|
f70a6aafb1 | ||
|
|
c3fa9f7aa8 | ||
|
|
a73ef3affd | ||
|
|
4e5d26a2d1 | ||
|
|
4b1bc7acd4 | ||
|
|
95d29c6910 | ||
|
|
c88ea2bd7c | ||
|
|
af157867d8 | ||
|
|
9476e16df6 | ||
|
|
9c148bf3f0 | ||
|
|
c8c96b9f6b | ||
|
|
108d7764ec | ||
|
|
5396cad2b9 | ||
|
|
2bae3d9d2f | ||
|
|
9cbaa9679d | ||
|
|
6228a962f6 | ||
|
|
1baff27553 | ||
|
|
4855b6bca6 | ||
|
|
ff0c66e38c | ||
|
|
83d2ca07f1 | ||
|
|
26152489f3 | ||
|
|
4ca4d7b5dd | ||
|
|
0dddf12831 | ||
|
|
25c098bad6 | ||
|
|
be9528dcb2 | ||
|
|
965385980f | ||
|
|
ca92cd03db | ||
|
|
cdec95b73a | ||
|
|
76bf3077e9 | ||
|
|
53858a7789 | ||
|
|
b98e25c9a7 | ||
|
|
be46f44bc9 | ||
|
|
fee6d450e4 | ||
|
|
173dc59039 | ||
|
|
950dd4e85c | ||
|
|
6632feb696 | ||
|
|
7b2622e67b | ||
|
|
9e5528ef83 | ||
|
|
3d920670e5 | ||
|
|
4d2afd827f | ||
|
|
9a4d0dfe5e | ||
|
|
2a240e62aa | ||
|
|
7a88adcf96 | ||
|
|
b84d2f2c29 | ||
|
|
2945838eef | ||
|
|
43aa8812b3 | ||
|
|
9a2467dc21 | ||
|
|
5a75625eef | ||
|
|
2f2890596d | ||
|
|
01fa0b357e | ||
|
|
c5f0dad84e | ||
|
|
7f7f4e81a5 | ||
|
|
8b423908ca | ||
|
|
598fe9f956 | ||
|
|
06e8b530ea | ||
|
|
d5c25f73bd | ||
|
|
73fa306719 | ||
|
|
8d0cea6fe4 | ||
|
|
273b57ee69 | ||
|
|
c1578b92e1 | ||
|
|
c69a741c90 | ||
|
|
f8d537c0c5 | ||
|
|
e371159826 | ||
|
|
7d912715bc | ||
|
|
d6449c2902 | ||
|
|
8a3868abd0 | ||
|
|
112047d2b3 | ||
|
|
cd9f584729 | ||
|
|
31741a1ab3 | ||
|
|
eb6440694a | ||
|
|
2c388308c7 | ||
|
|
1c8f744719 | ||
|
|
dfdc893d63 | ||
|
|
669aaab6b4 | ||
|
|
73017d3f5c | ||
|
|
38fa809656 | ||
|
|
0ed21a4acb | ||
|
|
9ae7d98193 | ||
|
|
07e60286f2 | ||
|
|
7f918b8a69 | ||
|
|
4e0ace6ec5 | ||
|
|
dca5f8d27b | ||
|
|
6478276064 | ||
|
|
7d603f97fe | ||
|
|
112fdb32af | ||
|
|
5a78df0318 | ||
|
|
6ac4266847 | ||
|
|
91487b85d0 | ||
|
|
178af8b849 | ||
|
|
853ef12c8f | ||
|
|
62cc2fa4cb | ||
|
|
1f4991833d | ||
|
|
9fedeefdbc | ||
|
|
29a77f7c5c | ||
|
|
a751b8c49d | ||
|
|
baacfc96bb | ||
|
|
8dcd1e8fd1 | ||
|
|
2a7857570a | ||
|
|
2f92b873e8 | ||
|
|
bce52e989f | ||
|
|
a917086969 | ||
|
|
34913ab077 | ||
|
|
9de22add08 | ||
|
|
b2f535d2e0 | ||
|
|
3e7b9a7b5a | ||
|
|
29d03fb133 | ||
|
|
d4aeb157cc | ||
|
|
853e60f76e | ||
|
|
7f3e491ecc | ||
|
|
88dfbe657c | ||
|
|
226fd167e7 | ||
|
|
cedfeab63c | ||
|
|
a882735deb | ||
|
|
61ebe0d0a0 | ||
|
|
ee546750b2 | ||
|
|
267d89a459 | ||
|
|
3b59afcd4f | ||
|
|
8b98448090 | ||
|
|
1d7ca206f4 | ||
|
|
7b7b9d3319 | ||
|
|
e5d45a6961 | ||
|
|
c7f8921cea | ||
|
|
58ebd68478 | ||
|
|
6234f53e2c | ||
|
|
ce0e671ac5 | ||
|
|
739c38d3d8 | ||
|
|
5561ac458b | ||
|
|
c0d0636e08 | ||
|
|
f4da83e920 | ||
|
|
50066ec238 | ||
|
|
dbd076543b | ||
|
|
2d4ed56f76 | ||
|
|
03cdcdd4aa | ||
|
|
0cc440aa1f | ||
|
|
f635835b1c | ||
|
|
3f08f16b9b | ||
|
|
c433ca77c4 | ||
|
|
70a92b80cf | ||
|
|
b3fbefe968 | ||
|
|
f38e4d27be | ||
|
|
c35e3b4bd7 | ||
|
|
b0608936d8 | ||
|
|
56b9d1add7 | ||
|
|
5ce531f2d5 | ||
|
|
c7e76cc26d | ||
|
|
142be86934 | ||
|
|
73dadbc873 | ||
|
|
50d5936846 | ||
|
|
4e86f5b252 | ||
|
|
b6b4df703a | ||
|
|
b17e6900ec | ||
|
|
08a60ca336 | ||
|
|
d8c053253d | ||
|
|
e4271b35dc | ||
|
|
95c34c30ba | ||
|
|
8e42dd95fc | ||
|
|
f2dd0de1ea | ||
|
|
701ef05562 | ||
|
|
c3228cecd0 | ||
|
|
47eacc5b80 | ||
|
|
909152c662 | ||
|
|
0f9221dc5a | ||
|
|
cfc937e8eb | ||
|
|
def0580078 | ||
|
|
3c7015567e | ||
|
|
a00f0b18a0 | ||
|
|
703f3b8c13 | ||
|
|
bf9bcfed68 | ||
|
|
f6dac1fe83 | ||
|
|
731c64c1a7 | ||
|
|
19494c3262 | ||
|
|
cf9a2ee0ef | ||
|
|
93e8bd6644 | ||
|
|
4d0f75353b | ||
|
|
fb035756a0 | ||
|
|
e0a00940af | ||
|
|
e74c3eeb2e | ||
|
|
05bf6d83f2 | ||
|
|
e4b65256de | ||
|
|
d744cfe21b | ||
|
|
6ae7da77ae | ||
|
|
0352884205 | ||
|
|
7c6edab04e | ||
|
|
997501bb12 | ||
|
|
d4f43a399e | ||
|
|
f6ec2163de | ||
|
|
3428b3c4c2 | ||
|
|
8ec16fdbbe | ||
|
|
39f699916c | ||
|
|
4a337185f5 | ||
|
|
298f5ec24f | ||
|
|
16402f26fe | ||
|
|
825743b225 | ||
|
|
c3b3947b9d | ||
|
|
1143f496db | ||
|
|
46d0ce89e9 | ||
|
|
79ced35010 | ||
|
|
18a06eb3bf | ||
|
|
d8c5f1aed3 | ||
|
|
3880326787 | ||
|
|
09d9396123 | ||
|
|
aeccf53e97 | ||
|
|
b1b8b2c14a | ||
|
|
fd9a31168d | ||
|
|
3f11c32c4a | ||
|
|
d65626e87c | ||
|
|
ccb77dee12 | ||
|
|
952da4efec | ||
|
|
49f2bfb460 | ||
|
|
9db92ed8ba | ||
|
|
4e2d76f6ed | ||
|
|
94dd73cb48 | ||
|
|
aeb9f4e441 | ||
|
|
1a4e3053ce | ||
|
|
18914447aa | ||
|
|
7e67a5bb2d | ||
|
|
9eaa0e5765 | ||
|
|
0e16aa339d | ||
|
|
c7b650d6ec | ||
|
|
bcc3cd32ae | ||
|
|
38ffd30b28 | ||
|
|
15bd58ddce | ||
|
|
7247bd1078 | ||
|
|
ac31767aef | ||
|
|
3f68330c70 | ||
|
|
0e71af25f4 | ||
|
|
e610c4d7fc | ||
|
|
0a041fe425 | ||
|
|
1595c6a0ed | ||
|
|
db7a11e8a6 | ||
|
|
53df4c4bfb | ||
|
|
1afcd2b98a | ||
|
|
08ffe1d44d | ||
|
|
66359b7058 | ||
|
|
30ab5c33ea | ||
|
|
0c5fb4c6b0 | ||
|
|
21b0b12948 | ||
|
|
cb3f6435ad | ||
|
|
235ae1fad7 | ||
|
|
1c6470eff3 | ||
|
|
0cf51d8142 | ||
|
|
38e5f70cbe | ||
|
|
56b0da0b13 | ||
|
|
d6f0a03270 | ||
|
|
b1b75ecf2f | ||
|
|
228852a55d | ||
|
|
f6a880e524 | ||
|
|
7e82dc729b | ||
|
|
d91a7c6b35 | ||
|
|
b4068f0ac7 | ||
|
|
b336a1e478 | ||
|
|
55afcddce0 | ||
|
|
ac7bb3c71b | ||
|
|
3aa7ff5a6b | ||
|
|
0b3414c46f | ||
|
|
fdcad8710b | ||
|
|
02a7b092dc | ||
|
|
d43781c604 | ||
|
|
cfbededcc4 | ||
|
|
9ba50a9c5e | ||
|
|
6377269a14 | ||
|
|
a8be81ea2b | ||
|
|
50950cba22 | ||
|
|
210e847904 | ||
|
|
54f7b6430d | ||
|
|
26e823fc25 | ||
|
|
10ea035b42 | ||
|
|
58fb7178ad | ||
|
|
cd358eb985 | ||
|
|
39d4b80323 | ||
|
|
45a4935b01 | ||
|
|
824e2a7b0b | ||
|
|
230d59f655 | ||
|
|
7f191887ec | ||
|
|
499613f105 | ||
|
|
20af2b5c0a | ||
|
|
cbc9d66bee | ||
|
|
c338612b9f | ||
|
|
edd0a7c614 | ||
|
|
1d259e4bc7 | ||
|
|
6c651e9d02 | ||
|
|
a29e0bf4b1 | ||
|
|
9d403d3072 | ||
|
|
184d044f26 | ||
|
|
0473aed2c3 | ||
|
|
db5920e83a | ||
|
|
80555235d7 | ||
|
|
acd842f178 | ||
|
|
a5dacd52e8 | ||
|
|
6e045e864a | ||
|
|
0541b04c3a | ||
|
|
07b2bcbfdf | ||
|
|
0e2b4bb721 | ||
|
|
ab3c06cd04 | ||
|
|
299ee7f82c | ||
|
|
ddd56e6f9b | ||
|
|
839043ea1b | ||
|
|
1e8aea616b | ||
|
|
727a88d82a | ||
|
|
1f54ad3238 | ||
|
|
694fd84188 | ||
|
|
271be551b0 | ||
|
|
fe481d7445 | ||
|
|
7a10ae3dea | ||
|
|
8c39e372e3 | ||
|
|
af6660d6ca | ||
|
|
d0da9d11bf | ||
|
|
0a2d39f15b | ||
|
|
8118a17e3c | ||
|
|
0f6564f31a | ||
|
|
dda6556e17 | ||
|
|
5c1408d4d7 | ||
|
|
aa6e671d89 | ||
|
|
e0de1427e9 | ||
|
|
db16ab4cdc | ||
|
|
ae703d50b2 | ||
|
|
f6c6255f64 | ||
|
|
a569c712f0 | ||
|
|
5c8c8d5e6e | ||
|
|
3f4f1ff75e | ||
|
|
1aa4f57a68 | ||
|
|
3f3ac377b2 | ||
|
|
de12233edc | ||
|
|
b36b101392 | ||
|
|
726449b6fb | ||
|
|
a0d7435550 | ||
|
|
11aed465a8 | ||
|
|
0f953226a6 | ||
|
|
ad181544cd | ||
|
|
df19163ce5 | ||
|
|
4328fbc350 | ||
|
|
7cd9afb6d2 | ||
|
|
1ad8b58f1b | ||
|
|
62e3d548c8 | ||
|
|
ea7abcb585 | ||
|
|
441bffecfc | ||
|
|
2c1ab33893 | ||
|
|
74500c369c | ||
|
|
6e0158039a | ||
|
|
c600239c54 | ||
|
|
93a48c0cf1 | ||
|
|
b88512df43 | ||
|
|
ca6debde66 | ||
|
|
8dd9848636 | ||
|
|
ec9da154ad | ||
|
|
46fc0ef563 | ||
|
|
514c92a998 | ||
|
|
96f9f33776 | ||
|
|
20553a112d | ||
|
|
9e49cad1c2 | ||
|
|
5c6e2a5e42 | ||
|
|
44d7aa14a4 | ||
|
|
bf8e3645cb | ||
|
|
6ea8d4e6d3 | ||
|
|
16c3223f3e | ||
|
|
b98e180361 | ||
|
|
80aade857e | ||
|
|
58700e4c07 | ||
|
|
d364472862 | ||
|
|
5d688a2e27 | ||
|
|
f4fa053a35 | ||
|
|
90373529b0 | ||
|
|
0416b6b429 | ||
|
|
bd991e33ca | ||
|
|
f162c5956e | ||
|
|
e6f717ff04 | ||
|
|
eb0c895e2c | ||
|
|
3af0d2f6a4 | ||
|
|
8f6fe8344b | ||
|
|
cb5307bb17 | ||
|
|
d9acf1a3e5 | ||
|
|
6fc945ac91 | ||
|
|
e5878e8207 | ||
|
|
b982a52086 | ||
|
|
f28ec846e7 |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -10,7 +10,7 @@ obj
|
||||
mods/*/*.dll
|
||||
|
||||
# Red Alert binary files
|
||||
*.[mM][iI][xX]
|
||||
mods/*/packages/*.[mM][iI][xX]
|
||||
|
||||
# Crap generated by OpenRa
|
||||
sheet-*.png
|
||||
@@ -25,6 +25,7 @@ log.txt
|
||||
*.exe
|
||||
OpenRA
|
||||
OpenRA.app
|
||||
*.vqa
|
||||
|
||||
# backup files by various editors
|
||||
*~
|
||||
@@ -43,6 +44,9 @@ settings.ini
|
||||
|
||||
packaging/windows/*.exe
|
||||
|
||||
# osx crap
|
||||
.DS_Store
|
||||
|
||||
# osx build crap
|
||||
packaging/osx/launcher/build/
|
||||
packaging/osx/launcher/OpenRA.xcodeproj/*.pbxuser
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.IO;
|
||||
using OpenRA.FileFormats;
|
||||
using System.IO;
|
||||
|
||||
namespace FileExtractor
|
||||
{
|
||||
@@ -17,10 +17,8 @@ namespace FileExtractor
|
||||
}
|
||||
|
||||
var mods = args[0].Split(',');
|
||||
var manifest = new Manifest(mods);
|
||||
|
||||
foreach (var folder in manifest.Folders) FileSystem.Mount(folder);
|
||||
foreach (var pkg in manifest.Packages) FileSystem.Mount(pkg);
|
||||
var manifest = new Manifest(mods);
|
||||
FileSystem.LoadFromManifest( manifest );
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
75
HACKING
75
HACKING
@@ -5,43 +5,82 @@ There are n main sections to OpenRA: UI, Rendering, unit behaviour, ...
|
||||
All units/structures/most things in the map are Actors. Actors contain a collection of traits.
|
||||
Traits consist of an info class and a class that does stuff
|
||||
|
||||
Actor assembly is done via the mod's yaml files. A section exists for each actor type, and within that section we list the traits the actor should have. These get looked up in the loaded mod DLLs. Each trait can contain properties, which are automatically loaded into the corresponding fields on the trait's ITraitInfo.
|
||||
Actor assembly is done via the mod's yaml files. A section exists for each actor type,
|
||||
and within that section we list the traits the actor should have.
|
||||
These get looked up in the loaded mod DLLs. Each trait can contain properties,
|
||||
which are automatically loaded into the corresponding fields on the trait's ITraitInfo.
|
||||
|
||||
- Traits: look at TraitInterfaces.cs
|
||||
We've tried to make individual traits implement as self-contained a unit of functionality as possible - all cross-trait references should be in terms of an interface from TraitInterfaces.cs.
|
||||
We've tried to make individual traits implement as self-contained a unit of functionality
|
||||
as possible - all cross-trait references should be in terms of an interface from
|
||||
TraitInterfaces.cs.
|
||||
|
||||
- Things an actor can be *doing* are represented as IActivity implementations. Actor has a queue of these. There's a standard set of activities in OpenRa.Game/Traits/Activities, and mods tend to define more as they need them. (RA defines various special-infantry actions as activities).
|
||||
- Things an actor can be *doing* are represented as IActivity implementations.
|
||||
Actor has a queue of these. There's a standard set of activities in
|
||||
OpenRa.Game/Traits/Activities, and mods tend to define more as they need them. (RA
|
||||
defines various special-infantry actions as activities).
|
||||
|
||||
- Units offer orders they can perform (given context) through traits that implement IIssueOrder. Every trait with this interface is given a chance to generate orders for the current context.
|
||||
- Units offer orders they can perform (given context) through traits that implement IIssueOrder.
|
||||
Every trait with this interface is given a chance to generate orders for the current context.
|
||||
|
||||
- For more complex things that require modal UI (like special abilities, RA-style sell/repair buttons, etc) we have IOrderGenerator implementations. This can completely replace the normal actors-provide-orders model temporarily. IOGs wiring is provided through OpenRa.Game/Controller.cs (ToggleInputMode<T>, CancelInputMode)
|
||||
- For more complex things that require modal UI (like special abilities,
|
||||
RA-style sell/repair buttons, etc) we have IOrderGenerator implementations. This can
|
||||
completely replace the normal actors-provide-orders model temporarily. IOGs wiring is
|
||||
provided through OpenRa.Game/Controller.cs (ToggleInputMode<T>, CancelInputMode)
|
||||
|
||||
- Things that don't affect gameplay, or (increasingly) are just transient are implemented as IEffect, rather than real Actors. This is similar to the temp ents mechanism in many other game engines.
|
||||
- Things that don't affect gameplay, or (increasingly) are just transient are implemented as
|
||||
IEffect, rather than real Actors. This is similar to the temp ents mechanism in many other
|
||||
game engines.
|
||||
|
||||
- Most player-level or global-level game behavior is implemented as traits on special Player and World actors. These are accessible via Player.PlayerActor and World.WorldActor. This includes production queue support, ore/tiberium growth, various palette manipulation magic.
|
||||
- Most player-level or global-level game behavior is implemented as traits on special Player
|
||||
and World actors. These are accessible via Player.PlayerActor and World.WorldActor. This
|
||||
includes production queue support, ore/tiberium growth, various palette manipulation magic.
|
||||
|
||||
- Many traits can be modified by adding an appropriate IFooModifier implementation to the unit. This includes rendering, where IRenderModifier allows you to define an arbitrary transform on the Renderables emitted by the actor's IRender implementation(s). Examples are things like cloaking, invisibility to certain players, flying units with shadows, etc. Other modifiers can affect movement speed, damage taken, weapon firepower, etc.
|
||||
- Many traits can be modified by adding an appropriate IFooModifier implementation to the unit.
|
||||
This includes rendering, where IRenderModifier allows you to define an arbitrary transform on
|
||||
the Renderables emitted by the actor's IRender implementation(s). Examples are things like
|
||||
cloaking, invisibility to certain players, flying units with shadows, etc. Other modifiers
|
||||
can affect movement speed, damage taken, weapon firepower, etc.
|
||||
|
||||
Game code is collected into "Mod" units. Mods can be added prior to starting the game. Currently there is no dependancy mechanism, but provided you are doing additions or overrides you can add multiple mods without problem.
|
||||
Game code is collected into "Mod" units. Mods can be added prior to starting the game.
|
||||
Currently there is no dependancy mechanism, but provided you are doing additions or overrides
|
||||
you can add multiple mods without problem.
|
||||
Everything is a mod (including RA - which is loaded by default).
|
||||
|
||||
The contents of the mod is defined in a manifest file mod.yaml. This lists the packages containing art assets (typically .mix files), yaml files defining actor defintions, and ini files containing legacy information that have yet to be ported over to the (relatively new) yaml system.
|
||||
The contents of the mod is defined in a manifest file mod.yaml. This lists the packages
|
||||
containing art assets (typically .mix files), yaml files defining actor defintions,
|
||||
and ini files containing legacy information that have yet to be ported over to
|
||||
the (relatively new) yaml system.
|
||||
|
||||
The unit artwork itself must be defined in a Sequences file (typically Sequences.xml; check mod.yaml for a list of what the mod uses); the format is self explanatory. There is also the SequenceEditor tool to make this easy.
|
||||
The unit artwork itself must be defined in a Sequences file (typically Sequences.xml;
|
||||
check mod.yaml for a list of what the mod uses); the format is self explanatory. There is
|
||||
also the SequenceEditor tool to make this easy.
|
||||
|
||||
Chrome artwork is similarly defined in Chrome.xml. Chrome is already mod dependent. Sortof ;) mod-dependent *behavior* would be nice too, not just skinning. This is a property of the traits however; once we port UI into traits this will become a non-issue.
|
||||
Chrome artwork is similarly defined in Chrome.xml. Chrome is already mod dependent. Sortof ;)
|
||||
mod-dependent *behavior* would be nice too, not just skinning. This is a property of the traits
|
||||
however; once we port UI into traits this will become a non-issue.
|
||||
|
||||
Rendering
|
||||
OpenRa.Game/Chrome.cs is the user interface.
|
||||
Three renderers (SpriteRenderer, LineRenderer, Rgba?Renderer) render most stuff. Don't forget to flush the renderer (if you want to see anything).
|
||||
Three renderers (SpriteRenderer, LineRenderer, Rgba?Renderer) render most stuff. Don't forget
|
||||
to flush the renderer (if you want to see anything).
|
||||
|
||||
UserSettings stores the data loaded from settings.ini (or defaults). Eventually we need to be able to save values changed in game into settings.ini (not yet implemented)
|
||||
UserSettings stores the data loaded from settings.ini (or defaults). Eventually we need to be
|
||||
able to save values changed in game into settings.ini (not yet implemented)
|
||||
|
||||
Bugs: There is a list of known bugs and features at http://openra.res0l.net/projects/openra/issues . There's also a few at http://github.com/chrisforbes/OpenRA/issues (which won't be ported over, but no more bugs should be added here).
|
||||
Bugs: There is a list of known bugs and features at http://red-bull.ijw.co.nz:3690/OpenRA .
|
||||
|
||||
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 chrisforbes/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.
|
||||
|
||||
|
||||
112
INSTALL
112
INSTALL
@@ -1,44 +1,47 @@
|
||||
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
|
||||
|
||||
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,6 +49,9 @@ 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
|
||||
@@ -54,4 +60,40 @@ have very strange errors.
|
||||
* OpenAL >= 1.1
|
||||
(http://connect.creativelabs.com/openal/Downloads/oalinst.zip)
|
||||
* Cg Toolkit >= 2.2
|
||||
(http://developer.download.nvidia.com/cg/Cg_2.2/Cg-2.2_October2009_Setup.exe)
|
||||
(http://developer.download.nvidia.com/cg/Cg_2.2/Cg-2.2_October2009_Setup.exe)
|
||||
|
||||
To compile OpenRA, open the OpenRA.sln solution in the main folder,
|
||||
or build it from the command-line with MSBuild.
|
||||
|
||||
Run the game with `OpenRA.Game.exe Game.Mods=ra` for Red Alert
|
||||
or `OpenRA.Game.exe Game.Mods=cnc` for Command & Conquer
|
||||
|
||||
|
||||
UBUNTU (substitute comparable packages for other linux distros):
|
||||
|
||||
* mono-gmcs
|
||||
* freetype
|
||||
* libmono-corlib1.0-cil
|
||||
* libmono-winforms2.0-cil
|
||||
* libopenal1
|
||||
* libsdl1.2-dev
|
||||
* nvidia-cg-toolkit (download the latest version from
|
||||
http://developer.nvidia.com/object/cg_download.html)
|
||||
|
||||
OpenRA is incompatible with Compiz, please disable desktop effects when trying
|
||||
to run OpenRA or the game will crash.
|
||||
|
||||
You will need to copy the Tao dependencies (.dll and .config) from the
|
||||
thirdparty/Tao directory into the game root, or install them permanently into
|
||||
your GAC with the following script
|
||||
|
||||
#!/bin/sh
|
||||
gacutil -i thirdparty/Tao/Tao.Cg.dll
|
||||
gacutil -i thirdparty/Tao/Tao.OpenGl.dll
|
||||
gacutil -i thirdparty/Tao/Tao.OpenAl.dll
|
||||
gacutil -i thirdparty/Tao/Tao.Sdl.dll
|
||||
gacutil -i thirdparty/Tao/Tao.FreeType.dll
|
||||
|
||||
To compile OpenRA, run `make' from the command line.
|
||||
Run the game with `mono OpenRA.Game.exe Game.Mods=ra` for Red Alert
|
||||
or `mono OpenRA.Game.exe Game.Mods=cnc` for Command & Conquer
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean,
|
||||
Paul Chote, Alli Witheford.
|
||||
|
||||
This file is part of OpenRA.
|
||||
|
||||
OpenRA is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenRA is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
To compile OpenRA, open the OpenRA.sln solution in the main folder,
|
||||
or build it from the command-line with MSBuild.
|
||||
|
||||
To run OpenRA, several files from the original game’s install need
|
||||
to be copied to the root of the project directory. The required files are:
|
||||
|
||||
redalert.mix
|
||||
conquer.mix
|
||||
temperat.mix
|
||||
interior.mix
|
||||
snow.mix
|
||||
sounds.mix
|
||||
allies.mix
|
||||
russian.mix
|
||||
general.mix
|
||||
|
||||
hires1.mix
|
||||
expand2.mix
|
||||
|
||||
Red Alert has been released by EA Games as freeware so it shouldn’t
|
||||
be too hard to find a legal copy of the CD images. Unfortunately the
|
||||
installer is 16-bit and so won’t run on 64-bit operating systems. This
|
||||
can be worked around by using the Red Alert Setup Manager
|
||||
(http://ra.afraid.org/html/downloads/utilities-3.html).
|
||||
Make sure you apply the no-CD protection fix so all the files needed
|
||||
are installed to the hard drive.
|
||||
|
||||
Dependencies - Make sure you have these installed, or you'll
|
||||
have very strange errors.
|
||||
|
||||
* mono-gmcs
|
||||
* libglfw2
|
||||
* nvidia-cg-toolkit
|
||||
* libmono-*
|
||||
37
Makefile
37
Makefile
@@ -16,7 +16,7 @@ COMMON_LIBS = System.dll System.Core.dll System.Drawing.dll System.Xml.dll
|
||||
fileformats_SRCS = $(shell find OpenRA.FileFormats/ -iname '*.cs')
|
||||
fileformats_TARGET = OpenRA.FileFormats.dll
|
||||
fileformats_KIND = library
|
||||
fileformats_LIBS = $(COMMON_LIBS) thirdparty/Tao/Tao.Sdl.dll WindowsBase.dll
|
||||
fileformats_LIBS = $(COMMON_LIBS) thirdparty/Tao/Tao.Sdl.dll thirdparty/WindowsBase.dll
|
||||
|
||||
gl_SRCS = $(shell find OpenRA.Gl/ -iname '*.cs')
|
||||
gl_TARGET = OpenRA.Gl.dll
|
||||
@@ -58,7 +58,7 @@ 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
|
||||
editor_EXTRA = -resource:OpenRA.Editor.Form1.resources -resource:OpenRA.Editor.MapSelect.resources
|
||||
|
||||
ralint_SRCS = $(shell find RALint/ -iname '*.cs')
|
||||
ralint_TARGET = RALint.exe
|
||||
@@ -91,7 +91,7 @@ clean:
|
||||
|
||||
distclean: clean
|
||||
|
||||
CORE = fileformats gl game seqed
|
||||
CORE = fileformats gl game editor
|
||||
|
||||
install: all
|
||||
@-echo "Installing OpenRA to $(INSTALL_DIR)"
|
||||
@@ -103,27 +103,37 @@ install: all
|
||||
@-cp $(foreach f,$(shell ls mods/cnc --hide=*.dll),mods/cnc/$(f)) $(INSTALL_DIR)/mods/cnc
|
||||
@cp -r mods/cnc/maps $(INSTALL_DIR)/mods/cnc
|
||||
@cp -r mods/cnc/chrome $(INSTALL_DIR)/mods/cnc
|
||||
@cp -r mods/cnc/bits $(INSTALL_DIR)/mods/cnc
|
||||
@cp -r mods/cnc/rules $(INSTALL_DIR)/mods/cnc
|
||||
@cp -r mods/cnc/sequences $(INSTALL_DIR)/mods/cnc
|
||||
@cp -r mods/cnc/tilesets $(INSTALL_DIR)/mods/cnc
|
||||
@cp -r mods/cnc/uibits $(INSTALL_DIR)/mods/cnc
|
||||
|
||||
@$(INSTALL_PROGRAM) -d $(INSTALL_DIR)/mods/ra
|
||||
@$(INSTALL_PROGRAM) $(ra_TARGET) $(INSTALL_DIR)/mods/ra
|
||||
@-cp $(foreach f,$(shell ls mods/ra --hide=*.dll),mods/ra/$(f)) $(INSTALL_DIR)/mods/ra
|
||||
@cp -r mods/ra/maps $(INSTALL_DIR)/mods/ra
|
||||
@cp -r mods/ra/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 mods/ra/rules $(INSTALL_DIR)/mods/ra
|
||||
@cp -r mods/ra/tilesets $(INSTALL_DIR)/mods/ra
|
||||
@cp -r mods/ra/uibits $(INSTALL_DIR)/mods/ra
|
||||
|
||||
@cp -r shaders $(INSTALL_DIR)
|
||||
@cp *.ttf $(INSTALL_DIR)
|
||||
@cp -r thirdparty $(INSTALL_DIR)
|
||||
@cp --parents -r thirdparty/Tao $(INSTALL_DIR)
|
||||
@$(INSTALL_PROGRAM) thirdparty/WindowsBase.dll $(INSTALL_DIR)
|
||||
@-$(INSTALL_PROGRAM) VERSION $(INSTALL_DIR)
|
||||
|
||||
@echo "#!/bin/sh" > openra
|
||||
@echo "cd "$(datadir)"/openra" >> openra
|
||||
@echo "mono "$(datadir)"/openra/OpenRA.Game.exe SupportDir=~/.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 "http://open-ra.org/get-dependency.php?ra-packages and"
|
||||
@echo "http://open-ra.org/get-dependency.php?cnc-packages"
|
||||
@echo "and extract their contents to"
|
||||
@echo "$(INSTALL_DIR)/mods/ra/packages and "
|
||||
@echo "$(INSTALL_DIR)/mods/cnc/packages respectively."
|
||||
@@ -140,9 +150,12 @@ mod_cnc: $(cnc_TARGET) $(ralint_TARGET)
|
||||
mono RALint.exe cnc
|
||||
mods: mod_ra mod_cnc
|
||||
|
||||
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.Form1.resources $(editor_TARGET)
|
||||
editor: OpenRA.Editor.MapSelect.resources OpenRA.Editor.Form1.resources $(editor_TARGET)
|
||||
ralint: $(ralint_TARGET)
|
||||
seqed: SequenceEditor.Form1.resources $(seqed_TARGET)
|
||||
SequenceEditor.Form1.resources:
|
||||
@@ -154,9 +167,12 @@ OpenRA.TilesetBuilder.Form1.resources:
|
||||
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)
|
||||
$$($(1)_TARGET): $$($(1)_SRCS) Makefile $$($(1)_DEPS) fixheader
|
||||
@echo CSC $$(@)
|
||||
@$(CSC) $$($(1)_LIBS:%=-r:%) \
|
||||
-out:$$(@) $(CSFLAGS) $$($(1)_FLAGS) \
|
||||
@@ -164,6 +180,7 @@ $$($(1)_TARGET): $$($(1)_SRCS) Makefile $$($(1)_DEPS)
|
||||
-t:"$$($(1)_KIND)" \
|
||||
$$($(1)_EXTRA) \
|
||||
$$($(1)_SRCS)
|
||||
@mono fixheader.exe $$(@)
|
||||
endef
|
||||
|
||||
$(foreach prog,$(PROGRAMS),$(eval $(call BUILD_ASSEMBLY,$(prog))))
|
||||
|
||||
769
OpenRA.Editor/Form1.Designer.cs
generated
769
OpenRA.Editor/Form1.Designer.cs
generated
@@ -28,176 +28,221 @@
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
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.tabControl1 = new System.Windows.Forms.TabControl();
|
||||
this.tabPage1 = new System.Windows.Forms.TabPage();
|
||||
this.tilePalette = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.tabPage2 = new System.Windows.Forms.TabPage();
|
||||
this.actorPalette = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.tabPage3 = new System.Windows.Forms.TabPage();
|
||||
this.resourcePalette = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
|
||||
this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.newToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.openToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.saveToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.saveAsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.cCRedAlertMapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.bitmapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.exotToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.propertiesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.resizeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.spawnpointsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.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.splitContainer1.Panel1.SuspendLayout();
|
||||
this.splitContainer1.Panel2.SuspendLayout();
|
||||
this.splitContainer1.SuspendLayout();
|
||||
this.tabControl1.SuspendLayout();
|
||||
this.tabPage1.SuspendLayout();
|
||||
this.tabPage2.SuspendLayout();
|
||||
this.tabPage3.SuspendLayout();
|
||||
this.menuStrip1.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;
|
||||
this.splitContainer1.Location = new System.Drawing.Point(0, 0);
|
||||
this.splitContainer1.Name = "splitContainer1";
|
||||
//
|
||||
// splitContainer1.Panel1
|
||||
//
|
||||
this.splitContainer1.Panel1.Controls.Add(this.tabControl1);
|
||||
//
|
||||
// splitContainer1.Panel2
|
||||
//
|
||||
this.splitContainer1.Panel2.Controls.Add(this.surface1);
|
||||
this.splitContainer1.Size = new System.Drawing.Size(985, 681);
|
||||
this.splitContainer1.SplitterDistance = 198;
|
||||
this.splitContainer1.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, 0);
|
||||
this.tabControl1.Multiline = true;
|
||||
this.tabControl1.Name = "tabControl1";
|
||||
this.tabControl1.SelectedIndex = 0;
|
||||
this.tabControl1.Size = new System.Drawing.Size(198, 681);
|
||||
this.tabControl1.TabIndex = 0;
|
||||
//
|
||||
// tabPage1
|
||||
//
|
||||
this.tabPage1.Controls.Add(this.tilePalette);
|
||||
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(190, 655);
|
||||
this.tabPage1.TabIndex = 0;
|
||||
this.tabPage1.Text = "Templates";
|
||||
this.tabPage1.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// tilePalette
|
||||
//
|
||||
this.tilePalette.AutoScroll = true;
|
||||
this.tilePalette.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
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.TabIndex = 1;
|
||||
//
|
||||
// tabPage2
|
||||
//
|
||||
this.tabPage2.Controls.Add(this.actorPalette);
|
||||
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(190, 655);
|
||||
this.tabPage2.TabIndex = 1;
|
||||
this.tabPage2.Text = "Actors";
|
||||
this.tabPage2.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// actorPalette
|
||||
//
|
||||
this.actorPalette.AutoScroll = true;
|
||||
this.actorPalette.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
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.TabIndex = 2;
|
||||
//
|
||||
// tabPage3
|
||||
//
|
||||
this.tabPage3.Controls.Add(this.resourcePalette);
|
||||
this.tabPage3.Location = new System.Drawing.Point(4, 22);
|
||||
this.tabPage3.Name = "tabPage3";
|
||||
this.tabPage3.Size = new System.Drawing.Size(190, 655);
|
||||
this.tabPage3.TabIndex = 2;
|
||||
this.tabPage3.Text = "Resources";
|
||||
this.tabPage3.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// resourcePalette
|
||||
//
|
||||
this.resourcePalette.AutoScroll = true;
|
||||
this.resourcePalette.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
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.TabIndex = 3;
|
||||
//
|
||||
// menuStrip1
|
||||
//
|
||||
this.menuStrip1.Dock = System.Windows.Forms.DockStyle.None;
|
||||
this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
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();
|
||||
this.tabPage2 = new System.Windows.Forms.TabPage();
|
||||
this.actorPalette = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.tabPage3 = new System.Windows.Forms.TabPage();
|
||||
this.resourcePalette = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
|
||||
this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.newToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.openToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.saveToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.saveAsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.cCRedAlertMapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.bitmapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuExport = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuMinimapToPNG = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.exotToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.propertiesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.resizeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.spawnpointsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.layersFloaterToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.tt = new System.Windows.Forms.ToolTip(this.components);
|
||||
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
|
||||
this.surface1 = new OpenRA.Editor.Surface();
|
||||
this.saveFileDialog = new System.Windows.Forms.SaveFileDialog();
|
||||
this.toolStripContainer1.ContentPanel.SuspendLayout();
|
||||
this.toolStripContainer1.TopToolStripPanel.SuspendLayout();
|
||||
this.toolStripContainer1.SuspendLayout();
|
||||
this.splitContainer1.Panel1.SuspendLayout();
|
||||
this.splitContainer1.Panel2.SuspendLayout();
|
||||
this.splitContainer1.SuspendLayout();
|
||||
this.splitContainer2.Panel1.SuspendLayout();
|
||||
this.splitContainer2.Panel2.SuspendLayout();
|
||||
this.splitContainer2.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pmMiniMap)).BeginInit();
|
||||
this.tabControl1.SuspendLayout();
|
||||
this.tabPage1.SuspendLayout();
|
||||
this.tabPage2.SuspendLayout();
|
||||
this.tabPage3.SuspendLayout();
|
||||
this.menuStrip1.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// toolStripContainer1
|
||||
//
|
||||
//
|
||||
// toolStripContainer1.ContentPanel
|
||||
//
|
||||
this.toolStripContainer1.ContentPanel.Controls.Add(this.splitContainer1);
|
||||
this.toolStripContainer1.ContentPanel.Size = new System.Drawing.Size(985, 727);
|
||||
this.toolStripContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.toolStripContainer1.Location = new System.Drawing.Point(0, 0);
|
||||
this.toolStripContainer1.Name = "toolStripContainer1";
|
||||
this.toolStripContainer1.Padding = new System.Windows.Forms.Padding(0, 0, 0, 22);
|
||||
this.toolStripContainer1.Size = new System.Drawing.Size(985, 773);
|
||||
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;
|
||||
this.splitContainer1.Location = new System.Drawing.Point(0, 0);
|
||||
this.splitContainer1.Name = "splitContainer1";
|
||||
//
|
||||
// splitContainer1.Panel1
|
||||
//
|
||||
this.splitContainer1.Panel1.Controls.Add(this.splitContainer2);
|
||||
//
|
||||
// splitContainer1.Panel2
|
||||
//
|
||||
this.splitContainer1.Panel2.Controls.Add(this.surface1);
|
||||
this.splitContainer1.Size = new System.Drawing.Size(985, 727);
|
||||
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, 727);
|
||||
this.splitContainer2.SplitterDistance = 160;
|
||||
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, 160);
|
||||
this.pmMiniMap.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
|
||||
this.pmMiniMap.TabIndex = 1;
|
||||
this.pmMiniMap.TabStop = false;
|
||||
//
|
||||
// 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, 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, 563);
|
||||
this.tabControl1.TabIndex = 0;
|
||||
//
|
||||
// tabPage1
|
||||
//
|
||||
this.tabPage1.Controls.Add(this.tilePalette);
|
||||
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, 539);
|
||||
this.tabPage1.TabIndex = 0;
|
||||
this.tabPage1.Text = "Templates";
|
||||
this.tabPage1.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// tilePalette
|
||||
//
|
||||
this.tilePalette.AutoScroll = true;
|
||||
this.tilePalette.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
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, 533);
|
||||
this.tilePalette.TabIndex = 1;
|
||||
//
|
||||
// tabPage2
|
||||
//
|
||||
this.tabPage2.Controls.Add(this.actorPalette);
|
||||
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, 539);
|
||||
this.tabPage2.TabIndex = 1;
|
||||
this.tabPage2.Text = "Actors";
|
||||
this.tabPage2.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// actorPalette
|
||||
//
|
||||
this.actorPalette.AutoScroll = true;
|
||||
this.actorPalette.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
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, 533);
|
||||
this.actorPalette.TabIndex = 2;
|
||||
//
|
||||
// tabPage3
|
||||
//
|
||||
this.tabPage3.Controls.Add(this.resourcePalette);
|
||||
this.tabPage3.Location = new System.Drawing.Point(4, 20);
|
||||
this.tabPage3.Name = "tabPage3";
|
||||
this.tabPage3.Size = new System.Drawing.Size(190, 539);
|
||||
this.tabPage3.TabIndex = 2;
|
||||
this.tabPage3.Text = "Resources";
|
||||
this.tabPage3.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// resourcePalette
|
||||
//
|
||||
this.resourcePalette.AutoScroll = true;
|
||||
this.resourcePalette.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
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, 539);
|
||||
this.resourcePalette.TabIndex = 3;
|
||||
//
|
||||
// menuStrip1
|
||||
//
|
||||
this.menuStrip1.Dock = System.Windows.Forms.DockStyle.None;
|
||||
this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.fileToolStripMenuItem,
|
||||
this.mapToolStripMenuItem});
|
||||
this.menuStrip1.Location = new System.Drawing.Point(0, 0);
|
||||
this.menuStrip1.Name = "menuStrip1";
|
||||
this.menuStrip1.Size = new System.Drawing.Size(985, 24);
|
||||
this.menuStrip1.TabIndex = 1;
|
||||
this.menuStrip1.Text = "menuStrip1";
|
||||
//
|
||||
// fileToolStripMenuItem
|
||||
//
|
||||
this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.mapToolStripMenuItem,
|
||||
this.toolsToolStripMenuItem});
|
||||
this.menuStrip1.Location = new System.Drawing.Point(0, 0);
|
||||
this.menuStrip1.Name = "menuStrip1";
|
||||
this.menuStrip1.Size = new System.Drawing.Size(985, 24);
|
||||
this.menuStrip1.TabIndex = 1;
|
||||
this.menuStrip1.Text = "menuStrip1";
|
||||
//
|
||||
// fileToolStripMenuItem
|
||||
//
|
||||
this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.newToolStripMenuItem,
|
||||
this.toolStripSeparator1,
|
||||
this.openToolStripMenuItem,
|
||||
@@ -205,172 +250,229 @@
|
||||
this.saveAsToolStripMenuItem,
|
||||
this.toolStripSeparator2,
|
||||
this.toolStripMenuItem1,
|
||||
this.mnuExport,
|
||||
this.toolStripSeparator3,
|
||||
this.exotToolStripMenuItem});
|
||||
this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
|
||||
this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20);
|
||||
this.fileToolStripMenuItem.Text = "&File";
|
||||
//
|
||||
// newToolStripMenuItem
|
||||
//
|
||||
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.Text = "&New...";
|
||||
this.newToolStripMenuItem.Click += new System.EventHandler(this.NewClicked);
|
||||
//
|
||||
// toolStripSeparator1
|
||||
//
|
||||
this.toolStripSeparator1.Name = "toolStripSeparator1";
|
||||
this.toolStripSeparator1.Size = new System.Drawing.Size(149, 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.Text = "&Open...";
|
||||
this.openToolStripMenuItem.Click += new System.EventHandler(this.OpenClicked);
|
||||
//
|
||||
// saveToolStripMenuItem
|
||||
//
|
||||
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.Text = "&Save";
|
||||
this.saveToolStripMenuItem.Click += new System.EventHandler(this.SaveClicked);
|
||||
//
|
||||
// saveAsToolStripMenuItem
|
||||
//
|
||||
this.saveAsToolStripMenuItem.Name = "saveAsToolStripMenuItem";
|
||||
this.saveAsToolStripMenuItem.Size = new System.Drawing.Size(152, 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);
|
||||
//
|
||||
// toolStripMenuItem1
|
||||
//
|
||||
this.toolStripMenuItem1.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
|
||||
this.fileToolStripMenuItem.Size = new System.Drawing.Size(35, 20);
|
||||
this.fileToolStripMenuItem.Text = "&File";
|
||||
//
|
||||
// newToolStripMenuItem
|
||||
//
|
||||
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.Text = "&New...";
|
||||
this.newToolStripMenuItem.Click += new System.EventHandler(this.NewClicked);
|
||||
//
|
||||
// toolStripSeparator1
|
||||
//
|
||||
this.toolStripSeparator1.Name = "toolStripSeparator1";
|
||||
this.toolStripSeparator1.Size = new System.Drawing.Size(122, 6);
|
||||
//
|
||||
// openToolStripMenuItem
|
||||
//
|
||||
this.openToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("openToolStripMenuItem.Image")));
|
||||
this.openToolStripMenuItem.Name = "openToolStripMenuItem";
|
||||
this.openToolStripMenuItem.Size = new System.Drawing.Size(125, 22);
|
||||
this.openToolStripMenuItem.Text = "&Open...";
|
||||
this.openToolStripMenuItem.Click += new System.EventHandler(this.OpenClicked);
|
||||
//
|
||||
// saveToolStripMenuItem
|
||||
//
|
||||
this.saveToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("saveToolStripMenuItem.Image")));
|
||||
this.saveToolStripMenuItem.Name = "saveToolStripMenuItem";
|
||||
this.saveToolStripMenuItem.Size = new System.Drawing.Size(125, 22);
|
||||
this.saveToolStripMenuItem.Text = "&Save";
|
||||
this.saveToolStripMenuItem.Click += new System.EventHandler(this.SaveClicked);
|
||||
//
|
||||
// saveAsToolStripMenuItem
|
||||
//
|
||||
this.saveAsToolStripMenuItem.Name = "saveAsToolStripMenuItem";
|
||||
this.saveAsToolStripMenuItem.Size = new System.Drawing.Size(125, 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(122, 6);
|
||||
//
|
||||
// toolStripMenuItem1
|
||||
//
|
||||
this.toolStripMenuItem1.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.cCRedAlertMapToolStripMenuItem,
|
||||
this.bitmapToolStripMenuItem});
|
||||
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
|
||||
this.toolStripMenuItem1.Size = new System.Drawing.Size(152, 22);
|
||||
this.toolStripMenuItem1.Text = "&Import";
|
||||
//
|
||||
// cCRedAlertMapToolStripMenuItem
|
||||
//
|
||||
this.cCRedAlertMapToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("cCRedAlertMapToolStripMenuItem.Image")));
|
||||
this.cCRedAlertMapToolStripMenuItem.Name = "cCRedAlertMapToolStripMenuItem";
|
||||
this.cCRedAlertMapToolStripMenuItem.Size = new System.Drawing.Size(195, 22);
|
||||
this.cCRedAlertMapToolStripMenuItem.Text = "&C&&C / Red Alert Map...";
|
||||
this.cCRedAlertMapToolStripMenuItem.Click += new System.EventHandler(this.ImportLegacyMapClicked);
|
||||
//
|
||||
// bitmapToolStripMenuItem
|
||||
//
|
||||
this.bitmapToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("bitmapToolStripMenuItem.Image")));
|
||||
this.bitmapToolStripMenuItem.Name = "bitmapToolStripMenuItem";
|
||||
this.bitmapToolStripMenuItem.Size = new System.Drawing.Size(195, 22);
|
||||
this.bitmapToolStripMenuItem.Text = "&Bitmap...";
|
||||
//
|
||||
// toolStripSeparator3
|
||||
//
|
||||
this.toolStripSeparator3.Name = "toolStripSeparator3";
|
||||
this.toolStripSeparator3.Size = new System.Drawing.Size(149, 6);
|
||||
//
|
||||
// exotToolStripMenuItem
|
||||
//
|
||||
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);
|
||||
//
|
||||
// mapToolStripMenuItem
|
||||
//
|
||||
this.mapToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
|
||||
this.toolStripMenuItem1.Size = new System.Drawing.Size(125, 22);
|
||||
this.toolStripMenuItem1.Text = "&Import";
|
||||
//
|
||||
// cCRedAlertMapToolStripMenuItem
|
||||
//
|
||||
this.cCRedAlertMapToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("cCRedAlertMapToolStripMenuItem.Image")));
|
||||
this.cCRedAlertMapToolStripMenuItem.Name = "cCRedAlertMapToolStripMenuItem";
|
||||
this.cCRedAlertMapToolStripMenuItem.Size = new System.Drawing.Size(185, 22);
|
||||
this.cCRedAlertMapToolStripMenuItem.Text = "&C&&C / Red Alert Map...";
|
||||
this.cCRedAlertMapToolStripMenuItem.Click += new System.EventHandler(this.ImportLegacyMapClicked);
|
||||
//
|
||||
// bitmapToolStripMenuItem
|
||||
//
|
||||
this.bitmapToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("bitmapToolStripMenuItem.Image")));
|
||||
this.bitmapToolStripMenuItem.Name = "bitmapToolStripMenuItem";
|
||||
this.bitmapToolStripMenuItem.Size = new System.Drawing.Size(185, 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(152, 22);
|
||||
this.mnuExport.Text = "&Export";
|
||||
//
|
||||
// mnuMinimapToPNG
|
||||
//
|
||||
this.mnuMinimapToPNG.Image = ((System.Drawing.Image)(resources.GetObject("mnuMinimapToPNG.Image")));
|
||||
this.mnuMinimapToPNG.Name = "mnuMinimapToPNG";
|
||||
this.mnuMinimapToPNG.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuMinimapToPNG.Text = "Minimap to PNG";
|
||||
this.mnuMinimapToPNG.Click += new System.EventHandler(this.mnuMinimapToPNG_Click);
|
||||
//
|
||||
// toolStripSeparator3
|
||||
//
|
||||
this.toolStripSeparator3.Name = "toolStripSeparator3";
|
||||
this.toolStripSeparator3.Size = new System.Drawing.Size(122, 6);
|
||||
//
|
||||
// exotToolStripMenuItem
|
||||
//
|
||||
this.exotToolStripMenuItem.Name = "exotToolStripMenuItem";
|
||||
this.exotToolStripMenuItem.Size = new System.Drawing.Size(125, 22);
|
||||
this.exotToolStripMenuItem.Text = "E&xit";
|
||||
this.exotToolStripMenuItem.Click += new System.EventHandler(this.CloseClicked);
|
||||
//
|
||||
// mapToolStripMenuItem
|
||||
//
|
||||
this.mapToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.propertiesToolStripMenuItem,
|
||||
this.resizeToolStripMenuItem,
|
||||
this.toolStripSeparator4,
|
||||
this.spawnpointsToolStripMenuItem});
|
||||
this.mapToolStripMenuItem.Name = "mapToolStripMenuItem";
|
||||
this.mapToolStripMenuItem.Size = new System.Drawing.Size(43, 20);
|
||||
this.mapToolStripMenuItem.Text = "&Map";
|
||||
//
|
||||
// propertiesToolStripMenuItem
|
||||
//
|
||||
this.propertiesToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("propertiesToolStripMenuItem.Image")));
|
||||
this.propertiesToolStripMenuItem.Name = "propertiesToolStripMenuItem";
|
||||
this.propertiesToolStripMenuItem.Size = new System.Drawing.Size(142, 22);
|
||||
this.propertiesToolStripMenuItem.Text = "&Properties...";
|
||||
this.propertiesToolStripMenuItem.Click += new System.EventHandler(this.PropertiesClicked);
|
||||
//
|
||||
// resizeToolStripMenuItem
|
||||
//
|
||||
this.resizeToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("resizeToolStripMenuItem.Image")));
|
||||
this.resizeToolStripMenuItem.Name = "resizeToolStripMenuItem";
|
||||
this.resizeToolStripMenuItem.Size = new System.Drawing.Size(142, 22);
|
||||
this.resizeToolStripMenuItem.Text = "&Resize...";
|
||||
this.resizeToolStripMenuItem.Click += new System.EventHandler(this.ResizeClicked);
|
||||
//
|
||||
// toolStripSeparator4
|
||||
//
|
||||
this.toolStripSeparator4.Name = "toolStripSeparator4";
|
||||
this.toolStripSeparator4.Size = new System.Drawing.Size(139, 6);
|
||||
//
|
||||
// spawnpointsToolStripMenuItem
|
||||
//
|
||||
this.spawnpointsToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("spawnpointsToolStripMenuItem.Image")));
|
||||
this.spawnpointsToolStripMenuItem.Name = "spawnpointsToolStripMenuItem";
|
||||
this.spawnpointsToolStripMenuItem.Size = new System.Drawing.Size(142, 22);
|
||||
this.spawnpointsToolStripMenuItem.Text = "&Spawnpoints";
|
||||
this.spawnpointsToolStripMenuItem.Click += new System.EventHandler(this.SpawnPointsClicked);
|
||||
//
|
||||
// tt
|
||||
//
|
||||
this.tt.ShowAlways = true;
|
||||
//
|
||||
// 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, 681);
|
||||
this.surface1.TabIndex = 5;
|
||||
this.surface1.Text = "surface1";
|
||||
//
|
||||
// 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.KeyPreview = true;
|
||||
this.MainMenuStrip = this.menuStrip1;
|
||||
this.Name = "Form1";
|
||||
this.Text = "OpenRA Editor";
|
||||
this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyUp);
|
||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.OnFormClosing);
|
||||
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);
|
||||
this.toolStripContainer1.ContentPanel.ResumeLayout(false);
|
||||
this.toolStripContainer1.TopToolStripPanel.ResumeLayout(false);
|
||||
this.toolStripContainer1.TopToolStripPanel.PerformLayout();
|
||||
this.toolStripContainer1.ResumeLayout(false);
|
||||
this.toolStripContainer1.PerformLayout();
|
||||
this.splitContainer1.Panel1.ResumeLayout(false);
|
||||
this.splitContainer1.Panel2.ResumeLayout(false);
|
||||
this.splitContainer1.ResumeLayout(false);
|
||||
this.tabControl1.ResumeLayout(false);
|
||||
this.tabPage1.ResumeLayout(false);
|
||||
this.tabPage2.ResumeLayout(false);
|
||||
this.tabPage3.ResumeLayout(false);
|
||||
this.menuStrip1.ResumeLayout(false);
|
||||
this.menuStrip1.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
this.mapToolStripMenuItem.Name = "mapToolStripMenuItem";
|
||||
this.mapToolStripMenuItem.Size = new System.Drawing.Size(39, 20);
|
||||
this.mapToolStripMenuItem.Text = "&Map";
|
||||
//
|
||||
// propertiesToolStripMenuItem
|
||||
//
|
||||
this.propertiesToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("propertiesToolStripMenuItem.Image")));
|
||||
this.propertiesToolStripMenuItem.Name = "propertiesToolStripMenuItem";
|
||||
this.propertiesToolStripMenuItem.Size = new System.Drawing.Size(135, 22);
|
||||
this.propertiesToolStripMenuItem.Text = "&Properties...";
|
||||
this.propertiesToolStripMenuItem.Click += new System.EventHandler(this.PropertiesClicked);
|
||||
//
|
||||
// resizeToolStripMenuItem
|
||||
//
|
||||
this.resizeToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("resizeToolStripMenuItem.Image")));
|
||||
this.resizeToolStripMenuItem.Name = "resizeToolStripMenuItem";
|
||||
this.resizeToolStripMenuItem.Size = new System.Drawing.Size(135, 22);
|
||||
this.resizeToolStripMenuItem.Text = "&Resize...";
|
||||
this.resizeToolStripMenuItem.Click += new System.EventHandler(this.ResizeClicked);
|
||||
//
|
||||
// toolStripSeparator4
|
||||
//
|
||||
this.toolStripSeparator4.Name = "toolStripSeparator4";
|
||||
this.toolStripSeparator4.Size = new System.Drawing.Size(132, 6);
|
||||
//
|
||||
// spawnpointsToolStripMenuItem
|
||||
//
|
||||
this.spawnpointsToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("spawnpointsToolStripMenuItem.Image")));
|
||||
this.spawnpointsToolStripMenuItem.Name = "spawnpointsToolStripMenuItem";
|
||||
this.spawnpointsToolStripMenuItem.Size = new System.Drawing.Size(135, 22);
|
||||
this.spawnpointsToolStripMenuItem.Text = "&Spawnpoints";
|
||||
this.spawnpointsToolStripMenuItem.Click += new System.EventHandler(this.SpawnPointsClicked);
|
||||
//
|
||||
// toolsToolStripMenuItem
|
||||
//
|
||||
this.toolsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.layersFloaterToolStripMenuItem});
|
||||
this.toolsToolStripMenuItem.Name = "toolsToolStripMenuItem";
|
||||
this.toolsToolStripMenuItem.Size = new System.Drawing.Size(44, 20);
|
||||
this.toolsToolStripMenuItem.Text = "Tools";
|
||||
this.toolsToolStripMenuItem.Visible = false;
|
||||
//
|
||||
// layersFloaterToolStripMenuItem
|
||||
//
|
||||
this.layersFloaterToolStripMenuItem.Name = "layersFloaterToolStripMenuItem";
|
||||
this.layersFloaterToolStripMenuItem.Size = new System.Drawing.Size(141, 22);
|
||||
this.layersFloaterToolStripMenuItem.Text = "Layers floater";
|
||||
this.layersFloaterToolStripMenuItem.Click += new System.EventHandler(this.layersFloaterToolStripMenuItem_Click);
|
||||
//
|
||||
// tt
|
||||
//
|
||||
this.tt.ShowAlways = true;
|
||||
//
|
||||
// statusStrip1
|
||||
//
|
||||
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 = 2;
|
||||
this.statusStrip1.Text = "statusStrip1";
|
||||
//
|
||||
// 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, 727);
|
||||
this.surface1.TabIndex = 5;
|
||||
this.surface1.Text = "surface1";
|
||||
this.surface1.Click += new System.EventHandler(this.OnSurfaceClicked);
|
||||
//
|
||||
// saveFileDialog
|
||||
//
|
||||
this.saveFileDialog.DefaultExt = "*.png";
|
||||
this.saveFileDialog.Filter = "PNG Image (*.png)|";
|
||||
this.saveFileDialog.Title = "Export minimap to PNG";
|
||||
//
|
||||
// Form1
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(985, 773);
|
||||
this.Controls.Add(this.statusStrip1);
|
||||
this.Controls.Add(this.toolStripContainer1);
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.KeyPreview = true;
|
||||
this.MainMenuStrip = this.menuStrip1;
|
||||
this.Name = "Form1";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "OpenRA Editor";
|
||||
this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyUp);
|
||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.OnFormClosing);
|
||||
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);
|
||||
this.toolStripContainer1.ContentPanel.ResumeLayout(false);
|
||||
this.toolStripContainer1.TopToolStripPanel.ResumeLayout(false);
|
||||
this.toolStripContainer1.TopToolStripPanel.PerformLayout();
|
||||
this.toolStripContainer1.ResumeLayout(false);
|
||||
this.toolStripContainer1.PerformLayout();
|
||||
this.splitContainer1.Panel1.ResumeLayout(false);
|
||||
this.splitContainer1.Panel2.ResumeLayout(false);
|
||||
this.splitContainer1.ResumeLayout(false);
|
||||
this.splitContainer2.Panel1.ResumeLayout(false);
|
||||
this.splitContainer2.Panel2.ResumeLayout(false);
|
||||
this.splitContainer2.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.pmMiniMap)).EndInit();
|
||||
this.tabControl1.ResumeLayout(false);
|
||||
this.tabPage1.ResumeLayout(false);
|
||||
this.tabPage2.ResumeLayout(false);
|
||||
this.tabPage3.ResumeLayout(false);
|
||||
this.menuStrip1.ResumeLayout(false);
|
||||
this.menuStrip1.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
@@ -385,8 +487,7 @@
|
||||
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.MenuStrip menuStrip1;
|
||||
private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem;
|
||||
@@ -405,7 +506,15 @@
|
||||
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 spawnpointsToolStripMenuItem;
|
||||
private System.Windows.Forms.StatusStrip statusStrip1;
|
||||
private System.Windows.Forms.ToolStripMenuItem toolsToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem layersFloaterToolStripMenuItem;
|
||||
private System.Windows.Forms.PictureBox pmMiniMap;
|
||||
private System.Windows.Forms.SplitContainer splitContainer2;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuExport;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuMinimapToPNG;
|
||||
private System.Windows.Forms.SaveFileDialog saveFileDialog;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,12 +11,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Editor
|
||||
@@ -32,23 +31,17 @@ namespace OpenRA.Editor
|
||||
|
||||
Text = "OpenRA Editor (mod:{0})".F(currentMod);
|
||||
|
||||
var manifest = new Manifest(new[] { currentMod });
|
||||
Game.LoadModAssemblies(manifest);
|
||||
Game.modData = new ModData(currentMod);
|
||||
|
||||
FileSystem.UnmountAll();
|
||||
foreach (var folder in manifest.Folders) FileSystem.Mount(folder);
|
||||
foreach (var pkg in manifest.Packages) FileSystem.Mount(pkg);
|
||||
|
||||
Rules.LoadRules(manifest, new Map());
|
||||
|
||||
folderBrowser.SelectedPath = new string[] { Environment.CurrentDirectory, "mods", currentMod, "maps" }
|
||||
.Aggregate(Path.Combine);
|
||||
Rules.LoadRules(Game.modData.Manifest, new Map());
|
||||
|
||||
surface1.AfterChange += MakeDirty;
|
||||
|
||||
string path = Directory.GetCurrentDirectory();
|
||||
Icon = new Icon(path + Path.DirectorySeparatorChar + "OpenRA.Editor" + Path.DirectorySeparatorChar + "OpenRA.Editor.Icon.ico");
|
||||
}
|
||||
|
||||
void MakeDirty() { dirty = true; }
|
||||
|
||||
string loadedMapName;
|
||||
string currentMod = "ra";
|
||||
TileSet tileset;
|
||||
@@ -62,12 +55,7 @@ namespace OpenRA.Editor
|
||||
|
||||
loadedMapName = mapname;
|
||||
|
||||
var manifest = new Manifest(new[] { currentMod });
|
||||
Game.LoadModAssemblies(manifest);
|
||||
|
||||
FileSystem.UnmountAll();
|
||||
foreach (var folder in manifest.Folders) FileSystem.Mount(folder);
|
||||
foreach (var pkg in manifest.Packages) FileSystem.Mount(pkg);
|
||||
Game.modData = new ModData(currentMod);
|
||||
|
||||
// load the map
|
||||
var map = new Map(new Folder(mapname));
|
||||
@@ -78,7 +66,7 @@ namespace OpenRA.Editor
|
||||
map.Players.Add("Neutral", new PlayerReference("Neutral",
|
||||
Rules.Info["world"].Traits.WithInterface<CountryInfo>().First().Race, true, true));
|
||||
|
||||
PrepareMapResources(manifest, map);
|
||||
PrepareMapResources(Game.modData.Manifest, map);
|
||||
|
||||
dirty = false;
|
||||
}
|
||||
@@ -91,36 +79,31 @@ namespace OpenRA.Editor
|
||||
|
||||
loadedMapName = null;
|
||||
|
||||
var manifest = new Manifest(new[] { currentMod });
|
||||
Game.LoadModAssemblies(manifest);
|
||||
Game.modData = new ModData(currentMod);
|
||||
|
||||
FileSystem.UnmountAll();
|
||||
foreach (var folder in manifest.Folders) FileSystem.Mount(folder);
|
||||
foreach (var pkg in manifest.Packages) FileSystem.Mount(pkg);
|
||||
|
||||
PrepareMapResources(manifest, map);
|
||||
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);
|
||||
Rules.LoadRules(manifest, map);
|
||||
tileset = Rules.TileSets[map.Theater];
|
||||
tileset.LoadTiles();
|
||||
var palette = new Palette(FileSystem.Open(tileset.Palette), true);
|
||||
|
||||
surface1.Bind(map, tileset, palette);
|
||||
|
||||
surface1.Bind(map, tileset, palette);
|
||||
// construct the palette of tiles
|
||||
var palettes = new[] { tilePalette, actorPalette, resourcePalette };
|
||||
foreach (var p in palettes) { p.Visible = false; p.SuspendLayout(); }
|
||||
|
||||
foreach (var t in tileset.Templates)
|
||||
{
|
||||
try
|
||||
{
|
||||
var bitmap = RenderTemplate(tileset, (ushort)t.Key, palette);
|
||||
var bitmap = RenderUtils.RenderTemplate(tileset, (ushort)t.Key, palette);
|
||||
var ibox = new PictureBox
|
||||
{
|
||||
Image = bitmap,
|
||||
@@ -134,7 +117,6 @@ namespace OpenRA.Editor
|
||||
|
||||
var template = t.Value;
|
||||
tilePalette.Controls.Add(ibox);
|
||||
|
||||
tt.SetToolTip(ibox,
|
||||
"{1}:{0} ({2}x{3})".F(
|
||||
template.Image,
|
||||
@@ -152,24 +134,25 @@ 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);
|
||||
|
||||
actorPalette.Controls.Add(ibox);
|
||||
|
||||
tt.SetToolTip(ibox,
|
||||
"{0}:{1}".F(
|
||||
info.Name,
|
||||
info.Category));
|
||||
"{0}".F(
|
||||
info.Name));
|
||||
|
||||
actorTemplates.Add(template);
|
||||
}
|
||||
@@ -184,15 +167,18 @@ namespace OpenRA.Editor
|
||||
{
|
||||
try
|
||||
{
|
||||
var template = RenderResourceType(a, tileset.Extensions, palette);
|
||||
var template = RenderUtils.RenderResourceType(a, tileset.Extensions, palette);
|
||||
var ibox = new PictureBox
|
||||
{
|
||||
Image = template.Bitmap,
|
||||
Width = template.Bitmap.Width,
|
||||
Height = template.Bitmap.Height,
|
||||
SizeMode = PictureBoxSizeMode.StretchImage
|
||||
Width = 32,
|
||||
Height = 32,
|
||||
SizeMode = PictureBoxSizeMode.Zoom,
|
||||
BorderStyle = BorderStyle.FixedSingle
|
||||
};
|
||||
|
||||
|
||||
|
||||
ibox.Click += (_, e) => surface1.SetResource(template);
|
||||
|
||||
resourcePalette.Controls.Add(ibox);
|
||||
@@ -209,103 +195,12 @@ namespace OpenRA.Editor
|
||||
|
||||
surface1.BindResourceTemplates(resourceTemplates);
|
||||
|
||||
foreach (var p in palettes) { p.Visible = true; p.ResumeLayout(); }
|
||||
}
|
||||
|
||||
static Bitmap RenderTemplate(TileSet ts, ushort n, Palette p)
|
||||
{
|
||||
var template = ts.Templates[n];
|
||||
var tile = ts.Tiles[n];
|
||||
|
||||
var bitmap = new Bitmap(24 * template.Size.X, 24 * template.Size.Y);
|
||||
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
|
||||
|
||||
unsafe
|
||||
foreach (var p in palettes)
|
||||
{
|
||||
int* q = (int*)data.Scan0.ToPointer();
|
||||
var stride = data.Stride >> 2;
|
||||
|
||||
for (var u = 0; u < template.Size.X; u++)
|
||||
for (var v = 0; v < template.Size.Y; v++)
|
||||
if (tile.TileBitmapBytes[u + v * template.Size.X] != null)
|
||||
{
|
||||
var rawImage = tile.TileBitmapBytes[u + v * template.Size.X];
|
||||
for (var i = 0; i < 24; i++)
|
||||
for (var j = 0; j < 24; j++)
|
||||
q[(v * 24 + j) * stride + u * 24 + i] = p.GetColor(rawImage[i + 24 * j]).ToArgb();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < 24; i++)
|
||||
for (var j = 0; j < 24; j++)
|
||||
q[(v * 24 + j) * stride + u * 24 + i] = Color.Transparent.ToArgb();
|
||||
}
|
||||
}
|
||||
|
||||
bitmap.UnlockBits(data);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
static ActorTemplate RenderActor(ActorInfo info, TileSet tileset, Palette p)
|
||||
{
|
||||
var ri = info.Traits.Get<RenderSimpleInfo>();
|
||||
string image = null;
|
||||
if (ri.OverrideTheater != null)
|
||||
for (int i = 0; i < ri.OverrideTheater.Length; i++)
|
||||
if (ri.OverrideTheater[i] == tileset.Id)
|
||||
image = ri.OverrideImage[i];
|
||||
|
||||
image = image ?? ri.Image ?? info.Name;
|
||||
using (var s = FileSystem.OpenWithExts(image, tileset.Extensions))
|
||||
{
|
||||
var shp = new ShpReader(s);
|
||||
var frame = shp[0];
|
||||
|
||||
var bitmap = new Bitmap(shp.Width, shp.Height);
|
||||
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
|
||||
|
||||
unsafe
|
||||
{
|
||||
int* q = (int*)data.Scan0.ToPointer();
|
||||
var stride = data.Stride >> 2;
|
||||
|
||||
for (var i = 0; i < shp.Width; i++)
|
||||
for (var j = 0; j < shp.Height; j++)
|
||||
q[j * stride + i] = p.GetColor(frame.Image[i + shp.Width * j]).ToArgb();
|
||||
}
|
||||
|
||||
bitmap.UnlockBits(data);
|
||||
return new ActorTemplate { Bitmap = bitmap, Info = info, Centered = !info.Traits.Contains<BuildingInfo>() };
|
||||
}
|
||||
}
|
||||
|
||||
static ResourceTemplate RenderResourceType(ResourceTypeInfo info, string[] exts, Palette p)
|
||||
{
|
||||
var image = info.SpriteNames[0];
|
||||
using (var s = FileSystem.OpenWithExts(image, exts))
|
||||
{
|
||||
var shp = new ShpReader(s);
|
||||
var frame = shp[shp.ImageCount - 1];
|
||||
|
||||
var bitmap = new Bitmap(shp.Width, shp.Height);
|
||||
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
|
||||
|
||||
unsafe
|
||||
{
|
||||
int* q = (int*)data.Scan0.ToPointer();
|
||||
var stride = data.Stride >> 2;
|
||||
|
||||
for (var i = 0; i < shp.Width; i++)
|
||||
for (var j = 0; j < shp.Height; j++)
|
||||
q[j * stride + i] = p.GetColor(frame.Image[i + shp.Width * j]).ToArgb();
|
||||
}
|
||||
|
||||
bitmap.UnlockBits(data);
|
||||
return new ResourceTemplate { Bitmap = bitmap, Info = info, Value = shp.ImageCount - 1 };
|
||||
p.Visible = true;
|
||||
p.ResumeLayout();
|
||||
}
|
||||
pmMiniMap.Image = Minimap.AddStaticResources(surface1.Map, Minimap.TerrainBitmap(surface1.Map, true));
|
||||
}
|
||||
|
||||
void ResizeClicked(object sender, EventArgs e)
|
||||
@@ -334,7 +229,7 @@ namespace OpenRA.Editor
|
||||
surface1.Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SaveClicked(object sender, EventArgs e)
|
||||
{
|
||||
if (loadedMapName == null)
|
||||
@@ -344,28 +239,62 @@ namespace OpenRA.Editor
|
||||
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())
|
||||
{
|
||||
loadedMapName = folderBrowser.SelectedPath;
|
||||
SaveClicked(sender, e);
|
||||
nms.MapFolderPath = new string[] { Environment.CurrentDirectory, "mods", currentMod, "maps" }
|
||||
.Aggregate(Path.Combine);
|
||||
|
||||
nms.txtNew.ReadOnly = false;
|
||||
nms.btnOk.Text = "Save";
|
||||
nms.txtNew.Text = "unnamed";
|
||||
nms.txtPathOut.ReadOnly = false;
|
||||
|
||||
if (DialogResult.OK == nms.ShowDialog())
|
||||
{
|
||||
if (nms.txtNew.Text == "")
|
||||
nms.txtNew.Text = "unnamed";
|
||||
|
||||
string mapfoldername = Path.Combine(nms.MapFolderPath, nms.txtNew.Text);
|
||||
loadedMapName = mapfoldername;
|
||||
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(mapfoldername);
|
||||
}
|
||||
catch (Exception ed)
|
||||
{
|
||||
MessageBox.Show("Directory creation failed: {0}", ed.ToString());
|
||||
}
|
||||
|
||||
SaveClicked(sender, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OpenClicked(object sender, EventArgs e)
|
||||
{
|
||||
folderBrowser.ShowNewFolderButton = true;
|
||||
using (var nms = new MapSelect())
|
||||
{
|
||||
nms.MapFolderPath = new string[] { Environment.CurrentDirectory, "mods", currentMod, "maps" }
|
||||
.Aggregate(Path.Combine);
|
||||
|
||||
if (DialogResult.OK == folderBrowser.ShowDialog())
|
||||
LoadMap(folderBrowser.SelectedPath);
|
||||
nms.txtNew.ReadOnly = true;
|
||||
nms.txtPathOut.ReadOnly = true;
|
||||
nms.btnOk.Text = "Open";
|
||||
|
||||
if (DialogResult.OK == nms.ShowDialog())
|
||||
{
|
||||
string mapfoldername = Path.Combine(nms.MapFolderPath, nms.txtNew.Text);
|
||||
LoadMap(mapfoldername);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NewClicked(object sender, EventArgs e)
|
||||
@@ -378,13 +307,12 @@ namespace OpenRA.Editor
|
||||
|
||||
if (DialogResult.OK == nmd.ShowDialog())
|
||||
{
|
||||
var map = new Map();
|
||||
var map = new Map(nmd.theater.SelectedItem as string);
|
||||
|
||||
map.Resize((int)nmd.width.Value, (int)nmd.height.Value);
|
||||
|
||||
map.TopLeft = new int2((int)nmd.cordonLeft.Value, (int)nmd.cordonTop.Value);
|
||||
map.BottomRight = new int2((int)nmd.cordonRight.Value, (int)nmd.cordonBottom.Value);
|
||||
map.Tileset = nmd.theater.SelectedItem as string;
|
||||
map.Players.Add("Neutral", new PlayerReference("Neutral", Rules.Info["world"].Traits.WithInterface<CountryInfo>().First().Race, true, true));
|
||||
NewMap(map);
|
||||
}
|
||||
@@ -432,9 +360,9 @@ namespace OpenRA.Editor
|
||||
|
||||
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 */
|
||||
@@ -448,7 +376,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;
|
||||
@@ -456,5 +384,43 @@ namespace OpenRA.Editor
|
||||
case DialogResult.Cancel: e.Cancel = true; break;
|
||||
}
|
||||
}
|
||||
|
||||
private void layersFloaterToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
var pb = new PaletteBox();
|
||||
pb.Show();
|
||||
}
|
||||
|
||||
private void OnSurfaceClicked(object sender, EventArgs e)
|
||||
{
|
||||
pmMiniMap.Image = Minimap.AddStaticResources(surface1.Map, Minimap.TerrainBitmap(surface1.Map, true));
|
||||
}
|
||||
|
||||
private void mnuMinimapToPNG_Click(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
saveFileDialog.InitialDirectory = new string[] { Environment.CurrentDirectory, "maps" }
|
||||
.Aggregate(Path.Combine);
|
||||
|
||||
FileInfo file = new FileInfo(loadedMapName + ".png");
|
||||
string name = file.Name;
|
||||
saveFileDialog.FileName = name;
|
||||
|
||||
saveFileDialog.ShowDialog();
|
||||
if (saveFileDialog.FileName == "")
|
||||
{
|
||||
saveFileDialog.FileName = name;
|
||||
}
|
||||
else
|
||||
{
|
||||
Bitmap png = new Bitmap(pmMiniMap.Image);
|
||||
|
||||
png.Save(saveFileDialog.FileName, System.Drawing.Imaging.ImageFormat.Png);
|
||||
}
|
||||
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<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 +237,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">
|
||||
@@ -291,7 +308,250 @@
|
||||
<metadata name="tt.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<metadata name="folderBrowser.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>182, 17</value>
|
||||
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>307, 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="$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>
|
||||
@@ -15,6 +15,8 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using OpenRA;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Traits;
|
||||
using System.Drawing;
|
||||
|
||||
namespace OpenRA.Editor
|
||||
{
|
||||
@@ -79,11 +81,26 @@ namespace OpenRA.Editor
|
||||
// {"wcrate","crate"},
|
||||
// {"scrate","crate"},
|
||||
};
|
||||
|
||||
|
||||
static Dictionary<string,Pair<Color,Color>> namedColorMapping = new Dictionary<string, Pair<Color, Color>>()
|
||||
{
|
||||
{"gold",Pair.New(Color.FromArgb(246,214,121),Color.FromArgb(40,32,8))},
|
||||
{"blue",Pair.New(Color.FromArgb(226,230,246),Color.FromArgb(8,20,52))},
|
||||
{"red",Pair.New(Color.FromArgb(255,20,0),Color.FromArgb(56,0,0))},
|
||||
{"neutral",Pair.New(Color.FromArgb(238,238,238),Color.FromArgb(44,28,24))},
|
||||
{"orange",Pair.New(Color.FromArgb(255,230,149),Color.FromArgb(56,0,0))},
|
||||
{"teal",Pair.New(Color.FromArgb(93,194,165),Color.FromArgb(0,32,32))},
|
||||
{"salmon",Pair.New(Color.FromArgb(210,153,125),Color.FromArgb(56,0,0))},
|
||||
{"green",Pair.New(Color.FromArgb(160,240,140),Color.FromArgb(20,20,20))},
|
||||
{"white",Pair.New(Color.FromArgb(255,255,255),Color.FromArgb(75,75,75))},
|
||||
{"black",Pair.New(Color.FromArgb(80,80,80),Color.FromArgb(5,5,5))},
|
||||
};
|
||||
|
||||
int MapSize;
|
||||
int ActorCount = 0;
|
||||
Map Map = new Map();
|
||||
|
||||
List<string> Players = new List<string>();
|
||||
|
||||
LegacyMapImporter(string filename)
|
||||
{
|
||||
ConvertIniMap(filename);
|
||||
@@ -96,7 +113,7 @@ namespace OpenRA.Editor
|
||||
}
|
||||
|
||||
enum IniMapFormat { RedAlert = 3, /* otherwise, cnc (2 variants exist, we don't care to differentiate) */ };
|
||||
|
||||
|
||||
public void ConvertIniMap(string iniFile)
|
||||
{
|
||||
var file = new IniFile(FileSystem.Open(iniFile));
|
||||
@@ -123,17 +140,12 @@ namespace OpenRA.Editor
|
||||
UnpackRATileData(ReadPackedSection(file.GetSection("MapPack")));
|
||||
UnpackRAOverlayData(ReadPackedSection(file.GetSection("OverlayPack")));
|
||||
ReadRATrees(file);
|
||||
// TODO: Fixme
|
||||
//tileset = new TileSet("tileSet.til","templates.ini",fileMapping[Pair.New("ra",Map.Tileset)].First);
|
||||
}
|
||||
else // CNC
|
||||
{
|
||||
UnpackCncTileData(FileSystem.Open(iniFile.Substring(0, iniFile.Length - 4) + ".bin"));
|
||||
ReadCncOverlay(file);
|
||||
ReadCncTrees(file);
|
||||
|
||||
// TODO: Fixme
|
||||
//tileset = new TileSet("tileSet.til","templates.ini",fileMapping[Pair.New("cnc",Map.Tileset)].First);
|
||||
}
|
||||
|
||||
LoadActors(file, "STRUCTURES");
|
||||
@@ -141,11 +153,13 @@ namespace OpenRA.Editor
|
||||
LoadActors(file, "INFANTRY");
|
||||
LoadSmudges(file, "SMUDGE");
|
||||
|
||||
foreach (var p in Players)
|
||||
LoadPlayer(file, p, (legacyMapFormat == IniMapFormat.RedAlert));
|
||||
|
||||
var wp = file.GetSection("Waypoints")
|
||||
.Where(kv => int.Parse(kv.Value) > 0)
|
||||
.Select(kv => Pair.New(int.Parse(kv.Key),
|
||||
LocationFromMapOffset(int.Parse(kv.Value), MapSize)))
|
||||
.Where(a => a.First < 8)
|
||||
.ToArray();
|
||||
|
||||
Map.PlayerCount = wp.Count();
|
||||
@@ -251,7 +265,7 @@ namespace OpenRA.Editor
|
||||
Map.MapResources[i, j] = new TileReference<byte, byte>(res.First, res.Second);
|
||||
|
||||
if (o != 255 && overlayActorMapping.ContainsKey(raOverlayNames[o]))
|
||||
Map.Actors.Add("Actor" + ActorCount,
|
||||
Map.Actors.Add("Actor" + ActorCount++,
|
||||
new ActorReference(overlayActorMapping[raOverlayNames[o]])
|
||||
{
|
||||
new LocationInit( new int2(i, j) ),
|
||||
@@ -269,7 +283,7 @@ namespace OpenRA.Editor
|
||||
foreach (KeyValuePair<string, string> kv in terrain)
|
||||
{
|
||||
var loc = int.Parse(kv.Key);
|
||||
Map.Actors.Add("Actor" + ActorCount,
|
||||
Map.Actors.Add("Actor" + ActorCount++,
|
||||
new ActorReference(kv.Value.ToLowerInvariant())
|
||||
{
|
||||
new LocationInit(new int2(loc % MapSize, loc / MapSize)),
|
||||
@@ -315,7 +329,7 @@ namespace OpenRA.Editor
|
||||
Map.MapResources[cell.X, cell.Y] = new TileReference<byte, byte>(res.First, res.Second);
|
||||
|
||||
if (overlayActorMapping.ContainsKey(kv.Value.ToLower()))
|
||||
Map.Actors.Add("Actor" + ActorCount,
|
||||
Map.Actors.Add("Actor" + ActorCount++,
|
||||
new ActorReference(overlayActorMapping[kv.Value.ToLower()])
|
||||
{
|
||||
new LocationInit(cell),
|
||||
@@ -333,7 +347,7 @@ namespace OpenRA.Editor
|
||||
foreach (KeyValuePair<string, string> kv in terrain)
|
||||
{
|
||||
var loc = int.Parse(kv.Key);
|
||||
Map.Actors.Add("Actor" + ActorCount,
|
||||
Map.Actors.Add("Actor" + ActorCount++,
|
||||
new ActorReference(kv.Value.Split(',')[0].ToLowerInvariant())
|
||||
{
|
||||
new LocationInit(new int2(loc % MapSize, loc / MapSize)),
|
||||
@@ -346,17 +360,57 @@ namespace OpenRA.Editor
|
||||
{
|
||||
foreach (var s in file.GetSection(section, true))
|
||||
{
|
||||
//num=owner,type,health,location,facing,...
|
||||
//Structures: num=owner,type,health,location,turret-facing,trigger
|
||||
//Units: num=owner,type,health,location,facing,action,trigger
|
||||
//Infantry: num=owner,type,health,location,subcell,action,facing,trigger
|
||||
var parts = s.Value.Split(',');
|
||||
var loc = int.Parse(parts[3]);
|
||||
if (parts[0] == "")
|
||||
parts[0] = "Neutral";
|
||||
Map.Actors.Add("Actor" + ActorCount,
|
||||
new ActorReference(parts[1].ToLowerInvariant())
|
||||
{
|
||||
new LocationInit(new int2(loc % MapSize, loc / MapSize)),
|
||||
new OwnerInit(parts[0])
|
||||
});
|
||||
|
||||
|
||||
if (!Players.Contains(parts[0]))
|
||||
Players.Add(parts[0]);
|
||||
|
||||
var stance = ActorStance.Stance.None;
|
||||
switch(parts[5])
|
||||
{
|
||||
case "Area Guard":
|
||||
case "Guard":
|
||||
stance = ActorStance.Stance.Guard;
|
||||
break;
|
||||
case "Defend Base":
|
||||
stance = ActorStance.Stance.Defend;
|
||||
break;
|
||||
case "Hunt":
|
||||
case "Rampage":
|
||||
case "Attack Base":
|
||||
case "Attack Units":
|
||||
case "Attack Civil.":
|
||||
case "Attack Tarcom":
|
||||
stance = ActorStance.Stance.Hunt;
|
||||
break;
|
||||
case "Retreat":
|
||||
case "Return":
|
||||
stance = ActorStance.Stance.Retreat;
|
||||
break;
|
||||
// do we care about `Harvest' and `Sticky'?
|
||||
}
|
||||
|
||||
var actor = new ActorReference(parts[1].ToLowerInvariant())
|
||||
{
|
||||
new LocationInit(new int2(loc % MapSize, loc / MapSize)),
|
||||
new OwnerInit(parts[0]),
|
||||
new HealthInit(float.Parse(parts[2])/256),
|
||||
new FacingInit((section == "INFANTRY") ? int.Parse(parts[6]) : int.Parse(parts[4])),
|
||||
new ActorStanceInit(stance),
|
||||
};
|
||||
|
||||
if (section == "INFANTRY")
|
||||
actor.Add(new SubcellInit(int.Parse(parts[4])));
|
||||
|
||||
Map.Actors.Add("Actor" + ActorCount++,actor);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,6 +424,42 @@ namespace OpenRA.Editor
|
||||
Map.Smudges.Add(new SmudgeReference(parts[0].ToLowerInvariant(), new int2(loc % MapSize, loc / MapSize), int.Parse(parts[2])));
|
||||
}
|
||||
}
|
||||
|
||||
void LoadPlayer(IniFile file, string section, bool isRA)
|
||||
{
|
||||
var c = (section == "BadGuy") ? "red" :
|
||||
(isRA) ? "blue" : "gold";
|
||||
|
||||
var color = namedColorMapping[c];
|
||||
|
||||
var pr = new PlayerReference
|
||||
{
|
||||
Name = section,
|
||||
OwnsWorld = (section == "Neutral"),
|
||||
NonCombatant = (section == "Neutral"),
|
||||
Race = (isRA) ? ((section == "BadGuy") ? "soviet" : "allies") : ((section == "BadGuy") ? "nod" : "gdi"),
|
||||
Color = color.First,
|
||||
Color2 = color.Second,
|
||||
};
|
||||
|
||||
var Neutral = new List<string>(){"Neutral"};
|
||||
foreach (var s in file.GetSection(section, true))
|
||||
{
|
||||
Console.WriteLine(s.Key);
|
||||
switch(s.Key)
|
||||
{
|
||||
case "Credits":
|
||||
pr.InitialCash = int.Parse(s.Value);
|
||||
break;
|
||||
case "Allies":
|
||||
pr.Allies = s.Value.Split(',').Intersect(Players).Except(Neutral).ToArray();
|
||||
pr.Enemies = s.Value.Split(',').SymmetricDifference(Players).Except(Neutral).ToArray();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Map.Players.Add(section, pr);
|
||||
}
|
||||
|
||||
static string Truncate(string s, int maxLength)
|
||||
{
|
||||
|
||||
360
OpenRA.Editor/MapSelect.Designer.cs
generated
Normal file
360
OpenRA.Editor/MapSelect.Designer.cs
generated
Normal file
@@ -0,0 +1,360 @@
|
||||
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();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pbMinimap)).BeginInit();
|
||||
this.pnlBottom.SuspendLayout();
|
||||
this.splitContainer1.Panel1.SuspendLayout();
|
||||
this.splitContainer1.Panel2.SuspendLayout();
|
||||
this.splitContainer1.SuspendLayout();
|
||||
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.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("MapIconsList.ImageStream")));
|
||||
this.MapIconsList.TransparentColor = System.Drawing.Color.Transparent;
|
||||
this.MapIconsList.Images.SetKeyName(0, "mapicon");
|
||||
//
|
||||
// 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.txtPathOut);
|
||||
this.pnlBottom.Controls.Add(this.lblPathOut);
|
||||
this.pnlBottom.Controls.Add(this.lblPath);
|
||||
this.pnlBottom.Controls.Add(this.btnCancel);
|
||||
this.pnlBottom.Controls.Add(this.btnOk);
|
||||
this.pnlBottom.Controls.Add(this.txtNew);
|
||||
this.pnlBottom.Controls.Add(this.lblNew);
|
||||
this.pnlBottom.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||
this.pnlBottom.Location = new System.Drawing.Point(0, 332);
|
||||
this.pnlBottom.MaximumSize = new System.Drawing.Size(0, 70);
|
||||
this.pnlBottom.Name = "pnlBottom";
|
||||
this.pnlBottom.Size = new System.Drawing.Size(494, 70);
|
||||
this.pnlBottom.TabIndex = 6;
|
||||
//
|
||||
// txtPathOut
|
||||
//
|
||||
this.txtPathOut.BackColor = System.Drawing.SystemColors.Window;
|
||||
this.txtPathOut.Location = new System.Drawing.Point(55, 10);
|
||||
this.txtPathOut.Name = "txtPathOut";
|
||||
this.txtPathOut.ReadOnly = true;
|
||||
this.txtPathOut.Size = new System.Drawing.Size(265, 20);
|
||||
this.txtPathOut.TabIndex = 0;
|
||||
this.txtPathOut.TextChanged += new System.EventHandler(this.txtPathOut_TextChanged);
|
||||
//
|
||||
// lblPathOut
|
||||
//
|
||||
this.lblPathOut.AutoSize = true;
|
||||
this.lblPathOut.Location = new System.Drawing.Point(55, 13);
|
||||
this.lblPathOut.Name = "lblPathOut";
|
||||
this.lblPathOut.Size = new System.Drawing.Size(0, 13);
|
||||
this.lblPathOut.TabIndex = 6;
|
||||
//
|
||||
// lblPath
|
||||
//
|
||||
this.lblPath.AutoSize = true;
|
||||
this.lblPath.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
|
||||
this.lblPath.Location = new System.Drawing.Point(12, 13);
|
||||
this.lblPath.Name = "lblPath";
|
||||
this.lblPath.Size = new System.Drawing.Size(37, 13);
|
||||
this.lblPath.TabIndex = 5;
|
||||
this.lblPath.Text = "Path:";
|
||||
//
|
||||
// splitContainer1
|
||||
//
|
||||
this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.splitContainer1.Location = new System.Drawing.Point(0, 0);
|
||||
this.splitContainer1.Name = "splitContainer1";
|
||||
//
|
||||
// splitContainer1.Panel1
|
||||
//
|
||||
this.splitContainer1.Panel1.Controls.Add(this.lblMapList);
|
||||
this.splitContainer1.Panel1.Controls.Add(this.MapList);
|
||||
//
|
||||
// splitContainer1.Panel2
|
||||
//
|
||||
this.splitContainer1.Panel2.Controls.Add(this.txtDesc);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.lblDesc);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.txtTheater);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.lblTheater);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.txtAuthor);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.lblAuthor);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.txtTitle);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.lblMapName);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.lblMinimap);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.pbMinimap);
|
||||
this.splitContainer1.Size = new System.Drawing.Size(494, 332);
|
||||
this.splitContainer1.SplitterDistance = 300;
|
||||
this.splitContainer1.TabIndex = 7;
|
||||
//
|
||||
// lblMapList
|
||||
//
|
||||
this.lblMapList.AutoSize = true;
|
||||
this.lblMapList.Location = new System.Drawing.Point(12, 9);
|
||||
this.lblMapList.Name = "lblMapList";
|
||||
this.lblMapList.Size = new System.Drawing.Size(81, 13);
|
||||
this.lblMapList.TabIndex = 1;
|
||||
this.lblMapList.Text = "Available maps:";
|
||||
//
|
||||
// txtDesc
|
||||
//
|
||||
this.txtDesc.BackColor = System.Drawing.SystemColors.ButtonFace;
|
||||
this.txtDesc.Location = new System.Drawing.Point(16, 289);
|
||||
this.txtDesc.Name = "txtDesc";
|
||||
this.txtDesc.ReadOnly = true;
|
||||
this.txtDesc.Size = new System.Drawing.Size(162, 20);
|
||||
this.txtDesc.TabIndex = 14;
|
||||
//
|
||||
// lblDesc
|
||||
//
|
||||
this.lblDesc.AutoSize = true;
|
||||
this.lblDesc.Location = new System.Drawing.Point(13, 273);
|
||||
this.lblDesc.Name = "lblDesc";
|
||||
this.lblDesc.Size = new System.Drawing.Size(63, 13);
|
||||
this.lblDesc.TabIndex = 13;
|
||||
this.lblDesc.Text = "Description:";
|
||||
//
|
||||
// txtTheater
|
||||
//
|
||||
this.txtTheater.BackColor = System.Drawing.SystemColors.ButtonFace;
|
||||
this.txtTheater.Location = new System.Drawing.Point(16, 252);
|
||||
this.txtTheater.Name = "txtTheater";
|
||||
this.txtTheater.ReadOnly = true;
|
||||
this.txtTheater.Size = new System.Drawing.Size(162, 20);
|
||||
this.txtTheater.TabIndex = 12;
|
||||
//
|
||||
// lblTheater
|
||||
//
|
||||
this.lblTheater.AutoSize = true;
|
||||
this.lblTheater.Location = new System.Drawing.Point(13, 236);
|
||||
this.lblTheater.Name = "lblTheater";
|
||||
this.lblTheater.Size = new System.Drawing.Size(47, 13);
|
||||
this.lblTheater.TabIndex = 11;
|
||||
this.lblTheater.Text = "Theater:";
|
||||
//
|
||||
// txtAuthor
|
||||
//
|
||||
this.txtAuthor.BackColor = System.Drawing.SystemColors.ButtonFace;
|
||||
this.txtAuthor.Location = new System.Drawing.Point(16, 214);
|
||||
this.txtAuthor.Name = "txtAuthor";
|
||||
this.txtAuthor.ReadOnly = true;
|
||||
this.txtAuthor.Size = new System.Drawing.Size(162, 20);
|
||||
this.txtAuthor.TabIndex = 10;
|
||||
//
|
||||
// lblAuthor
|
||||
//
|
||||
this.lblAuthor.AutoSize = true;
|
||||
this.lblAuthor.Location = new System.Drawing.Point(13, 198);
|
||||
this.lblAuthor.Name = "lblAuthor";
|
||||
this.lblAuthor.Size = new System.Drawing.Size(41, 13);
|
||||
this.lblAuthor.TabIndex = 9;
|
||||
this.lblAuthor.Text = "Author:";
|
||||
//
|
||||
// txtTitle
|
||||
//
|
||||
this.txtTitle.BackColor = System.Drawing.SystemColors.ButtonFace;
|
||||
this.txtTitle.Location = new System.Drawing.Point(16, 177);
|
||||
this.txtTitle.Name = "txtTitle";
|
||||
this.txtTitle.ReadOnly = true;
|
||||
this.txtTitle.Size = new System.Drawing.Size(162, 20);
|
||||
this.txtTitle.TabIndex = 8;
|
||||
//
|
||||
// lblMapName
|
||||
//
|
||||
this.lblMapName.AutoSize = true;
|
||||
this.lblMapName.Location = new System.Drawing.Point(13, 161);
|
||||
this.lblMapName.Name = "lblMapName";
|
||||
this.lblMapName.Size = new System.Drawing.Size(30, 13);
|
||||
this.lblMapName.TabIndex = 7;
|
||||
this.lblMapName.Text = "Title:";
|
||||
//
|
||||
// lblMinimap
|
||||
//
|
||||
this.lblMinimap.AutoSize = true;
|
||||
this.lblMinimap.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
|
||||
this.lblMinimap.Location = new System.Drawing.Point(29, 9);
|
||||
this.lblMinimap.Name = "lblMinimap";
|
||||
this.lblMinimap.Size = new System.Drawing.Size(71, 13);
|
||||
this.lblMinimap.TabIndex = 6;
|
||||
this.lblMinimap.Text = "Map preview:";
|
||||
//
|
||||
// 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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
78
OpenRA.Editor/MapSelect.cs
Normal file
78
OpenRA.Editor/MapSelect.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using OpenRA.FileFormats;
|
||||
using System.Windows.Forms;
|
||||
using System.IO;
|
||||
using OpenRA.Graphics;
|
||||
|
||||
namespace OpenRA.Editor
|
||||
{
|
||||
public partial class MapSelect : Form
|
||||
{
|
||||
public string MapFolderPath;
|
||||
|
||||
public MapSelect()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void MapSelect_Load(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
DirectoryInfo directory = new DirectoryInfo(MapFolderPath);
|
||||
DirectoryInfo[] directories = directory.GetDirectories();
|
||||
MapList.Items.Clear();
|
||||
txtPathOut.Text = MapFolderPath;
|
||||
foreach (DirectoryInfo subDirectory in directories)
|
||||
{
|
||||
ListViewItem map1 = new ListViewItem(subDirectory.Name);
|
||||
map1.ImageIndex = 0;
|
||||
MapList.Items.Add(map1);
|
||||
|
||||
}
|
||||
if (txtNew.Text == "unnamed")
|
||||
{
|
||||
//dumb indian code
|
||||
}
|
||||
else
|
||||
{
|
||||
MapList.Items[0].Selected = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void MapList_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (MapList.SelectedItems.Count == 1)
|
||||
{
|
||||
txtNew.Text = MapList.SelectedItems[0].Text;
|
||||
var map = new Map(new Folder(Path.Combine(MapFolderPath, MapList.SelectedItems[0].Text)));
|
||||
txtTitle.Text = map.Title;
|
||||
txtAuthor.Text = map.Author;
|
||||
txtTheater.Text = map.Theater;
|
||||
txtDesc.Text = map.Description;
|
||||
pbMinimap.Image = null;
|
||||
try
|
||||
{
|
||||
pbMinimap.Image = Minimap.AddStaticResources(map, Minimap.TerrainBitmap(map, true));
|
||||
}
|
||||
catch (Exception ed)
|
||||
{
|
||||
Console.WriteLine("No map preview image found: {0}", ed.ToString());
|
||||
}
|
||||
finally { }
|
||||
}
|
||||
}
|
||||
|
||||
private void txtPathOut_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
MapFolderPath = txtPathOut.Text;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
192
OpenRA.Editor/MapSelect.resx
Normal file
192
OpenRA.Editor/MapSelect.resx
Normal file
@@ -0,0 +1,192 @@
|
||||
<?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>
|
||||
<data name="MapIconsList.ImageStream" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>
|
||||
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0yLjAuMC4w
|
||||
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
|
||||
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAABW
|
||||
DgAAAk1TRnQBSQFMAwEBAAEoAQABKAEAARgBAAEYAQAE/wEhAQAI/wFCAU0BNgcAATYDAAEoAwABYAMA
|
||||
ARgDAAEBAQABIAYAASQhAAEBAx8BLAM/AW8DSQGJAzYBWQMYASIDAQECDAADHQEqA0gBhQNCAXYDDwEU
|
||||
AwEBAgMNARIDMwFSA0MBdwNRAacDDwEU/wAwAAEBAwMBBAM0BFQBwgFlAVMBUgH0AV4CWAHYA0oBjQMW
|
||||
AR4DAgEDAwABAQMCAQMDGgElA00BlAEIAQkBJgH9A1ABpAM1AVcDQQFzA1MBugJDAVMB4wJTAVQBsgMA
|
||||
AQH/ADAAAQEDDAEQA0IBdAFVAVQBUQHYAZkBiAGBAf8BoAGMAYUB/wF8AXABZQH4AzoBYQMKAQ4DCgEN
|
||||
Ax0BKgM/AW0DVAG7ARkCGgH5AQABBQG/Af8BFwEbAUcB+QE5AUYBSwHrAQABBQFEAf8CCAFOAf0DDQER
|
||||
/wAxAAMDAQQDHQEpA1ABpAFdAVMBUQHtAZsBiwGDAf8BnAGMAYQB/wGWAYQBdwH/AVsBWgFYAdgDMwFT
|
||||
AzQBVANPAZ0CUwFSAdMCTAFOAfMBMAGeAbsB/wEUAXMBqwH/ARQBdQG/Af8BEAFmAbYB/wEXAY0BwgH/
|
||||
AUgBYQFpAeEDAQEC/wAwAAEBAwkBDAMwAUwBVgJVAcMBewFqAWAB+gGoAZkBjwH/AZMBhAF3Af8BjAF3
|
||||
AXAB/wGHAXEBbAH/A1YBvgNTAbwBTAFIAUYB5QF2AVsBUgH6AYMBbQFlAf8BUQFIAUcB/wEOAUsBpAH/
|
||||
AQMBGgG4Af8BDQFRAZUB/wEZAZUBwAH/AUABagGBAesDMwFSAw0BEgMCAQP/ACUAAwEBAgMYASEDSwGP
|
||||
A1EB3AGbAY4BhQH9AaEBkQGJAf8BhwFzAWsB/wGBAW4BZQH/AXUBZwFgAf8BUwFKAUMB/QFHAT4BOwH8
|
||||
AZYBhgF5Af8BowGSAYoB/wFTAUoBUwH/AQMBGAHzAf8BEgFgAaYB/wEVAXYBlQH/AS8B/QH+Af8BBwEy
|
||||
AZQB/wEVAXoByAH/AgABVAH/A00BlAMZASP/ACUAAwYBCAMtAUYDUwG8AWoBZQFiAfQBqgGbAZEB/wGJ
|
||||
AXQBbQH/AYwBdwFuAf8BmgGJAYEB/wGLAXcBbwH/AXUBZQFeAf8BhgFxAWkB/wGVAYYBegH/AUEBPAFK
|
||||
Af8BEwEfAYgB/wEKAREBrgH/ARwBegGVAf8BKgHfAeIB/wEOAVMBdwH/AQkBOQG8Af8BGQGBAaoB/wEK
|
||||
ARIBqQH/ASABJQFSAfcDUQGg/wAlAAMQARUDQQFyA08B1gGTAYQBcgH9AZoBiQGDAf8BjwGAAXMB/wGW
|
||||
AYYBeAH/AZ8BjQGEAf8BlgGFAXkB/wGUAYQBdwH/AZQBgwF3Af8BlwGHAYAB/wFqAV8BXAH/AWMBVwFW
|
||||
Af8BYAFVAVMB/wFTAVcBWAH/ASIBYwGaAf8BDQFLAZ0B/wEgAY4BsAH/AUwBnAGvAf8BaAGaAa4B/wE7
|
||||
AUsBWgH+A1ABn/8AJQADGAEiA00BlQF8AXUBbwH8AagBmAGOAf8BkQGBAXUB/wGNAXcBcAH/AZoBiQGB
|
||||
Af8BkwGDAXYB/wGZAYgBgQH/AZwBiwGDAf8BlQGGAXgB/wGWAYYBeQH/AaABjwGHAf8BlgGFAXgB/wF2
|
||||
AW8BbAH/AUwBbQGBAf8BHgE7AV0B/wEdAZ4BhAH/AVMBlwGpAf8BhgHFAd8B/wGIAb4B1wH/AUUBXwFi
|
||||
AfsDQQFz/wAlAAMYASIDTQGVAZ0BjwGGAf8BmwGLAYMB/wGGAXEBagH/AYUBbwFoAf8BiAFzAWwB/wGJ
|
||||
AXQBbAH/AZABdwFvAf8BlQGEAXcB/wGWAYUBeAH/AZ8BjwGGAf8BmQGLAYQB/wFtAYABhgH/AVYBkwGw
|
||||
Af8BWgGmAccB/wFMAYMBpAH/AQUBFgGgAf8BYwGaAbAB/wGCAb8B2QH/AXEBrQHIAf8BXQFpAXIB3gMq
|
||||
AUD/ACEAAwMBBAMmATgDUAGjAZoBjAGEAf8BpwGWAY4B/wGXAYYBegH/AZQBggF2Af8BlAGDAXcB/wGW
|
||||
AYUBeAH/AZIBeQFyAf8BjwF5AXIB/wGVAYQBeAH/AY8BdgFrAf8BcAGAAYcB/wFaAZcBswH/AU8BmgHC
|
||||
Af8BZQG1AdQB/wFlAaQBvgH/AR4BKgE1Af8BeAG6AdMB/wGAAbsB1QH/AYEBvwHaAf8BVQFWAVkBtQMP
|
||||
ART/ACEAAwoBDQNBAXMDUgHPAasBmgGRAf8BmgGJAYIB/wGOAXgBcQH/AZEBgQF1Af8BlQGEAXcB/wGY
|
||||
AYgBgAH/AYsBdQFuAf8BkQF6AXMB/wF4AW4BagH/AW8BrwHIAf8BWQGoAc0B/wFZAasBzAH/AVUBpgHJ
|
||||
Af8BdQHDAeAB/wF6AcIB3wH/AYMBwAHbAf8BggHBAd0B/wFvAa4ByAH/AYsBvwHbAf8DSAGGAwUBB/8A
|
||||
IQADHgErA1EBoAFSAVABTQHtAYMBbwFoAf8BgwFuAWcB/wGBAWwBZQH/AYEBbQFmAf8BiAFzAWsB/wGH
|
||||
AXIBawH/AZQBhAF4Af8BhQF2AXMB/wFUAWwBgwH/AU0BhAGmAf8BZgGwAdAB/wFdAaoBywH/AWEBsQHR
|
||||
Af8BdgG/Ad0B/wGFAcgB4wH/AYEBxAHfAf8BiAHHAeIB/wF3AbYB0QH/AW0BngG2Af8DPgFrAwIBA/8A
|
||||
IQADOAFcA1UByAFrAlwB+AGRAYABdAH/AZgBiAGAAf8BlQGEAXgB/wGNAXcBcAH/AZUBhAF4Af8BmAGH
|
||||
AYAB/wGTAYMBdwH/AWgBgAGLAf8BVgGQAbEB/wE3AUoBagH/AWMBqQHKAf8BYAGuAc8B/wFhAawBzAH/
|
||||
AXYBvwHcAf8BiQHMAecB/wGDAcYB4gH/AYUBxQHgAf8BhwHDAd4B/wFIAYMBmwH/AzwBaAMEAQX/ACEA
|
||||
A0kBiQFXAVYBVQHiAaQBkwGKAf8BrAGcAZMB/wGlAZUBjAH/AZYBhgF5Af8BkAF5AXQB/wGZAYgBgQH/
|
||||
AaIBkQGJAf8BbgFdAVUB/wFkAZUBqwH/AWgBtQHVAf8BcgHBAd0B/wF0AbsB2wH/AV4BrAHOAf8BXwGt
|
||||
AcwB/wF4AcMB4AH/AYgBywHmAf8BhQHGAeQB/wGDAcYB4gH/AYcBvwHdAf8BQwFVAWkB7gMbASb/ACUA
|
||||
A08BpQFiAlgB7wGjAZMBigH/AZgBhwGAAf8BnwGOAYYB/wGdAYwBhAH/AZABeQFzAf8BiAFyAWsB/wGI
|
||||
AXYBbwH/AWoBhQGPAf8BaAGwAdAB/wFvAbwB2gH/AWYBtgHWAf8BXwGxAdAB/wFdAa8B0AH/AXEBvQHa
|
||||
Af8BcAG7AdoB/wGAAcQB3wH/AY8BzQHpAf8BigHJAeUB/wFbAZcBrAH9A0QBeQMAAQH/ACUAA1MBsQFs
|
||||
Al8B8wGjAZIBigH/AZUBgwF4Af8BlAGCAXcB/wGUAYUBdwH/AYQBiwGNAf8BWwFzAYYB/wFcAYcBnQH/
|
||||
AWEBrwHSAf8BbwG7AdoB/wF3AcEB3gH/AWwBuQHXAf8BYQGzAdIB/wFpAbkB1gH/AYABxQHhAf8BeAHC
|
||||
Ad8B/wGAAcUB4QH/AYUBxAHhAf8BiQHGAeIB/wFSAXMBhAHzAzEBTv8AKQADUQHHAXsBcQFnAfgBqwGb
|
||||
AZIB/wGQAYABdQH/AYQBbwFmAf8BcgGaAasB/wFiAasBzwH/AWQBsgHTAf8BbQG8AdoB/wFrAbgB1QH/
|
||||
AXEBvgHbAf8BdgG/Ad0B/wFwAb4B2wH/AWgBuQHWAf8BgAHHAeEB/wGJAcsB5AH/AYoBzAHnAf8BjQHR
|
||||
AewB/wGFAckB5gH/AW0BswHUAf8DTgGYAzABTAMAAQEDAAEB/wAhAAM+AWwBYgFfAV4ByQGJAYIBfAH1
|
||||
AaQBkwGLAf8BhgGeAakB/wFnAa8B0gH/AXgBxAHgAf8BdgHCAd4B/wF2AcIB3gH/AXEBvwHbAf8BcwG8
|
||||
AdoB/wFyAbsB2AH/AXQBuwHZAf8BdAG/Ad0B/wFhAZ0BwwH/AUEBYwGUAf8BbQGnAcgB/wGHAcQB4AH/
|
||||
AYgBzQHpAf8BXwFxAXkB4AMsAUQDBwEJAwQBBgMAAQH/ACEAAwQBBQMZASMDNAFUA0oBiQFYAlsBwQFh
|
||||
AXIBeQHiAW4BlwGoAfUBfQG0Ac8B/gGAAcUB4gH/AXIBvAHaAf8BcQG8AdoB/wFwAbsB2AH/AXUBvAHZ
|
||||
Af8BjgHPAesB/wFtAa8B0gH/AU8BdQGkAf8BbAGrAc0B/wFuAa8BzwH/AY8BygHnAf8BWAFjAWYB0QMi
|
||||
ATH/AD0AAwEBAgMJAQwDGgElA0IBdgFSAVwBZQHqAYEBxAHgAf4BigHHAeQB/wF5AcAB3QH/AYoBxgHi
|
||||
Af8BlgHUAe4B/wF5AbgB1wH/AWEBoQHIAf8BaQGmAcwB/wFZAZIBvwH/AX8BwwHdAf4CRgFHAYEDAwEE
|
||||
/wBJAAMCAQMDEAEWAzIBUANKAY0DUAGdA1IBoQFmAXUBewHgAXIBrwHFAf0BYAGXAb4B/wFgAZQBwAH/
|
||||
AW8BqAHOAf8BQAF5AaoB/wM1AVYDAAEB/wBVAAMCAQMDBgEIAwoBDQMoAT0DQAFxAU8CUQGcAVsBYgFo
|
||||
AdYBZQF/AZMB8gFKAX0BoQH8AyABL/8AcAABAQMIAQsDJAE2A0YBgQMDAQT/ADEAAUIBTQE+BwABPgMA
|
||||
ASgDAAFgAwABGAMAAQEBAAEBBQABIAEBFgAD/wEAAeABOAEBCQABwAEAAQEJAAHAAQABAwkAAcABAAED
|
||||
CQABgAsAAYALAAGACwABgAsAAYALAAGAPQABAQsAAQELAAEDIwABBwkAAfABAAEHCQAB/gEAAQcJAAH/
|
||||
AcABDwkAAf8B/gEPCQAL
|
||||
</value>
|
||||
</data>
|
||||
</root>
|
||||
22
OpenRA.Editor/NewMapDialog.Designer.cs
generated
Normal file → Executable file
22
OpenRA.Editor/NewMapDialog.Designer.cs
generated
Normal file → Executable file
@@ -55,7 +55,7 @@
|
||||
this.button2.Location = new System.Drawing.Point(229, 160);
|
||||
this.button2.Name = "button2";
|
||||
this.button2.Size = new System.Drawing.Size(75, 23);
|
||||
this.button2.TabIndex = 12;
|
||||
this.button2.TabIndex = 7;
|
||||
this.button2.Text = "OK";
|
||||
this.button2.UseVisualStyleBackColor = true;
|
||||
//
|
||||
@@ -65,7 +65,7 @@
|
||||
this.button1.Location = new System.Drawing.Point(310, 160);
|
||||
this.button1.Name = "button1";
|
||||
this.button1.Size = new System.Drawing.Size(75, 23);
|
||||
this.button1.TabIndex = 13;
|
||||
this.button1.TabIndex = 8;
|
||||
this.button1.Text = "Cancel";
|
||||
this.button1.UseVisualStyleBackColor = true;
|
||||
//
|
||||
@@ -106,12 +106,13 @@
|
||||
0});
|
||||
this.cordonBottom.Name = "cordonBottom";
|
||||
this.cordonBottom.Size = new System.Drawing.Size(105, 20);
|
||||
this.cordonBottom.TabIndex = 8;
|
||||
this.cordonBottom.TabIndex = 5;
|
||||
this.cordonBottom.Value = new decimal(new int[] {
|
||||
112,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.cordonBottom.Enter += new System.EventHandler(this.SelectText);
|
||||
//
|
||||
// cordonTop
|
||||
//
|
||||
@@ -129,6 +130,7 @@
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.cordonTop.Enter += new System.EventHandler(this.SelectText);
|
||||
//
|
||||
// cordonRight
|
||||
//
|
||||
@@ -140,12 +142,13 @@
|
||||
0});
|
||||
this.cordonRight.Name = "cordonRight";
|
||||
this.cordonRight.Size = new System.Drawing.Size(105, 20);
|
||||
this.cordonRight.TabIndex = 5;
|
||||
this.cordonRight.TabIndex = 4;
|
||||
this.cordonRight.Value = new decimal(new int[] {
|
||||
112,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.cordonRight.Enter += new System.EventHandler(this.SelectText);
|
||||
//
|
||||
// cordonLeft
|
||||
//
|
||||
@@ -157,12 +160,13 @@
|
||||
0});
|
||||
this.cordonLeft.Name = "cordonLeft";
|
||||
this.cordonLeft.Size = new System.Drawing.Size(105, 20);
|
||||
this.cordonLeft.TabIndex = 7;
|
||||
this.cordonLeft.TabIndex = 2;
|
||||
this.cordonLeft.Value = new decimal(new int[] {
|
||||
16,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.cordonLeft.Enter += new System.EventHandler(this.SelectText);
|
||||
//
|
||||
// height
|
||||
//
|
||||
@@ -179,12 +183,13 @@
|
||||
0});
|
||||
this.height.Name = "height";
|
||||
this.height.Size = new System.Drawing.Size(105, 20);
|
||||
this.height.TabIndex = 6;
|
||||
this.height.TabIndex = 1;
|
||||
this.height.Value = new decimal(new int[] {
|
||||
128,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.height.Enter += new System.EventHandler(this.SelectText);
|
||||
//
|
||||
// width
|
||||
//
|
||||
@@ -201,12 +206,13 @@
|
||||
0});
|
||||
this.width.Name = "width";
|
||||
this.width.Size = new System.Drawing.Size(105, 20);
|
||||
this.width.TabIndex = 4;
|
||||
this.width.TabIndex = 0;
|
||||
this.width.Value = new decimal(new int[] {
|
||||
128,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.width.Enter += new System.EventHandler(this.SelectText);
|
||||
//
|
||||
// label4
|
||||
//
|
||||
@@ -224,7 +230,7 @@
|
||||
this.theater.Location = new System.Drawing.Point(169, 121);
|
||||
this.theater.Name = "theater";
|
||||
this.theater.Size = new System.Drawing.Size(216, 21);
|
||||
this.theater.TabIndex = 15;
|
||||
this.theater.TabIndex = 6;
|
||||
//
|
||||
// NewMapDialog
|
||||
//
|
||||
|
||||
5
OpenRA.Editor/NewMapDialog.cs
Normal file → Executable file
5
OpenRA.Editor/NewMapDialog.cs
Normal file → Executable file
@@ -18,5 +18,10 @@ namespace OpenRA.Editor
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void SelectText(object sender, System.EventArgs e)
|
||||
{
|
||||
(sender as NumericUpDown).Select(0, (sender as NumericUpDown).ToString().Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BIN
OpenRA.Editor/OpenRA.Editor.Icon.ico
Normal file
BIN
OpenRA.Editor/OpenRA.Editor.Icon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
@@ -12,6 +12,9 @@
|
||||
<AssemblyName>OpenRA.Editor</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ApplicationIcon>OpenRA.Editor.Icon.ico</ApplicationIcon>
|
||||
<StartupObject>
|
||||
</StartupObject>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@@ -33,6 +36,7 @@
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
@@ -59,12 +63,24 @@
|
||||
<DependentUpon>Form1.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="LegacyMapImporter.cs" />
|
||||
<Compile Include="MapSelect.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MapSelect.Designer.cs">
|
||||
<DependentUpon>MapSelect.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="NewMapDialog.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="NewMapDialog.Designer.cs">
|
||||
<DependentUpon>NewMapDialog.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="PaletteBox.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="PaletteBox.Designer.cs">
|
||||
<DependentUpon>PaletteBox.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="PropertiesDialog.cs">
|
||||
<SubType>Form</SubType>
|
||||
@@ -76,9 +92,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,6 +125,7 @@
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
<Compile Include="RenderUtils.cs" />
|
||||
<Compile Include="ResizeDialog.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
@@ -123,6 +146,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>
|
||||
136
OpenRA.Editor/RenderUtils.cs
Normal file
136
OpenRA.Editor/RenderUtils.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
#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.Drawing.Imaging;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Editor
|
||||
{
|
||||
static class RenderUtils
|
||||
{
|
||||
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);
|
||||
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 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] = p.GetColor(rawImage[i + ts.TileSize * j]).ToArgb();
|
||||
}
|
||||
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] = Color.Transparent.ToArgb();
|
||||
}
|
||||
}
|
||||
|
||||
bitmap.UnlockBits(data);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
static Bitmap RenderShp(ShpReader shp, Palette p)
|
||||
{
|
||||
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 stride2 = data.Stride >> 2;
|
||||
|
||||
for (var i = 0; i < shp.Width; i++)
|
||||
for (var j = 0; j < shp.Height; j++)
|
||||
q[j * stride2 + i] = p.GetColor(frame.Image[i + shp.Width * j]).ToArgb();
|
||||
}
|
||||
|
||||
bitmap.UnlockBits(data);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
public static ActorTemplate RenderActor(ActorInfo info, TileSet tileset, Palette p)
|
||||
{
|
||||
var ri = info.Traits.Get<RenderSimpleInfo>();
|
||||
string image = null;
|
||||
if (ri.OverrideTheater != null)
|
||||
for (int i = 0; i < ri.OverrideTheater.Length; i++)
|
||||
if (ri.OverrideTheater[i] == tileset.Id)
|
||||
image = ri.OverrideImage[i];
|
||||
|
||||
image = image ?? ri.Image ?? info.Name;
|
||||
using (var s = FileSystem.OpenWithExts(image, tileset.Extensions))
|
||||
{
|
||||
var shp = new ShpReader(s);
|
||||
var bitmap = RenderShp(shp, p);
|
||||
|
||||
try
|
||||
{
|
||||
using (var s2 = FileSystem.OpenWithExts(image + "2", tileset.Extensions))
|
||||
{
|
||||
var shp2 = new ShpReader(s2);
|
||||
var roofBitmap = RenderShp(shp2, p);
|
||||
|
||||
using (var g = System.Drawing.Graphics.FromImage(bitmap))
|
||||
g.DrawImage(roofBitmap, 0, 0);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
return new ActorTemplate { Bitmap = bitmap, Info = info, Centered = !info.Traits.Contains<BuildingInfo>() };
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
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 };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
158
OpenRA.Editor/Surface.cs
Normal file → Executable file
158
OpenRA.Editor/Surface.cs
Normal file → Executable file
@@ -25,6 +25,8 @@ namespace OpenRA.Editor
|
||||
public Palette Palette { get; private set; }
|
||||
int2 Offset;
|
||||
|
||||
float Zoom = 1.0f;
|
||||
|
||||
BrushTemplate Brush;
|
||||
ActorTemplate Actor;
|
||||
ResourceTemplate Resource;
|
||||
@@ -80,7 +82,34 @@ namespace OpenRA.Editor
|
||||
Offset -= dx;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
|
||||
protected override void OnMouseWheel(MouseEventArgs e)
|
||||
{
|
||||
base.OnMouseWheel(e);
|
||||
|
||||
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);
|
||||
@@ -96,7 +125,7 @@ namespace OpenRA.Editor
|
||||
Erase();
|
||||
|
||||
if (e.Button == MouseButtons.Left)
|
||||
Draw();
|
||||
Draw();
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
@@ -208,18 +237,27 @@ namespace OpenRA.Editor
|
||||
|
||||
void Erase()
|
||||
{
|
||||
// Crash preventing
|
||||
var BrushLocation = GetBrushLocation();
|
||||
|
||||
if (Map == null || BrushLocation.X >= Map.MapSize.X ||
|
||||
BrushLocation.Y >= Map.MapSize.Y ||
|
||||
BrushLocation.X < 0 ||
|
||||
BrushLocation.Y < 0)
|
||||
return;
|
||||
|
||||
Actor = null;
|
||||
Brush = null;
|
||||
Resource = null;
|
||||
Waypoint = null;
|
||||
|
||||
var key = Map.Actors.FirstOrDefault(a => a.Value.Location() == GetBrushLocation());
|
||||
var key = Map.Actors.FirstOrDefault(a => a.Value.Location() == BrushLocation);
|
||||
if (key.Key != null) Map.Actors.Remove(key.Key);
|
||||
|
||||
if (Map.MapResources[GetBrushLocation().X, GetBrushLocation().Y].type != 0)
|
||||
if (Map.MapResources[BrushLocation.X, BrushLocation.Y].type != 0)
|
||||
{
|
||||
Map.MapResources[GetBrushLocation().X, GetBrushLocation().Y] = new TileReference<byte, byte>();
|
||||
var ch = new int2((GetBrushLocation().X) / ChunkSize, (GetBrushLocation().Y) / ChunkSize);
|
||||
Map.MapResources[BrushLocation.X, BrushLocation.Y] = new TileReference<byte, byte>();
|
||||
var ch = new int2((BrushLocation.X) / ChunkSize, (BrushLocation.Y) / ChunkSize);
|
||||
if (Chunks.ContainsKey(ch))
|
||||
{
|
||||
Chunks[ch].Dispose();
|
||||
@@ -227,7 +265,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();
|
||||
@@ -308,7 +346,7 @@ namespace OpenRA.Editor
|
||||
Bitmap RenderChunk(int u, int v)
|
||||
{
|
||||
|
||||
var bitmap = new Bitmap(ChunkSize * 24, ChunkSize * 24);
|
||||
var bitmap = new Bitmap(ChunkSize * TileSet.TileSize, ChunkSize * TileSet.TileSize);
|
||||
bitmap.SetPixel(0, 0, Color.Green);
|
||||
|
||||
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
@@ -326,9 +364,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 +377,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);
|
||||
@@ -358,28 +396,56 @@ namespace OpenRA.Editor
|
||||
|
||||
int2 GetBrushLocation()
|
||||
{
|
||||
var v = MousePos - Offset;
|
||||
return new int2(v.X / 24, v.Y / 24);
|
||||
var vX = (int)Math.Floor((MousePos.X - Offset.X) / Zoom);
|
||||
var vY = (int)Math.Floor((MousePos.Y - Offset.Y) / Zoom);
|
||||
return new int2(vX / TileSet.TileSize, vY / TileSet.TileSize);
|
||||
}
|
||||
|
||||
void DrawActor(System.Drawing.Graphics g, int2 p, ActorTemplate t)
|
||||
{
|
||||
g.DrawImage(t.Bitmap,
|
||||
((24 * p + Offset
|
||||
- (t.Centered
|
||||
? new int2(t.Bitmap.Width / 2 - 12, t.Bitmap.Height / 2 - 12)
|
||||
: int2.Zero)).ToPoint()));
|
||||
float OffsetX = t.Centered ? t.Bitmap.Width / 2 - TileSet.TileSize/2 : 0;
|
||||
float DrawX = TileSet.TileSize * p.X * Zoom + Offset.X - OffsetX;
|
||||
|
||||
float OffsetY = t.Centered ? t.Bitmap.Height / 2 - TileSet.TileSize/2 : 0;
|
||||
float DrawY = TileSet.TileSize * p.Y * Zoom + Offset.Y - OffsetY;
|
||||
|
||||
float width = t.Bitmap.Width * Zoom;
|
||||
float height = t.Bitmap.Height * Zoom;
|
||||
RectangleF sourceRect = new RectangleF(0, 0, t.Bitmap.Width, t.Bitmap.Height);
|
||||
RectangleF destRect = new RectangleF(DrawX, DrawY, width, height);
|
||||
g.DrawImage(t.Bitmap, destRect, sourceRect, GraphicsUnit.Pixel);
|
||||
}
|
||||
|
||||
void DrawImage(System.Drawing.Graphics g, Bitmap bmp, int2 location)
|
||||
{
|
||||
float OffsetX = bmp.Width / 2 - TileSet.TileSize / 2;
|
||||
float DrawX = TileSet.TileSize * location.X * Zoom + Offset.X - OffsetX;
|
||||
|
||||
float OffsetY = bmp.Height / 2 - TileSet.TileSize / 2;
|
||||
float DrawY = TileSet.TileSize * location.Y * Zoom + Offset.Y - OffsetY;
|
||||
|
||||
float width = bmp.Width * Zoom;
|
||||
float height = bmp.Height * Zoom;
|
||||
RectangleF sourceRect = new RectangleF(0, 0, bmp.Width, bmp.Height);
|
||||
RectangleF destRect = new RectangleF(DrawX, DrawY, width, height);
|
||||
g.DrawImage(bmp, destRect, sourceRect, GraphicsUnit.Pixel);
|
||||
}
|
||||
|
||||
void DrawActorBorder(System.Drawing.Graphics g, int2 p, ActorTemplate t)
|
||||
{
|
||||
var origin = (24 * p + Offset
|
||||
- (t.Centered
|
||||
? new int2(t.Bitmap.Width / 2 - 12, t.Bitmap.Height / 2 - 12)
|
||||
: int2.Zero)).ToPoint();
|
||||
float OffsetX = t.Centered ? t.Bitmap.Width / 2 - TileSet.TileSize / 2 : 0;
|
||||
float DrawX = TileSet.TileSize * p.X * Zoom + Offset.X - OffsetX;
|
||||
|
||||
float OffsetY = t.Centered ? t.Bitmap.Height / 2 - TileSet.TileSize / 2 : 0;
|
||||
float DrawY = TileSet.TileSize * p.Y * Zoom + Offset.Y - OffsetY;
|
||||
|
||||
float width = t.Bitmap.Width * Zoom;
|
||||
float height = t.Bitmap.Height * Zoom;
|
||||
RectangleF sourceRect = new RectangleF(0, 0, t.Bitmap.Width, t.Bitmap.Height);
|
||||
RectangleF destRect = new RectangleF(DrawX, DrawY, width, height);
|
||||
g.DrawRectangle(CordonPen,
|
||||
origin.X, origin.Y,
|
||||
t.Bitmap.Width, t.Bitmap.Height );
|
||||
DrawX, DrawY,
|
||||
t.Bitmap.Width * Zoom, t.Bitmap.Height * Zoom);
|
||||
}
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
@@ -392,37 +458,49 @@ namespace OpenRA.Editor
|
||||
{
|
||||
var x = new int2(u/ChunkSize,v/ChunkSize);
|
||||
if (!Chunks.ContainsKey(x)) Chunks[x] = RenderChunk(u / ChunkSize, v / ChunkSize);
|
||||
e.Graphics.DrawImage(Chunks[x], (24 * ChunkSize * x + Offset).ToPoint());
|
||||
|
||||
Bitmap bmp = Chunks[x];
|
||||
|
||||
float DrawX = TileSet.TileSize* 1f * (float)ChunkSize * (float)x.X * Zoom + Offset.X;
|
||||
float DrawY = TileSet.TileSize * 1f * (float)ChunkSize * (float)x.Y * Zoom + Offset.Y;
|
||||
RectangleF sourceRect = new RectangleF(0, 0, bmp.Width, bmp.Height);
|
||||
RectangleF destRect = new RectangleF(DrawX, DrawY, bmp.Width * Zoom, bmp.Height * Zoom);
|
||||
e.Graphics.DrawImage(bmp, destRect, sourceRect, GraphicsUnit.Pixel);
|
||||
}
|
||||
|
||||
e.Graphics.DrawRectangle(CordonPen,
|
||||
new Rectangle(Map.XOffset * 24 + Offset.X, Map.YOffset * 24 + Offset.Y, Map.Width * 24, Map.Height * 24));
|
||||
Map.XOffset * TileSet.TileSize * Zoom + Offset.X,
|
||||
Map.YOffset * TileSet.TileSize * Zoom + Offset.Y,
|
||||
Map.Width * TileSet.TileSize * Zoom,
|
||||
Map.Height * TileSet.TileSize * Zoom);
|
||||
|
||||
foreach (var ar in Map.Actors)
|
||||
DrawActor(e.Graphics, ar.Value.Location(), ActorTemplates[ar.Value.Type]);
|
||||
|
||||
foreach (var wp in Map.Waypoints)
|
||||
e.Graphics.DrawRectangle(Pens.LimeGreen, new Rectangle(
|
||||
24 * wp.Value.X + Offset.X + 4,
|
||||
24 * wp.Value.Y + Offset.Y + 4,
|
||||
16, 16));
|
||||
e.Graphics.DrawRectangle(Pens.LimeGreen,
|
||||
TileSet.TileSize * wp.Value.X * Zoom + Offset.X + 4,
|
||||
TileSet.TileSize * wp.Value.Y * Zoom + Offset.Y + 4,
|
||||
(TileSet.TileSize - 8) * Zoom, (TileSet.TileSize - 8) * Zoom);
|
||||
|
||||
if (Brush != null)
|
||||
e.Graphics.DrawImage(Brush.Bitmap,
|
||||
(24 * GetBrushLocation() + Offset).ToPoint());
|
||||
TileSet.TileSize * GetBrushLocation().X * Zoom + Offset.X,
|
||||
TileSet.TileSize * GetBrushLocation().Y * Zoom + Offset.Y,
|
||||
Brush.Bitmap.Width * Zoom,
|
||||
Brush.Bitmap.Height * Zoom);
|
||||
|
||||
if (Actor != null)
|
||||
DrawActor(e.Graphics, GetBrushLocation(), Actor);
|
||||
|
||||
if (Resource != null)
|
||||
e.Graphics.DrawImage(Resource.Bitmap,
|
||||
(24 * GetBrushLocation() + Offset).ToPoint());
|
||||
DrawImage(e.Graphics, Resource.Bitmap, GetBrushLocation());
|
||||
|
||||
if (Waypoint != null)
|
||||
e.Graphics.DrawRectangle(Pens.LimeGreen, new Rectangle(
|
||||
24 * GetBrushLocation().X + Offset.X + 4,
|
||||
24 * GetBrushLocation().Y + Offset.Y + 4,
|
||||
16, 16));
|
||||
e.Graphics.DrawRectangle(Pens.LimeGreen,
|
||||
TileSet.TileSize * GetBrushLocation().X * Zoom + Offset.X + 4,
|
||||
TileSet.TileSize * GetBrushLocation().Y * Zoom + Offset.Y + 4,
|
||||
(TileSet.TileSize - 8) * Zoom, (TileSet.TileSize - 8) * Zoom);
|
||||
|
||||
if (Brush == null && Actor == null && Resource == null)
|
||||
{
|
||||
|
||||
@@ -36,5 +36,10 @@ namespace OpenRA.FileFormats
|
||||
}
|
||||
|
||||
public IEnumerable<uint> AllFileHashes() { return hashes; }
|
||||
|
||||
public bool Exists(string filename)
|
||||
{
|
||||
return hashes.Contains(PackageEntry.HashFilename(filename));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace OpenRA.FileFormats
|
||||
{
|
||||
throw new InvalidOperationException("FieldLoader: Cannot parse `{0}` into `{1}.{2}` ".F(s,f,t) );
|
||||
};
|
||||
|
||||
|
||||
public static Action<string,Type> UnknownFieldAction = (s,f) =>
|
||||
{
|
||||
throw new NotImplementedException( "FieldLoader: Missing field `{0}` on `{1}`".F( s, f.Name ) );
|
||||
@@ -30,13 +30,32 @@ namespace OpenRA.FileFormats
|
||||
|
||||
public static void Load( object self, MiniYaml my )
|
||||
{
|
||||
foreach( var x in my.Nodes )
|
||||
if (!x.Key.StartsWith("-"))
|
||||
LoadField(self, x.Key, x.Value.Value);
|
||||
var loadDict = typeLoadInfo[ self.GetType() ];
|
||||
|
||||
foreach( var field in self.GetType().GetFields())
|
||||
if( field.HasAttribute<FieldFromYamlKeyAttribute>() )
|
||||
field.SetValue( self, GetValue( field.Name, field.FieldType, my.Value ) );
|
||||
foreach( var kv in loadDict )
|
||||
{
|
||||
object val;
|
||||
if( kv.Value != null )
|
||||
val = kv.Value( kv.Key.Name, kv.Key.FieldType, my );
|
||||
else if( !TryGetValueFromYaml( kv.Key.Name, kv.Key.FieldType, my, out val ) )
|
||||
continue;
|
||||
|
||||
kv.Key.SetValue( self, val );
|
||||
}
|
||||
}
|
||||
|
||||
static bool TryGetValueFromYaml( string fieldName, Type fieldType, MiniYaml yaml, out object ret )
|
||||
{
|
||||
ret = null;
|
||||
var n = yaml.Nodes.Where( x=>x.Key == fieldName ).ToList();
|
||||
if( n.Count == 0 )
|
||||
return false;
|
||||
if( n.Count == 1 && n[ 0 ].Value.Nodes.Count == 0 )
|
||||
{
|
||||
ret = GetValue( fieldName, fieldType, n[ 0 ].Value.Value );
|
||||
return true;
|
||||
}
|
||||
throw new InvalidOperationException( "TryGetValueFromYaml: unable to load field {0} (of type {1})".F( fieldName, fieldType ) );
|
||||
}
|
||||
|
||||
public static T Load<T>(MiniYaml y) where T : new()
|
||||
@@ -45,15 +64,6 @@ namespace OpenRA.FileFormats
|
||||
Load(t, y);
|
||||
return t;
|
||||
}
|
||||
|
||||
public static void LoadFields( object self, Dictionary<string,MiniYaml> my, IEnumerable<string> fields )
|
||||
{
|
||||
foreach (var field in fields)
|
||||
{
|
||||
if (!my.ContainsKey(field)) continue;
|
||||
LoadField(self,field,my[field].Value);
|
||||
}
|
||||
}
|
||||
|
||||
public static void LoadField( object self, string key, string value )
|
||||
{
|
||||
@@ -66,7 +76,7 @@ namespace OpenRA.FileFormats
|
||||
else
|
||||
field.SetValue( self, GetValue( field.Name, field.FieldType, value ) );
|
||||
}
|
||||
|
||||
|
||||
public static object GetValue( string field, Type fieldType, string x )
|
||||
{
|
||||
if (x != null) x = x.Trim();
|
||||
@@ -77,7 +87,7 @@ namespace OpenRA.FileFormats
|
||||
return res;
|
||||
return InvalidValueAction(x,fieldType, field);
|
||||
}
|
||||
|
||||
|
||||
else if( fieldType == typeof( ushort ) )
|
||||
{
|
||||
ushort res;
|
||||
@@ -96,7 +106,7 @@ namespace OpenRA.FileFormats
|
||||
|
||||
else if (fieldType == typeof(string))
|
||||
return x;
|
||||
|
||||
|
||||
else if (fieldType == typeof(Color))
|
||||
{
|
||||
var parts = x.Split(',');
|
||||
@@ -106,14 +116,14 @@ namespace OpenRA.FileFormats
|
||||
return Color.FromArgb(int.Parse(parts[0]), int.Parse(parts[1]), int.Parse(parts[2]), int.Parse(parts[3]));
|
||||
return InvalidValueAction(x,fieldType, field);
|
||||
}
|
||||
|
||||
|
||||
else if (fieldType.IsEnum)
|
||||
{
|
||||
if (!Enum.GetNames(fieldType).Select(a => a.ToLower()).Contains(x.ToLower()))
|
||||
return InvalidValueAction(x,fieldType, field);
|
||||
return Enum.Parse(fieldType, x, true);
|
||||
}
|
||||
|
||||
|
||||
else if (fieldType == typeof(bool))
|
||||
return ParseYesNo(x, fieldType, field);
|
||||
|
||||
@@ -134,7 +144,19 @@ namespace OpenRA.FileFormats
|
||||
var parts = x.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
return new int2(int.Parse(parts[0]), int.Parse(parts[1]));
|
||||
}
|
||||
|
||||
else if (fieldType == typeof(float2))
|
||||
{
|
||||
var parts = x.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
float xx = 0;
|
||||
float yy = 0;
|
||||
float res;
|
||||
if (float.TryParse(parts[0].Replace("%",""), out res))
|
||||
xx = res * (parts[0].Contains( '%' ) ? 0.01f : 1f);
|
||||
if (float.TryParse(parts[1].Replace("%",""), out res))
|
||||
yy = res * (parts[1].Contains( '%' ) ? 0.01f : 1f);
|
||||
return new float2(xx,yy);
|
||||
}
|
||||
|
||||
UnknownFieldAction("[Type] {0}".F(x),fieldType);
|
||||
return null;
|
||||
}
|
||||
@@ -148,13 +170,62 @@ namespace OpenRA.FileFormats
|
||||
if( p == "false" ) return false;
|
||||
return InvalidValueAction(p,fieldType, field);
|
||||
}
|
||||
|
||||
static Cache<Type, Dictionary<FieldInfo, Func<string, Type, MiniYaml, object>>> typeLoadInfo = new Cache<Type, Dictionary<FieldInfo, Func<string, Type, MiniYaml, object>>>( GetTypeLoadInfo );
|
||||
|
||||
static Dictionary<FieldInfo, Func<string, Type, MiniYaml, object>> GetTypeLoadInfo( Type type )
|
||||
{
|
||||
var ret = new Dictionary<FieldInfo, Func<string, Type, MiniYaml, object>>();
|
||||
|
||||
foreach( var field 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 );
|
||||
if( loadUsing.Length != 0 )
|
||||
ret[ field ] = ( _1, fieldType, yaml ) => loadUsing[ 0 ].LoaderFunc( field )( yaml );
|
||||
else if( fromYamlKey.Length != 0 )
|
||||
ret[ field ] = ( f, ft, yaml ) => GetValue( f, ft, yaml.Value );
|
||||
else if( load.Length != 0 )
|
||||
ret[ field ] = null;
|
||||
}
|
||||
|
||||
if( ret.Count == 0 )
|
||||
foreach( var f in type.GetFields() )
|
||||
ret.Add( f, null );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
[AttributeUsage( AttributeTargets.Field )]
|
||||
public class LoadAttribute : Attribute { }
|
||||
|
||||
[AttributeUsage( AttributeTargets.Field )]
|
||||
public class LoadUsingAttribute : Attribute
|
||||
{
|
||||
Func<MiniYaml, object> loaderFuncCache;
|
||||
public readonly string Loader;
|
||||
|
||||
public LoadUsingAttribute( string loader )
|
||||
{
|
||||
Loader = loader;
|
||||
}
|
||||
|
||||
internal Func<MiniYaml, object> LoaderFunc( FieldInfo field )
|
||||
{
|
||||
const BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
|
||||
if( loaderFuncCache == null )
|
||||
loaderFuncCache = (Func<MiniYaml, object>)Delegate.CreateDelegate( typeof( Func<MiniYaml, object> ), field.DeclaringType.GetMethod( Loader, bf ) );
|
||||
return loaderFuncCache;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class FieldSaver
|
||||
{
|
||||
public static MiniYaml Save(object o)
|
||||
{
|
||||
var dict = new Dictionary<string, MiniYaml>();
|
||||
var nodes = new List<MiniYamlNode>();
|
||||
string root = null;
|
||||
|
||||
foreach( var f in o.GetType().GetFields( BindingFlags.Public | BindingFlags.Instance ) )
|
||||
@@ -162,12 +233,12 @@ namespace OpenRA.FileFormats
|
||||
if( f.HasAttribute<FieldFromYamlKeyAttribute>() )
|
||||
root = FormatValue( o, f );
|
||||
else
|
||||
dict.Add( f.Name, new MiniYaml( FormatValue( o, f ) ) );
|
||||
nodes.Add( new MiniYamlNode( f.Name, FormatValue( o, f ) ) );
|
||||
}
|
||||
|
||||
return new MiniYaml( root, dict );
|
||||
return new MiniYaml( root, nodes );
|
||||
}
|
||||
|
||||
|
||||
public static MiniYaml SaveDifferences(object o, object from)
|
||||
{
|
||||
if (o.GetType() != from.GetType())
|
||||
@@ -175,10 +246,10 @@ namespace OpenRA.FileFormats
|
||||
|
||||
var fields = o.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance)
|
||||
.Where(f => FormatValue(o,f) != FormatValue(from,f));
|
||||
|
||||
return new MiniYaml(null, fields.ToDictionary(
|
||||
f => f.Name,
|
||||
f => new MiniYaml(FormatValue(o, f))));
|
||||
|
||||
return new MiniYaml( null, fields.Select( f => new MiniYamlNode(
|
||||
f.Name,
|
||||
FormatValue( o, f ) ) ).ToList() );
|
||||
}
|
||||
|
||||
public static string FormatValue(object o, FieldInfo f)
|
||||
@@ -193,7 +264,7 @@ namespace OpenRA.FileFormats
|
||||
var c = (Color)v;
|
||||
return "{0},{1},{2},{3}".F(c.A,c.R,c.G,c.B);
|
||||
}
|
||||
|
||||
|
||||
return f.FieldType.IsArray
|
||||
? string.Join(",", ((Array)v).OfType<object>().Select(a => a.ToString()).ToArray())
|
||||
: v.ToString();
|
||||
|
||||
@@ -76,6 +76,46 @@ namespace OpenRA.FileFormats
|
||||
return (short)current;
|
||||
}
|
||||
|
||||
public static byte[] LoadSound(byte[] raw, ref int index)
|
||||
{
|
||||
var br = new BinaryReader(new MemoryStream(raw));
|
||||
var dataSize = raw.Length;
|
||||
var outputSize = raw.Length * 4;
|
||||
|
||||
var output = new byte[outputSize];
|
||||
var offset = 0;
|
||||
var currentSample = 0;
|
||||
|
||||
while (dataSize-- > 0)
|
||||
{
|
||||
var b = br.ReadByte();
|
||||
|
||||
var t = DecodeSample(b, ref index, ref currentSample);
|
||||
output[offset++] = (byte)t;
|
||||
output[offset++] = (byte)(t >> 8);
|
||||
|
||||
t = DecodeSample((byte)(b >> 4), ref index, ref currentSample);
|
||||
output[offset++] = (byte)t;
|
||||
output[offset++] = (byte)(t >> 8);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
public static float SoundLength(Stream s)
|
||||
{
|
||||
var br = new BinaryReader(s);
|
||||
var sampleRate = br.ReadUInt16();
|
||||
/*var dataSize = */ br.ReadInt32();
|
||||
var outputSize = br.ReadInt32();
|
||||
var flags = (SoundFlags) br.ReadByte();
|
||||
|
||||
var samples = outputSize;
|
||||
if (0 != (flags & SoundFlags.Stereo)) samples /= 2;
|
||||
if (0 != (flags & SoundFlags._16Bit)) samples /= 2;
|
||||
return samples / sampleRate;
|
||||
}
|
||||
|
||||
public static byte[] LoadSound(Stream s)
|
||||
{
|
||||
var br = new BinaryReader(s);
|
||||
|
||||
@@ -64,14 +64,18 @@ namespace OpenRA.FileFormats
|
||||
allFiles = new Cache<uint, List<IFolder>>( _ => new List<IFolder>() );
|
||||
}
|
||||
|
||||
public static void LoadFromManifest( Manifest manifest )
|
||||
{
|
||||
UnmountAll();
|
||||
foreach (var dir in manifest.Folders) Mount(dir);
|
||||
foreach (var pkg in manifest.Packages) Mount(pkg);
|
||||
}
|
||||
|
||||
static Stream GetFromCache( Cache<uint, List<IFolder>> index, string filename )
|
||||
{
|
||||
foreach( var folder in index[ PackageEntry.HashFilename( filename ) ] )
|
||||
{
|
||||
Stream s = folder.GetContent(filename);
|
||||
if( s != null )
|
||||
return s;
|
||||
}
|
||||
if (folder.Exists(filename))
|
||||
return folder.GetContent(filename);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -86,9 +90,8 @@ namespace OpenRA.FileFormats
|
||||
|
||||
foreach( IFolder folder in mountedFolders )
|
||||
{
|
||||
Stream s = folder.GetContent(filename);
|
||||
if( s != null )
|
||||
return s;
|
||||
if (folder.Exists(filename))
|
||||
return folder.GetContent(filename);
|
||||
}
|
||||
|
||||
throw new FileNotFoundException( string.Format( "File not found: {0}", filename ), filename );
|
||||
@@ -109,11 +112,8 @@ namespace OpenRA.FileFormats
|
||||
foreach( var ext in exts )
|
||||
{
|
||||
foreach( IFolder folder in mountedFolders )
|
||||
{
|
||||
Stream s = folder.GetContent( filename + ext );
|
||||
if( s != null )
|
||||
return s;
|
||||
}
|
||||
if (folder.Exists(filename + ext))
|
||||
return folder.GetContent( filename + ext );
|
||||
}
|
||||
|
||||
throw new FileNotFoundException( string.Format( "File not found: {0}", filename ), filename );
|
||||
@@ -122,15 +122,8 @@ namespace OpenRA.FileFormats
|
||||
public static bool Exists(string filename)
|
||||
{
|
||||
foreach (var folder in mountedFolders)
|
||||
{
|
||||
var s = folder.GetContent(filename);
|
||||
if (s != null)
|
||||
{
|
||||
s.Dispose();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (folder.Exists(filename))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,5 +30,10 @@ namespace OpenRA.FileFormats
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace OpenRA.FileFormats.Graphics
|
||||
IVertexBuffer<Vertex> CreateVertexBuffer( int length );
|
||||
IIndexBuffer CreateIndexBuffer( int length );
|
||||
ITexture CreateTexture( Bitmap bitmap );
|
||||
ITexture CreateTexture();
|
||||
IShader CreateShader( Stream stream );
|
||||
|
||||
Size WindowSize { get; }
|
||||
@@ -70,14 +71,9 @@ namespace OpenRA.FileFormats.Graphics
|
||||
|
||||
public interface ITexture
|
||||
{
|
||||
void SetData( Bitmap bitmap );
|
||||
}
|
||||
|
||||
public interface IFont
|
||||
{
|
||||
void DrawText( string text, int2 pos, Color c );
|
||||
|
||||
int2 Measure( string text );
|
||||
void SetData(Bitmap bitmap);
|
||||
void SetData(uint[,] colors);
|
||||
void SetData(byte[] colors, int width, int height);
|
||||
}
|
||||
|
||||
public enum PrimitiveType
|
||||
|
||||
294
OpenRA.FileFormats/Graphics/VqaReader.cs
Normal file
294
OpenRA.FileFormats/Graphics/VqaReader.cs
Normal file
@@ -0,0 +1,294 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class VqaReader
|
||||
{
|
||||
public readonly ushort Frames;
|
||||
public readonly byte Framerate;
|
||||
public readonly ushort Width;
|
||||
public readonly ushort Height;
|
||||
|
||||
Stream stream;
|
||||
int currentFrame;
|
||||
ushort numColors;
|
||||
ushort blockWidth;
|
||||
ushort blockHeight;
|
||||
byte cbParts;
|
||||
int2 blocks;
|
||||
UInt32[] offsets;
|
||||
uint[] palette;
|
||||
|
||||
// Stores a list of subpixels, referenced by the VPTZ chunk
|
||||
byte[] cbf;
|
||||
byte[] cbp;
|
||||
int cbChunk = 0;
|
||||
int cbOffset = 0;
|
||||
|
||||
// Top half contains block info, bottom half contains references to cbf array
|
||||
byte[] origData;
|
||||
|
||||
// Final frame output
|
||||
uint[,] frameData;
|
||||
byte[] audioData; // audio for this frame: 22050Hz 16bit mono pcm, uncompressed.
|
||||
|
||||
public byte[] AudioData { get { return audioData; } }
|
||||
public int CurrentFrame { get { return currentFrame; } }
|
||||
|
||||
public VqaReader( Stream stream )
|
||||
{
|
||||
this.stream = stream;
|
||||
BinaryReader reader = new BinaryReader( stream );
|
||||
|
||||
// Decode FORM chunk
|
||||
if (new String(reader.ReadChars(4)) != "FORM")
|
||||
throw new InvalidDataException("Invalid vqa (invalid FORM section)");
|
||||
/*var length = */ reader.ReadUInt32();
|
||||
|
||||
if (new String(reader.ReadChars(8)) != "WVQAVQHD")
|
||||
throw new InvalidDataException("Invalid vqa (not WVQAVQHD)");
|
||||
/* var length = */reader.ReadUInt32();
|
||||
|
||||
/*var version = */reader.ReadUInt16();
|
||||
/*var flags = */reader.ReadUInt16();
|
||||
Frames = reader.ReadUInt16();
|
||||
Width = reader.ReadUInt16();
|
||||
Height = reader.ReadUInt16();
|
||||
|
||||
blockWidth = reader.ReadByte();
|
||||
blockHeight = reader.ReadByte();
|
||||
Framerate = reader.ReadByte();
|
||||
cbParts = reader.ReadByte();
|
||||
blocks = new int2(Width / blockWidth, Height / blockHeight);
|
||||
|
||||
numColors = reader.ReadUInt16();
|
||||
/*var maxBlocks = */reader.ReadUInt16();
|
||||
/*var unknown1 = */reader.ReadUInt16();
|
||||
/*var unknown2 = */reader.ReadUInt32();
|
||||
|
||||
// Audio
|
||||
/*var freq = */reader.ReadUInt16();
|
||||
/*var channels = */reader.ReadByte();
|
||||
/*var bits = */reader.ReadByte();
|
||||
/*var unknown3 = */reader.ReadChars(14);
|
||||
|
||||
|
||||
var frameSize = NextPowerOf2(Math.Max(Width,Height));
|
||||
cbf = new byte[Width*Height];
|
||||
cbp = new byte[Width*Height];
|
||||
palette = new uint[numColors];
|
||||
origData = new byte[2*blocks.X*blocks.Y];
|
||||
frameData = new uint[frameSize,frameSize];
|
||||
|
||||
var type = new String(reader.ReadChars(4));
|
||||
if (type != "FINF")
|
||||
{
|
||||
reader.ReadBytes(27);
|
||||
type = new String(reader.ReadChars(4));
|
||||
}
|
||||
|
||||
/*var length = */reader.ReadUInt16();
|
||||
/*var unknown4 = */reader.ReadUInt16();
|
||||
|
||||
// Frame offsets
|
||||
offsets = new UInt32[Frames];
|
||||
for (int i = 0; i < Frames; i++)
|
||||
{
|
||||
offsets[i] = reader.ReadUInt32();
|
||||
if (offsets[i] > 0x40000000) offsets[i] -= 0x40000000;
|
||||
offsets[i] <<= 1;
|
||||
}
|
||||
|
||||
CollectAudioData();
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
currentFrame = cbOffset = cbChunk = 0;
|
||||
LoadFrame();
|
||||
}
|
||||
|
||||
void CollectAudioData()
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
var adpcmIndex = 0;
|
||||
|
||||
bool compressed = false;
|
||||
for (var i = 0; i < Frames; i++)
|
||||
{
|
||||
stream.Seek(offsets[i], SeekOrigin.Begin);
|
||||
BinaryReader reader = new BinaryReader(stream);
|
||||
var end = (i < Frames - 1) ? offsets[i + 1] : stream.Length;
|
||||
|
||||
while (reader.BaseStream.Position < end)
|
||||
{
|
||||
var type = new String(reader.ReadChars(4));
|
||||
var length = int2.Swap(reader.ReadUInt32());
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case "SND0":
|
||||
case "SND2":
|
||||
var rawAudio = reader.ReadBytes((int)length);
|
||||
ms.Write(rawAudio);
|
||||
compressed = (type == "SND2");
|
||||
break;
|
||||
default:
|
||||
reader.ReadBytes((int)length);
|
||||
break;
|
||||
}
|
||||
|
||||
if (reader.PeekChar() == 0) reader.ReadByte();
|
||||
}
|
||||
}
|
||||
|
||||
audioData = (compressed) ? AudLoader.LoadSound(ms.ToArray(), ref adpcmIndex) : ms.ToArray();
|
||||
}
|
||||
|
||||
public void AdvanceFrame()
|
||||
{
|
||||
currentFrame++;
|
||||
LoadFrame();
|
||||
}
|
||||
|
||||
void LoadFrame()
|
||||
{
|
||||
if (currentFrame >= Frames)
|
||||
return;
|
||||
|
||||
// Seek to the start of the frame
|
||||
stream.Seek(offsets[currentFrame], SeekOrigin.Begin);
|
||||
BinaryReader reader = new BinaryReader(stream);
|
||||
var end = (currentFrame < Frames - 1) ? offsets[currentFrame+1] : stream.Length;
|
||||
|
||||
while(reader.BaseStream.Position < end)
|
||||
{
|
||||
var type = new String(reader.ReadChars(4));
|
||||
var length = int2.Swap(reader.ReadUInt32());
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case "VQFR":
|
||||
DecodeVQFR(reader);
|
||||
break;
|
||||
default:
|
||||
// Don't parse sound here.
|
||||
reader.ReadBytes((int)length);
|
||||
break;
|
||||
}
|
||||
|
||||
// Chunks are aligned on even bytes; advance by a byte if the next one is null
|
||||
if (reader.PeekChar() == 0) reader.ReadByte();
|
||||
}
|
||||
}
|
||||
|
||||
// VQA Frame
|
||||
public void DecodeVQFR(BinaryReader reader)
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
// Chunks are aligned on even bytes; may be padded with a single null
|
||||
if (reader.PeekChar() == 0) reader.ReadByte();
|
||||
var type = new String(reader.ReadChars(4));
|
||||
int subchunkLength = (int)int2.Swap(reader.ReadUInt32());
|
||||
|
||||
switch(type)
|
||||
{
|
||||
// Full frame-modifier
|
||||
case "CBFZ":
|
||||
Format80.DecodeInto( reader.ReadBytes(subchunkLength), cbf );
|
||||
break;
|
||||
case "CBF0":
|
||||
cbf = reader.ReadBytes(subchunkLength);
|
||||
break;
|
||||
|
||||
// frame-modifier chunk
|
||||
case "CBP0":
|
||||
case "CBPZ":
|
||||
// Partial buffer is full; dump and recreate
|
||||
if (cbChunk == cbParts)
|
||||
{
|
||||
if (type == "CBP0")
|
||||
cbf = (byte[])cbp.Clone();
|
||||
else
|
||||
Format80.DecodeInto( cbp, cbf );
|
||||
|
||||
cbOffset = cbChunk = 0;
|
||||
}
|
||||
|
||||
var bytes = reader.ReadBytes(subchunkLength);
|
||||
bytes.CopyTo(cbp,cbOffset);
|
||||
cbOffset += subchunkLength;
|
||||
cbChunk++;
|
||||
break;
|
||||
|
||||
// Palette
|
||||
case "CPL0":
|
||||
for (int i = 0; i < numColors; i++)
|
||||
{
|
||||
byte r = (byte)(reader.ReadByte() << 2);
|
||||
byte g = (byte)(reader.ReadByte() << 2);
|
||||
byte b = (byte)(reader.ReadByte() << 2);
|
||||
palette[i] = (uint)((255 << 24) | (r << 16) | (g << 8) | b);
|
||||
}
|
||||
break;
|
||||
|
||||
// Frame data
|
||||
case "VPTZ":
|
||||
Format80.DecodeInto( reader.ReadBytes(subchunkLength), origData );
|
||||
// This is the last subchunk
|
||||
return;
|
||||
default:
|
||||
throw new InvalidDataException("Unknown sub-chunk {0}".F(type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int cachedFrame = -1;
|
||||
public uint[,] FrameData { get
|
||||
{
|
||||
if (cachedFrame != currentFrame)
|
||||
{
|
||||
cachedFrame = currentFrame;
|
||||
for (var y = 0; y < blocks.Y; y++)
|
||||
for (var x = 0; x < blocks.X; x++)
|
||||
{
|
||||
var px = origData[x + y*blocks.X];
|
||||
var mod = origData[x + (y + blocks.Y)*blocks.X];
|
||||
for (var j = 0; j < blockHeight; j++)
|
||||
for (var i = 0; i < blockWidth; i++)
|
||||
{
|
||||
var cbfi = (mod*256 + px)*8 + j*blockWidth + i;
|
||||
byte color = (mod == 0x0f) ? px : cbf[cbfi];
|
||||
frameData[y*blockHeight + j, x*blockWidth + i] = palette[color];
|
||||
}
|
||||
}
|
||||
}
|
||||
return frameData;
|
||||
}}
|
||||
|
||||
int NextPowerOf2(int v)
|
||||
{
|
||||
--v;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
++v;
|
||||
return v;
|
||||
}
|
||||
}
|
||||
}
|
||||
65
OpenRA.FileFormats/Manifest.cs
Normal file
65
OpenRA.FileFormats/Manifest.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
/* describes what is to be loaded in order to run a set of mods */
|
||||
|
||||
public class Manifest
|
||||
{
|
||||
public readonly string[]
|
||||
Folders, Packages, Rules,
|
||||
Sequences, Cursors, Chrome, Assemblies, ChromeLayout,
|
||||
Weapons, Voices, Music, Movies, TileSets;
|
||||
|
||||
public readonly string ShellmapUid, LoadScreen;
|
||||
public readonly int TileSize = 24;
|
||||
|
||||
public Manifest(string[] 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");
|
||||
Sequences = YamlList(yaml, "Sequences");
|
||||
Cursors = YamlList(yaml, "Cursors");
|
||||
Chrome = YamlList(yaml, "Chrome");
|
||||
Assemblies = YamlList(yaml, "Assemblies");
|
||||
ChromeLayout = YamlList(yaml, "ChromeLayout");
|
||||
Weapons = YamlList(yaml, "Weapons");
|
||||
Voices = YamlList(yaml, "Voices");
|
||||
Music = YamlList(yaml, "Music");
|
||||
Movies = YamlList(yaml, "Movies");
|
||||
TileSets = YamlList(yaml, "TileSets");
|
||||
|
||||
ShellmapUid = yaml.First( x => x.Key == "ShellmapUid" ).Value.Value;
|
||||
LoadScreen = yaml.First( x => x.Key == "LoadScreen" ).Value.Value;
|
||||
|
||||
if (yaml.FirstOrDefault( x => x.Key == "TileSize" ) != null)
|
||||
TileSize = int.Parse(yaml.First( x => x.Key == "TileSize" ).Value.Value);
|
||||
}
|
||||
|
||||
static string[] YamlList(List<MiniYamlNode> ys, string key)
|
||||
{
|
||||
var y = ys.FirstOrDefault( x => x.Key == key );
|
||||
if( y == null )
|
||||
return new string[ 0 ];
|
||||
|
||||
return y.Value.NodesDict.Keys.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,39 +21,41 @@ namespace OpenRA.FileFormats
|
||||
|
||||
// Yaml map data
|
||||
public readonly string Uid;
|
||||
public bool Selectable;
|
||||
[FieldLoader.Load] public bool Selectable;
|
||||
|
||||
public string Title;
|
||||
public string Description;
|
||||
public string Author;
|
||||
public int PlayerCount;
|
||||
public string Tileset;
|
||||
[FieldLoader.Load] public string Title;
|
||||
[FieldLoader.Load] public string Description;
|
||||
[FieldLoader.Load] public string Author;
|
||||
[FieldLoader.Load] public int PlayerCount;
|
||||
[FieldLoader.Load] public string Tileset;
|
||||
|
||||
[FieldLoader.LoadUsing( "LoadWaypoints" )]
|
||||
public Dictionary<string, int2> Waypoints = new Dictionary<string, int2>();
|
||||
public IEnumerable<int2> SpawnPoints { get { return Waypoints.Select(kv => kv.Value); } }
|
||||
|
||||
public int2 TopLeft;
|
||||
public int2 BottomRight;
|
||||
[FieldLoader.Load] public int2 TopLeft;
|
||||
[FieldLoader.Load] public int2 BottomRight;
|
||||
public int Width { get { return BottomRight.X - TopLeft.X; } }
|
||||
public int Height { get { return BottomRight.Y - TopLeft.Y; } }
|
||||
|
||||
static List<string> Fields = new List<string>() {
|
||||
"Selectable", "Title", "Description", "Author", "PlayerCount", "Tileset", "TopLeft", "BottomRight"
|
||||
};
|
||||
|
||||
public MapStub(IFolder package)
|
||||
{
|
||||
Package = package;
|
||||
var yaml = MiniYaml.FromStream(Package.GetContent("map.yaml"));
|
||||
FieldLoader.LoadFields(this, yaml, Fields);
|
||||
FieldLoader.Load( this, new MiniYaml( null, yaml ) );
|
||||
|
||||
// Waypoints
|
||||
foreach (var wp in yaml["Waypoints"].Nodes)
|
||||
{
|
||||
string[] loc = wp.Value.Value.Split(',');
|
||||
Waypoints.Add(wp.Key, new int2(int.Parse(loc[0]), int.Parse(loc[1])));
|
||||
}
|
||||
|
||||
Uid = Package.GetContent("map.uid").ReadAllText();
|
||||
}
|
||||
|
||||
static object LoadWaypoints( MiniYaml y )
|
||||
{
|
||||
var ret = new Dictionary<string, int2>();
|
||||
foreach( var wp in y.NodesDict[ "Waypoints" ].NodesDict )
|
||||
{
|
||||
string[] loc = wp.Value.Value.Split( ',' );
|
||||
ret.Add( wp.Key, new int2( int.Parse( loc[ 0 ] ), int.Parse( loc[ 1 ] ) ) );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,14 +14,21 @@ namespace OpenRA.FileFormats
|
||||
{
|
||||
public class PlayerReference
|
||||
{
|
||||
public readonly string Name;
|
||||
public readonly string Palette;
|
||||
public readonly string Race;
|
||||
public readonly bool OwnsWorld = false;
|
||||
public readonly bool NonCombatant = false;
|
||||
public readonly Color Color = Color.FromArgb(238,238,238);
|
||||
public readonly Color Color2 = Color.FromArgb(44,28,24);
|
||||
|
||||
public string Name;
|
||||
public string Palette;
|
||||
public string Race;
|
||||
public bool OwnsWorld = false;
|
||||
public bool NonCombatant = false;
|
||||
public bool Playable = false;
|
||||
public bool DefaultStartingUnits = false;
|
||||
public Color Color = Color.FromArgb(238,238,238);
|
||||
public Color Color2 = Color.FromArgb(44,28,24);
|
||||
|
||||
public int InitialCash = 0;
|
||||
public string[] Allies = {};
|
||||
public string[] Enemies = {};
|
||||
|
||||
public PlayerReference() {}
|
||||
public PlayerReference(MiniYaml my)
|
||||
{
|
||||
FieldLoader.Load(this, my);
|
||||
|
||||
@@ -17,15 +17,15 @@ namespace OpenRA.FileFormats
|
||||
{
|
||||
public readonly List<byte[]> TileBitmapBytes = new List<byte[]>();
|
||||
|
||||
public Terrain( Stream stream )
|
||||
public Terrain( Stream stream, int size )
|
||||
{
|
||||
// Try loading as a cnc .tem
|
||||
BinaryReader reader = new BinaryReader( stream );
|
||||
int Width = reader.ReadUInt16();
|
||||
int Height = reader.ReadUInt16();
|
||||
|
||||
if( Width != 24 || Height != 24 )
|
||||
throw new InvalidDataException( string.Format( "{0}x{1}", Width, Height ) );
|
||||
|
||||
if( Width != size || Height != size )
|
||||
throw new InvalidDataException( "{0}x{1} != {2}x{2}".F(Width, Height, size ) );
|
||||
|
||||
/*NumTiles = */reader.ReadUInt16();
|
||||
/*Zero1 = */reader.ReadUInt16();
|
||||
@@ -46,9 +46,7 @@ namespace OpenRA.FileFormats
|
||||
reader = new BinaryReader( stream );
|
||||
Width = reader.ReadUInt16();
|
||||
Height = reader.ReadUInt16();
|
||||
if( Width != 24 || Height != 24 )
|
||||
throw new InvalidDataException( string.Format( "{0}x{1}", Width, Height ) );
|
||||
|
||||
|
||||
/*NumTiles = */reader.ReadUInt16();
|
||||
reader.ReadUInt16();
|
||||
/*XDim = */reader.ReadUInt16();
|
||||
@@ -67,8 +65,8 @@ namespace OpenRA.FileFormats
|
||||
{
|
||||
if (b != 255)
|
||||
{
|
||||
stream.Position = ImgStart + b * 24 * 24;
|
||||
TileBitmapBytes.Add(new BinaryReader(stream).ReadBytes(24 * 24));
|
||||
stream.Position = ImgStart + b * size * size;
|
||||
TileBitmapBytes.Add(new BinaryReader(stream).ReadBytes(size * size));
|
||||
}
|
||||
else
|
||||
TileBitmapBytes.Add(null);
|
||||
|
||||
@@ -31,38 +31,39 @@ namespace OpenRA.FileFormats
|
||||
|
||||
public class TileTemplate
|
||||
{
|
||||
public ushort Id;
|
||||
public string Image;
|
||||
public int2 Size;
|
||||
public bool PickAny;
|
||||
[FieldLoader.Load] public ushort Id;
|
||||
[FieldLoader.Load] public string Image;
|
||||
[FieldLoader.Load] public int2 Size;
|
||||
[FieldLoader.Load] public bool PickAny;
|
||||
|
||||
[FieldLoader.LoadUsing( "LoadTiles" )]
|
||||
public Dictionary<byte, string> Tiles = new Dictionary<byte, string>();
|
||||
|
||||
static List<string> fields = new List<string>() {"Id", "Image", "Size", "PickAny"};
|
||||
|
||||
public TileTemplate() {}
|
||||
public TileTemplate(MiniYaml my)
|
||||
{
|
||||
FieldLoader.LoadFields(this, my.Nodes, fields);
|
||||
FieldLoader.Load( this, my );
|
||||
}
|
||||
|
||||
Tiles = my.Nodes["Tiles"].Nodes.ToDictionary(
|
||||
static object LoadTiles( MiniYaml y )
|
||||
{
|
||||
return y.NodesDict["Tiles"].NodesDict.ToDictionary(
|
||||
t => byte.Parse(t.Key),
|
||||
t => t.Value.Value);
|
||||
t => t.Value.Value );
|
||||
}
|
||||
|
||||
public MiniYaml Save()
|
||||
{
|
||||
var root = new Dictionary<string, MiniYaml>();
|
||||
foreach (var field in fields)
|
||||
var root = new List<MiniYamlNode>();
|
||||
foreach (var field in new string[] {"Id", "Image", "Size", "PickAny"})
|
||||
{
|
||||
FieldInfo f = this.GetType().GetField(field);
|
||||
if (f.GetValue(this) == null) continue;
|
||||
root.Add(field, new MiniYaml(FieldSaver.FormatValue(this, f), null));
|
||||
root.Add( new MiniYamlNode( field, FieldSaver.FormatValue( this, f ) ) );
|
||||
}
|
||||
|
||||
root.Add("Tiles",
|
||||
new MiniYaml(null, Tiles.ToDictionary(
|
||||
p => p.Key.ToString(),
|
||||
p => new MiniYaml(p.Value))));
|
||||
root.Add( new MiniYamlNode( "Tiles", null,
|
||||
Tiles.Select( x => new MiniYamlNode( x.Key.ToString(), x.Value ) ).ToList() ) );
|
||||
|
||||
return new MiniYaml(null, root);
|
||||
}
|
||||
@@ -73,26 +74,27 @@ namespace OpenRA.FileFormats
|
||||
public string Name;
|
||||
public string Id;
|
||||
public string Palette;
|
||||
public int TileSize = 24;
|
||||
public string[] Extensions;
|
||||
public Dictionary<string, TerrainTypeInfo> Terrain = new Dictionary<string, TerrainTypeInfo>();
|
||||
public Dictionary<ushort, Terrain> Tiles = new Dictionary<ushort, Terrain>();
|
||||
public Dictionary<ushort, TileTemplate> Templates = new Dictionary<ushort, TileTemplate>();
|
||||
static List<string> fields = new List<string>() {"Name", "Id", "Palette", "Extensions"};
|
||||
static List<string> fields = new List<string>() {"Name", "TileSize", "Id", "Palette", "Extensions"};
|
||||
|
||||
public TileSet() {}
|
||||
public TileSet( string filepath )
|
||||
{
|
||||
var yaml = MiniYaml.FromFile(filepath);
|
||||
var yaml = MiniYaml.DictFromFile( filepath );
|
||||
|
||||
// General info
|
||||
FieldLoader.Load(this, yaml["General"]);
|
||||
|
||||
// TerrainTypes
|
||||
Terrain = yaml["Terrain"].Nodes.Values
|
||||
Terrain = yaml["Terrain"].NodesDict.Values
|
||||
.Select(y => new TerrainTypeInfo(y)).ToDictionary(t => t.Type);
|
||||
|
||||
// Templates
|
||||
Templates = yaml["Templates"].Nodes.Values
|
||||
Templates = yaml["Templates"].NodesDict.Values
|
||||
.Select(y => new TileTemplate(y)).ToDictionary(t => t.Id);
|
||||
}
|
||||
|
||||
@@ -102,38 +104,31 @@ namespace OpenRA.FileFormats
|
||||
using( Stream s = FileSystem.OpenWithExts(t.Value.Image, Extensions) )
|
||||
{
|
||||
if( !Tiles.ContainsKey( t.Key ) )
|
||||
Tiles.Add( t.Key, new Terrain( s ) );
|
||||
Tiles.Add( t.Key, new Terrain( s, TileSize ) );
|
||||
}
|
||||
}
|
||||
|
||||
public void Save(string filepath)
|
||||
{
|
||||
var root = new Dictionary<string, MiniYaml>();
|
||||
var root = new List<MiniYamlNode>();
|
||||
var gen = new List<MiniYamlNode>();
|
||||
foreach (var field in fields)
|
||||
{
|
||||
FieldInfo f = this.GetType().GetField(field);
|
||||
if (f.GetValue(this) == null) continue;
|
||||
root.Add(field, new MiniYaml(FieldSaver.FormatValue(this, f), null));
|
||||
gen.Add( new MiniYamlNode( field, FieldSaver.FormatValue( this, f ) ) );
|
||||
}
|
||||
|
||||
var gen = new Dictionary<string, MiniYaml>();
|
||||
foreach (var field in fields)
|
||||
{
|
||||
FieldInfo f = this.GetType().GetField(field);
|
||||
if (f.GetValue(this) == null) continue;
|
||||
gen.Add(field, new MiniYaml(FieldSaver.FormatValue(this, f), null));
|
||||
}
|
||||
root.Add("General", new MiniYaml(null, gen));
|
||||
|
||||
root.Add("Terrain",
|
||||
new MiniYaml(null, Terrain.ToDictionary(
|
||||
t => "TerrainType@{0}".F(t.Value.Type),
|
||||
t => t.Value.Save())));
|
||||
|
||||
root.Add("Templates",
|
||||
new MiniYaml(null, Templates.ToDictionary(
|
||||
t => "Template@{0}".F(t.Value.Id),
|
||||
t => t.Value.Save())));
|
||||
root.Add( new MiniYamlNode( "General", null, gen ) );
|
||||
|
||||
root.Add( new MiniYamlNode( "Terrain", null,
|
||||
Terrain.Select( t => new MiniYamlNode(
|
||||
"TerrainType@{0}".F( t.Value.Type ),
|
||||
t.Value.Save() ) ).ToList() ) );
|
||||
|
||||
root.Add( new MiniYamlNode( "Templates", null,
|
||||
Templates.Select( t => new MiniYamlNode(
|
||||
"Template@{0}".F( t.Value.Id ),
|
||||
t.Value.Save() ) ).ToList() ) );
|
||||
root.WriteToFile(filepath);
|
||||
}
|
||||
|
||||
@@ -143,7 +138,7 @@ namespace OpenRA.FileFormats
|
||||
if( Tiles.TryGetValue( r.type, out tile ) )
|
||||
return tile.TileBitmapBytes[ r.image ];
|
||||
|
||||
byte[] missingTile = new byte[ 24 * 24 ];
|
||||
byte[] missingTile = new byte[ TileSize * TileSize ];
|
||||
for( int i = 0 ; i < missingTile.Length ; i++ )
|
||||
missingTile[ i ] = 0x36;
|
||||
|
||||
|
||||
@@ -15,38 +15,80 @@ using System.Linq;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
using MiniYamlNodes = Dictionary<string, MiniYaml>;
|
||||
using MiniYamlNodes = List<MiniYamlNode>;
|
||||
|
||||
public class MiniYamlNode
|
||||
{
|
||||
public struct SourceLocation
|
||||
{
|
||||
public string Filename; public int Line;
|
||||
}
|
||||
|
||||
public SourceLocation Location;
|
||||
public string Key;
|
||||
public MiniYaml Value;
|
||||
|
||||
public MiniYamlNode( string k, MiniYaml v )
|
||||
{
|
||||
Key = k;
|
||||
Value = v;
|
||||
}
|
||||
|
||||
public MiniYamlNode( string k, MiniYaml v, SourceLocation loc )
|
||||
: this( k, v )
|
||||
{
|
||||
Location = loc;
|
||||
}
|
||||
|
||||
public MiniYamlNode( string k, string v )
|
||||
: this( k, v, null )
|
||||
{
|
||||
}
|
||||
public MiniYamlNode( string k, string v, List<MiniYamlNode> n )
|
||||
: this( k, new MiniYaml( v, n ) )
|
||||
{
|
||||
}
|
||||
|
||||
public MiniYamlNode( string k, string v, List<MiniYamlNode> n, SourceLocation loc )
|
||||
: this( k, new MiniYaml( v, n ), loc )
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class MiniYaml
|
||||
{
|
||||
public string Value;
|
||||
public Dictionary<string, MiniYaml> Nodes = new Dictionary<string,MiniYaml>();
|
||||
public List<MiniYamlNode> Nodes;
|
||||
|
||||
public MiniYaml( string value ) : this( value, new Dictionary<string, MiniYaml>() ) { }
|
||||
public Dictionary<string, MiniYaml> NodesDict { get { return Nodes.ToDictionary( x => x.Key, x => x.Value ); } }
|
||||
|
||||
public MiniYaml( string value, Dictionary<string, MiniYaml> nodes )
|
||||
public MiniYaml( string value ) : this( value, null ) { }
|
||||
|
||||
public MiniYaml( string value, List<MiniYamlNode> nodes )
|
||||
{
|
||||
Value = value;
|
||||
Nodes = nodes;
|
||||
Nodes = nodes ?? new List<MiniYamlNode>();
|
||||
}
|
||||
|
||||
public static MiniYaml FromDictionary<K,V>(Dictionary<K,V>dict)
|
||||
{
|
||||
return new MiniYaml( null, dict.ToDictionary( x=>x.Key.ToString(), x=>new MiniYaml(x.Value.ToString())));
|
||||
}
|
||||
|
||||
public static MiniYaml FromList<T>(List<T>list)
|
||||
{
|
||||
return new MiniYaml( null, list.ToDictionary( x=>x.ToString(), x=>new MiniYaml(null)));
|
||||
}
|
||||
|
||||
static Dictionary<string, MiniYaml> FromLines(string[] lines)
|
||||
{
|
||||
var levels = new List<Dictionary<string, MiniYaml>>();
|
||||
levels.Add(new Dictionary<string, MiniYaml>());
|
||||
|
||||
public static MiniYaml FromDictionary<K, V>( Dictionary<K, V> dict )
|
||||
{
|
||||
return new MiniYaml( null, dict.Select( x => new MiniYamlNode( x.Key.ToString(), new MiniYaml( x.Value.ToString() ) ) ).ToList() );
|
||||
}
|
||||
|
||||
public static MiniYaml FromList<T>( List<T> list )
|
||||
{
|
||||
return new MiniYaml( null, list.Select( x => new MiniYamlNode( x.ToString(), new MiniYaml( null ) ) ).ToList() );
|
||||
}
|
||||
|
||||
static List<MiniYamlNode> FromLines(string[] lines, string filename)
|
||||
{
|
||||
var levels = new List<List<MiniYamlNode>>();
|
||||
levels.Add(new List<MiniYamlNode>());
|
||||
|
||||
var lineNo = 0;
|
||||
foreach (var line in lines)
|
||||
{
|
||||
++lineNo;
|
||||
var t = line.TrimStart(' ', '\t');
|
||||
if (t.Length == 0 || t[0] == '#')
|
||||
continue;
|
||||
@@ -57,28 +99,28 @@ namespace OpenRA.FileFormats
|
||||
while (levels.Count > level + 1)
|
||||
levels.RemoveAt(levels.Count - 1);
|
||||
|
||||
var colon = t.IndexOf(':');
|
||||
var d = new Dictionary<string, MiniYaml>();
|
||||
try
|
||||
{
|
||||
if (colon == -1)
|
||||
levels[level].Add(t.Trim(), new MiniYaml(null, d));
|
||||
else
|
||||
{
|
||||
var value = t.Substring(colon + 1).Trim();
|
||||
if (value.Length == 0)
|
||||
value = null;
|
||||
levels[level].Add(t.Substring(0, colon).Trim(), new MiniYaml(value, d));
|
||||
}
|
||||
}
|
||||
catch (ArgumentException) { throw new InvalidDataException("Duplicate Identifier:`{0}`".F(t)); }
|
||||
var d = new List<MiniYamlNode>();
|
||||
var rhs = SplitAtColon( ref t );
|
||||
levels[ level ].Add( new MiniYamlNode( t, rhs, d, new MiniYamlNode.SourceLocation { Filename = filename, Line = lineNo } ) );
|
||||
|
||||
levels.Add(d);
|
||||
}
|
||||
return levels[0];
|
||||
return levels[ 0 ];
|
||||
}
|
||||
|
||||
public static Dictionary<string, MiniYaml> FromFileInPackage( string path )
|
||||
static string SplitAtColon( ref string t )
|
||||
{
|
||||
var colon = t.IndexOf(':');
|
||||
if( colon == -1 )
|
||||
return null;
|
||||
var ret = t.Substring( colon + 1 ).Trim();
|
||||
if( ret.Length == 0 )
|
||||
ret = null;
|
||||
t = t.Substring( 0, colon ).Trim();
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static List<MiniYamlNode> FromFileInPackage( string path )
|
||||
{
|
||||
StreamReader reader = new StreamReader( FileSystem.Open(path) );
|
||||
List<string> lines = new List<string>();
|
||||
@@ -87,54 +129,67 @@ namespace OpenRA.FileFormats
|
||||
lines.Add(reader.ReadLine());
|
||||
reader.Close();
|
||||
|
||||
return FromLines(lines.ToArray());
|
||||
}
|
||||
|
||||
public static Dictionary<string, MiniYaml> FromFile( string path )
|
||||
{
|
||||
return FromLines(File.ReadAllLines( path ));
|
||||
return FromLines(lines.ToArray(), path);
|
||||
}
|
||||
|
||||
public static Dictionary<string, MiniYaml> FromStream(Stream s)
|
||||
public static Dictionary<string, MiniYaml> DictFromFile( string path )
|
||||
{
|
||||
return FromFile( path ).ToDictionary( x => x.Key, x => x.Value );
|
||||
}
|
||||
|
||||
public static Dictionary<string, MiniYaml> DictFromStream( Stream stream )
|
||||
{
|
||||
return FromStream( stream ).ToDictionary( x => x.Key, x => x.Value );
|
||||
}
|
||||
|
||||
public static List<MiniYamlNode> FromFile( string path )
|
||||
{
|
||||
return FromLines(File.ReadAllLines( path ), path);
|
||||
}
|
||||
|
||||
public static List<MiniYamlNode> FromStream(Stream s)
|
||||
{
|
||||
using (var reader = new StreamReader(s))
|
||||
return FromString(reader.ReadToEnd());
|
||||
}
|
||||
|
||||
public static Dictionary<string, MiniYaml> FromString(string text)
|
||||
public static List<MiniYamlNode> FromString(string text)
|
||||
{
|
||||
return FromLines(text.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries));
|
||||
return FromLines(text.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries), "<no filename available>");
|
||||
}
|
||||
|
||||
public static Dictionary<string, MiniYaml> Merge( Dictionary<string, MiniYaml> a, Dictionary<string, MiniYaml> b )
|
||||
public static List<MiniYamlNode> Merge( List<MiniYamlNode> a, List<MiniYamlNode> b )
|
||||
{
|
||||
if( a.Count == 0 )
|
||||
return b;
|
||||
if( b.Count == 0 )
|
||||
return a;
|
||||
|
||||
var ret = new Dictionary<string, MiniYaml>();
|
||||
var ret = new List<MiniYamlNode>();
|
||||
|
||||
var keys = a.Keys.Union( b.Keys ).ToList();
|
||||
var aDict = a.ToDictionary( x => x.Key );
|
||||
var bDict = b.ToDictionary( x => x.Key );
|
||||
var keys = aDict.Keys.Union( bDict.Keys ).ToList();
|
||||
|
||||
var noInherit = keys.Where( x => x.Length > 0 && x[ 0 ] == '-' ).Select( x => x.Substring( 1 ) ).ToList();
|
||||
|
||||
foreach( var key in keys )
|
||||
{
|
||||
MiniYaml aa, bb;
|
||||
a.TryGetValue( key, out aa );
|
||||
b.TryGetValue( key, out bb );
|
||||
MiniYamlNode aa, bb;
|
||||
aDict.TryGetValue( key, out aa );
|
||||
bDict.TryGetValue( key, out bb );
|
||||
|
||||
// if( key.Length > 0 && key[ 0 ] == '-' )
|
||||
// continue;
|
||||
// else
|
||||
if( noInherit.Contains( key ) )
|
||||
{
|
||||
if( aa != null )
|
||||
ret.Add( key, aa );
|
||||
ret.Add( aa );
|
||||
}
|
||||
else
|
||||
ret.Add( key, Merge( aa, bb ) );
|
||||
{
|
||||
var loc = aa == null ? default( MiniYamlNode.SourceLocation ) : aa.Location;
|
||||
var merged = ( aa == null || bb == null ) ? aa ?? bb : new MiniYamlNode( key, Merge( aa.Value, bb.Value ), loc );
|
||||
ret.Add( merged );
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
<Compile Include="Folder.cs" />
|
||||
<Compile Include="Graphics\IGraphicsDevice.cs" />
|
||||
<Compile Include="Graphics\Vertex.cs" />
|
||||
<Compile Include="Manifest.cs" />
|
||||
<Compile Include="MiniYaml.cs" />
|
||||
<Compile Include="PackageEntry.cs" />
|
||||
<Compile Include="Package.cs" />
|
||||
@@ -71,7 +72,6 @@
|
||||
<Compile Include="Primitives\DisposableAction.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Thirdparty\Random.cs" />
|
||||
<Compile Include="Session.cs" />
|
||||
<Compile Include="Support\Log.cs" />
|
||||
<Compile Include="Support\Stopwatch.cs" />
|
||||
<Compile Include="Support\Timer.cs" />
|
||||
@@ -99,6 +99,7 @@
|
||||
<Compile Include="Map\SmudgeReference.cs" />
|
||||
<Compile Include="Map\PlayerReference.cs" />
|
||||
<Compile Include="CompressedPackage.cs" />
|
||||
<Compile Include="Graphics\VqaReader.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.
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace OpenRA.FileFormats
|
||||
public interface IFolder
|
||||
{
|
||||
Stream GetContent(string filename);
|
||||
bool Exists(string filename);
|
||||
IEnumerable<uint> AllFileHashes();
|
||||
}
|
||||
|
||||
@@ -143,6 +144,11 @@ namespace OpenRA.FileFormats
|
||||
{
|
||||
return index.Keys;
|
||||
}
|
||||
|
||||
public bool Exists(string filename)
|
||||
{
|
||||
return index.ContainsKey(PackageEntry.HashFilename(filename));
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
|
||||
@@ -11,20 +11,38 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class Palette
|
||||
{
|
||||
List<Color> colors = new List<Color>();
|
||||
|
||||
uint[] colors;
|
||||
public Color GetColor(int index)
|
||||
{
|
||||
return colors[index];
|
||||
return Color.FromArgb((int)colors[index]);
|
||||
}
|
||||
|
||||
public void SetColor(int index, Color color)
|
||||
{
|
||||
colors[index] = (uint)color.ToArgb();
|
||||
}
|
||||
|
||||
public void SetColor(int index, uint color)
|
||||
{
|
||||
colors[index] = (uint)color;
|
||||
}
|
||||
|
||||
public uint[] Values
|
||||
{
|
||||
get { return colors; }
|
||||
}
|
||||
|
||||
public Palette(Stream s, bool remapTransparent)
|
||||
{
|
||||
colors = new uint[256];
|
||||
|
||||
using (BinaryReader reader = new BinaryReader(s))
|
||||
{
|
||||
for (int i = 0; i < 256; i++)
|
||||
@@ -32,24 +50,29 @@ namespace OpenRA.FileFormats
|
||||
byte r = (byte)(reader.ReadByte() << 2);
|
||||
byte g = (byte)(reader.ReadByte() << 2);
|
||||
byte b = (byte)(reader.ReadByte() << 2);
|
||||
|
||||
colors.Add(Color.FromArgb(r, g, b));
|
||||
colors[i] = (uint)((255 << 24) | (r << 16) | (g << 8) | b);
|
||||
}
|
||||
}
|
||||
|
||||
colors[0] = Color.FromArgb(0, 0, 0, 0);
|
||||
|
||||
colors[0] = 0;
|
||||
if (remapTransparent)
|
||||
{
|
||||
colors[3] = Color.FromArgb(178, 0, 0, 0);
|
||||
colors[4] = Color.FromArgb(140, 0, 0, 0);
|
||||
colors[1] = 178u << 24; // Hack for d2k; may have side effects
|
||||
colors[3] = 178u << 24;
|
||||
colors[4] = 140u << 24;
|
||||
}
|
||||
}
|
||||
|
||||
public Palette(Palette p, IPaletteRemap r)
|
||||
{
|
||||
for (int i = 0; i < 256; i++)
|
||||
colors.Add(r.GetRemappedColor(p.GetColor(i), i));
|
||||
colors = new uint[256];
|
||||
for(int i = 0; i < 256; i++)
|
||||
colors[i] = (uint)r.GetRemappedColor(Color.FromArgb((int)p.colors[i]),i).ToArgb();
|
||||
}
|
||||
|
||||
public Palette(Palette p)
|
||||
{
|
||||
colors = (uint[])p.colors.Clone();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,15 +15,16 @@ using System.Linq;
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
// TODO: ship this out of here.
|
||||
public enum PaletteFormat { ra, cnc, d2k }
|
||||
|
||||
public class PlayerColorRemap : IPaletteRemap
|
||||
{
|
||||
Dictionary<int, Color> remapColors;
|
||||
|
||||
public PlayerColorRemap(Color c1, Color c2, bool useSplitRamp)
|
||||
public PlayerColorRemap(Color c1, Color c2, PaletteFormat fmt)
|
||||
{
|
||||
var baseIndex = useSplitRamp ? 0xb0 : 80;
|
||||
var ramp = useSplitRamp
|
||||
var baseIndex = (fmt == PaletteFormat.cnc) ? 0xb0 : (fmt == PaletteFormat.d2k) ? 240 : 80;
|
||||
var ramp = (fmt == PaletteFormat.cnc)
|
||||
? new[] { 0, 2, 4, 6, 8, 10, 13, 15, 1, 3, 5, 7, 9, 11, 12, 14 }
|
||||
: new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -53,5 +53,11 @@ namespace OpenRA
|
||||
public float2 ToFloat2() { return new float2(X, Y); }
|
||||
|
||||
public override string ToString() { return string.Format("{0},{1}", X, Y); }
|
||||
|
||||
// Change endianness of a uint32
|
||||
public static uint Swap(uint orig)
|
||||
{
|
||||
return (uint)((orig & 0xff000000) >> 24) | ((orig & 0x00ff0000) >> 8) | ((orig & 0x0000ff00) << 8) | ((orig & 0x000000ff) << 24);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
// todo: ship most of this back to the Game assembly;
|
||||
// it was only in FileFormats due to the original server model,
|
||||
// in a sep. process.
|
||||
|
||||
public class Session
|
||||
{
|
||||
public List<Client> Clients = new List<Client>();
|
||||
public Global GlobalSettings = new Global();
|
||||
|
||||
public enum ClientState
|
||||
{
|
||||
NotReady,
|
||||
Ready
|
||||
}
|
||||
|
||||
public class Client
|
||||
{
|
||||
public int Index;
|
||||
public System.Drawing.Color Color1;
|
||||
public System.Drawing.Color Color2;
|
||||
public string Country;
|
||||
public int SpawnPoint;
|
||||
public string Name;
|
||||
public ClientState State;
|
||||
public int Team;
|
||||
}
|
||||
|
||||
public class Global
|
||||
{
|
||||
public string Map;
|
||||
public string[] Mods = { "ra" }; // mod names
|
||||
public int OrderLatency = 3;
|
||||
public int RandomSeed = 0;
|
||||
public bool LockTeams = false; // don't allow team changes after game start.
|
||||
public bool AllowCheats = false;
|
||||
}
|
||||
}
|
||||
|
||||
public class Manifest
|
||||
{
|
||||
public readonly string[]
|
||||
Folders, Packages, Rules,
|
||||
Sequences, Chrome, Assemblies, ChromeLayout,
|
||||
Weapons, Voices, Music, TileSets;
|
||||
|
||||
public readonly string ShellmapUid;
|
||||
|
||||
public Manifest(string[] mods)
|
||||
{
|
||||
var yaml = mods
|
||||
.Select(m => MiniYaml.FromFile("mods/" + m + "/mod.yaml"))
|
||||
.Aggregate(MiniYaml.Merge);
|
||||
|
||||
Folders = YamlList(yaml, "Folders");
|
||||
Packages = YamlList(yaml, "Packages");
|
||||
Rules = YamlList(yaml, "Rules");
|
||||
Sequences = YamlList(yaml, "Sequences");
|
||||
Chrome = YamlList(yaml, "Chrome");
|
||||
Assemblies = YamlList(yaml, "Assemblies");
|
||||
ChromeLayout = YamlList(yaml, "ChromeLayout");
|
||||
Weapons = YamlList(yaml, "Weapons");
|
||||
Voices = YamlList(yaml, "Voices");
|
||||
Music = YamlList(yaml, "Music");
|
||||
TileSets = YamlList(yaml, "TileSets");
|
||||
|
||||
ShellmapUid = yaml["ShellmapUid"].Value;
|
||||
}
|
||||
|
||||
static string[] YamlList(Dictionary<string, MiniYaml> ys, string key)
|
||||
{
|
||||
return ys.ContainsKey(key) ? ys[key].Nodes.Keys.ToArray() : new string[] { };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,10 +19,8 @@ namespace OpenRA
|
||||
{
|
||||
public struct ChannelInfo
|
||||
{
|
||||
public bool Upload;
|
||||
public string Filename;
|
||||
public StreamWriter Writer;
|
||||
public bool Diff;
|
||||
}
|
||||
|
||||
public static class Log
|
||||
@@ -41,7 +39,7 @@ namespace OpenRA
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddChannel(string channelName, string filename, bool upload, bool diff)
|
||||
public static void AddChannel(string channelName, string filename)
|
||||
{
|
||||
if (channels.ContainsKey(channelName)) return;
|
||||
|
||||
@@ -52,7 +50,7 @@ namespace OpenRA
|
||||
{
|
||||
StreamWriter writer = File.CreateText(LogPathPrefix + filename);
|
||||
writer.AutoFlush = true;
|
||||
channels.Add(channelName, new ChannelInfo() { Upload = upload, Filename = filename, Writer = writer, Diff = diff });
|
||||
channels.Add(channelName, new ChannelInfo() { Filename = filename, Writer = writer });
|
||||
return;
|
||||
}
|
||||
catch (IOException) { filename = f + ".{0}".F(++i); }
|
||||
@@ -60,7 +58,7 @@ namespace OpenRA
|
||||
//if no logs exist, just make it
|
||||
StreamWriter w = File.CreateText(LogPathPrefix + filename);
|
||||
w.AutoFlush = true;
|
||||
channels.Add(channelName, new ChannelInfo() { Upload = upload, Filename = filename, Writer = w, Diff = diff });
|
||||
channels.Add(channelName, new ChannelInfo() { Filename = filename, Writer = w });
|
||||
|
||||
}
|
||||
|
||||
@@ -72,35 +70,5 @@ namespace OpenRA
|
||||
|
||||
info.Writer.WriteLine(format, args);
|
||||
}
|
||||
|
||||
public static void Upload(int gameId)
|
||||
{
|
||||
foreach (var kvp in channels.Where(x => x.Value.Upload))
|
||||
{
|
||||
kvp.Value.Writer.Close();
|
||||
var logfile = File.OpenRead(Log.LogPathPrefix + kvp.Value.Filename);
|
||||
byte[] fileContents = logfile.ReadAllBytes();
|
||||
var ms = new MemoryStream();
|
||||
|
||||
using (var gzip = new GZipStream(ms, CompressionMode.Compress, true))
|
||||
gzip.Write(fileContents, 0, fileContents.Length);
|
||||
|
||||
ms.Position = 0;
|
||||
byte[] buffer = ms.ReadAllBytes();
|
||||
|
||||
WebRequest request = WebRequest.Create("http://open-ra.org/logs/upload.php");
|
||||
request.ContentType = "application/x-gzip";
|
||||
request.ContentLength = buffer.Length;
|
||||
request.Method = "POST";
|
||||
request.Headers.Add("Game-ID", gameId.ToString());
|
||||
request.Headers.Add("Channel", kvp.Key);
|
||||
// request.Headers.Add("Diff", kvp.Value.Diff ? "1" : "0");
|
||||
|
||||
using (var requestStream = request.GetRequestStream())
|
||||
requestStream.Write(buffer, 0, buffer.Length);
|
||||
|
||||
//var response = (HttpWebResponse)request.GetResponse();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
5
OpenRA.FileFormats/Thirdparty/Random.cs
vendored
5
OpenRA.FileFormats/Thirdparty/Random.cs
vendored
@@ -18,6 +18,8 @@ namespace OpenRA.Thirdparty
|
||||
{
|
||||
uint[] mt = new uint[624];
|
||||
int index = 0;
|
||||
|
||||
public int Last;
|
||||
|
||||
public Random() : this(Environment.TickCount) { }
|
||||
|
||||
@@ -39,7 +41,8 @@ namespace OpenRA.Thirdparty
|
||||
y ^= y >> 18;
|
||||
|
||||
index = (index + 1) % 624;
|
||||
return (int)(y % int.MaxValue);
|
||||
Last = (int)(y % int.MaxValue);
|
||||
return Last;
|
||||
}
|
||||
|
||||
public int Next(int low, int high) { return low + Next() % (high - low); }
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace OpenRA.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
static class TypeExts
|
||||
public static class TypeExts
|
||||
{
|
||||
public static IEnumerable<Type> BaseTypes( this Type t )
|
||||
{
|
||||
|
||||
@@ -6,35 +6,33 @@
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.Traits;
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Support;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Traits.Activities;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public class Actor
|
||||
{
|
||||
[Sync]
|
||||
public readonly TypeDictionary traits = new TypeDictionary();
|
||||
public readonly ActorInfo Info;
|
||||
|
||||
public readonly World World;
|
||||
public readonly uint ActorID;
|
||||
|
||||
public int2 Location { get { return traits.Get<IOccupySpace>().TopLeft; } }
|
||||
public int2 Location { get { return Trait<IOccupySpace>().TopLeft; } }
|
||||
[Sync]
|
||||
public Player Owner;
|
||||
|
||||
IActivity currentActivity;
|
||||
public Group Group;
|
||||
|
||||
public Group Group;
|
||||
|
||||
internal Actor(World world, string name, TypeDictionary initDict )
|
||||
{
|
||||
var init = new ActorInitializer( this, initDict );
|
||||
@@ -51,10 +49,10 @@ namespace OpenRA
|
||||
|
||||
Info = Rules.Info[name.ToLowerInvariant()];
|
||||
foreach (var trait in Info.TraitsInConstructOrder())
|
||||
traits.Add(trait.Create(init));
|
||||
AddTrait(trait.Create(init));
|
||||
}
|
||||
|
||||
if( CenterLocation == float2.Zero && traits.Contains<IOccupySpace>() )
|
||||
if( CenterLocation == float2.Zero && HasTrait<IOccupySpace>() )
|
||||
CenterLocation = Traits.Util.CenterOfCell(Location);
|
||||
|
||||
Size = Lazy.New(() =>
|
||||
@@ -64,26 +62,31 @@ namespace OpenRA
|
||||
return new float2(si.Bounds[0], si.Bounds[1]);
|
||||
|
||||
// auto size from render
|
||||
var firstSprite = traits.WithInterface<IRender>().SelectMany(x => x.Render(this)).FirstOrDefault();
|
||||
var firstSprite = TraitsImplementing<IRender>().SelectMany(x => x.Render(this)).FirstOrDefault();
|
||||
if (firstSprite.Sprite == null) return float2.Zero;
|
||||
return firstSprite.Sprite.size;
|
||||
});
|
||||
}
|
||||
|
||||
public void Tick()
|
||||
{
|
||||
{
|
||||
var wasIdle = currentActivity is Idle;
|
||||
while (currentActivity != null)
|
||||
{
|
||||
var a = currentActivity;
|
||||
|
||||
var sw = new Stopwatch();
|
||||
currentActivity = a.Tick(this) ?? new Idle();
|
||||
|
||||
var dt = sw.ElapsedTime();
|
||||
if(dt > Game.Settings.Debug.LongTickThreshold)
|
||||
Log.Write("perf", "[{2}] Activity: {0} ({1:0.000} ms)", a, dt * 1000, Game.LocalTick);
|
||||
|
||||
if (a == currentActivity) break;
|
||||
|
||||
if (currentActivity is Idle)
|
||||
{
|
||||
if (!wasIdle)
|
||||
foreach (var ni in traits.WithInterface<INotifyIdle>())
|
||||
foreach (var ni in TraitsImplementing<INotifyIdle>())
|
||||
ni.Idle(this);
|
||||
|
||||
break;
|
||||
@@ -102,25 +105,24 @@ namespace OpenRA
|
||||
|
||||
public IEnumerable<Renderable> Render()
|
||||
{
|
||||
var mods = traits.WithInterface<IRenderModifier>();
|
||||
var sprites = traits.WithInterface<IRender>().SelectMany(x => x.Render(this));
|
||||
var mods = TraitsImplementing<IRenderModifier>();
|
||||
var sprites = TraitsImplementing<IRender>().SelectMany(x => x.Render(this));
|
||||
return mods.Aggregate(sprites, (m, p) => p.ModifyRender(this, m));
|
||||
}
|
||||
|
||||
public Order Order( int2 xy, MouseInput mi )
|
||||
public Order Order( int2 xy, MouseInput mi, Actor underCursor )
|
||||
{
|
||||
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<SelectableInfo>())
|
||||
.OrderByDescending(a => a.Info.Traits.Contains<SelectableInfo>() ? a.Info.Traits.Get<SelectableInfo>().Priority : int.MinValue)
|
||||
.FirstOrDefault();
|
||||
|
||||
return traits.WithInterface<IIssueOrder>()
|
||||
return TraitsImplementing<IIssueOrder>()
|
||||
.OrderByDescending( x => x.OrderPriority( this, xy, mi, underCursor ) )
|
||||
.Select( x => x.IssueOrder( this, xy, mi, underCursor ) )
|
||||
.FirstOrDefault( x => x != null );
|
||||
}
|
||||
@@ -137,14 +139,14 @@ namespace OpenRA
|
||||
|
||||
if (useAltitude)
|
||||
{
|
||||
var move = traits.GetOrDefault<IMove>();
|
||||
var move = TraitOrDefault<IMove>();
|
||||
if (move != null) loc -= new float2(0, move.Altitude);
|
||||
}
|
||||
|
||||
return new RectangleF(loc.X, loc.Y, size.X, size.Y);
|
||||
}
|
||||
|
||||
public bool IsInWorld { get; set; }
|
||||
public bool IsInWorld { get; internal set; }
|
||||
|
||||
public void QueueActivity( IActivity nextActivity )
|
||||
{
|
||||
@@ -188,5 +190,42 @@ namespace OpenRA
|
||||
{
|
||||
return "{0} {1}{2}".F( Info.Name, ActorID, IsInWorld ? "" : " (not in world)" );
|
||||
}
|
||||
|
||||
public T Trait<T>()
|
||||
{
|
||||
return World.traitDict.Get<T>( this );
|
||||
}
|
||||
|
||||
public T TraitOrDefault<T>()
|
||||
{
|
||||
return World.traitDict.GetOrDefault<T>( this );
|
||||
}
|
||||
|
||||
public IEnumerable<T> TraitsImplementing<T>()
|
||||
{
|
||||
return World.traitDict.WithInterface<T>( this );
|
||||
}
|
||||
|
||||
public bool HasTrait<T>()
|
||||
{
|
||||
return World.traitDict.Contains<T>( this );
|
||||
}
|
||||
|
||||
public void AddTrait( object trait )
|
||||
{
|
||||
World.traitDict.AddTrait( this, trait );
|
||||
}
|
||||
|
||||
public bool Destroyed { get; private set; }
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
World.AddFrameEndTask( w =>
|
||||
{
|
||||
World.Remove( this );
|
||||
World.traitDict.RemoveActor( this );
|
||||
Destroyed = true;
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ namespace OpenRA
|
||||
{
|
||||
if( player != null )
|
||||
return player;
|
||||
return world.players.First( x => x.Value.InternalName == PlayerName ).Value;
|
||||
return world.players.Values.First( x => x.InternalName == PlayerName );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,9 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
@@ -22,6 +23,9 @@ 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 )
|
||||
@@ -41,7 +45,7 @@ namespace OpenRA.FileFormats
|
||||
foreach( var init in InitDict )
|
||||
{
|
||||
var initName = init.GetType().Name;
|
||||
ret.Nodes.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,7 +17,7 @@ namespace OpenRA
|
||||
CursorSequence sequence;
|
||||
public Cursor(string cursor)
|
||||
{
|
||||
sequence = SequenceProvider.GetCursorSequence(cursor);
|
||||
sequence = CursorProvider.GetCursorSequence(cursor);
|
||||
}
|
||||
|
||||
public void Draw(int frame, float2 pos)
|
||||
|
||||
@@ -28,12 +28,15 @@ namespace OpenRA.Effects
|
||||
|
||||
public void Tick( World world )
|
||||
{
|
||||
if (--remainingTicks == 0)
|
||||
if (--remainingTicks == 0 || !target.IsInWorld)
|
||||
world.AddFrameEndTask(w => w.Remove(this));
|
||||
}
|
||||
|
||||
public IEnumerable<Renderable> Render()
|
||||
{
|
||||
if (!target.IsInWorld)
|
||||
yield break;
|
||||
|
||||
if (remainingTicks % 2 == 0)
|
||||
foreach (var r in target.Render())
|
||||
yield return r.WithPalette("highlight");
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace OpenRA.Effects
|
||||
|
||||
public IEnumerable<Renderable> Render()
|
||||
{
|
||||
yield return new Renderable(anim.Image, pos - .5f * anim.Image.size, "shadow");
|
||||
yield return new Renderable(anim.Image, pos - .5f * anim.Image.size, "shadow", (int)pos.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace OpenRA
|
||||
a( x );
|
||||
var dt = sw.ElapsedTime() - t;
|
||||
if( dt > time )
|
||||
Log.Write("perf", text, x, dt * 1000);
|
||||
Log.Write("perf", text, x, dt * 1000, Game.LocalTick);
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,148 +8,49 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.FileFormats.Graphics;
|
||||
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.Support;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
using XRandom = OpenRA.Thirdparty.Random;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public static class Game
|
||||
{
|
||||
public static readonly int CellSize = 24;
|
||||
public static int CellSize { get { return modData.Manifest.TileSize; } }
|
||||
|
||||
public static ModData modData;
|
||||
public static World world;
|
||||
public static Viewport viewport;
|
||||
internal static UserSettings Settings;
|
||||
public static Settings Settings;
|
||||
|
||||
internal static OrderManager orderManager;
|
||||
|
||||
public static bool skipMakeAnims = true;
|
||||
|
||||
public static XRandom CosmeticRandom = new XRandom(); // not synced
|
||||
|
||||
public static Renderer Renderer;
|
||||
static int2 clientSize;
|
||||
static string mapName;
|
||||
public static Session LobbyInfo = new Session();
|
||||
static bool packageChangePending;
|
||||
static bool mapChangePending;
|
||||
static Pair<Assembly, string>[] ModAssemblies;
|
||||
|
||||
static void LoadModPackages()
|
||||
{
|
||||
FileSystem.UnmountAll();
|
||||
Timer.Time("reset: {0}");
|
||||
|
||||
foreach (var dir in Manifest.Folders) FileSystem.Mount(dir);
|
||||
foreach (var pkg in Manifest.Packages) FileSystem.Mount(pkg);
|
||||
|
||||
Timer.Time("mount temporary packages: {0}");
|
||||
}
|
||||
|
||||
public static void LoadModAssemblies(Manifest m)
|
||||
{
|
||||
// All the core namespaces
|
||||
var asms = typeof(Game).Assembly.GetNamespaces()
|
||||
.Select(c => Pair.New(typeof(Game).Assembly, c))
|
||||
.ToList();
|
||||
|
||||
// Namespaces from each mod assembly
|
||||
foreach (var a in m.Assemblies)
|
||||
{
|
||||
var asm = Assembly.LoadFile(Path.GetFullPath(a));
|
||||
asms.AddRange(asm.GetNamespaces().Select(ns => Pair.New(asm, ns)));
|
||||
}
|
||||
|
||||
ModAssemblies = asms.ToArray();
|
||||
}
|
||||
|
||||
public static Action<string> MissingTypeAction =
|
||||
s => { throw new InvalidOperationException("Cannot locate type: {0}".F(s)); };
|
||||
|
||||
public static T CreateObject<T>(string classname)
|
||||
{
|
||||
foreach (var mod in ModAssemblies)
|
||||
{
|
||||
var fullTypeName = mod.Second + "." + classname;
|
||||
var obj = mod.First.CreateInstance(fullTypeName);
|
||||
if (obj != null)
|
||||
return (T)obj;
|
||||
}
|
||||
|
||||
MissingTypeAction(classname);
|
||||
return default(T);
|
||||
}
|
||||
|
||||
public static Dictionary<string, MapStub> AvailableMaps;
|
||||
|
||||
// TODO: Do this nicer
|
||||
static Dictionary<string, MapStub> FindMaps(string[] mods)
|
||||
{
|
||||
var paths = new[] { "maps/" }.Concat(mods.Select(m => "mods/" + m + "/maps/"))
|
||||
.Where(p => Directory.Exists(p))
|
||||
.SelectMany(p => Directory.GetDirectories(p)).ToList();
|
||||
|
||||
return paths.Select(p => new MapStub(new Folder(p))).ToDictionary(m => m.Uid);
|
||||
}
|
||||
|
||||
static void ChangeMods()
|
||||
{
|
||||
Timer.Time("----ChangeMods");
|
||||
Manifest = new Manifest(LobbyInfo.GlobalSettings.Mods);
|
||||
Timer.Time("manifest: {0}");
|
||||
LoadModAssemblies(Manifest);
|
||||
SheetBuilder.Initialize();
|
||||
LoadModPackages();
|
||||
Timer.Time("load assemblies, packages: {0}");
|
||||
packageChangePending = false;
|
||||
}
|
||||
public static bool HasInputFocus = false;
|
||||
|
||||
public static Manifest Manifest;
|
||||
|
||||
static void LoadMap(string mapName)
|
||||
static void LoadMap(string uid)
|
||||
{
|
||||
Timer.Time("----LoadMap");
|
||||
SheetBuilder.Initialize();
|
||||
Manifest = new Manifest(LobbyInfo.GlobalSettings.Mods);
|
||||
Timer.Time("manifest: {0}");
|
||||
|
||||
if (!Game.AvailableMaps.ContainsKey(mapName))
|
||||
throw new InvalidDataException("Cannot find map with Uid {0}".F(mapName));
|
||||
|
||||
var map = new Map(Game.AvailableMaps[mapName].Package);
|
||||
|
||||
viewport = new Viewport(clientSize, map.TopLeft, map.BottomRight, Renderer);
|
||||
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.
|
||||
ChromeProvider.Initialize(Manifest.Chrome);
|
||||
Timer.Time("viewport, ChromeProvider: {0}");
|
||||
world = new World(Manifest, map);
|
||||
Timer.Time("world: {0}");
|
||||
|
||||
SequenceProvider.Initialize(Manifest.Sequences);
|
||||
Timer.Time("ChromeProv, SeqProv: {0}");
|
||||
|
||||
Timer.Time("----end LoadMap");
|
||||
Debug("Map change {0} -> {1}".F(Game.mapName, mapName));
|
||||
world = new World(modData.Manifest, map);
|
||||
}
|
||||
|
||||
|
||||
public static void MoveViewport(int2 loc)
|
||||
{
|
||||
viewport.Center(loc);
|
||||
@@ -167,7 +68,7 @@ namespace OpenRA
|
||||
|
||||
lastConnectionState = ConnectionState.PreConnecting;
|
||||
ConnectionStateChanged();
|
||||
|
||||
|
||||
orderManager = new OrderManager(new NetworkConnection(host, port), ChooseReplayFilename());
|
||||
}
|
||||
|
||||
@@ -180,7 +81,7 @@ namespace OpenRA
|
||||
{
|
||||
lastConnectionState = ConnectionState.PreConnecting;
|
||||
ConnectionStateChanged();
|
||||
|
||||
|
||||
if (orderManager != null) orderManager.Dispose();
|
||||
orderManager = new OrderManager(new EchoConnection());
|
||||
}
|
||||
@@ -195,96 +96,28 @@ namespace OpenRA
|
||||
internal static int RenderFrame = 0;
|
||||
internal static int LocalTick = 0;
|
||||
const int NetTickScale = 3; // 120ms net tick for 40ms local tick
|
||||
|
||||
static Queue<Pair<int, string>> syncReports = new Queue<Pair<int, string>>();
|
||||
const int numSyncReports = 5;
|
||||
|
||||
internal static void UpdateSyncReport()
|
||||
{
|
||||
if (!Settings.RecordSyncReports)
|
||||
return;
|
||||
|
||||
while (syncReports.Count >= numSyncReports) syncReports.Dequeue();
|
||||
syncReports.Enqueue(Pair.New(orderManager.FrameNumber, GenerateSyncReport()));
|
||||
}
|
||||
|
||||
static string GenerateSyncReport()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("Actors:");
|
||||
foreach (var a in world.Actors)
|
||||
sb.AppendLine("\t {0} {1} {2} ({3})".F(
|
||||
a.ActorID,
|
||||
a.Info.Name,
|
||||
(a.Owner == null) ? "null" : a.Owner.InternalName,
|
||||
Sync.CalculateSyncHash(a)));
|
||||
|
||||
sb.AppendLine("Tick Actors:");
|
||||
foreach (var a in world.Queries.WithTraitMultiple<object>())
|
||||
{
|
||||
var sync = Sync.CalculateSyncHash(a.Trait);
|
||||
if (sync != 0)
|
||||
sb.AppendLine("\t {0} {1} {2} {3} ({4})".F(
|
||||
a.Actor.ActorID,
|
||||
a.Actor.Info.Name,
|
||||
(a.Actor.Owner == null) ? "null" : a.Actor.Owner.InternalName,
|
||||
a.Trait.GetType().Name,
|
||||
sync));
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
internal static void DumpSyncReport(int frame)
|
||||
{
|
||||
var f = syncReports.FirstOrDefault(a => a.First == frame);
|
||||
if (f == default(Pair<int, string>))
|
||||
{
|
||||
Log.Write("sync", "No sync report available!");
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Write("sync", "Sync for net frame {0} -------------", f.First);
|
||||
Log.Write("sync", "{0}", f.Second);
|
||||
}
|
||||
|
||||
public static event Action ConnectionStateChanged = () => { };
|
||||
static ConnectionState lastConnectionState = ConnectionState.PreConnecting;
|
||||
|
||||
public static int LocalClientId { get { return orderManager.Connection.LocalClientId; } }
|
||||
|
||||
static void Tick()
|
||||
{
|
||||
if (packageChangePending)
|
||||
{
|
||||
// TODO: Only do this on mod change
|
||||
Timer.Time("----begin maplist");
|
||||
AvailableMaps = FindMaps(LobbyInfo.GlobalSettings.Mods);
|
||||
Timer.Time("maplist: {0}");
|
||||
ChangeMods();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mapChangePending)
|
||||
{
|
||||
mapName = LobbyInfo.GlobalSettings.Map;
|
||||
mapChangePending = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (orderManager.Connection.ConnectionState != lastConnectionState)
|
||||
{
|
||||
lastConnectionState = orderManager.Connection.ConnectionState;
|
||||
ConnectionStateChanged();
|
||||
}
|
||||
|
||||
|
||||
int t = Environment.TickCount;
|
||||
int dt = t - lastTime;
|
||||
if (dt >= Settings.Timestep)
|
||||
if (dt >= Settings.Game.Timestep)
|
||||
{
|
||||
using (new PerfSample("tick_time"))
|
||||
{
|
||||
lastTime += Settings.Timestep;
|
||||
lastTime += Settings.Game.Timestep;
|
||||
Widget.DoTick(world);
|
||||
|
||||
Sound.Tick();
|
||||
orderManager.TickImmediate(world);
|
||||
|
||||
var isNetTick = LocalTick % NetTickScale == 0;
|
||||
@@ -293,6 +126,8 @@ namespace OpenRA
|
||||
{
|
||||
++LocalTick;
|
||||
|
||||
Log.Write("debug", "--Tick: {0} ({1})", LocalTick, isNetTick ? "net" : "local");
|
||||
|
||||
if (isNetTick) orderManager.Tick(world);
|
||||
|
||||
world.OrderGenerator.Tick(world);
|
||||
@@ -326,33 +161,10 @@ namespace OpenRA
|
||||
|
||||
internal static void SyncLobbyInfo(string data)
|
||||
{
|
||||
var oldLobbyInfo = LobbyInfo;
|
||||
LobbyInfo = Session.Deserialize(data);
|
||||
|
||||
var session = new Session();
|
||||
session.GlobalSettings.Mods = Settings.InitialMods;
|
||||
|
||||
var ys = MiniYaml.FromString(data);
|
||||
foreach (var y in ys)
|
||||
{
|
||||
if (y.Key == "GlobalSettings")
|
||||
{
|
||||
FieldLoader.Load(session.GlobalSettings, y.Value);
|
||||
continue;
|
||||
}
|
||||
|
||||
int index;
|
||||
if (!int.TryParse(y.Key, out index))
|
||||
continue; // not a player.
|
||||
|
||||
var client = new Session.Client();
|
||||
FieldLoader.Load(client, y.Value);
|
||||
session.Clients.Add(client);
|
||||
}
|
||||
|
||||
LobbyInfo = session;
|
||||
|
||||
if (!world.GameHasStarted)
|
||||
world.SharedRandom = new OpenRA.Thirdparty.Random(LobbyInfo.GlobalSettings.RandomSeed);
|
||||
if( !world.GameHasStarted )
|
||||
world.SharedRandom = new XRandom( LobbyInfo.GlobalSettings.RandomSeed );
|
||||
|
||||
if (orderManager.Connection.ConnectionState == ConnectionState.Connected)
|
||||
world.SetLocalPlayer(orderManager.Connection.LocalClientId);
|
||||
@@ -364,69 +176,33 @@ namespace OpenRA
|
||||
Debug("Order lag is now {0} frames.".F(LobbyInfo.GlobalSettings.OrderLatency));
|
||||
}
|
||||
|
||||
if (mapName != LobbyInfo.GlobalSettings.Map)
|
||||
mapChangePending = true;
|
||||
|
||||
if (string.Join(",", oldLobbyInfo.GlobalSettings.Mods)
|
||||
!= string.Join(",", LobbyInfo.GlobalSettings.Mods))
|
||||
{
|
||||
Debug("Mods list changed, reloading: {0}".F(string.Join(",", LobbyInfo.GlobalSettings.Mods)));
|
||||
packageChangePending = true;
|
||||
}
|
||||
|
||||
LobbyInfoChanged();
|
||||
}
|
||||
|
||||
public static void IssueOrder(Order o) { orderManager.IssueOrder(o); } /* avoid exposing the OM to mod code */
|
||||
|
||||
static void LoadShellMap(string map)
|
||||
{
|
||||
LoadMap(map);
|
||||
world.Queries = new World.AllQueries(world);
|
||||
|
||||
foreach (var gs in world.WorldActor.traits.WithInterface<IGameStarted>())
|
||||
gs.GameStarted(world);
|
||||
orderManager.StartGame();
|
||||
}
|
||||
|
||||
public static event Action OnGameStart = () => { };
|
||||
internal static void StartGame()
|
||||
public static event Action AfterGameStart = () => {};
|
||||
public static event Action BeforeGameStart = () => {};
|
||||
internal static void StartGame(string map)
|
||||
{
|
||||
LoadMap(LobbyInfo.GlobalSettings.Map);
|
||||
BeforeGameStart();
|
||||
LoadMap(map);
|
||||
if (orderManager.GameStarted) return;
|
||||
Widget.SelectedWidget = null;
|
||||
|
||||
world.Queries = new World.AllQueries(world);
|
||||
Widget.SelectedWidget = null;
|
||||
|
||||
foreach (var gs in world.WorldActor.traits.WithInterface<IGameStarted>())
|
||||
gs.GameStarted(world);
|
||||
LocalTick = 0;
|
||||
|
||||
viewport.GoToStartLocation(world.LocalPlayer);
|
||||
orderManager.StartGame();
|
||||
OnGameStart();
|
||||
}
|
||||
|
||||
public static Stance ChooseInitialStance(Player p, Player q)
|
||||
{
|
||||
if (p == q) return Stance.Ally;
|
||||
|
||||
// Hack: All map players are neutral wrt everyone else
|
||||
if (p.Index < 0 || q.Index < 0) return Stance.Neutral;
|
||||
|
||||
var pc = GetClientForPlayer(p);
|
||||
var qc = GetClientForPlayer(q);
|
||||
|
||||
return pc.Team != 0 && pc.Team == qc.Team
|
||||
? Stance.Ally : Stance.Enemy;
|
||||
}
|
||||
|
||||
static Session.Client GetClientForPlayer(Player p)
|
||||
{
|
||||
return LobbyInfo.Clients.Single(c => c.Index == p.Index);
|
||||
viewport.RefreshPalette();
|
||||
AfterGameStart();
|
||||
}
|
||||
|
||||
public static void DispatchMouseInput(MouseInputEvent ev, MouseEventArgs e, Modifiers modifierKeys)
|
||||
{
|
||||
if (world == null)
|
||||
return;
|
||||
|
||||
int sync = world.SyncHash();
|
||||
var initialWorld = world;
|
||||
|
||||
@@ -438,12 +214,12 @@ namespace OpenRA
|
||||
Modifiers = modifierKeys,
|
||||
};
|
||||
Widget.HandleInput(world, mi);
|
||||
|
||||
|
||||
if (sync != world.SyncHash() && world == initialWorld)
|
||||
throw new InvalidOperationException("Desync in DispatchMouseInput");
|
||||
}
|
||||
|
||||
internal static bool IsHost
|
||||
public static bool IsHost
|
||||
{
|
||||
get { return orderManager.Connection.LocalClientId == 0; }
|
||||
}
|
||||
@@ -455,8 +231,11 @@ namespace OpenRA
|
||||
|
||||
public static void HandleKeyEvent(KeyInput e)
|
||||
{
|
||||
if (world == null)
|
||||
return;
|
||||
|
||||
int sync = world.SyncHash();
|
||||
|
||||
|
||||
if (Widget.HandleKeyPress(e))
|
||||
return;
|
||||
|
||||
@@ -468,67 +247,39 @@ namespace OpenRA
|
||||
public static Modifiers GetModifierKeys() { return modifiers; }
|
||||
public static void HandleModifierKeys(Modifiers mods) { modifiers = mods; }
|
||||
|
||||
static Size GetResolution(Settings settings, WindowMode windowmode)
|
||||
{
|
||||
var desktopResolution = Screen.PrimaryScreen.Bounds.Size;
|
||||
var customSize = (windowmode == WindowMode.Windowed) ? Settings.WindowedSize : Settings.FullscreenSize;
|
||||
|
||||
if (customSize.X > 0 && customSize.Y > 0)
|
||||
{
|
||||
desktopResolution.Width = customSize.X;
|
||||
desktopResolution.Height = customSize.Y;
|
||||
}
|
||||
return new Size(
|
||||
desktopResolution.Width,
|
||||
desktopResolution.Height);
|
||||
}
|
||||
|
||||
internal static void Initialize(Settings settings)
|
||||
internal static void Initialize(Arguments args)
|
||||
{
|
||||
AppDomain.CurrentDomain.AssemblyResolve += FileSystem.ResolveAssembly;
|
||||
|
||||
|
||||
var defaultSupport = Environment.GetFolderPath(Environment.SpecialFolder.Personal)
|
||||
+ Path.DirectorySeparatorChar + "OpenRA";
|
||||
|
||||
SupportDir = settings.GetValue("SupportDir", defaultSupport);
|
||||
Settings = new UserSettings(settings);
|
||||
|
||||
|
||||
SupportDir = args.GetValue("SupportDir", defaultSupport);
|
||||
Settings = new Settings(SupportDir + "settings.yaml", args);
|
||||
|
||||
Log.LogPath = SupportDir + "Logs" + Path.DirectorySeparatorChar;
|
||||
Log.AddChannel("perf", "perf.log", false, false);
|
||||
Log.AddChannel("debug", "debug.log", false, false);
|
||||
Log.AddChannel("sync", "syncreport.log", true, true);
|
||||
|
||||
LobbyInfo.GlobalSettings.Mods = Settings.InitialMods;
|
||||
Manifest = new Manifest(LobbyInfo.GlobalSettings.Mods);
|
||||
|
||||
// Load the default mod to access required files
|
||||
LoadModPackages();
|
||||
|
||||
Renderer.SheetSize = Settings.SheetSize;
|
||||
|
||||
var resolution = GetResolution(settings, Game.Settings.WindowMode);
|
||||
Renderer = new Renderer(resolution, Game.Settings.WindowMode);
|
||||
resolution = Renderer.Resolution;
|
||||
clientSize = new int2(resolution);
|
||||
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 );
|
||||
|
||||
Sound.Initialize();
|
||||
PerfHistory.items["render"].hasNormalTick = false;
|
||||
PerfHistory.items["batches"].hasNormalTick = false;
|
||||
PerfHistory.items["text"].hasNormalTick = false;
|
||||
PerfHistory.items["cursor"].hasNormalTick = false;
|
||||
AvailableMaps = FindMaps(LobbyInfo.GlobalSettings.Mods);
|
||||
|
||||
ChangeMods();
|
||||
|
||||
if (Settings.Replay != null)
|
||||
orderManager = new OrderManager(new ReplayConnection(Settings.Replay));
|
||||
else
|
||||
JoinLocal();
|
||||
|
||||
LoadShellMap(Manifest.ShellmapUid);
|
||||
PerfHistory.items["cursor"].hasNormalTick = false;
|
||||
|
||||
|
||||
JoinLocal();
|
||||
StartGame(modData.Manifest.ShellmapUid);
|
||||
|
||||
|
||||
ResetTimer();
|
||||
}
|
||||
|
||||
@@ -542,78 +293,49 @@ namespace OpenRA
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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", s);
|
||||
{
|
||||
AddChatLine(Color.White, "Debug", String.Format(s,args));
|
||||
}
|
||||
|
||||
public static void Disconnect()
|
||||
{
|
||||
var shellmap = Manifest.ShellmapUid;
|
||||
orderManager.Dispose();
|
||||
var shellmap = modData.Manifest.ShellmapUid;
|
||||
LobbyInfo.GlobalSettings.Mods = Settings.InitialMods;
|
||||
LobbyInfo = new Session();
|
||||
LobbyInfo.GlobalSettings.Mods = Settings.Game.Mods;
|
||||
LoadShellMap(shellmap);
|
||||
JoinLocal();
|
||||
StartGame(shellmap);
|
||||
|
||||
Widget.RootWidget.CloseWindow();
|
||||
Widget.RootWidget.OpenWindow("MAINMENU_BG");
|
||||
|
||||
}
|
||||
|
||||
static string baseSupportDir = null;
|
||||
public static string SupportDir
|
||||
set {
|
||||
{
|
||||
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);
|
||||
|
||||
}
|
||||
get {return baseSupportDir;}
|
||||
}
|
||||
|
||||
|
||||
internal static int GetGameId()
|
||||
{
|
||||
try
|
||||
{
|
||||
string s = File.ReadAllText(SupportDir + "currentgameid");
|
||||
return int.Parse(s);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return 0;
|
||||
baseSupportDir = dir + Path.DirectorySeparatorChar;
|
||||
}
|
||||
get { return baseSupportDir; }
|
||||
}
|
||||
internal static void SetGameId(int id)
|
||||
|
||||
public static T CreateObject<T>( string name )
|
||||
var file = File.CreateText(SupportDir + "currentgameid");
|
||||
file.Write(id);
|
||||
file.Flush();
|
||||
file.Close();
|
||||
}
|
||||
|
||||
public static void InitializeEngineWithMods(string[] mods)
|
||||
{
|
||||
AppDomain.CurrentDomain.AssemblyResolve += FileSystem.ResolveAssembly;
|
||||
Manifest = new Manifest(mods);
|
||||
LoadModAssemblies(Manifest);
|
||||
|
||||
FileSystem.UnmountAll();
|
||||
foreach (var folder in Manifest.Folders) FileSystem.Mount(folder);
|
||||
foreach (var pkg in Manifest.Packages) FileSystem.Mount(pkg);
|
||||
|
||||
Rules.LoadRules(Manifest, new Map());
|
||||
{
|
||||
return modData.ObjectCreator.CreateObject<T>( name );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,27 +19,22 @@ namespace OpenRA
|
||||
public class ActorInfo
|
||||
{
|
||||
public readonly string Name;
|
||||
public readonly string Category;
|
||||
public readonly TypeDictionary Traits = new TypeDictionary();
|
||||
|
||||
public ActorInfo( string name, MiniYaml node, Dictionary<string, MiniYaml> allUnits )
|
||||
{
|
||||
var mergedNode = MergeWithParent( node, allUnits ).Nodes;
|
||||
var mergedNode = MergeWithParent( node, allUnits ).NodesDict;
|
||||
|
||||
Name = name;
|
||||
MiniYaml categoryNode;
|
||||
if( mergedNode.TryGetValue( "Category", out categoryNode ) )
|
||||
Category = categoryNode.Value;
|
||||
|
||||
foreach( var t in mergedNode )
|
||||
if( t.Key != "Inherits" && t.Key != "Category" && !t.Key.StartsWith("-") )
|
||||
if( t.Key != "Inherits" && !t.Key.StartsWith("-") )
|
||||
Traits.Add( LoadTraitInfo( t.Key.Split('@')[0], t.Value ) );
|
||||
}
|
||||
|
||||
static MiniYaml GetParent( MiniYaml node, Dictionary<string, MiniYaml> allUnits )
|
||||
{
|
||||
MiniYaml inherits;
|
||||
node.Nodes.TryGetValue( "Inherits", out inherits );
|
||||
node.NodesDict.TryGetValue( "Inherits", out inherits );
|
||||
if( inherits == null || string.IsNullOrEmpty( inherits.Value ) )
|
||||
return null;
|
||||
|
||||
|
||||
@@ -13,38 +13,22 @@ using OpenRA.FileFormats;
|
||||
namespace OpenRA.GameRules
|
||||
{
|
||||
public class MusicInfo
|
||||
{
|
||||
public readonly MusicPool Pool;
|
||||
public readonly string[] Music = { };
|
||||
{
|
||||
public readonly string Filename = null;
|
||||
public readonly string Title = null;
|
||||
public readonly int Length = 0; // seconds
|
||||
public readonly bool Exists = false;
|
||||
|
||||
public MusicInfo( MiniYaml y )
|
||||
public MusicInfo( string key, MiniYaml value )
|
||||
{
|
||||
FieldLoader.Load(this, y);
|
||||
Pool = new MusicPool(Music);
|
||||
Filename = key+".aud";
|
||||
Title = value.Value;
|
||||
|
||||
if (!FileSystem.Exists(Filename))
|
||||
return;
|
||||
|
||||
Exists = true;
|
||||
Length = (int)AudLoader.SoundLength(FileSystem.Open(Filename));
|
||||
}
|
||||
}
|
||||
|
||||
public class MusicPool
|
||||
{
|
||||
readonly string[] clips;
|
||||
int playing = 0;
|
||||
|
||||
public MusicPool(params string[] clips)
|
||||
{
|
||||
this.clips = clips;
|
||||
}
|
||||
|
||||
public string GetNext()
|
||||
{
|
||||
playing = (playing + 1) % clips.Length;
|
||||
return clips[playing];
|
||||
}
|
||||
public string GetPrev()
|
||||
{
|
||||
playing = (playing + clips.Length - 1) % clips.Length;
|
||||
return clips[playing];
|
||||
}
|
||||
public string GetCurrent(){ return clips[playing];}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,20 +18,20 @@ namespace OpenRA
|
||||
{
|
||||
public static class Rules
|
||||
{
|
||||
public static TechTree TechTree;
|
||||
|
||||
public static Dictionary<string, ActorInfo> Info;
|
||||
public static Dictionary<string, WeaponInfo> Weapons;
|
||||
public static Dictionary<string, VoiceInfo> Voices;
|
||||
public static Dictionary<string, MusicInfo> Music;
|
||||
public static Dictionary<string, string> Movies;
|
||||
public static Dictionary<string, TileSet> TileSets;
|
||||
|
||||
public static void LoadRules(Manifest m, Map map)
|
||||
{
|
||||
Info = LoadYamlRules(m.Rules, map.Rules, (k, y) => new ActorInfo(k.Key.ToLowerInvariant(), k.Value, y));
|
||||
Weapons = LoadYamlRules(m.Weapons, map.Weapons, (k, _) => new WeaponInfo(k.Key.ToLowerInvariant(), k.Value));
|
||||
Voices = LoadYamlRules(m.Voices, map.Voices, (k, _) => new VoiceInfo(k.Value));
|
||||
Music = LoadYamlRules(m.Music, map.Music, (k, _) => new MusicInfo(k.Value));
|
||||
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));
|
||||
Music = LoadYamlRules(m.Music, new List<MiniYamlNode>(), (k, _) => new MusicInfo(k.Key, k.Value));
|
||||
Movies = LoadYamlRules(m.Movies, new List<MiniYamlNode>(), (k, v) => k.Value.Value);
|
||||
|
||||
TileSets = new Dictionary<string, TileSet>();
|
||||
foreach (var file in m.TileSets)
|
||||
@@ -39,19 +39,13 @@ namespace OpenRA
|
||||
var t = new TileSet(file);
|
||||
TileSets.Add(t.Id,t);
|
||||
}
|
||||
|
||||
TechTree = new TechTree();
|
||||
}
|
||||
|
||||
static Dictionary<string, T> LoadYamlRules<T>(string[] files, Dictionary<string,MiniYaml>dict, Func<KeyValuePair<string, MiniYaml>, Dictionary<string, MiniYaml>, T> f)
|
||||
static Dictionary<string, T> LoadYamlRules<T>(string[] files, List<MiniYamlNode> dict, Func<MiniYamlNode, Dictionary<string, MiniYaml>, T> f)
|
||||
{
|
||||
var y = files.Select(a => MiniYaml.FromFile(a)).Aggregate(dict,MiniYaml.Merge);
|
||||
return y.ToDictionary(kv => kv.Key.ToLowerInvariant(), kv => f(kv, y));
|
||||
}
|
||||
|
||||
public static IEnumerable<string> Categories()
|
||||
{
|
||||
return Info.Values.Select( x => x.Category ).Distinct().Where( g => g != null ).ToList();
|
||||
var yy = y.ToDictionary( x => x.Key, x => x.Value );
|
||||
return y.ToDictionary(kv => kv.Key.ToLowerInvariant(), kv => f(kv, yy));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
159
OpenRA.Game/GameRules/Settings.cs
Executable file
159
OpenRA.Game/GameRules/Settings.cs
Executable file
@@ -0,0 +1,159 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.FileFormats.Graphics;
|
||||
using System;
|
||||
|
||||
namespace OpenRA.GameRules
|
||||
{
|
||||
public class ServerSettings
|
||||
{
|
||||
public string Name = "OpenRA Game";
|
||||
public int ListenPort = 1234;
|
||||
public int ExternalPort = 1234;
|
||||
public bool AdvertiseOnline = true;
|
||||
public string MasterServer = "http://open-ra.org/master/";
|
||||
public bool AllowCheats = false;
|
||||
}
|
||||
|
||||
public class DebugSettings
|
||||
{
|
||||
public bool PerfGraph = false;
|
||||
public bool RecordSyncReports = true;
|
||||
public bool ShowCollisions = false;
|
||||
public float LongTickThreshold = 0.001f;
|
||||
}
|
||||
|
||||
public class GraphicSettings
|
||||
{
|
||||
public WindowMode Mode = WindowMode.PseudoFullscreen;
|
||||
public int2 FullscreenSize = new int2(Screen.PrimaryScreen.Bounds.Width,Screen.PrimaryScreen.Bounds.Height);
|
||||
public int2 WindowedSize = new int2(1024,768);
|
||||
public readonly int2 MinResolution = new int2(800, 600);
|
||||
}
|
||||
|
||||
public class SoundSettings
|
||||
{
|
||||
public float SoundVolume = 0.5f;
|
||||
public float MusicVolume = 0.5f;
|
||||
public float VideoVolume = 0.5f;
|
||||
public bool Shuffle = false;
|
||||
public bool Repeat = false;
|
||||
}
|
||||
|
||||
public class PlayerSettings
|
||||
{
|
||||
public string Name = "Newbie";
|
||||
public Color Color1 = Color.FromArgb(255,160,238);
|
||||
public Color Color2 = Color.FromArgb(68,0,56);
|
||||
public string LastServer = "localhost:1234";
|
||||
}
|
||||
|
||||
public class GameSettings
|
||||
{
|
||||
public string[] Mods = { "ra" };
|
||||
public bool MatchTimer = true;
|
||||
|
||||
// Behaviour settings
|
||||
public bool ViewportEdgeScroll = true;
|
||||
public bool InverseDragScroll = false;
|
||||
|
||||
// Internal game settings
|
||||
public int Timestep = 40;
|
||||
public int SheetSize = 2048;
|
||||
}
|
||||
|
||||
public class Settings
|
||||
{
|
||||
string SettingsFile;
|
||||
|
||||
public PlayerSettings Player = new PlayerSettings();
|
||||
public GameSettings Game = new GameSettings();
|
||||
public SoundSettings Sound = new SoundSettings();
|
||||
public GraphicSettings Graphics = new GraphicSettings();
|
||||
public ServerSettings Server = new ServerSettings();
|
||||
public DebugSettings Debug = new DebugSettings();
|
||||
|
||||
Dictionary<string, object> Sections;
|
||||
public Settings(string file, Arguments args)
|
||||
{
|
||||
SettingsFile = file;
|
||||
Sections = new Dictionary<string, object>()
|
||||
{
|
||||
{"Player", Player},
|
||||
{"Game", Game},
|
||||
{"Sound", Sound},
|
||||
{"Graphics", Graphics},
|
||||
{"Server", Server},
|
||||
{"Debug", Debug}
|
||||
};
|
||||
|
||||
// Override fieldloader to ignore invalid entries
|
||||
var err1 = FieldLoader.UnknownFieldAction;
|
||||
var err2 = FieldLoader.InvalidValueAction;
|
||||
|
||||
FieldLoader.UnknownFieldAction = (s,f) =>
|
||||
{
|
||||
System.Console.WriteLine( "Ignoring unknown field `{0}` on `{1}`".F( s, f.Name ) );
|
||||
};
|
||||
|
||||
if (File.Exists(SettingsFile))
|
||||
{
|
||||
System.Console.WriteLine("Loading settings file {0}",SettingsFile);
|
||||
var yaml = MiniYaml.DictFromFile(SettingsFile);
|
||||
|
||||
foreach (var kv in Sections)
|
||||
if (yaml.ContainsKey(kv.Key))
|
||||
LoadSectionYaml(yaml[kv.Key], kv.Value);
|
||||
}
|
||||
|
||||
// Override with commandline args
|
||||
foreach (var kv in Sections)
|
||||
foreach (var f in kv.Value.GetType().GetFields())
|
||||
if (args.Contains(kv.Key+"."+f.Name))
|
||||
OpenRA.FileFormats.FieldLoader.LoadField( kv.Value, f.Name, args.GetValue(kv.Key+"."+f.Name, "") );
|
||||
|
||||
FieldLoader.UnknownFieldAction = err1;
|
||||
FieldLoader.InvalidValueAction = err2;
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
var root = new List<MiniYamlNode>();
|
||||
foreach( var kv in Sections )
|
||||
root.Add( new MiniYamlNode( kv.Key, SectionYaml( kv.Value ) ) );
|
||||
|
||||
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());
|
||||
FieldLoader.InvalidValueAction = (s,t,f) =>
|
||||
{
|
||||
object ret = defaults.GetType().GetField(f).GetValue(defaults);
|
||||
System.Console.WriteLine("FieldLoader: Cannot parse `{0}` into `{2}:{1}`; substituting default `{3}`".F(s,t.Name,f,ret) );
|
||||
return ret;
|
||||
};
|
||||
|
||||
FieldLoader.Load(section, yaml);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.GameRules
|
||||
{
|
||||
public class TechTree
|
||||
{
|
||||
readonly Cache<string, List<ActorInfo>> producesIndex = new Cache<string, List<ActorInfo>>(x => new List<ActorInfo>());
|
||||
|
||||
public TechTree()
|
||||
{
|
||||
foreach( var info in Rules.Info.Values )
|
||||
{
|
||||
var pi = info.Traits.GetOrDefault<ProductionInfo>();
|
||||
if (pi != null)
|
||||
foreach( var p in pi.Produces )
|
||||
producesIndex[ p ].Add( info );
|
||||
}
|
||||
}
|
||||
|
||||
public Cache<string, List<Actor>> GatherBuildings( Player player )
|
||||
{
|
||||
var ret = new Cache<string, List<Actor>>( x => new List<Actor>() );
|
||||
if (player == null)
|
||||
return ret;
|
||||
|
||||
foreach( var b in player.World.Queries.OwnedBy[player].Where( x=>x.Info.Traits.Contains<BuildingInfo>() ) )
|
||||
{
|
||||
ret[ b.Info.Name ].Add( b );
|
||||
var buildable = b.Info.Traits.GetOrDefault<BuildableInfo>();
|
||||
if( buildable != null )
|
||||
foreach( var alt in buildable.AlternateName )
|
||||
ret[ alt ].Add( b );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool CanBuild( ActorInfo info, Player player, Cache<string, List<Actor>> playerBuildings )
|
||||
{
|
||||
if (player == null)
|
||||
return false;
|
||||
|
||||
var bi = info.Traits.GetOrDefault<BuildableInfo>();
|
||||
if( bi == null ) return false;
|
||||
|
||||
if( !bi.Owner.Contains( player.Country.Race ) )
|
||||
return false;
|
||||
|
||||
foreach( var p in bi.Prerequisites )
|
||||
if( playerBuildings[ p ].Count == 0 )
|
||||
return false;
|
||||
|
||||
if( producesIndex[ info.Category ].All( x => playerBuildings[ x.Name ].Count == 0 ) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public IEnumerable<string> BuildableItems( Player player, params string[] categories )
|
||||
{
|
||||
if (player == null)
|
||||
yield break;
|
||||
|
||||
var playerBuildings = GatherBuildings( player );
|
||||
foreach (var unit in AllBuildables(categories))
|
||||
if( CanBuild( unit, player, playerBuildings ) )
|
||||
yield return unit.Name;
|
||||
}
|
||||
|
||||
public IEnumerable<ActorInfo> AllBuildables(params string[] categories)
|
||||
{
|
||||
return Rules.Info.Values
|
||||
.Where( x => x.Name[ 0 ] != '^' )
|
||||
.Where( x => categories.Contains( x.Category ) )
|
||||
.Where( x => x.Traits.Contains<BuildableInfo>() );
|
||||
}
|
||||
|
||||
public IEnumerable<ActorInfo> UnitBuiltAt( ActorInfo info )
|
||||
{
|
||||
var builtAt = info.Traits.Get<BuildableInfo>().BuiltAt;
|
||||
if( builtAt.Length != 0 )
|
||||
return builtAt.Select( x => Rules.Info[ x.ToLowerInvariant() ] );
|
||||
else
|
||||
return producesIndex[ info.Category ];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.FileFormats.Graphics;
|
||||
|
||||
namespace OpenRA.GameRules
|
||||
{
|
||||
public class UserSettings
|
||||
{
|
||||
// Behaviour settings
|
||||
public bool ViewportEdgeScroll = true;
|
||||
|
||||
// Debug settings
|
||||
public bool PerfDebug = false;
|
||||
public bool RecordSyncReports = true;
|
||||
public bool ShowGameTimer = true;
|
||||
public bool DeveloperMode = false;
|
||||
public bool UnitDebug = false;
|
||||
|
||||
// Window settings
|
||||
public WindowMode WindowMode = WindowMode.PseudoFullscreen;
|
||||
public int2 FullscreenSize = new int2(Screen.PrimaryScreen.Bounds.Width,Screen.PrimaryScreen.Bounds.Height);
|
||||
public int2 WindowedSize = new int2(1024,768);
|
||||
public readonly static int2 MinResolution = new int2(800, 600);
|
||||
|
||||
//Sound Settings
|
||||
public float SoundVolume = 0.5f;
|
||||
public float MusicVolume = 0.5f;
|
||||
public bool MusicPlayer = false;
|
||||
|
||||
// Internal game settings
|
||||
public int Timestep = 40;
|
||||
public int SheetSize = 2048;
|
||||
|
||||
// External game settings
|
||||
public string LastServer = "localhost:1234";
|
||||
public string Replay = null;
|
||||
public string PlayerName = "Newbie";
|
||||
public Color PlayerColor1 = Color.FromArgb(255,160,238);
|
||||
public Color PlayerColor2 = Color.FromArgb(68,0,56);
|
||||
|
||||
public string[] InitialMods = { "ra" };
|
||||
|
||||
// Server settings
|
||||
public string LastServerTitle = "OpenRA Game";
|
||||
public int ListenPort = 1234;
|
||||
public int ExternalPort = 1234;
|
||||
public bool AdvertiseOnline = true;
|
||||
public string MasterServer = "http://open-ra.org/master/";
|
||||
public bool AllowCheats = false;
|
||||
|
||||
string SettingsFile;
|
||||
UserSettings defaults;
|
||||
|
||||
public UserSettings() {}
|
||||
public UserSettings(Settings args)
|
||||
{
|
||||
defaults = new UserSettings();
|
||||
SettingsFile = Game.SupportDir + "settings.yaml";
|
||||
|
||||
// Override settings loading to not crash
|
||||
var err1 = FieldLoader.UnknownFieldAction;
|
||||
var err2 = FieldLoader.InvalidValueAction;
|
||||
|
||||
FieldLoader.InvalidValueAction = (s,t,f) =>
|
||||
{
|
||||
object ret = defaults.GetType().GetField(f).GetValue(defaults);
|
||||
System.Console.WriteLine("FieldLoader: Cannot parse `{0}` into `{2}:{1}`; substituting default `{3}`".F(s,t.Name,f,ret) );
|
||||
return ret;
|
||||
};
|
||||
|
||||
FieldLoader.UnknownFieldAction = (s,f) =>
|
||||
{
|
||||
System.Console.WriteLine( "Ignoring unknown field `{0}` on `{1}`".F( s, f.Name ) );
|
||||
};
|
||||
|
||||
if (File.Exists(SettingsFile))
|
||||
{
|
||||
System.Console.WriteLine("Loading settings file {0}",SettingsFile);
|
||||
var yaml = MiniYaml.FromFile(SettingsFile);
|
||||
FieldLoader.Load(this, yaml["Settings"]);
|
||||
}
|
||||
|
||||
foreach (var f in this.GetType().GetFields())
|
||||
if (args.Contains(f.Name))
|
||||
OpenRA.FileFormats.FieldLoader.LoadField( this, f.Name, args.GetValue(f.Name, "") );
|
||||
|
||||
FieldLoader.UnknownFieldAction = err1;
|
||||
FieldLoader.InvalidValueAction = err2;
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
Dictionary<string, MiniYaml> root = new Dictionary<string, MiniYaml>();
|
||||
root.Add("Settings", FieldSaver.SaveDifferences(this, defaults));
|
||||
root.WriteToFile(SettingsFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,33 +9,40 @@
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using System;
|
||||
|
||||
namespace OpenRA.GameRules
|
||||
{
|
||||
public class VoiceInfo
|
||||
{
|
||||
public readonly string[] SovietVariants = { ".aud" };
|
||||
public readonly string[] AlliedVariants = { ".aud" };
|
||||
public readonly string[] Select = { };
|
||||
public readonly string[] Move = { };
|
||||
public readonly string[] Attack = null;
|
||||
public readonly string[] Die = { };
|
||||
public readonly Dictionary<string,string[]> Variants;
|
||||
public readonly Dictionary<string,string[]> Voices;
|
||||
public readonly string DefaultVariant = ".aud" ;
|
||||
[FieldLoader.Load] public readonly string[] DisableVariants = { };
|
||||
|
||||
static Dictionary<string, string[]> Load( MiniYaml y, string name )
|
||||
{
|
||||
return y.NodesDict.ContainsKey( name )
|
||||
? y.NodesDict[ name ].NodesDict.ToDictionary(
|
||||
a => a.Key,
|
||||
a => (string[])FieldLoader.GetValue( "(value)", typeof( string[] ), a.Value.Value ) )
|
||||
: new Dictionary<string, string[]>();
|
||||
}
|
||||
|
||||
public readonly Lazy<Dictionary<string, VoicePool>> Pools;
|
||||
|
||||
public VoiceInfo( MiniYaml y )
|
||||
{
|
||||
FieldLoader.Load(this, y);
|
||||
|
||||
Pools = Lazy.New(() =>
|
||||
new Dictionary<string, VoicePool>
|
||||
{
|
||||
{ "Select", new VoicePool(Select) },
|
||||
{ "Move", new VoicePool(Move) },
|
||||
{ "Attack", new VoicePool( Attack ?? Move ) },
|
||||
{ "Die", new VoicePool(Die) },
|
||||
});
|
||||
FieldLoader.Load( this, y );
|
||||
Variants = Load(y, "Variants");
|
||||
Voices = Load(y, "Voices");
|
||||
|
||||
if (!Voices.ContainsKey("Attack"))
|
||||
Voices.Add("Attack", Voices["Move"]);
|
||||
|
||||
Pools = Lazy.New(() => Voices.ToDictionary( a => a.Key, a => new VoicePool(a.Value) ));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,42 +12,54 @@ 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
|
||||
|
||||
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
|
||||
{
|
||||
@@ -65,55 +77,48 @@ namespace OpenRA.GameRules
|
||||
public Target target;
|
||||
public int2 dest;
|
||||
public int destAltitude;
|
||||
public float firepowerModifier = 1.0f;
|
||||
}
|
||||
|
||||
public interface IProjectileInfo { IEffect Create(ProjectileArgs args); }
|
||||
|
||||
public class WeaponInfo
|
||||
{
|
||||
public readonly float Range = 0;
|
||||
public readonly string Report = null;
|
||||
public readonly int ROF = 1;
|
||||
public readonly int Burst = 1;
|
||||
public readonly bool Charges = false;
|
||||
public readonly bool Underwater = false;
|
||||
public readonly string[] ValidTargets = { "Ground" };
|
||||
public readonly int BurstDelay = 5;
|
||||
[FieldLoader.Load] public readonly float Range = 0;
|
||||
[FieldLoader.Load] public readonly string Report = null;
|
||||
[FieldLoader.Load] public readonly int ROF = 1;
|
||||
[FieldLoader.Load] public readonly int Burst = 1;
|
||||
[FieldLoader.Load] public readonly bool Charges = false;
|
||||
[FieldLoader.Load] public readonly bool Underwater = false;
|
||||
[FieldLoader.Load] public readonly string[] ValidTargets = { "Ground" };
|
||||
[FieldLoader.Load] public readonly int BurstDelay = 5;
|
||||
|
||||
public IProjectileInfo Projectile;
|
||||
public List<WarheadInfo> Warheads = new List<WarheadInfo>();
|
||||
[FieldLoader.LoadUsing( "LoadProjectile" )] public IProjectileInfo Projectile;
|
||||
[FieldLoader.LoadUsing( "LoadWarheads" )] public List<WarheadInfo> Warheads;
|
||||
|
||||
public WeaponInfo(string name, MiniYaml content)
|
||||
{
|
||||
foreach (var kv in content.Nodes)
|
||||
{
|
||||
var key = kv.Key.Split('@')[0];
|
||||
switch (key)
|
||||
{
|
||||
case "Range": FieldLoader.LoadField(this, "Range", content.Nodes["Range"].Value); break;
|
||||
case "ROF": FieldLoader.LoadField(this, "ROF", content.Nodes["ROF"].Value); break;
|
||||
case "Report": FieldLoader.LoadField(this, "Report", content.Nodes["Report"].Value); break;
|
||||
case "Burst": FieldLoader.LoadField(this, "Burst", content.Nodes["Burst"].Value); break;
|
||||
case "Charges": FieldLoader.LoadField(this, "Charges", content.Nodes["Charges"].Value); break;
|
||||
case "ValidTargets": FieldLoader.LoadField(this, "ValidTargets", content.Nodes["ValidTargets"].Value); break;
|
||||
case "Underwater": FieldLoader.LoadField(this, "Underwater", content.Nodes["Underwater"].Value); break;
|
||||
case "BurstDelay": FieldLoader.LoadField(this, "BurstDelay", content.Nodes["BurstDelay"].Value); break;
|
||||
FieldLoader.Load( this, content );
|
||||
}
|
||||
|
||||
case "Warhead":
|
||||
{
|
||||
var warhead = new WarheadInfo();
|
||||
FieldLoader.Load(warhead, kv.Value);
|
||||
Warheads.Add(warhead);
|
||||
} break;
|
||||
static object LoadProjectile( MiniYaml yaml )
|
||||
{
|
||||
MiniYaml proj;
|
||||
if( !yaml.NodesDict.TryGetValue( "Projectile", out proj ) )
|
||||
return null;
|
||||
var ret = Game.CreateObject<IProjectileInfo>( proj.Value + "Info" );
|
||||
FieldLoader.Load( ret, proj );
|
||||
return ret;
|
||||
}
|
||||
|
||||
// in this case, it's an implementation of IProjectileInfo
|
||||
default:
|
||||
{
|
||||
Projectile = Game.CreateObject<IProjectileInfo>(key + "Info");
|
||||
FieldLoader.Load(Projectile, kv.Value);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
static object LoadWarheads( MiniYaml yaml )
|
||||
{
|
||||
var ret = new List<WarheadInfo>();
|
||||
foreach( var w in yaml.Nodes )
|
||||
if( w.Key.Split( '@' )[ 0 ] == "Warhead" )
|
||||
ret.Add( new WarheadInfo( w.Value ) );
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
67
OpenRA.Game/Graphics/CursorProvider.cs
Normal file
67
OpenRA.Game/Graphics/CursorProvider.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
public static class CursorProvider
|
||||
{
|
||||
static Dictionary<string, CursorSequence> cursors;
|
||||
|
||||
public static void Initialize(string[] sequenceFiles)
|
||||
{
|
||||
cursors = new Dictionary<string, CursorSequence>();
|
||||
|
||||
foreach (var f in sequenceFiles)
|
||||
LoadSequenceSource(f);
|
||||
}
|
||||
|
||||
static void LoadSequenceSource(string filename)
|
||||
{
|
||||
XmlDocument document = new XmlDocument();
|
||||
document.Load(FileSystem.Open(filename));
|
||||
|
||||
foreach (XmlElement eCursor in document.SelectNodes("/sequences/cursor"))
|
||||
LoadSequencesForCursor(eCursor);
|
||||
}
|
||||
|
||||
static void LoadSequencesForCursor(XmlElement eCursor)
|
||||
{
|
||||
Game.modData.LoadScreen.Display();
|
||||
string cursorSrc = eCursor.GetAttribute("src");
|
||||
string palette = eCursor.GetAttribute("palette");
|
||||
|
||||
foreach (XmlElement eSequence in eCursor.SelectNodes("./sequence"))
|
||||
cursors.Add(eSequence.GetAttribute("name"), new CursorSequence(cursorSrc, palette, eSequence));
|
||||
|
||||
}
|
||||
|
||||
public static bool HasCursorSequence(string cursor)
|
||||
{
|
||||
return cursors.ContainsKey(cursor);
|
||||
}
|
||||
|
||||
public static CursorSequence GetCursorSequence(string cursor)
|
||||
{
|
||||
try { return cursors[cursor]; }
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Cursor does not have a sequence `{0}`".F(cursor));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,7 @@ namespace OpenRA.Graphics
|
||||
|
||||
public CursorSequence(string cursorSrc, string palette, XmlElement e)
|
||||
{
|
||||
sprites = CursorSheetBuilder.LoadAllSprites(cursorSrc);
|
||||
sprites = Game.modData.CursorSheetBuilder.LoadAllSprites(cursorSrc);
|
||||
|
||||
start = int.Parse(e.GetAttribute("start"));
|
||||
this.palette = palette;
|
||||
|
||||
@@ -14,25 +14,32 @@ using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
static class CursorSheetBuilder
|
||||
public class CursorSheetBuilder
|
||||
{
|
||||
static Cache<string, Sprite[]> cursors = new Cache<string, Sprite[]>(LoadCursors);
|
||||
static readonly string[] exts = { ".shp" };
|
||||
ModData modData;
|
||||
Cache<string, Sprite[]> cursors;
|
||||
readonly string[] exts = { ".shp" };
|
||||
|
||||
static Sprite[] LoadCursors(string filename)
|
||||
public CursorSheetBuilder( ModData modData )
|
||||
{
|
||||
this.modData = modData;
|
||||
this.cursors = new Cache<string, Sprite[]>( LoadCursors );
|
||||
}
|
||||
|
||||
Sprite[] LoadCursors(string filename)
|
||||
{
|
||||
try
|
||||
{
|
||||
var shp = new Dune2ShpReader(FileSystem.OpenWithExts(filename, exts));
|
||||
return shp.Select(a => SheetBuilder.SharedInstance.Add(a.Image, a.Size)).ToArray();
|
||||
return shp.Select(a => modData.SheetBuilder.Add(a.Image, a.Size)).ToArray();
|
||||
}
|
||||
catch (IndexOutOfRangeException) // This will occur when loading a custom (RA-format) .shp
|
||||
{
|
||||
var shp = new ShpReader(FileSystem.OpenWithExts(filename, exts));
|
||||
return shp.Select(a => SheetBuilder.SharedInstance.Add(a.Image, shp.Size)).ToArray();
|
||||
return shp.Select(a => modData.SheetBuilder.Add(a.Image, shp.Size)).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public static Sprite[] LoadAllSprites(string filename) { return cursors[filename]; }
|
||||
public Sprite[] LoadAllSprites(string filename) { return cursors[filename]; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,78 +10,70 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.FileFormats.Graphics;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
class HardwarePalette : Sheet
|
||||
class HardwarePalette
|
||||
{
|
||||
public const int MaxPalettes = 64;
|
||||
int allocated = 0;
|
||||
|
||||
// We need to store the Palettes themselves for the remap palettes to work
|
||||
// We should probably try to fix this somehow
|
||||
static Dictionary<string, Palette> palettes;
|
||||
static Dictionary<string, int> indices;
|
||||
ITexture texture;
|
||||
Dictionary<string, Palette> palettes;
|
||||
Dictionary<string, int> indices;
|
||||
|
||||
public HardwarePalette(Map map)
|
||||
: base(new Size(256, MaxPalettes))
|
||||
{
|
||||
palettes = new Dictionary<string, Palette>();
|
||||
indices = new Dictionary<string, int>();
|
||||
texture = Game.Renderer.Device.CreateTexture();
|
||||
}
|
||||
|
||||
public Palette GetPalette(string name)
|
||||
{
|
||||
try { return palettes[name]; }
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Palette `{0}` does not exist".F(name));
|
||||
}
|
||||
Palette ret;
|
||||
if (!palettes.TryGetValue(name,out ret))
|
||||
throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
|
||||
return ret;
|
||||
}
|
||||
|
||||
public int GetPaletteIndex(string name)
|
||||
{
|
||||
try { return indices[name]; }
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Palette `{0}` does not exist".F(name));
|
||||
}
|
||||
int ret;
|
||||
if (!indices.TryGetValue(name,out ret))
|
||||
throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
|
||||
return ret;
|
||||
}
|
||||
|
||||
public int AddPalette(string name, Palette p)
|
||||
public void AddPalette(string name, Palette p)
|
||||
{
|
||||
palettes.Add(name, p);
|
||||
indices.Add(name, allocated);
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
this[new Point(i, allocated)] = p.GetColor(i);
|
||||
}
|
||||
return allocated++;
|
||||
}
|
||||
|
||||
public void UpdatePalette(string name, Palette p)
|
||||
{
|
||||
palettes[name] = p;
|
||||
var j = indices[name];
|
||||
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
this[new Point(i, j)] = p.GetColor(i);
|
||||
}
|
||||
indices.Add(name, allocated++);
|
||||
}
|
||||
|
||||
public void Update(IEnumerable<IPaletteModifier> paletteMods)
|
||||
{
|
||||
var b = new Bitmap(Bitmap);
|
||||
var copy = palettes.ToDictionary(p => p.Key, p => new Palette(p.Value));
|
||||
|
||||
foreach (var mod in paletteMods)
|
||||
mod.AdjustPalette(b);
|
||||
|
||||
Texture.SetData(b);
|
||||
Game.Renderer.PaletteTexture = Texture;
|
||||
mod.AdjustPalette(copy);
|
||||
|
||||
var data = new uint[MaxPalettes,256];
|
||||
foreach (var pal in copy)
|
||||
{
|
||||
var j = indices[pal.Key];
|
||||
var c = pal.Value.Values;
|
||||
for (var i = 0; i < 256; i++)
|
||||
data[j,i] = c[i];
|
||||
}
|
||||
|
||||
// Doesn't work
|
||||
texture.SetData(data);
|
||||
Game.Renderer.PaletteTexture = texture;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.Width;
|
||||
var height = map.Height;
|
||||
|
||||
if (!actualSize)
|
||||
{
|
||||
width = height = Util.NextPowerOf2(Math.Max(map.Width, map.Height));
|
||||
}
|
||||
|
||||
Bitmap terrain = new Bitmap(width, height);
|
||||
|
||||
var bitmapData = terrain.LockBits(new Rectangle(0, 0, terrain.Width, terrain.Height),
|
||||
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||
@@ -38,6 +51,9 @@ namespace OpenRA.Graphics
|
||||
var mapX = x + map.TopLeft.X;
|
||||
var mapY = y + map.TopLeft.Y;
|
||||
var type = tileset.GetTerrainType(map.MapTiles[mapX, mapY]);
|
||||
if (!tileset.Terrain.ContainsKey(type))
|
||||
throw new InvalidDataException("Tileset {0} lacks terraintype {1}".F(tileset.Id, type));
|
||||
|
||||
*(c + (y * bitmapData.Stride >> 2) + x) = tileset.Terrain[type].Color.ToArgb();
|
||||
}
|
||||
}
|
||||
@@ -122,7 +138,7 @@ namespace OpenRA.Graphics
|
||||
|
||||
foreach (var t in world.Queries.WithTraitMultiple<IRadarSignature>())
|
||||
{
|
||||
if (!t.Actor.IsVisible())
|
||||
if (!t.Actor.IsVisible(world.LocalPlayer))
|
||||
continue;
|
||||
|
||||
var color = t.Trait.RadarSignatureColor(t.Actor);
|
||||
|
||||
@@ -15,6 +15,7 @@ using System.Reflection;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.FileFormats.Graphics;
|
||||
using OpenRA.Support;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
@@ -22,8 +23,6 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
internal static int SheetSize;
|
||||
|
||||
readonly IGraphicsDevice device;
|
||||
|
||||
public IShader SpriteShader { get; private set; } /* note: shared shader params */
|
||||
public IShader LineShader { get; private set; }
|
||||
public IShader RgbaSpriteShader { get; private set; }
|
||||
@@ -38,12 +37,8 @@ namespace OpenRA.Graphics
|
||||
|
||||
public readonly SpriteFont RegularFont, BoldFont, TitleFont;
|
||||
|
||||
public Size Resolution { get { return device.WindowSize; } }
|
||||
|
||||
public Renderer(Size resolution, OpenRA.FileFormats.Graphics.WindowMode windowMode)
|
||||
public Renderer()
|
||||
{
|
||||
device = CreateDevice( Assembly.LoadFile( Path.GetFullPath( "OpenRA.Gl.dll" ) ), resolution.Width, resolution.Height, windowMode, false );
|
||||
|
||||
SpriteShader = device.CreateShader(FileSystem.Open("shaders/world-shp.fx"));
|
||||
LineShader = device.CreateShader(FileSystem.Open("shaders/line.fx"));
|
||||
RgbaSpriteShader = device.CreateShader(FileSystem.Open("shaders/chrome-rgba.fx"));
|
||||
@@ -59,23 +54,16 @@ namespace OpenRA.Graphics
|
||||
TitleFont = new SpriteFont("titles.ttf", 48);
|
||||
}
|
||||
|
||||
IGraphicsDevice CreateDevice( Assembly rendererDll, int width, int height, WindowMode window, bool vsync )
|
||||
{
|
||||
foreach( RendererAttribute r in rendererDll.GetCustomAttributes( typeof( RendererAttribute ), false ) )
|
||||
{
|
||||
return (IGraphicsDevice)r.Type.GetConstructor( new Type[] { typeof( int ), typeof( int ), typeof( WindowMode ), typeof( bool ) } )
|
||||
.Invoke( new object[] { width, height, window, vsync } );
|
||||
}
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IGraphicsDevice Device { get { return device; } }
|
||||
|
||||
public void BeginFrame(float2 r1, float2 r2, float2 scroll)
|
||||
public void BeginFrame(float2 scroll)
|
||||
{
|
||||
device.Begin();
|
||||
device.Clear(Color.Black);
|
||||
|
||||
float2 r1 = new float2(2f/Resolution.Width, -2f/Resolution.Height);
|
||||
float2 r2 = new float2(-1, 1);
|
||||
|
||||
SetShaderParams( SpriteShader, r1, r2, scroll );
|
||||
SetShaderParams( LineShader, r1, r2, scroll );
|
||||
SetShaderParams( RgbaSpriteShader, r1, r2, scroll );
|
||||
@@ -127,5 +115,44 @@ namespace OpenRA.Graphics
|
||||
RgbaSpriteRenderer.Flush();
|
||||
LineRenderer.Flush();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static IGraphicsDevice device;
|
||||
|
||||
public static Size Resolution { get { return device.WindowSize; } }
|
||||
|
||||
internal static void Initialize( OpenRA.FileFormats.Graphics.WindowMode windowMode )
|
||||
{
|
||||
var resolution = GetResolution( windowMode );
|
||||
device = CreateDevice( Assembly.LoadFile( Path.GetFullPath( "OpenRA.Gl.dll" ) ), resolution.Width, resolution.Height, windowMode, false );
|
||||
}
|
||||
|
||||
static Size GetResolution(WindowMode windowmode)
|
||||
{
|
||||
var desktopResolution = Screen.PrimaryScreen.Bounds.Size;
|
||||
var customSize = (windowmode == WindowMode.Windowed) ? Game.Settings.Graphics.WindowedSize : Game.Settings.Graphics.FullscreenSize;
|
||||
|
||||
if (customSize.X > 0 && customSize.Y > 0)
|
||||
{
|
||||
desktopResolution.Width = customSize.X;
|
||||
desktopResolution.Height = customSize.Y;
|
||||
}
|
||||
return new Size(
|
||||
desktopResolution.Width,
|
||||
desktopResolution.Height);
|
||||
}
|
||||
|
||||
static IGraphicsDevice CreateDevice( Assembly rendererDll, int width, int height, WindowMode window, bool vsync )
|
||||
{
|
||||
foreach( RendererAttribute r in rendererDll.GetCustomAttributes( typeof( RendererAttribute ), false ) )
|
||||
{
|
||||
return (IGraphicsDevice)r.Type.GetConstructor( new Type[] { typeof( int ), typeof( int ), typeof( WindowMode ), typeof( bool ) } )
|
||||
.Invoke( new object[] { width, height, window, vsync } );
|
||||
}
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#endregion
|
||||
|
||||
using System.Xml;
|
||||
using OpenRA.FileFormats;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
@@ -24,34 +26,55 @@ namespace OpenRA.Graphics
|
||||
public int Facings { get { return facings; } }
|
||||
public int Tick { get { return tick; } }
|
||||
|
||||
public Sequence(string unit, XmlElement e)
|
||||
string srcOverride;
|
||||
public Sequence(string unit, string name, MiniYaml info)
|
||||
{
|
||||
string srcOverride = e.GetAttribute("src");
|
||||
Name = e.GetAttribute("name");
|
||||
|
||||
srcOverride = info.Value;
|
||||
Name = name;
|
||||
var d = info.NodesDict;
|
||||
|
||||
sprites = SpriteSheetBuilder.LoadAllSprites(string.IsNullOrEmpty(srcOverride) ? unit : srcOverride );
|
||||
start = int.Parse(e.GetAttribute("start"));
|
||||
start = int.Parse(d["Start"].Value);
|
||||
|
||||
if (e.GetAttribute("length") == "*" || e.GetAttribute("end") == "*")
|
||||
length = sprites.Length - Start;
|
||||
else if (e.HasAttribute("length"))
|
||||
length = int.Parse(e.GetAttribute("length"));
|
||||
else if (e.HasAttribute("end"))
|
||||
length = int.Parse(e.GetAttribute("end")) - int.Parse(e.GetAttribute("start"));
|
||||
else
|
||||
if (!d.ContainsKey("Length"))
|
||||
length = 1;
|
||||
else if (d["Length"].Value == "*")
|
||||
length = sprites.Length - Start;
|
||||
else
|
||||
length = int.Parse(d["Length"].Value);
|
||||
|
||||
if( e.HasAttribute( "facings" ) )
|
||||
facings = int.Parse( e.GetAttribute( "facings" ) );
|
||||
|
||||
if(d.ContainsKey("Facings"))
|
||||
facings = int.Parse(d["Facings"].Value);
|
||||
else
|
||||
facings = 1;
|
||||
|
||||
if (e.HasAttribute("tick"))
|
||||
tick = int.Parse(e.GetAttribute("tick"));
|
||||
if(d.ContainsKey("Tick"))
|
||||
tick = int.Parse(d["Tick"].Value);
|
||||
else
|
||||
tick = 40;
|
||||
}
|
||||
|
||||
|
||||
public MiniYaml Save()
|
||||
{
|
||||
var root = new List<MiniYamlNode>();
|
||||
|
||||
root.Add(new MiniYamlNode("Start", start.ToString()));
|
||||
|
||||
if (length > 1 && (start != 0 || length != sprites.Length - start))
|
||||
root.Add(new MiniYamlNode("Length", length.ToString()));
|
||||
else if (length > 1 && length == sprites.Length - start)
|
||||
root.Add(new MiniYamlNode("Length", "*"));
|
||||
|
||||
if (facings > 1)
|
||||
root.Add(new MiniYamlNode("Facings", facings.ToString()));
|
||||
|
||||
if (tick != 40)
|
||||
root.Add(new MiniYamlNode("Tick", tick.ToString()));
|
||||
|
||||
return new MiniYaml(srcOverride, root);
|
||||
}
|
||||
|
||||
public Sprite GetSprite( int frame )
|
||||
{
|
||||
return GetSprite( frame, 0 );
|
||||
|
||||
@@ -20,51 +20,39 @@ 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)
|
||||
{
|
||||
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(MiniYaml.Merge);
|
||||
|
||||
foreach (var s in sequences)
|
||||
LoadSequencesForUnit(s.Key, s.Value);
|
||||
}
|
||||
|
||||
static void LoadSequenceSource(string filename)
|
||||
static void LoadSequencesForUnit(string unit, MiniYaml sequences)
|
||||
{
|
||||
XmlDocument document = new XmlDocument();
|
||||
document.Load(FileSystem.Open(filename));
|
||||
|
||||
foreach (XmlElement eUnit in document.SelectNodes("/sequences/unit"))
|
||||
LoadSequencesForUnit(eUnit);
|
||||
|
||||
foreach (XmlElement eCursor in document.SelectNodes("/sequences/cursor"))
|
||||
LoadSequencesForCursor(eCursor);
|
||||
}
|
||||
|
||||
static void LoadSequencesForCursor(XmlElement eCursor)
|
||||
{
|
||||
string cursorSrc = eCursor.GetAttribute("src");
|
||||
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)
|
||||
{
|
||||
string unitName = eUnit.GetAttribute("name");
|
||||
Game.modData.LoadScreen.Display();
|
||||
try {
|
||||
var sequences = eUnit.SelectNodes("./sequence").OfType<XmlElement>()
|
||||
.Select(e => new Sequence(unitName, e))
|
||||
.ToDictionary(s => s.Name);
|
||||
|
||||
units.Add(unitName, sequences);
|
||||
var seq = sequences.NodesDict.ToDictionary(x => x.Key, x => new Sequence(unit,x.Key,x.Value));
|
||||
units.Add(unit, seq);
|
||||
} catch (FileNotFoundException) {} // Do nothing; we can crash later if we actually wanted art
|
||||
}
|
||||
|
||||
public static MiniYaml SaveSequencesForUnit(string unitname)
|
||||
{
|
||||
var ret = new List<MiniYamlNode>();
|
||||
foreach (var s in units[unitname])
|
||||
ret.Add(new MiniYamlNode(s.Key, s.Value.Save()));
|
||||
|
||||
return new MiniYaml(null, ret);
|
||||
}
|
||||
|
||||
public static Sequence GetSequence(string unitName, string sequenceName)
|
||||
{
|
||||
try { return units[unitName][sequenceName]; }
|
||||
@@ -79,20 +67,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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,18 +16,21 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
public class Sheet
|
||||
{
|
||||
protected readonly Bitmap bitmap;
|
||||
Bitmap bitmap;
|
||||
ITexture texture;
|
||||
bool dirty;
|
||||
byte[] data;
|
||||
public readonly Size Size;
|
||||
|
||||
public Sheet(Size size)
|
||||
{
|
||||
this.bitmap = new Bitmap(size.Width, size.Height);
|
||||
Size = size;
|
||||
}
|
||||
|
||||
internal Sheet(string filename)
|
||||
public Sheet(string filename)
|
||||
{
|
||||
this.bitmap = (Bitmap)Image.FromStream(FileSystem.Open(filename));
|
||||
bitmap = (Bitmap)Image.FromStream(FileSystem.Open(filename));
|
||||
Size = bitmap.Size;
|
||||
}
|
||||
|
||||
public ITexture Texture
|
||||
@@ -35,28 +38,30 @@ namespace OpenRA.Graphics
|
||||
get
|
||||
{
|
||||
if (texture == null)
|
||||
texture = Game.Renderer.Device.CreateTexture(bitmap);
|
||||
{
|
||||
texture = Game.Renderer.Device.CreateTexture();
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
if (dirty)
|
||||
{
|
||||
texture.SetData(bitmap);
|
||||
dirty = false;
|
||||
if (data != null)
|
||||
{
|
||||
texture.SetData(data, Size.Width, Size.Height);
|
||||
dirty = false;
|
||||
}
|
||||
else if (bitmap != null)
|
||||
{
|
||||
texture.SetData(bitmap);
|
||||
dirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
return texture;
|
||||
}
|
||||
}
|
||||
|
||||
public Size Size { get { return bitmap.Size; } }
|
||||
|
||||
protected Color this[Point p]
|
||||
{
|
||||
get { return bitmap.GetPixel(p.X, p.Y); }
|
||||
set { bitmap.SetPixel(p.X, p.Y, value); }
|
||||
}
|
||||
|
||||
public Bitmap Bitmap { get { return bitmap; } } // for perf
|
||||
|
||||
public byte[] Data { get { if (data == null) data = new byte[4 * Size.Width * Size.Height]; return data; } }
|
||||
public void MakeDirty() { dirty = true; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,12 +14,6 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
public class SheetBuilder
|
||||
{
|
||||
public static SheetBuilder SharedInstance;
|
||||
internal static void Initialize()
|
||||
{
|
||||
SharedInstance = new SheetBuilder(TextureChannel.Red);
|
||||
}
|
||||
|
||||
internal SheetBuilder(TextureChannel ch)
|
||||
{
|
||||
current = null;
|
||||
|
||||
@@ -64,12 +64,9 @@ namespace OpenRA.Graphics
|
||||
Game.Renderer.RgbaSpriteRenderer.DrawSprite(g.Sprite,
|
||||
new float2(
|
||||
(int)Math.Round(p.X + g.Offset.X, 0),
|
||||
p.Y + g.Offset.Y),
|
||||
"chrome");
|
||||
p.Y + g.Offset.Y));
|
||||
p.X += g.Advance;
|
||||
}
|
||||
|
||||
// r.Flush();
|
||||
}
|
||||
|
||||
public int2 Measure(string text)
|
||||
@@ -100,13 +97,20 @@ namespace OpenRA.Graphics
|
||||
unsafe
|
||||
{
|
||||
var p = (byte*)_glyph.bitmap.buffer;
|
||||
var dest = s.sheet.Data;
|
||||
var destStride = s.sheet.Size.Width * 4;
|
||||
|
||||
for (var j = 0; j < s.size.Y; j++)
|
||||
{
|
||||
for (var i = 0; i < s.size.X; i++)
|
||||
if (p[i] != 0)
|
||||
s.sheet.Bitmap.SetPixel(i + s.bounds.Left, j + s.bounds.Top,
|
||||
Color.FromArgb(p[i], c.Second.R, c.Second.G, c.Second.B));
|
||||
{
|
||||
var q = destStride * (j + s.bounds.Top) + 4 * (i + s.bounds.Left);
|
||||
dest[q] = c.Second.B;
|
||||
dest[q + 1] = c.Second.G;
|
||||
dest[q + 2] = c.Second.R;
|
||||
dest[q + 3] = p[i];
|
||||
}
|
||||
|
||||
p += _glyph.bitmap.pitch;
|
||||
}
|
||||
|
||||
@@ -60,22 +60,39 @@ namespace OpenRA.Graphics
|
||||
sprites = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void DrawSprite(Sprite s, float2 location, string palette)
|
||||
{
|
||||
DrawSprite(s, location, palette, s.size);
|
||||
DrawSprite(s, location, Game.world.WorldRenderer.GetPaletteIndex(palette), s.size);
|
||||
}
|
||||
|
||||
|
||||
public void DrawSprite(Sprite s, float2 location, string palette, float2 size)
|
||||
{
|
||||
DrawSprite(s, location, Game.world.WorldRenderer.GetPaletteIndex(palette), size);
|
||||
}
|
||||
|
||||
public void DrawSprite(Sprite s, float2 location, int paletteIndex, float2 size)
|
||||
{
|
||||
if (s.sheet != currentSheet)
|
||||
Flush();
|
||||
|
||||
currentSheet = s.sheet;
|
||||
Util.FastCreateQuad(vertices, indices, location.ToInt2(), s, Game.world.WorldRenderer.GetPaletteIndex(palette), nv, ni, size);
|
||||
Util.FastCreateQuad(vertices, indices, location.ToInt2(), s, paletteIndex, nv, ni, size);
|
||||
nv += 4; ni += 6;
|
||||
if (++sprites >= spritesPerBatch)
|
||||
Flush();
|
||||
}
|
||||
|
||||
|
||||
// For RGBASpriteRenderer, which doesn't use palettes
|
||||
public void DrawSprite(Sprite s, float2 location)
|
||||
{
|
||||
DrawSprite(s, location, 0, s.size);
|
||||
}
|
||||
|
||||
public void DrawSprite(Sprite s, float2 location, float2 size)
|
||||
{
|
||||
DrawSprite(s, location, 0, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
public static void Initialize( TileSet tileset )
|
||||
{
|
||||
/* .tem: hack to allow incomplete theaters (interior) to work, falling back to temperate for the missing art */
|
||||
exts = tileset.Extensions;
|
||||
sprites = new Cache<string, Sprite[]>( LoadSprites );
|
||||
}
|
||||
@@ -28,7 +27,7 @@ namespace OpenRA.Graphics
|
||||
static Sprite[] LoadSprites(string filename)
|
||||
{
|
||||
var shp = new ShpReader(FileSystem.OpenWithExts(filename, exts));
|
||||
return shp.Select(a => SheetBuilder.SharedInstance.Add(a.Image, shp.Size)).ToArray();
|
||||
return shp.Select(a => Game.modData.SheetBuilder.Add(a.Image, shp.Size)).ToArray();
|
||||
}
|
||||
|
||||
public static Sprite[] LoadAllSprites(string filename) { return sprites[filename]; }
|
||||
|
||||
@@ -31,9 +31,8 @@ namespace OpenRA.Graphics
|
||||
this.map = world.Map;
|
||||
|
||||
Size tileSize = new Size( Game.CellSize, Game.CellSize );
|
||||
|
||||
var tileMapping = new Cache<TileReference<ushort,byte>, Sprite>(
|
||||
x => SheetBuilder.SharedInstance.Add(world.TileSet.GetBytes(x), tileSize));
|
||||
x => Game.modData.SheetBuilder.Add(world.TileSet.GetBytes(x), tileSize));
|
||||
|
||||
Vertex[] vertices = new Vertex[4 * map.Height * map.Width];
|
||||
ushort[] indices = new ushort[6 * map.Height * map.Width];
|
||||
@@ -47,7 +46,7 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
Sprite tile = tileMapping[map.MapTiles[i, j]];
|
||||
// TODO: The zero below should explicitly refer to the terrain palette, but this code is called
|
||||
// before the palettes are created
|
||||
// before the palettes are created. Therefore assumes that "terrain" is the first palette to be defined
|
||||
Util.FastCreateQuad(vertices, indices, Game.CellSize * new float2(i, j), tile, 0, nv, ni, tile.size);
|
||||
nv += 4;
|
||||
ni += 6;
|
||||
@@ -68,9 +67,9 @@ namespace OpenRA.Graphics
|
||||
int indicesPerRow = map.Width * 6;
|
||||
int verticesPerRow = map.Width * 4;
|
||||
|
||||
int visibleRows = (int)(viewport.Height / 24.0f + 2);
|
||||
int visibleRows = (int)(viewport.Height * 1f / Game.CellSize + 2);
|
||||
|
||||
int firstRow = (int)((viewport.Location.Y) / 24.0f - map.YOffset);
|
||||
int firstRow = (int)(viewport.Location.Y * 1f / Game.CellSize - map.YOffset);
|
||||
int lastRow = firstRow + visibleRows;
|
||||
|
||||
if (lastRow < 0 || firstRow > map.Height)
|
||||
@@ -98,7 +97,7 @@ namespace OpenRA.Graphics
|
||||
new Range<int>(indicesPerRow * firstRow, indicesPerRow * lastRow),
|
||||
PrimitiveType.TriangleList, Game.Renderer.SpriteShader));
|
||||
|
||||
foreach (var r in world.WorldActor.traits.WithInterface<IRenderOverlay>())
|
||||
foreach (var r in world.WorldActor.TraitsImplementing<IRenderOverlay>())
|
||||
r.Render();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,42 +65,23 @@ namespace OpenRA.Graphics
|
||||
|
||||
public static void FastCopyIntoChannel(Sprite dest, byte[] src)
|
||||
{
|
||||
var bitmap = dest.sheet.Bitmap;
|
||||
BitmapData bits = null;
|
||||
uint[] channelMasks = { 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 };
|
||||
int[] shifts = { 16, 8, 0, 24 };
|
||||
var masks = new int[] { 2, 1, 0, 3 }; // hack, our channel order is nuts.
|
||||
var data = dest.sheet.Data;
|
||||
var srcStride = dest.bounds.Width;
|
||||
var destStride = dest.sheet.Size.Width * 4;
|
||||
var destOffset = destStride * dest.bounds.Top + dest.bounds.Left * 4 + masks[(int)dest.channel];
|
||||
var destSkip = destStride - 4 * srcStride;
|
||||
var height = dest.bounds.Height;
|
||||
|
||||
uint mask = channelMasks[(int)dest.channel];
|
||||
int shift = shifts[(int)dest.channel];
|
||||
|
||||
try
|
||||
var srcOffset = 0;
|
||||
for (var j = 0; j < height; j++)
|
||||
{
|
||||
bits = bitmap.LockBits(dest.bounds, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||
|
||||
int width = dest.bounds.Width;
|
||||
int height = dest.bounds.Height;
|
||||
|
||||
unsafe
|
||||
for (int i = 0; i < srcStride; i++, srcOffset++)
|
||||
{
|
||||
fixed (byte* srcbase = &src[0])
|
||||
{
|
||||
byte* s = srcbase;
|
||||
uint* t = (uint*)bits.Scan0.ToPointer();
|
||||
int stride = bits.Stride >> 2;
|
||||
|
||||
for (int j = 0; j < height; j++)
|
||||
{
|
||||
uint* p = t;
|
||||
for (int i = 0; i < width; i++, p++)
|
||||
*p = (*p & ~mask) | ((mask & ((uint)*s++) << shift));
|
||||
t += stride;
|
||||
}
|
||||
}
|
||||
data[destOffset] = src[srcOffset];
|
||||
destOffset += 4;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
bitmap.UnlockBits(bits);
|
||||
destOffset += destSkip;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@ namespace OpenRA.Graphics
|
||||
readonly float2 screenSize;
|
||||
float2 scrollPosition;
|
||||
readonly Renderer renderer;
|
||||
readonly int2 mapStart;
|
||||
readonly int2 mapEnd;
|
||||
|
||||
public float2 Location { get { return scrollPosition; } }
|
||||
|
||||
@@ -35,50 +37,93 @@ namespace OpenRA.Graphics
|
||||
|
||||
public void Scroll(float2 delta)
|
||||
{
|
||||
scrollPosition = scrollPosition + delta;
|
||||
this.Scroll(delta, false);
|
||||
}
|
||||
|
||||
public void Scroll(float2 delta, bool ignoreBorders)
|
||||
{
|
||||
float2 newScrollPosition = scrollPosition + delta;
|
||||
|
||||
if(!ignoreBorders)
|
||||
newScrollPosition = this.NormalizeScrollPosition(newScrollPosition);
|
||||
|
||||
scrollPosition = newScrollPosition;
|
||||
}
|
||||
|
||||
private float2 NormalizeScrollPosition(float2 newScrollPosition)
|
||||
{
|
||||
float2 topLeftBorder = (Game.CellSize* mapStart).ToFloat2();
|
||||
float2 bottomRightBorder = (Game.CellSize* mapEnd).ToFloat2();
|
||||
|
||||
if(newScrollPosition.Y < topLeftBorder.Y - screenSize.Y/2)
|
||||
newScrollPosition.Y = topLeftBorder.Y - screenSize.Y/2;
|
||||
if(newScrollPosition.X < topLeftBorder.X - screenSize.X/2)
|
||||
newScrollPosition.X = topLeftBorder.X - screenSize.X/2;
|
||||
if(newScrollPosition.Y > bottomRightBorder.Y - screenSize.Y/2)
|
||||
newScrollPosition.Y = bottomRightBorder.Y - screenSize.Y/2;
|
||||
if(newScrollPosition.X > bottomRightBorder.X - screenSize.X/2)
|
||||
newScrollPosition.X = bottomRightBorder.X - screenSize.X/2;
|
||||
|
||||
return newScrollPosition;
|
||||
}
|
||||
|
||||
public ScrollDirection GetBlockedDirections()
|
||||
{
|
||||
int2 topLeftBorder = (Game.CellSize* mapStart);
|
||||
int2 bottomRightBorder = (Game.CellSize* mapEnd);
|
||||
|
||||
ScrollDirection blockedDirections = ScrollDirection.None;
|
||||
|
||||
if(scrollPosition.Y <= topLeftBorder.Y - screenSize.Y/2)
|
||||
blockedDirections = blockedDirections.Set(ScrollDirection.Up, true);
|
||||
if(scrollPosition.X <= topLeftBorder.X - screenSize.X/2)
|
||||
blockedDirections = blockedDirections.Set(ScrollDirection.Left, true);
|
||||
if(scrollPosition.Y >= bottomRightBorder.Y - screenSize.Y/2)
|
||||
blockedDirections = blockedDirections.Set(ScrollDirection.Down, true);
|
||||
if(scrollPosition.X >= bottomRightBorder.X - screenSize.X/2)
|
||||
blockedDirections = blockedDirections.Set(ScrollDirection.Right, true);
|
||||
|
||||
return blockedDirections;
|
||||
}
|
||||
|
||||
public Viewport(float2 screenSize, int2 mapStart, int2 mapEnd, Renderer renderer)
|
||||
{
|
||||
this.screenSize = screenSize;
|
||||
this.renderer = renderer;
|
||||
this.mapStart = mapStart;
|
||||
this.mapEnd = mapEnd;
|
||||
|
||||
this.scrollPosition = Game.CellSize* mapStart;
|
||||
}
|
||||
|
||||
public void DrawRegions( World world )
|
||||
{
|
||||
Timer.Time( "DrawRegions start" );
|
||||
|
||||
world.WorldRenderer.palette.Update(
|
||||
world.WorldActor.traits.WithInterface<IPaletteModifier>());
|
||||
|
||||
float2 r1 = new float2(2, -2) / screenSize;
|
||||
float2 r2 = new float2(-1, 1);
|
||||
|
||||
renderer.BeginFrame(r1, r2, scrollPosition.ToInt2());
|
||||
renderer.BeginFrame(scrollPosition);
|
||||
world.WorldRenderer.Draw();
|
||||
Timer.Time( "worldRenderer: {0}" );
|
||||
|
||||
Widget.DoDraw(world);
|
||||
Timer.Time( "widgets: {0}" );
|
||||
|
||||
var cursorName = Widget.RootWidget.GetCursorOuter(Viewport.LastMousePos) ?? "default";
|
||||
var c = new Cursor(cursorName);
|
||||
c.Draw((int)cursorFrame, Viewport.LastMousePos + Location);
|
||||
Timer.Time( "cursors: {0}" );
|
||||
|
||||
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>());
|
||||
}
|
||||
|
||||
public void Tick()
|
||||
{
|
||||
cursorFrame += 0.5f;
|
||||
RefreshPalette();
|
||||
}
|
||||
|
||||
public float2 ViewToWorld(int2 loc)
|
||||
@@ -92,7 +137,7 @@ namespace OpenRA.Graphics
|
||||
|
||||
public void Center(int2 loc)
|
||||
{
|
||||
scrollPosition = (Game.CellSize*loc - .5f * new float2(Width, Height)).ToInt2();
|
||||
scrollPosition = this.NormalizeScrollPosition(Game.CellSize*loc - .5f * new float2(Width, Height));
|
||||
}
|
||||
|
||||
public void Center(IEnumerable<Actor> actors)
|
||||
@@ -103,12 +148,7 @@ namespace OpenRA.Graphics
|
||||
.Select(a => a.CenterLocation)
|
||||
.Aggregate((a, b) => a + b);
|
||||
|
||||
scrollPosition = (avgPos - .5f * new float2(Width, Height)).ToInt2();
|
||||
}
|
||||
|
||||
public void GoToStartLocation( Player player )
|
||||
{
|
||||
Center( player.World.Queries.OwnedBy[ player ].WithTrait<Selectable>().Select( a => a.Actor ) );
|
||||
scrollPosition = this.NormalizeScrollPosition((avgPos - .5f * new float2(Width, Height)));
|
||||
}
|
||||
|
||||
public Rectangle? ShroudBounds()
|
||||
@@ -118,5 +158,13 @@ namespace OpenRA.Graphics
|
||||
if (localPlayer.Shroud.Disabled) return null;
|
||||
return localPlayer.Shroud.Bounds;
|
||||
}
|
||||
|
||||
public Rectangle ViewBounds()
|
||||
{
|
||||
int2 boundary = new int2(1,1); // Add a curtain of cells around the viewport to account for rounding errors
|
||||
var tl = ViewToWorld(int2.Zero).ToInt2() - boundary;
|
||||
var br = ViewToWorld(new int2(Width, Height)).ToInt2() + boundary;
|
||||
return Rectangle.FromLTRB(tl.X, tl.Y, br.X, br.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
readonly World world;
|
||||
internal readonly TerrainRenderer terrainRenderer;
|
||||
internal readonly UiOverlay uiOverlay;
|
||||
public readonly UiOverlay uiOverlay;
|
||||
internal readonly HardwarePalette palette;
|
||||
|
||||
internal WorldRenderer(World world)
|
||||
@@ -36,17 +36,12 @@ namespace OpenRA.Graphics
|
||||
public int GetPaletteIndex(string name) { return palette.GetPaletteIndex(name); }
|
||||
public Palette GetPalette(string name) { return palette.GetPalette(name); }
|
||||
public void AddPalette(string name, Palette pal) { palette.AddPalette(name, pal); }
|
||||
public void UpdatePalette(string name, Palette pal) { palette.UpdatePalette(name, pal); }
|
||||
|
||||
class SpriteComparer : IComparer<Renderable>
|
||||
{
|
||||
public int Compare(Renderable x, Renderable y)
|
||||
{
|
||||
var result = x.ZOffset.CompareTo(y.ZOffset);
|
||||
if (result == 0)
|
||||
result = x.Pos.Y.CompareTo(y.Pos.Y);
|
||||
|
||||
return result;
|
||||
return (x.Z + x.ZOffset).CompareTo(y.Z + y.ZOffset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,8 +138,8 @@ namespace OpenRA.Graphics
|
||||
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);
|
||||
Game.Renderer.LineRenderer.DrawLine(new float2(0, j * Game.CellSize), new float2(world.Map.MapSize.X * Game.CellSize, j * Game.CellSize), Color.Black, Color.Black);
|
||||
Game.Renderer.LineRenderer.DrawLine(new float2(j * Game.CellSize, 0), new float2(j * Game.CellSize, world.Map.MapSize.Y * Game.CellSize), Color.Black, Color.Black);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,13 +25,13 @@ namespace OpenRA
|
||||
public string Uid;
|
||||
|
||||
// Yaml map data
|
||||
public bool Selectable = true;
|
||||
public int MapFormat;
|
||||
public string Title;
|
||||
public string Description;
|
||||
public string Author;
|
||||
public int PlayerCount;
|
||||
public string Tileset;
|
||||
[FieldLoader.Load] public 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>();
|
||||
@@ -39,18 +39,14 @@ namespace OpenRA
|
||||
public Dictionary<string, int2> Waypoints = new Dictionary<string, int2>();
|
||||
|
||||
// Rules overrides
|
||||
public Dictionary<string, MiniYaml> Rules = new Dictionary<string, MiniYaml>();
|
||||
public Dictionary<string, MiniYaml> Weapons = new Dictionary<string, MiniYaml>();
|
||||
public Dictionary<string, MiniYaml> Voices = new Dictionary<string, MiniYaml>();
|
||||
public Dictionary<string, MiniYaml> Music = new Dictionary<string, MiniYaml>();
|
||||
public Dictionary<string, MiniYaml> Terrain = new Dictionary<string, MiniYaml>();
|
||||
|
||||
public List<MiniYamlNode> Rules = new List<MiniYamlNode>();
|
||||
|
||||
// Binary map data
|
||||
public byte TileFormat = 1;
|
||||
public int2 MapSize;
|
||||
[FieldLoader.Load] public int2 MapSize;
|
||||
|
||||
public int2 TopLeft;
|
||||
public int2 BottomRight;
|
||||
[FieldLoader.Load] public int2 TopLeft;
|
||||
[FieldLoader.Load] public int2 BottomRight;
|
||||
|
||||
public TileReference<ushort, byte>[,] MapTiles;
|
||||
public TileReference<byte, byte>[,] MapResources;
|
||||
@@ -65,19 +61,23 @@ namespace OpenRA
|
||||
public IEnumerable<int2> SpawnPoints { get { return Waypoints.Select(kv => kv.Value); } }
|
||||
public Rectangle Bounds { get { return Rectangle.FromLTRB(TopLeft.X, TopLeft.Y, BottomRight.X, BottomRight.Y); } }
|
||||
|
||||
static List<string> SimpleFields = new List<string>() {
|
||||
"Selectable", "MapFormat", "Title", "Description", "Author", "PlayerCount", "Tileset", "MapSize", "TopLeft", "BottomRight"
|
||||
};
|
||||
|
||||
public Map()
|
||||
{
|
||||
// Do nothing; not a valid map (editor hack)
|
||||
}
|
||||
|
||||
public Map(string tileset)
|
||||
{
|
||||
MapSize = new int2(1, 1);
|
||||
Tileset = tileset;
|
||||
MapResources = new TileReference<byte, byte>[1, 1];
|
||||
MapTiles = new TileReference<ushort, byte>[1, 1]
|
||||
{ { new TileReference<ushort, byte> {
|
||||
type = (ushort)0xffffu,
|
||||
image = (byte)0xffu,
|
||||
index = (byte)0xffu } } };
|
||||
|
||||
var tile = OpenRA.Rules.TileSets[Tileset].Templates.First();
|
||||
MapTiles = new TileReference<ushort, byte>[1, 1]
|
||||
{ { new TileReference<ushort, byte> {
|
||||
type = tile.Key,
|
||||
image = (byte)(tile.Value.PickAny ? 0xffu : 0),
|
||||
index = (byte)(tile.Value.PickAny ? 0xffu : 0) } } };
|
||||
|
||||
PlayerCount = 0;
|
||||
TopLeft = new int2(0, 0);
|
||||
@@ -90,22 +90,22 @@ namespace OpenRA
|
||||
|
||||
class Format2ActorReference
|
||||
{
|
||||
public string Id;
|
||||
public string Type;
|
||||
public int2 Location;
|
||||
public string Owner;
|
||||
public string Id = null;
|
||||
public string Type = null;
|
||||
public int2 Location = int2.Zero;
|
||||
public string Owner = null;
|
||||
}
|
||||
|
||||
public Map(IFolder package)
|
||||
{
|
||||
Package = package;
|
||||
var yaml = MiniYaml.FromStream(Package.GetContent("map.yaml"));
|
||||
var yaml = new MiniYaml( null, MiniYaml.FromStream( Package.GetContent( "map.yaml" ) ) );
|
||||
|
||||
// 'Simple' metadata
|
||||
FieldLoader.LoadFields(this, yaml, SimpleFields);
|
||||
FieldLoader.Load( this, yaml );
|
||||
|
||||
// Waypoints
|
||||
foreach (var wp in yaml["Waypoints"].Nodes)
|
||||
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])));
|
||||
@@ -124,7 +124,7 @@ namespace OpenRA
|
||||
Players.Add("Neutral", new PlayerReference("Neutral", "allies", true, true));
|
||||
|
||||
int actors = 0;
|
||||
foreach (var kv in yaml["Actors"].Nodes)
|
||||
foreach (var kv in yaml.NodesDict["Actors"].NodesDict)
|
||||
{
|
||||
string[] vals = kv.Value.Value.Split(' ');
|
||||
string[] loc = vals[2].Split(',');
|
||||
@@ -138,13 +138,13 @@ namespace OpenRA
|
||||
|
||||
case 2:
|
||||
{
|
||||
foreach (var kv in yaml["Players"].Nodes)
|
||||
foreach (var kv in yaml.NodesDict["Players"].NodesDict)
|
||||
{
|
||||
var player = new PlayerReference(kv.Value);
|
||||
Players.Add(player.Name, player);
|
||||
}
|
||||
|
||||
foreach (var kv in yaml["Actors"].Nodes)
|
||||
foreach (var kv in yaml.NodesDict["Actors"].NodesDict)
|
||||
{
|
||||
var oldActorReference = FieldLoader.Load<Format2ActorReference>(kv.Value);
|
||||
Actors.Add(oldActorReference.Id, new ActorReference(oldActorReference.Type)
|
||||
@@ -157,22 +157,38 @@ namespace OpenRA
|
||||
|
||||
case 3:
|
||||
{
|
||||
foreach (var kv in yaml["Players"].Nodes)
|
||||
foreach (var kv in yaml.NodesDict["Players"].NodesDict)
|
||||
{
|
||||
var player = new PlayerReference(kv.Value);
|
||||
Players.Add(player.Name, player);
|
||||
}
|
||||
|
||||
foreach (var kv in yaml["Actors"].Nodes)
|
||||
Actors.Add(kv.Key, new ActorReference(kv.Value.Value, kv.Value.Nodes));
|
||||
foreach (var kv in yaml.NodesDict["Actors"].NodesDict)
|
||||
Actors.Add(kv.Key, new ActorReference(kv.Value.Value, kv.Value.NodesDict));
|
||||
} break;
|
||||
|
||||
default:
|
||||
throw new InvalidDataException("Map format {0} is not supported.".F(MapFormat));
|
||||
}
|
||||
|
||||
/* hack: make some slots. */
|
||||
if (!Players.Any(p => p.Value.Playable))
|
||||
{
|
||||
for (int index = 0; index < Waypoints.Count; index++)
|
||||
{
|
||||
var p = new PlayerReference
|
||||
{
|
||||
Name = "Multi{0}".F(index),
|
||||
Race = "Random",
|
||||
Playable = true,
|
||||
DefaultStartingUnits = true
|
||||
};
|
||||
Players.Add(p.Name, p);
|
||||
}
|
||||
}
|
||||
|
||||
// Smudges
|
||||
foreach (var kv in yaml["Smudges"].Nodes)
|
||||
foreach (var kv in yaml.NodesDict["Smudges"].NodesDict)
|
||||
{
|
||||
string[] vals = kv.Key.Split(' ');
|
||||
string[] loc = vals[1].Split(',');
|
||||
@@ -180,7 +196,7 @@ namespace OpenRA
|
||||
}
|
||||
|
||||
// Rules
|
||||
Rules = yaml["Rules"].Nodes;
|
||||
Rules = yaml.NodesDict["Rules"].Nodes;
|
||||
|
||||
CustomTerrain = new string[MapSize.X, MapSize.Y];
|
||||
LoadUid();
|
||||
@@ -191,27 +207,27 @@ namespace OpenRA
|
||||
{
|
||||
MapFormat = 3;
|
||||
|
||||
var root = new Dictionary<string, MiniYaml>();
|
||||
foreach (var field in SimpleFields)
|
||||
var root = new List<MiniYamlNode>();
|
||||
foreach (var field in new string[] {"Selectable", "MapFormat", "Title", "Description", "Author", "PlayerCount", "Tileset", "MapSize", "TopLeft", "BottomRight"})
|
||||
{
|
||||
FieldInfo f = this.GetType().GetField(field);
|
||||
if (f.GetValue(this) == null) continue;
|
||||
root.Add(field, new MiniYaml(FieldSaver.FormatValue(this, f), null));
|
||||
root.Add( new MiniYamlNode( field, FieldSaver.FormatValue( this, f ) ) );
|
||||
}
|
||||
|
||||
root.Add("Players",
|
||||
new MiniYaml(null, Players.ToDictionary(
|
||||
p => "PlayerReference@{0}".F(p.Key),
|
||||
p => FieldSaver.Save(p.Value))));
|
||||
root.Add( new MiniYamlNode( "Players", null,
|
||||
Players.Select( p => new MiniYamlNode(
|
||||
"PlayerReference@{0}".F( p.Key ),
|
||||
FieldSaver.Save( p.Value ) ) ).ToList() ) );
|
||||
|
||||
root.Add("Actors",
|
||||
new MiniYaml( null, Actors.ToDictionary(
|
||||
x => x.Key,
|
||||
x => x.Value.Save() ) ) );
|
||||
root.Add( new MiniYamlNode( "Actors", null,
|
||||
Actors.Select( x => new MiniYamlNode(
|
||||
x.Key,
|
||||
x.Value.Save() ) ).ToList() ) );
|
||||
|
||||
root.Add("Waypoints", MiniYaml.FromDictionary<string, int2>(Waypoints));
|
||||
root.Add("Smudges", MiniYaml.FromList<SmudgeReference>(Smudges));
|
||||
root.Add("Rules", new MiniYaml(null, Rules));
|
||||
root.Add( new MiniYamlNode( "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"));
|
||||
|
||||
77
OpenRA.Game/ModData.cs
Executable file
77
OpenRA.Game/ModData.cs
Executable file
@@ -0,0 +1,77 @@
|
||||
#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));
|
||||
|
||||
var map = new Map(AvailableMaps[uid].Package);
|
||||
|
||||
Rules.LoadRules(Manifest, map);
|
||||
if (map.Theater != cachedTheatre)
|
||||
{
|
||||
SpriteSheetBuilder.Initialize( Rules.TileSets[map.Tileset] );
|
||||
SequenceProvider.Initialize(Manifest.Sequences);
|
||||
CursorProvider.Initialize(Manifest.Cursors);
|
||||
cachedTheatre = map.Theater;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
public interface ILoadScreen { void Display(); void Init(); }
|
||||
}
|
||||
@@ -140,8 +140,11 @@ namespace OpenRA.Network
|
||||
|
||||
}
|
||||
catch (SocketException) { /* drop this on the floor; we'll pick up the disconnect from the reader thread */ }
|
||||
catch (ObjectDisposedException) { /* ditto */ }
|
||||
}
|
||||
|
||||
bool disposed = false;
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
if (disposed) return;
|
||||
|
||||
@@ -177,19 +177,19 @@ namespace OpenRA
|
||||
return new Order("Command", null, text) { IsImmediate = true };
|
||||
}
|
||||
|
||||
public static Order StartProduction(Player subject, string item, int count)
|
||||
public static Order StartProduction(Actor subject, string item, int count)
|
||||
{
|
||||
return new Order("StartProduction", subject.PlayerActor, new int2( count, 0 ), item );
|
||||
return new Order("StartProduction", subject, new int2( count, 0 ), item );
|
||||
}
|
||||
|
||||
public static Order PauseProduction(Player subject, string item, bool pause)
|
||||
public static Order PauseProduction(Actor subject, string item, bool pause)
|
||||
{
|
||||
return new Order("PauseProduction", subject.PlayerActor, new int2( pause ? 1 : 0, 0 ), item);
|
||||
return new Order("PauseProduction", subject, new int2( pause ? 1 : 0, 0 ), item);
|
||||
}
|
||||
|
||||
public static Order CancelProduction(Player subject, string item)
|
||||
public static Order CancelProduction(Actor subject, string item)
|
||||
{
|
||||
return new Order("CancelProduction", subject.PlayerActor, item);
|
||||
return new Order("CancelProduction", subject, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ namespace OpenRA.Network
|
||||
{
|
||||
class OrderManager : IDisposable
|
||||
{
|
||||
SyncReport syncReport = new SyncReport();
|
||||
|
||||
public int FrameNumber { get; private set; }
|
||||
|
||||
public int FramesAhead = 0;
|
||||
@@ -109,7 +111,7 @@ namespace OpenRA.Network
|
||||
{
|
||||
if (packet.Length != existingSync.Length)
|
||||
{
|
||||
Game.DumpSyncReport(frame);
|
||||
syncReport.DumpSyncReport(frame);
|
||||
OutOfSync(frame);
|
||||
}
|
||||
else
|
||||
@@ -118,7 +120,7 @@ namespace OpenRA.Network
|
||||
{
|
||||
if (packet[i] != existingSync[i])
|
||||
{
|
||||
Game.DumpSyncReport(frame);
|
||||
syncReport.DumpSyncReport(frame);
|
||||
|
||||
if (i < SyncHeaderSize)
|
||||
OutOfSync(frame, "Tick");
|
||||
@@ -189,7 +191,7 @@ namespace OpenRA.Network
|
||||
Connection.Send( ss );
|
||||
WriteToReplay( frameData, ss );
|
||||
|
||||
Game.UpdateSyncReport();
|
||||
syncReport.UpdateSyncReport();
|
||||
|
||||
CheckSync( ss );
|
||||
|
||||
|
||||
106
OpenRA.Game/Network/Session.cs
Normal file
106
OpenRA.Game/Network/Session.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Network
|
||||
{
|
||||
public class Session
|
||||
{
|
||||
public List<Client> Clients = new List<Client>();
|
||||
public List<Slot> Slots = new List<Slot>();
|
||||
public Global GlobalSettings = new Global();
|
||||
|
||||
public enum ClientState
|
||||
{
|
||||
NotReady,
|
||||
Ready
|
||||
}
|
||||
|
||||
public class Client
|
||||
{
|
||||
public int Index;
|
||||
public Color Color1;
|
||||
public Color Color2;
|
||||
public string Country;
|
||||
public int SpawnPoint;
|
||||
public string Name;
|
||||
public ClientState State;
|
||||
public int Team;
|
||||
public int Slot; // which slot we're in, or -1 for `observer`.
|
||||
}
|
||||
|
||||
public class Slot
|
||||
{
|
||||
public int Index;
|
||||
public string Bot; // trait name of the bot to initialize in this slot, or null otherwise.
|
||||
public bool Closed; // host has explicitly closed this slot.
|
||||
public string MapPlayer; // playerReference to bind against.
|
||||
|
||||
// todo: more stuff?
|
||||
}
|
||||
|
||||
public class Global
|
||||
{
|
||||
public string Map;
|
||||
public string[] Mods = { "ra" }; // mod names
|
||||
public int OrderLatency = 3;
|
||||
public int RandomSeed = 0;
|
||||
public bool LockTeams = false; // don't allow team changes after game start.
|
||||
public bool AllowCheats = false;
|
||||
}
|
||||
|
||||
public string Serialize()
|
||||
{
|
||||
var clientData = new List<MiniYamlNode>();
|
||||
|
||||
foreach( var client in Clients )
|
||||
clientData.Add( new MiniYamlNode( "Client@{0}".F( client.Index ), FieldSaver.Save( client ) ) );
|
||||
|
||||
foreach( var slot in Slots )
|
||||
clientData.Add( new MiniYamlNode( "Slot@{0}".F( slot.Index ), FieldSaver.Save( slot ) ) );
|
||||
|
||||
clientData.Add( new MiniYamlNode( "GlobalSettings", FieldSaver.Save( GlobalSettings ) ) );
|
||||
|
||||
return clientData.WriteToString();
|
||||
}
|
||||
|
||||
public static Session Deserialize(string data)
|
||||
{
|
||||
var session = new Session();
|
||||
session.GlobalSettings.Mods = Game.Settings.Game.Mods;
|
||||
|
||||
var ys = MiniYaml.FromString(data);
|
||||
foreach (var y in ys)
|
||||
{
|
||||
var yy = y.Key.Split('@');
|
||||
|
||||
switch( yy[0] )
|
||||
{
|
||||
case "GlobalSettings":
|
||||
FieldLoader.Load(session.GlobalSettings, y.Value);
|
||||
break;
|
||||
|
||||
case "Client":
|
||||
session.Clients.Add(FieldLoader.Load<Session.Client>(y.Value));
|
||||
break;
|
||||
|
||||
case "Slot":
|
||||
session.Slots.Add(FieldLoader.Load<Session.Slot>(y.Value ));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return session;
|
||||
}
|
||||
}
|
||||
}
|
||||
89
OpenRA.Game/Network/SyncReport.cs
Executable file
89
OpenRA.Game/Network/SyncReport.cs
Executable file
@@ -0,0 +1,89 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Support;
|
||||
|
||||
namespace OpenRA.Network
|
||||
{
|
||||
class SyncReport
|
||||
{
|
||||
const int numSyncReports = 5;
|
||||
Report[] syncReports = new Report[numSyncReports];
|
||||
int curIndex = 0;
|
||||
|
||||
public SyncReport()
|
||||
{
|
||||
for (var i = 0; i < numSyncReports; i++)
|
||||
syncReports[i] = new SyncReport.Report();
|
||||
}
|
||||
|
||||
internal void UpdateSyncReport()
|
||||
{
|
||||
if (!Game.Settings.Debug.RecordSyncReports)
|
||||
return;
|
||||
|
||||
GenerateSyncReport(syncReports[curIndex]);
|
||||
curIndex = ++curIndex % numSyncReports;
|
||||
}
|
||||
|
||||
void GenerateSyncReport(Report report)
|
||||
{
|
||||
report.Frame = Game.orderManager.FrameNumber;
|
||||
report.SyncedRandom = Game.world.SharedRandom.Last;
|
||||
report.Traits.Clear();
|
||||
foreach (var a in Game.world.Queries.WithTraitMultiple<object>())
|
||||
{
|
||||
var sync = Sync.CalculateSyncHash(a.Trait);
|
||||
if (sync != 0)
|
||||
report.Traits.Add(new TraitReport()
|
||||
{
|
||||
ActorID = a.Actor.ActorID,
|
||||
Type = a.Actor.Info.Name,
|
||||
Owner = (a.Actor.Owner == null) ? "null" : a.Actor.Owner.InternalName,
|
||||
Trait = a.Trait.GetType().Name,
|
||||
Hash = sync
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
internal void DumpSyncReport(int frame)
|
||||
{
|
||||
foreach (var r in syncReports)
|
||||
if (r.Frame == frame)
|
||||
{
|
||||
Log.Write("sync", "Sync for net frame {0} -------------", r.Frame);
|
||||
Log.Write("sync", "SharedRandom: "+r.SyncedRandom);
|
||||
Log.Write("sync", "Synced Traits:");
|
||||
foreach (var a in r.Traits)
|
||||
Log.Write("sync", "\t {0} {1} {2} {3} ({4})".F(
|
||||
a.ActorID,
|
||||
a.Type,
|
||||
a.Owner,
|
||||
a.Trait,
|
||||
a.Hash
|
||||
));
|
||||
return;
|
||||
}
|
||||
Log.Write("sync", "No sync report available!");
|
||||
}
|
||||
|
||||
class Report
|
||||
{
|
||||
public int Frame;
|
||||
public int SyncedRandom;
|
||||
public List<TraitReport> Traits = new List<TraitReport>();
|
||||
}
|
||||
|
||||
struct TraitReport
|
||||
{
|
||||
public uint ActorID;
|
||||
public string Type;
|
||||
public string Owner;
|
||||
public string Trait;
|
||||
public int Hash;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -16,16 +16,34 @@ namespace OpenRA.Network
|
||||
{
|
||||
static class UnitOrders
|
||||
{
|
||||
static Session.Client FindClientById(int id)
|
||||
{
|
||||
return Game.LobbyInfo.Clients.FirstOrDefault(c => c.Index == id);
|
||||
}
|
||||
|
||||
static Player FindPlayerByClientId(int id)
|
||||
{
|
||||
/* todo: find the interactive player. */
|
||||
return Game.world.players.Values.FirstOrDefault(p => p.ClientIndex == id);
|
||||
}
|
||||
|
||||
public static void ProcessOrder( World world, int clientId, Order order )
|
||||
{
|
||||
// Drop exploiting orders
|
||||
if (order.Subject != null && order.Subject.Owner.ClientIndex != clientId)
|
||||
{
|
||||
Game.Debug("Detected exploit order from {0}: {1}".F(clientId, order.OrderString));
|
||||
return;
|
||||
}
|
||||
|
||||
switch( order.OrderString )
|
||||
{
|
||||
case "Chat":
|
||||
{
|
||||
var client = Game.LobbyInfo.Clients.FirstOrDefault(c => c.Index == clientId);
|
||||
var client = FindClientById(clientId);
|
||||
if (client != null)
|
||||
{
|
||||
var player = world.players.Values.FirstOrDefault(p => p.Index == client.Index);
|
||||
var player = FindPlayerByClientId(clientId);
|
||||
if (player != null && player.WinState == WinState.Lost)
|
||||
Game.AddChatLine(client.Color1, client.Name + " (Dead)", order.TargetString);
|
||||
else
|
||||
@@ -35,10 +53,10 @@ namespace OpenRA.Network
|
||||
}
|
||||
case "TeamChat":
|
||||
{
|
||||
var client = Game.LobbyInfo.Clients.FirstOrDefault(c => c.Index == clientId);
|
||||
var client = FindClientById(clientId);
|
||||
if (client != null)
|
||||
{
|
||||
var player = world.players.Values.FirstOrDefault(p => p.Index == client.Index);
|
||||
var player = FindPlayerByClientId(clientId);
|
||||
var display = (world.GameHasStarted) ?
|
||||
player != null && (world.LocalPlayer != null && player.Stances[world.LocalPlayer] == Stance.Ally
|
||||
|| player.WinState == WinState.Lost) :
|
||||
@@ -55,7 +73,7 @@ namespace OpenRA.Network
|
||||
case "StartGame":
|
||||
{
|
||||
Game.AddChatLine(Color.White, "Server", "The game has started.");
|
||||
Game.StartGame();
|
||||
Game.StartGame(Game.LobbyInfo.GlobalSettings.Map);
|
||||
break;
|
||||
}
|
||||
case "SyncInfo":
|
||||
@@ -70,7 +88,7 @@ namespace OpenRA.Network
|
||||
order.Player.Stances[targetPlayer] = (Stance)order.TargetLocation.Y;
|
||||
|
||||
if (targetPlayer == world.LocalPlayer)
|
||||
world.WorldActor.traits.Get<Shroud>().UpdatePlayerStance(world, order.Player, oldStance, order.Player.Stances[targetPlayer]);
|
||||
world.WorldActor.Trait<Shroud>().UpdatePlayerStance(world, order.Player, oldStance, order.Player.Stances[targetPlayer]);
|
||||
|
||||
Game.Debug("{0} has set diplomatic stance vs {1} to {2}".F(
|
||||
order.Player.PlayerName, targetPlayer.PlayerName, order.Player.Stances[targetPlayer]));
|
||||
@@ -79,7 +97,7 @@ namespace OpenRA.Network
|
||||
default:
|
||||
{
|
||||
if( !order.IsImmediate )
|
||||
foreach (var t in order.Subject.traits.WithInterface<IResolveOrder>())
|
||||
foreach (var t in order.Subject.TraitsImplementing<IResolveOrder>())
|
||||
t.ResolveOrder(order.Subject, order);
|
||||
break;
|
||||
}
|
||||
|
||||
48
OpenRA.Game/ObjectCreator.cs
Executable file
48
OpenRA.Game/ObjectCreator.cs
Executable file
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public class ObjectCreator
|
||||
{
|
||||
Pair<Assembly, string>[] ModAssemblies;
|
||||
|
||||
public ObjectCreator( Manifest manifest )
|
||||
{
|
||||
// All the core namespaces
|
||||
var asms = typeof(Game).Assembly.GetNamespaces()
|
||||
.Select(c => Pair.New(typeof(Game).Assembly, c))
|
||||
.ToList();
|
||||
|
||||
// Namespaces from each mod assembly
|
||||
foreach (var a in manifest.Assemblies)
|
||||
{
|
||||
var asm = Assembly.LoadFile(Path.GetFullPath(a));
|
||||
asms.AddRange(asm.GetNamespaces().Select(ns => Pair.New(asm, ns)));
|
||||
}
|
||||
|
||||
ModAssemblies = asms.ToArray();
|
||||
}
|
||||
|
||||
public static Action<string> MissingTypeAction =
|
||||
s => { throw new InvalidOperationException("Cannot locate type: {0}".F(s)); };
|
||||
|
||||
public T CreateObject<T>(string classname)
|
||||
{
|
||||
foreach (var mod in ModAssemblies)
|
||||
{
|
||||
var fullTypeName = mod.Second + "." + classname;
|
||||
var obj = mod.First.CreateInstance(fullTypeName);
|
||||
if (obj != null)
|
||||
return (T)obj;
|
||||
}
|
||||
|
||||
MissingTypeAction(classname);
|
||||
return default(T);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
@@ -75,7 +75,6 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Effects\RepairIndicator.cs" />
|
||||
<Compile Include="GameRules\WeaponInfo.cs" />
|
||||
<Compile Include="Group.cs" />
|
||||
<Compile Include="Orders\GenericSelectTarget.cs" />
|
||||
@@ -83,7 +82,6 @@
|
||||
<Compile Include="Traits\BaseBuilding.cs" />
|
||||
<Compile Include="Traits\LintAttributes.cs" />
|
||||
<Compile Include="Traits\Player\PlayerResources.cs" />
|
||||
<Compile Include="Traits\Player\TechTreeCache.cs" />
|
||||
<Compile Include="Traits\World\Shroud.cs" />
|
||||
<Compile Include="Widgets\ChatEntryWidget.cs" />
|
||||
<Compile Include="Widgets\Delegates\ConnectionDialogsDelegate.cs" />
|
||||
@@ -99,8 +97,6 @@
|
||||
<Compile Include="Effects\MoveFlash.cs" />
|
||||
<Compile Include="Exts.cs" />
|
||||
<Compile Include="GameRules\ActorInfo.cs" />
|
||||
<Compile Include="GameRules\TechTree.cs" />
|
||||
<Compile Include="GameRules\UserSettings.cs" />
|
||||
<Compile Include="GameRules\VoiceInfo.cs" />
|
||||
<Compile Include="Effects\IEffect.cs" />
|
||||
<Compile Include="Graphics\ChromeProvider.cs" />
|
||||
@@ -138,7 +134,6 @@
|
||||
<Compile Include="Traits\Activities\RemoveSelf.cs" />
|
||||
<Compile Include="Traits\Activities\Sell.cs" />
|
||||
<Compile Include="Orders\IOrderGenerator.cs" />
|
||||
<Compile Include="Orders\PlaceBuildingOrderGenerator.cs" />
|
||||
<Compile Include="Player.cs" />
|
||||
<Compile Include="Graphics\Sheet.cs" />
|
||||
<Compile Include="PathFinder.cs" />
|
||||
@@ -152,30 +147,21 @@
|
||||
<Compile Include="Support\Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Graphics\Renderer.cs" />
|
||||
<Compile Include="Support\Settings.cs" />
|
||||
<Compile Include="Graphics\Sprite.cs" />
|
||||
<Compile Include="Graphics\SpriteRenderer.cs" />
|
||||
<Compile Include="Graphics\SpriteSheetBuilder.cs" />
|
||||
<Compile Include="Graphics\TerrainRenderer.cs" />
|
||||
<Compile Include="Traits\Activities\Move.cs" />
|
||||
<Compile Include="Traits\Activities\Turn.cs" />
|
||||
<Compile Include="Traits\Buildable.cs" />
|
||||
<Compile Include="Traits\Building.cs" />
|
||||
<Compile Include="Traits\World\BuildingInfluence.cs" />
|
||||
<Compile Include="Traits\Player\PlaceBuilding.cs" />
|
||||
<Compile Include="Traits\World\PlayerColorPalette.cs" />
|
||||
<Compile Include="Traits\World\ResourceLayer.cs" />
|
||||
<Compile Include="Traits\World\ResourceType.cs" />
|
||||
<Compile Include="Traits\SupportPower.cs" />
|
||||
<Compile Include="Traits\ProvidesRadar.cs" />
|
||||
<Compile Include="Traits\Selectable.cs" />
|
||||
<Compile Include="Traits\Player\ProductionQueue.cs" />
|
||||
<Compile Include="Traits\Mobile.cs" />
|
||||
<Compile Include="Traits\Production.cs" />
|
||||
<Compile Include="Traits\RallyPoint.cs" />
|
||||
<Compile Include="Traits\Render\RenderSimple.cs" />
|
||||
<Compile Include="Traits\TraitsInterfaces.cs" />
|
||||
<Compile Include="Traits\Turreted.cs" />
|
||||
<Compile Include="Traits\World\UnitInfluence.cs" />
|
||||
<Compile Include="Network\UnitOrders.cs" />
|
||||
<Compile Include="Traits\Util.cs" />
|
||||
@@ -195,8 +181,6 @@
|
||||
<Compile Include="Widgets\BackgroundWidget.cs" />
|
||||
<Compile Include="Widgets\LabelWidget.cs" />
|
||||
<Compile Include="Widgets\CheckboxWidget.cs" />
|
||||
<Compile Include="Traits\World\BibLayer.cs" />
|
||||
<Compile Include="Traits\World\SmudgeLayer.cs" />
|
||||
<Compile Include="Widgets\Delegates\MusicPlayerDelegate.cs" />
|
||||
<Compile Include="Widgets\PerfGraphWidget.cs" />
|
||||
<Compile Include="Widgets\Delegates\PerfDebugDelegate.cs" />
|
||||
@@ -204,7 +188,6 @@
|
||||
<Compile Include="Widgets\ColorBlockWidget.cs" />
|
||||
<Compile Include="GameRules\MusicInfo.cs" />
|
||||
<Compile Include="Widgets\ImageWidget.cs" />
|
||||
<Compile Include="Traits\SharesCell.cs" />
|
||||
<Compile Include="Widgets\TextFieldWidget.cs" />
|
||||
<Compile Include="Widgets\ChatDisplayWidget.cs" />
|
||||
<Compile Include="Widgets\Delegates\MapChooserDelegate.cs" />
|
||||
@@ -219,8 +202,16 @@
|
||||
<Compile Include="Traits\RevealsShroud.cs" />
|
||||
<Compile Include="Traits\Targetable.cs" />
|
||||
<Compile Include="Traits\Health.cs" />
|
||||
<Compile Include="Traits\RepairableBuilding.cs" />
|
||||
<Compile Include="Traits\Activities\Drag.cs" />
|
||||
<Compile Include="Widgets\VqaPlayerWidget.cs" />
|
||||
<Compile Include="Widgets\Delegates\VideoPlayerDelegate.cs" />
|
||||
<Compile Include="GameRules\Settings.cs" />
|
||||
<Compile Include="Support\Arguments.cs" />
|
||||
<Compile Include="Traits\ActorStance.cs" />
|
||||
<Compile Include="Traits\Armor.cs" />
|
||||
<Compile Include="Graphics\CursorProvider.cs" />
|
||||
<Compile Include="Traits\Player\TechTree.cs" />
|
||||
<Compile Include="Traits\Player\PowerManager.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">
|
||||
@@ -229,7 +220,15 @@
|
||||
</ProjectReference>
|
||||
<Compile Include="ActorInitializer.cs" />
|
||||
<Compile Include="ActorReference.cs" />
|
||||
<Compile Include="ModData.cs" />
|
||||
<Compile Include="Map.cs" />
|
||||
<Compile Include="Network\Session.cs" />
|
||||
<Compile Include="ObjectCreator.cs" />
|
||||
<Compile Include="Network\SyncReport.cs" />
|
||||
<Compile Include="TraitDictionary.cs" />
|
||||
<Compile Include="Traits\SharesCell.cs" />
|
||||
<Compile Include="Traits\Valued.cs" />
|
||||
<Compile Include="Traits\World\BibLayer.cs" />
|
||||
<Compile Include="Widgets\Delegates\DeveloperModeDelegate.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -260,7 +259,4 @@
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
<ItemGroup>
|
||||
<Folder Include="Traits\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -18,9 +18,14 @@ namespace OpenRA.Orders
|
||||
class UnitOrderGenerator : IOrderGenerator
|
||||
{
|
||||
public IEnumerable<Order> Order( World world, int2 xy, MouseInput mi )
|
||||
{
|
||||
{
|
||||
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();
|
||||
|
||||
var orders = world.Selection.Actors
|
||||
.Select(a => a.Order(xy, mi))
|
||||
.Select(a => a.Order(xy, mi, underCursor))
|
||||
.Where(o => o != null)
|
||||
.ToArray();
|
||||
|
||||
@@ -38,28 +43,41 @@ namespace OpenRA.Orders
|
||||
public void RenderBeforeWorld(World world)
|
||||
{
|
||||
foreach (var a in world.Selection.Actors)
|
||||
foreach (var t in a.traits.WithInterface<IPreRenderSelection>())
|
||||
t.RenderBeforeWorld(a);
|
||||
if (!a.Destroyed)
|
||||
foreach (var t in a.TraitsImplementing<IPreRenderSelection>())
|
||||
t.RenderBeforeWorld(a);
|
||||
|
||||
Game.Renderer.Flush();
|
||||
}
|
||||
|
||||
public void RenderAfterWorld( World world )
|
||||
{
|
||||
foreach (var a in world.Selection.Actors)
|
||||
foreach (var t in a.traits.WithInterface<IPostRenderSelection>())
|
||||
t.RenderAfterWorld(a);
|
||||
foreach (var a in world.Selection.Actors)
|
||||
if (!a.Destroyed)
|
||||
foreach (var t in a.TraitsImplementing<IPostRenderSelection>())
|
||||
t.RenderAfterWorld(a);
|
||||
|
||||
Game.Renderer.Flush();
|
||||
}
|
||||
|
||||
public string GetCursor( World world, int2 xy, MouseInput mi )
|
||||
{
|
||||
{
|
||||
if (mi.Modifiers.HasModifier(Modifiers.Shift) || !world.Selection.Actors.Any())
|
||||
{
|
||||
var underCursor = world.FindUnitsAtMouse(mi.Location)
|
||||
.Where(a => a.Info.Traits.Contains<SelectableInfo>())
|
||||
.Any();
|
||||
|
||||
if (underCursor)
|
||||
return "select";
|
||||
}
|
||||
|
||||
var c = Order(world, xy, mi)
|
||||
.Select(o => o.Subject.traits.WithInterface<IOrderCursor>()
|
||||
.Select(o => o.Subject.TraitsImplementing<IOrderCursor>()
|
||||
.Select(pc => pc.CursorForOrder(o.Subject, o)).FirstOrDefault(a => a != null))
|
||||
.FirstOrDefault(a => a != null);
|
||||
|
||||
return c ??
|
||||
(world.FindUnitsAtMouse(mi.Location)
|
||||
.Any(a => a.Info.Traits.Contains<SelectableInfo>())
|
||||
? "select" : "default");
|
||||
return c ?? "default";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,11 +49,13 @@ namespace OpenRA
|
||||
cached.tick = Game.LocalTick;
|
||||
return new List<int2>(cached.result);
|
||||
}
|
||||
|
||||
var mi = self.Info.Traits.Get<MobileInfo>();
|
||||
|
||||
var pb = FindBidiPath(
|
||||
PathSearch.FromPoint(self, target, from, true)
|
||||
PathSearch.FromPoint(world, mi, target, from, true)
|
||||
.WithCustomBlocker(AvoidUnitsNear(from, 4, self)),
|
||||
PathSearch.FromPoint(self, from, target, true)
|
||||
PathSearch.FromPoint(world, mi, from, target, true)
|
||||
.WithCustomBlocker(AvoidUnitsNear(from, 4, self))
|
||||
.InReverse());
|
||||
|
||||
@@ -69,11 +71,11 @@ namespace OpenRA
|
||||
{
|
||||
using( new PerfSample( "find_unit_path_multiple_src" ) )
|
||||
{
|
||||
var mobile = self.traits.Get<Mobile>();
|
||||
var mobileInfo = self.Info.Traits.Get<MobileInfo>();
|
||||
var tilesInRange = world.FindTilesInCircle(target, range)
|
||||
.Where( t => mobile.CanEnterCell(t));
|
||||
.Where( t => Mobile.CanEnterCell(self.World, mobileInfo, t, null, true));
|
||||
|
||||
var path = FindPath( PathSearch.FromPoints( self, tilesInRange, src, false )
|
||||
var path = FindPath( PathSearch.FromPoints( world, mobileInfo, tilesInRange, src, false )
|
||||
.WithCustomBlocker(AvoidUnitsNear(src, 4, self))
|
||||
.InReverse());
|
||||
path.Reverse();
|
||||
@@ -86,7 +88,7 @@ namespace OpenRA
|
||||
return q =>
|
||||
p != q &&
|
||||
((p - q).LengthSquared < dist * dist) &&
|
||||
(world.WorldActor.traits.Get<UnitInfluence>().GetUnitsAt(q).Any(a => a.Group != self.Group));
|
||||
(world.WorldActor.Trait<UnitInfluence>().GetUnitsAt(q).Any(a => a.Group != self.Group));
|
||||
}
|
||||
|
||||
public List<int2> FindPath( PathSearch search )
|
||||
|
||||
@@ -24,16 +24,19 @@ namespace OpenRA
|
||||
Func<int2, bool> customBlock;
|
||||
public bool checkForBlocked;
|
||||
public Actor ignoreBuilding;
|
||||
Actor self;
|
||||
public bool inReverse;
|
||||
Mobile mobile;
|
||||
|
||||
public PathSearch(Actor self)
|
||||
|
||||
MobileInfo mobileInfo;
|
||||
BuildingInfluence bim;
|
||||
UnitInfluence uim;
|
||||
|
||||
public PathSearch(World world, MobileInfo mobileInfo)
|
||||
{
|
||||
this.self = self;
|
||||
world = self.World;
|
||||
this.world = world;
|
||||
bim = world.WorldActor.Trait<BuildingInfluence>();
|
||||
uim = world.WorldActor.Trait<UnitInfluence>();
|
||||
cellInfo = InitCellInfo();
|
||||
mobile = self.traits.Get<Mobile>();
|
||||
this.mobileInfo = mobileInfo;
|
||||
queue = new PriorityQueue<PathDistance>();
|
||||
}
|
||||
|
||||
@@ -61,13 +64,19 @@ namespace OpenRA
|
||||
return this;
|
||||
}
|
||||
|
||||
public PathSearch FromPoint(int2 from)
|
||||
public PathSearch WithoutLaneBias()
|
||||
{
|
||||
AddInitialCell( self.World, from );
|
||||
LaneBias = 0f;
|
||||
return this;
|
||||
}
|
||||
|
||||
const float LaneBias = .5f;
|
||||
public PathSearch FromPoint(int2 from)
|
||||
{
|
||||
AddInitialCell( world, from );
|
||||
return this;
|
||||
}
|
||||
|
||||
float LaneBias = .5f;
|
||||
|
||||
public int2 Expand( World world )
|
||||
{
|
||||
@@ -80,7 +89,7 @@ namespace OpenRA
|
||||
|
||||
cellInfo[p.Location.X, p.Location.Y].Seen = true;
|
||||
|
||||
var thisCost = mobile.MovementCostForCell(self, p.Location);
|
||||
var thisCost = Mobile.MovementCostForCell(mobileInfo, world, p.Location);
|
||||
|
||||
if (thisCost == float.PositiveInfinity)
|
||||
return p.Location;
|
||||
@@ -93,12 +102,12 @@ namespace OpenRA
|
||||
if( cellInfo[ newHere.X, newHere.Y ].Seen )
|
||||
continue;
|
||||
|
||||
var costHere = mobile.MovementCostForCell(self, newHere);
|
||||
var costHere = Mobile.MovementCostForCell(mobileInfo, world, newHere);
|
||||
|
||||
if (costHere == float.PositiveInfinity)
|
||||
continue;
|
||||
|
||||
if (!mobile.CanEnterCell(newHere, ignoreBuilding, checkForBlocked))
|
||||
if (!Mobile.CanEnterCell(mobileInfo, world, uim, bim, newHere, ignoreBuilding, checkForBlocked))
|
||||
continue;
|
||||
|
||||
if (customBlock != null && customBlock(newHere))
|
||||
@@ -154,33 +163,33 @@ namespace OpenRA
|
||||
queue.Add( new PathDistance( heuristic( location ), location ) );
|
||||
}
|
||||
|
||||
public static PathSearch Search( Actor self, bool checkForBlocked )
|
||||
public static PathSearch Search( World world, MobileInfo mi, bool checkForBlocked )
|
||||
{
|
||||
var search = new PathSearch(self) {
|
||||
var search = new PathSearch(world, mi) {
|
||||
checkForBlocked = checkForBlocked };
|
||||
return search;
|
||||
}
|
||||
|
||||
public static PathSearch FromPoint( Actor self, int2 from, int2 target, bool checkForBlocked )
|
||||
public static PathSearch FromPoint( World world, MobileInfo mi, int2 from, int2 target, bool checkForBlocked )
|
||||
{
|
||||
var search = new PathSearch(self) {
|
||||
var search = new PathSearch(world, mi) {
|
||||
heuristic = DefaultEstimator( target ),
|
||||
checkForBlocked = checkForBlocked };
|
||||
|
||||
search.AddInitialCell( self.World, from );
|
||||
search.AddInitialCell( world, from );
|
||||
return search;
|
||||
}
|
||||
|
||||
public static PathSearch FromPoints(Actor self, IEnumerable<int2> froms, int2 target, bool checkForBlocked)
|
||||
public static PathSearch FromPoints(World world, MobileInfo mi, IEnumerable<int2> froms, int2 target, bool checkForBlocked)
|
||||
{
|
||||
var search = new PathSearch(self)
|
||||
var search = new PathSearch(world, mi)
|
||||
{
|
||||
heuristic = DefaultEstimator(target),
|
||||
checkForBlocked = checkForBlocked
|
||||
};
|
||||
|
||||
foreach (var sl in froms)
|
||||
search.AddInitialCell(self.World, sl);
|
||||
search.AddInitialCell(world, sl);
|
||||
|
||||
return search;
|
||||
}
|
||||
|
||||
@@ -8,10 +8,11 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Network;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA
|
||||
@@ -34,7 +35,9 @@ namespace OpenRA
|
||||
public readonly string InternalName;
|
||||
public readonly CountryInfo Country;
|
||||
public readonly int Index;
|
||||
public readonly bool NonCombatant = false;
|
||||
public readonly bool NonCombatant = false;
|
||||
public readonly int ClientIndex;
|
||||
public readonly PlayerReference PlayerRef;
|
||||
|
||||
public ShroudRenderer Shroud;
|
||||
public World World { get; private set; }
|
||||
@@ -43,47 +46,52 @@ namespace OpenRA
|
||||
{
|
||||
World = world;
|
||||
Shroud = new ShroudRenderer(this, world.Map);
|
||||
|
||||
PlayerActor = world.CreateActor("Player", new TypeDictionary{ new OwnerInit( this ) });
|
||||
|
||||
Index = index;
|
||||
Palette = "player"+index;
|
||||
Color = pr.Color;
|
||||
Color2 = pr.Color2;
|
||||
Color2 = pr.Color2;
|
||||
ClientIndex = 0; /* it's a map player, "owned" by host */
|
||||
|
||||
PlayerName = InternalName = pr.Name;
|
||||
NonCombatant = pr.NonCombatant;
|
||||
Country = world.GetCountries()
|
||||
.FirstOrDefault(c => pr.Race == c.Race);
|
||||
.FirstOrDefault(c => pr.Race == c.Race)
|
||||
?? world.GetCountries().Random(world.SharedRandom);
|
||||
|
||||
PlayerRef = pr;
|
||||
|
||||
RegisterPlayerColor(world, Palette);
|
||||
RegisterPlayerColor(world, Palette);
|
||||
PlayerActor = world.CreateActor("Player", new TypeDictionary{ new OwnerInit( this ) });
|
||||
}
|
||||
|
||||
public Player( World world, Session.Client client )
|
||||
public Player( World world, Session.Client client, PlayerReference pr, int index )
|
||||
{
|
||||
World = world;
|
||||
Shroud = new ShroudRenderer(this, world.Map);
|
||||
|
||||
PlayerActor = world.CreateActor("Player", new TypeDictionary{ new OwnerInit( this ) });
|
||||
|
||||
Index = client.Index;
|
||||
Palette = "player"+client.Index;
|
||||
Index = index;
|
||||
Palette = "player"+index;
|
||||
Color = client.Color1;
|
||||
Color2 = client.Color2;
|
||||
PlayerName = client.Name;
|
||||
InternalName = "Multi{0}".F(client.Index);
|
||||
PlayerName = client.Name;
|
||||
InternalName = pr.Name;
|
||||
Country = world.GetCountries()
|
||||
.FirstOrDefault(c => client != null && client.Country == c.Race)
|
||||
?? world.GetCountries().Random(world.SharedRandom);
|
||||
?? world.GetCountries().Random(world.SharedRandom);
|
||||
|
||||
ClientIndex = client.Index;
|
||||
PlayerRef = pr;
|
||||
|
||||
RegisterPlayerColor(world, Palette);
|
||||
RegisterPlayerColor(world, Palette);
|
||||
PlayerActor = world.CreateActor("Player", new TypeDictionary{ new OwnerInit( this ) });
|
||||
}
|
||||
|
||||
public void RegisterPlayerColor(World world, string palette)
|
||||
{
|
||||
var info = Rules.Info["world"].Traits.Get<PlayerColorPaletteInfo>();
|
||||
var newpal = new Palette(world.WorldRenderer.GetPalette(info.BasePalette),
|
||||
new PlayerColorRemap(Color, Color2, info.SplitRamp));
|
||||
new PlayerColorRemap(Color, Color2, info.PaletteFormat));
|
||||
world.WorldRenderer.AddPalette(palette, newpal);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace OpenRA
|
||||
public void Add(World w, Actor a)
|
||||
{
|
||||
actors.Add(a);
|
||||
foreach (var ns in w.WorldActor.traits.WithInterface<INotifySelection>())
|
||||
foreach (var ns in w.WorldActor.TraitsImplementing<INotifySelection>())
|
||||
ns.SelectionChanged();
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace OpenRA
|
||||
{
|
||||
return actors.AsEnumerable().Contains(a);
|
||||
}
|
||||
|
||||
public void Combine(World world, IEnumerable<Actor> newSelection, bool isCombine, bool isClick)
|
||||
{
|
||||
var oldSelection = actors.AsEnumerable();
|
||||
@@ -42,9 +43,10 @@ namespace OpenRA
|
||||
actors = (isCombine ? oldSelection.Union(newSelection) : newSelection).ToList();
|
||||
|
||||
var voicedUnit = actors.FirstOrDefault(a => a.Owner == world.LocalPlayer && a.HasVoice());
|
||||
Sound.PlayVoice("Select", voicedUnit);
|
||||
if (voicedUnit != null)
|
||||
Sound.PlayVoice("Select", voicedUnit, voicedUnit.Owner.Country.Race);
|
||||
|
||||
foreach (var ns in world.WorldActor.traits.WithInterface<INotifySelection>())
|
||||
foreach (var ns in world.WorldActor.TraitsImplementing<INotifySelection>())
|
||||
ns.SelectionChanged();
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,6 @@ namespace OpenRA.Server
|
||||
public static class ProtocolVersion
|
||||
{
|
||||
// you *must* increment this whenever you make an incompatible protocol change
|
||||
public static readonly int Version = 5;
|
||||
public static readonly int Version = 6;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,10 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.Network;
|
||||
|
||||
namespace OpenRA.Server
|
||||
{
|
||||
@@ -31,7 +32,6 @@ namespace OpenRA.Server
|
||||
static Session lobbyInfo;
|
||||
static bool GameStarted = false;
|
||||
static string Name;
|
||||
static WebClient wc = new WebClient();
|
||||
static int ExternalPort;
|
||||
static int randomSeed;
|
||||
|
||||
@@ -44,24 +44,29 @@ namespace OpenRA.Server
|
||||
static bool isInternetServer;
|
||||
static string masterServerUrl;
|
||||
static bool isInitialPing;
|
||||
static ModData ModData;
|
||||
static Map Map;
|
||||
|
||||
public static void ServerMain(bool internetServer, string masterServerUrl, string name, int port, int extport, string[] mods, string map, bool cheats)
|
||||
public static void ServerMain(ModData modData, Settings settings, string map)
|
||||
{
|
||||
Log.AddChannel("server", "server.log", false, false);
|
||||
Log.AddChannel("server", "server.log");
|
||||
|
||||
isInitialPing = true;
|
||||
Server.masterServerUrl = masterServerUrl;
|
||||
isInternetServer = internetServer;
|
||||
listener = new TcpListener(IPAddress.Any, port);
|
||||
Name = name;
|
||||
ExternalPort = extport;
|
||||
Server.masterServerUrl = settings.Server.MasterServer;
|
||||
isInternetServer = settings.Server.AdvertiseOnline;
|
||||
listener = new TcpListener(IPAddress.Any, settings.Server.ListenPort);
|
||||
Name = settings.Server.Name;
|
||||
ExternalPort = settings.Server.ExternalPort;
|
||||
randomSeed = (int)DateTime.Now.ToBinary();
|
||||
ModData = modData;
|
||||
|
||||
lobbyInfo = new Session();
|
||||
lobbyInfo.GlobalSettings.Mods = mods;
|
||||
lobbyInfo.GlobalSettings.Mods = settings.Game.Mods;
|
||||
lobbyInfo.GlobalSettings.RandomSeed = randomSeed;
|
||||
lobbyInfo.GlobalSettings.Map = map;
|
||||
lobbyInfo.GlobalSettings.AllowCheats = cheats;
|
||||
lobbyInfo.GlobalSettings.AllowCheats = settings.Server.AllowCheats;
|
||||
|
||||
LoadMap(); // populates the Session's slots, too.
|
||||
|
||||
Log.Write("server", "Initial mods: ");
|
||||
foreach( var m in lobbyInfo.GlobalSettings.Mods )
|
||||
@@ -86,7 +91,7 @@ namespace OpenRA.Server
|
||||
checkRead.Add( listener.Server );
|
||||
foreach( var c in conns ) checkRead.Add( c.socket );
|
||||
|
||||
Socket.Select( checkRead, null, null, MasterPingInterval * 1000000 );
|
||||
Socket.Select( checkRead, null, null, MasterPingInterval * 10000 );
|
||||
|
||||
foreach( Socket s in checkRead )
|
||||
if( s == listener.Server ) AcceptConnection();
|
||||
@@ -94,6 +99,10 @@ namespace OpenRA.Server
|
||||
|
||||
if (Environment.TickCount - lastPing > MasterPingInterval * 1000)
|
||||
PingMasterServer();
|
||||
else
|
||||
lock (masterServerMessages)
|
||||
while (masterServerMessages.Count > 0)
|
||||
SendChat(null, masterServerMessages.Dequeue());
|
||||
|
||||
if (conns.Count() == 0)
|
||||
{
|
||||
@@ -103,8 +112,47 @@ namespace OpenRA.Server
|
||||
}
|
||||
}
|
||||
} ) { IsBackground = true }.Start();
|
||||
|
||||
|
||||
}
|
||||
|
||||
static Session.Slot MakeSlotFromPlayerReference(PlayerReference pr)
|
||||
{
|
||||
if (!pr.Playable) return null;
|
||||
return new Session.Slot
|
||||
{
|
||||
MapPlayer = pr.Name,
|
||||
Bot = null, /* todo: allow the map to specify a bot class? */
|
||||
Closed = false,
|
||||
};
|
||||
}
|
||||
|
||||
static void LoadMap()
|
||||
{
|
||||
Map = new Map(ModData.AvailableMaps[lobbyInfo.GlobalSettings.Map].Package);
|
||||
lobbyInfo.Slots = Map.Players
|
||||
.Select(p => MakeSlotFromPlayerReference(p.Value))
|
||||
.Where(s => s != null)
|
||||
.Select((s, i) => { s.Index = i; return s; })
|
||||
.ToList();
|
||||
}
|
||||
|
||||
/* lobby rework todo:
|
||||
*
|
||||
* - auto-assign players to slots
|
||||
* - show all the slots in the lobby ui.
|
||||
* - rework the game start so we actually use the slots.
|
||||
* - all players should be able to click an empty slot to move to it
|
||||
* - host should be able to choose whether a slot is open/closed/bot, with
|
||||
* potentially more than one choice of bot class.
|
||||
* - host should be able to kick a client from the lobby by closing its slot.
|
||||
* - change lobby commands so the host can configure bots, rather than
|
||||
* just configuring itself.
|
||||
* - "teams together" option for team games -- will eliminate most need
|
||||
* for manual spawnpoint choosing.
|
||||
* - pick sensible non-conflicting colors for bots.
|
||||
*/
|
||||
|
||||
static int ChooseFreePlayerIndex()
|
||||
{
|
||||
for (var i = 0; i < 8; i++)
|
||||
@@ -114,6 +162,11 @@ namespace OpenRA.Server
|
||||
throw new InvalidOperationException("Already got 8 players");
|
||||
}
|
||||
|
||||
static int ChooseFreeSlot()
|
||||
{
|
||||
return lobbyInfo.Slots.First(s => !s.Closed && s.Bot == null).Index;
|
||||
}
|
||||
|
||||
static void AcceptConnection()
|
||||
{
|
||||
var newConn = new Connection { socket = listener.AcceptSocket() };
|
||||
@@ -136,18 +189,19 @@ namespace OpenRA.Server
|
||||
newConn.socket.Send(BitConverter.GetBytes(newConn.PlayerIndex));
|
||||
conns.Add(newConn);
|
||||
|
||||
var defaults = new GameRules.UserSettings();
|
||||
var defaults = new GameRules.PlayerSettings();
|
||||
lobbyInfo.Clients.Add(
|
||||
new Session.Client()
|
||||
{
|
||||
Index = newConn.PlayerIndex,
|
||||
Color1 = defaults.PlayerColor1,
|
||||
Color2 = defaults.PlayerColor2,
|
||||
Name = defaults.PlayerName,
|
||||
Color1 = defaults.Color1,
|
||||
Color2 = defaults.Color2,
|
||||
Name = defaults.Name,
|
||||
Country = "random",
|
||||
State = Session.ClientState.NotReady,
|
||||
SpawnPoint = 0,
|
||||
Team = 0,
|
||||
Slot = ChooseFreeSlot(),
|
||||
});
|
||||
|
||||
Log.Write("server", "Client {0}: Accepted connection from {1}",
|
||||
@@ -325,6 +379,103 @@ namespace OpenRA.Server
|
||||
SyncLobbyInfo();
|
||||
return true;
|
||||
}},
|
||||
{ "slot",
|
||||
s =>
|
||||
{
|
||||
int slot;
|
||||
if (!int.TryParse(s, out slot)) { Log.Write("server", "Invalid slot: {0}", s ); return false; }
|
||||
|
||||
var slotData = lobbyInfo.Slots.FirstOrDefault( x => x.Index == slot );
|
||||
if (slotData == null || slotData.Closed || slotData.Bot != null
|
||||
|| lobbyInfo.Clients.Any( c => c.Slot == slot ))
|
||||
return false;
|
||||
|
||||
GetClient(conn).Slot = slot;
|
||||
SyncLobbyInfo();
|
||||
return true;
|
||||
}},
|
||||
{ "slot_close",
|
||||
s =>
|
||||
{
|
||||
int slot;
|
||||
if (!int.TryParse(s, out slot)) { Log.Write("server", "Invalid slot: {0}", s ); return false; }
|
||||
|
||||
var slotData = lobbyInfo.Slots.FirstOrDefault( x => x.Index == slot );
|
||||
if (slotData == null)
|
||||
return false;
|
||||
|
||||
if (conn.PlayerIndex != 0)
|
||||
{
|
||||
SendChatTo( conn, "Only the host can alter slots" );
|
||||
return true;
|
||||
}
|
||||
|
||||
slotData.Closed = true;
|
||||
slotData.Bot = null;
|
||||
|
||||
/* kick any player that's in the slot */
|
||||
var occupant = lobbyInfo.Clients.FirstOrDefault( c => c.Slot == slotData.Index );
|
||||
if (occupant != null)
|
||||
{
|
||||
var occupantConn = conns.FirstOrDefault( c => c.PlayerIndex == occupant.Index );
|
||||
if (occupantConn != null)
|
||||
DropClient( occupantConn, new Exception() );
|
||||
}
|
||||
|
||||
SyncLobbyInfo();
|
||||
return true;
|
||||
}},
|
||||
{ "slot_open",
|
||||
s =>
|
||||
{
|
||||
int slot;
|
||||
if (!int.TryParse(s, out slot)) { Log.Write("server", "Invalid slot: {0}", s ); return false; }
|
||||
|
||||
var slotData = lobbyInfo.Slots.FirstOrDefault( x => x.Index == slot );
|
||||
if (slotData == null)
|
||||
return false;
|
||||
|
||||
if (conn.PlayerIndex != 0)
|
||||
{
|
||||
SendChatTo( conn, "Only the host can alter slots" );
|
||||
return true;
|
||||
}
|
||||
|
||||
slotData.Closed = false;
|
||||
slotData.Bot = null;
|
||||
|
||||
SyncLobbyInfo();
|
||||
return true;
|
||||
}},
|
||||
{ "slot_bot",
|
||||
s =>
|
||||
{
|
||||
var parts = s.Split(' ');
|
||||
|
||||
if (parts.Length != 2)
|
||||
{
|
||||
SendChatTo( conn, "Malformed slot_bot command" );
|
||||
return true;
|
||||
}
|
||||
|
||||
int slot;
|
||||
if (!int.TryParse(parts[0], out slot)) { Log.Write("server", "Invalid slot: {0}", s ); return false; }
|
||||
|
||||
var slotData = lobbyInfo.Slots.FirstOrDefault( x => x.Index == slot );
|
||||
if (slotData == null)
|
||||
return false;
|
||||
|
||||
if (conn.PlayerIndex != 0)
|
||||
{
|
||||
SendChatTo( conn, "Only the host can alter slots" );
|
||||
return true;
|
||||
}
|
||||
|
||||
slotData.Bot = parts[1];
|
||||
|
||||
SyncLobbyInfo();
|
||||
return true;
|
||||
}},
|
||||
{ "map",
|
||||
s =>
|
||||
{
|
||||
@@ -334,6 +485,8 @@ namespace OpenRA.Server
|
||||
return true;
|
||||
}
|
||||
lobbyInfo.GlobalSettings.Map = s;
|
||||
LoadMap();
|
||||
|
||||
foreach(var client in lobbyInfo.Clients)
|
||||
{
|
||||
client.SpawnPoint = 0;
|
||||
@@ -406,7 +559,9 @@ namespace OpenRA.Server
|
||||
};
|
||||
}
|
||||
break;
|
||||
case "Chat": case "TeamChat":
|
||||
|
||||
case "Chat":
|
||||
case "TeamChat":
|
||||
foreach (var c in conns.Except(conn).ToArray())
|
||||
DispatchOrdersToClient(c, GetClient(conn).Index, 0, so.Serialize());
|
||||
break;
|
||||
@@ -420,8 +575,6 @@ namespace OpenRA.Server
|
||||
|
||||
public static void DropClient(Connection toDrop, Exception e)
|
||||
{
|
||||
Log.Write("server", "Client dropped: {0}.", toDrop.socket.RemoteEndPoint);
|
||||
|
||||
conns.Remove(toDrop);
|
||||
SendChat(toDrop, "Connection Dropped");
|
||||
|
||||
@@ -435,62 +588,57 @@ namespace OpenRA.Server
|
||||
|
||||
static void SyncLobbyInfo()
|
||||
{
|
||||
var clientData = lobbyInfo.Clients.ToDictionary(
|
||||
a => a.Index.ToString(),
|
||||
a => FieldSaver.Save(a));
|
||||
|
||||
clientData["GlobalSettings"] = FieldSaver.Save(lobbyInfo.GlobalSettings);
|
||||
|
||||
DispatchOrders(null, 0,
|
||||
new ServerOrder("SyncInfo", clientData.WriteToString()).Serialize());
|
||||
new ServerOrder("SyncInfo", lobbyInfo.Serialize()).Serialize());
|
||||
|
||||
PingMasterServer();
|
||||
}
|
||||
|
||||
static volatile bool isBusy;
|
||||
static Queue<string> masterServerMessages = new Queue<string>();
|
||||
static void PingMasterServer()
|
||||
{
|
||||
if (wc.IsBusy || !isInternetServer) return;
|
||||
|
||||
var url = "ping.php?port={0}&name={1}&state={2}&players={3}&mods={4}&map={5}";
|
||||
wc.DownloadDataCompleted += PingMasterServerResponse;
|
||||
if (isInitialPing)
|
||||
{
|
||||
url += "&new=1";
|
||||
isInitialPing = false;
|
||||
}
|
||||
else
|
||||
wc.DownloadDataCompleted -= PingMasterServerResponse;
|
||||
|
||||
wc.DownloadDataAsync(new Uri(
|
||||
masterServerUrl + url.F(
|
||||
ExternalPort, Uri.EscapeUriString(Name),
|
||||
GameStarted ? 2 : 1, // todo: post-game states, etc.
|
||||
lobbyInfo.Clients.Count,
|
||||
string.Join(",", lobbyInfo.GlobalSettings.Mods),
|
||||
lobbyInfo.GlobalSettings.Map)));
|
||||
if (isBusy || !isInternetServer) return;
|
||||
|
||||
lastPing = Environment.TickCount;
|
||||
}
|
||||
isBusy = true;
|
||||
|
||||
static void PingMasterServerResponse(object sender, DownloadDataCompletedEventArgs e)
|
||||
{
|
||||
if (e.Error != null)
|
||||
{
|
||||
Log.Write("server", "Error pinging Master Server; {0}", e.Error.Message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.Result.Length == 0)
|
||||
{
|
||||
Log.Write("server", "Error pinging Master Server; Empty Response");
|
||||
return;
|
||||
}
|
||||
|
||||
string s = Encoding.UTF8.GetString(e.Result);
|
||||
int gameId;
|
||||
if (int.TryParse(s.Trim(), out gameId))
|
||||
Game.SetGameId(gameId);
|
||||
Log.Write("server", "Game ID: {0}", gameId);
|
||||
Action a = () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var url = "ping.php?port={0}&name={1}&state={2}&players={3}&mods={4}&map={5}";
|
||||
if (isInitialPing) url += "&new=1";
|
||||
|
||||
using (var wc = new WebClient())
|
||||
{
|
||||
wc.DownloadData(
|
||||
masterServerUrl + url.F(
|
||||
ExternalPort, Uri.EscapeUriString(Name),
|
||||
GameStarted ? 2 : 1, // todo: post-game states, etc.
|
||||
lobbyInfo.Clients.Count,
|
||||
string.Join(",", lobbyInfo.GlobalSettings.Mods),
|
||||
lobbyInfo.GlobalSettings.Map));
|
||||
|
||||
if (isInitialPing)
|
||||
{
|
||||
isInitialPing = false;
|
||||
lock (masterServerMessages)
|
||||
masterServerMessages.Enqueue("Master server communication established.");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Log.Write("server", ex.ToString());
|
||||
lock( masterServerMessages )
|
||||
masterServerMessages.Enqueue( "Master server communication failed." );
|
||||
}
|
||||
|
||||
isBusy = false;
|
||||
};
|
||||
|
||||
a.BeginInvoke(null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace OpenRA
|
||||
|
||||
public ShroudRenderer(Player owner, Map map)
|
||||
{
|
||||
this.shroud = owner.World.WorldActor.traits.Get<Traits.Shroud>();
|
||||
this.shroud = owner.World.WorldActor.Trait<Traits.Shroud>();
|
||||
this.map = map;
|
||||
|
||||
sprites = new Sprite[map.MapSize.X, map.MapSize.Y];
|
||||
@@ -145,7 +145,7 @@ namespace OpenRA
|
||||
}
|
||||
|
||||
var clipRect = Bounds.HasValue ? Rectangle.Intersect(Bounds.Value, map.Bounds) : map.Bounds;
|
||||
|
||||
clipRect = Rectangle.Intersect(Game.viewport.ViewBounds(), clipRect);
|
||||
var miny = clipRect.Top;
|
||||
var maxy = clipRect.Bottom;
|
||||
var minx = clipRect.Left;
|
||||
|
||||
@@ -21,10 +21,10 @@ namespace OpenRA
|
||||
{
|
||||
static ISoundEngine soundEngine;
|
||||
static Cache<string, ISoundSource> sounds;
|
||||
static ISoundSource rawSource;
|
||||
static ISound music;
|
||||
|
||||
static bool paused;
|
||||
static bool stopped;
|
||||
static ISound video;
|
||||
static string currentMusic;
|
||||
|
||||
static ISoundSource LoadSound(string filename)
|
||||
{
|
||||
@@ -32,13 +32,18 @@ namespace OpenRA
|
||||
return soundEngine.AddSoundSourceFromMemory(data, 1, 16, 22050);
|
||||
}
|
||||
|
||||
static ISoundSource LoadSoundRaw(byte[] rawData)
|
||||
{
|
||||
return soundEngine.AddSoundSourceFromMemory(rawData, 1, 16, 22050);
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
soundEngine = new OpenAlSoundEngine();
|
||||
sounds = new Cache<string, ISoundSource>(LoadSound);
|
||||
music = null;
|
||||
paused = false;
|
||||
stopped = false;
|
||||
currentMusic = null;
|
||||
video = null;
|
||||
}
|
||||
|
||||
public static void SetListenerPosition(float2 position) { soundEngine.SetListenerPosition(position); }
|
||||
@@ -73,36 +78,91 @@ namespace OpenRA
|
||||
Play(name, pos);
|
||||
}
|
||||
|
||||
public static void PlayMusic(string name)
|
||||
public static void PlayVideo(byte[] raw)
|
||||
{
|
||||
if (name == "" || name == null)
|
||||
return;
|
||||
|
||||
if (music != null)
|
||||
soundEngine.StopSound(music);
|
||||
|
||||
var sound = sounds[name];
|
||||
music = soundEngine.Play2D(sound, true, true, float2.Zero, MusicVolume);
|
||||
rawSource = LoadSoundRaw(raw);
|
||||
video = soundEngine.Play2D(rawSource, false, true, float2.Zero, SoundVolume);
|
||||
}
|
||||
|
||||
public static bool MusicPaused
|
||||
|
||||
public static void PlayVideo()
|
||||
{
|
||||
get { return paused; }
|
||||
set {
|
||||
paused = value;
|
||||
if (music != null)
|
||||
soundEngine.PauseSound(music, paused);
|
||||
if (video != null)
|
||||
soundEngine.PauseSound(video, false);
|
||||
}
|
||||
|
||||
public static void PauseVideo()
|
||||
{
|
||||
if (video != null)
|
||||
soundEngine.PauseSound(video, true);
|
||||
}
|
||||
|
||||
public static void StopVideo()
|
||||
{
|
||||
if (video != null)
|
||||
soundEngine.StopSound(video);
|
||||
}
|
||||
|
||||
public static void Tick()
|
||||
{
|
||||
// Song finished
|
||||
if (MusicPlaying && !music.Playing)
|
||||
{
|
||||
StopMusic();
|
||||
OnMusicComplete();
|
||||
}
|
||||
}
|
||||
|
||||
public static bool MusicStopped
|
||||
static Action OnMusicComplete;
|
||||
public static bool MusicPlaying { get; private set; }
|
||||
|
||||
public static void PlayMusic(string name)
|
||||
{
|
||||
get { return stopped; }
|
||||
set {
|
||||
stopped = value;
|
||||
if (music != null && stopped)
|
||||
soundEngine.StopSound(music);
|
||||
PlayMusicThen(name, () => {});
|
||||
}
|
||||
public static void PlayMusicThen(string name, Action then)
|
||||
{
|
||||
OnMusicComplete = then;
|
||||
|
||||
if (name == "" || name == null)
|
||||
return;
|
||||
|
||||
if (name == currentMusic && music != null)
|
||||
{
|
||||
soundEngine.PauseSound(music, false);
|
||||
return;
|
||||
}
|
||||
StopMusic();
|
||||
|
||||
currentMusic = name;
|
||||
MusicPlaying = true;
|
||||
var sound = sounds[name];
|
||||
music = soundEngine.Play2D(sound, false, true, float2.Zero, MusicVolume);
|
||||
}
|
||||
|
||||
public static void PlayMusic()
|
||||
{
|
||||
if (music == null)
|
||||
return;
|
||||
MusicPlaying = true;
|
||||
soundEngine.PauseSound(music, false);
|
||||
}
|
||||
|
||||
public static void StopMusic()
|
||||
{
|
||||
if (music != null)
|
||||
soundEngine.StopSound(music);
|
||||
|
||||
MusicPlaying = false;
|
||||
currentMusic = null;
|
||||
}
|
||||
|
||||
public static void PauseMusic()
|
||||
{
|
||||
if (music == null)
|
||||
return;
|
||||
|
||||
MusicPlaying = false;
|
||||
soundEngine.PauseSound(music, true);
|
||||
}
|
||||
|
||||
public static float GlobalVolume
|
||||
@@ -113,27 +173,48 @@ namespace OpenRA
|
||||
|
||||
public static float SoundVolume
|
||||
{
|
||||
get { return Game.Settings.SoundVolume; }
|
||||
get { return Game.Settings.Sound.SoundVolume; }
|
||||
set
|
||||
{
|
||||
Game.Settings.SoundVolume = value;
|
||||
soundEngine.SetSoundVolume(value, music);
|
||||
Game.Settings.Sound.SoundVolume = value;
|
||||
soundEngine.SetSoundVolume(value, music, video);
|
||||
}
|
||||
}
|
||||
|
||||
public static float MusicVolume
|
||||
{
|
||||
get { return Game.Settings.MusicVolume; }
|
||||
get { return Game.Settings.Sound.MusicVolume; }
|
||||
set
|
||||
{
|
||||
Game.Settings.MusicVolume = value;
|
||||
Game.Settings.Sound.MusicVolume = value;
|
||||
if (music != null)
|
||||
music.Volume = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static float VideoVolume
|
||||
{
|
||||
get { return Game.Settings.Sound.VideoVolume; }
|
||||
set
|
||||
{
|
||||
Game.Settings.Sound.VideoVolume = value;
|
||||
if (video != null)
|
||||
video.Volume = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static float MusicSeekPosition
|
||||
{
|
||||
get { return (music != null)? music.SeekPosition : 0; }
|
||||
}
|
||||
|
||||
public static float VideoSeekPosition
|
||||
{
|
||||
get { return (video != null)? video.SeekPosition : 0; }
|
||||
}
|
||||
|
||||
// Returns true if it played a phrase
|
||||
public static bool PlayVoice(string phrase, Actor voicedUnit)
|
||||
public static bool PlayVoice(string phrase, Actor voicedUnit, string variant)
|
||||
{
|
||||
if (voicedUnit == null) return false;
|
||||
if (phrase == null) return false;
|
||||
@@ -147,20 +228,10 @@ namespace OpenRA
|
||||
var clip = vi.Pools.Value[phrase].GetNext();
|
||||
if (clip == null)
|
||||
return false;
|
||||
|
||||
if (clip.Contains(".")) /* no variants! */
|
||||
{
|
||||
Play(clip);
|
||||
return true;
|
||||
}
|
||||
|
||||
// todo: fix this
|
||||
var variants = (voicedUnit.Owner.Country.Race == "allies")
|
||||
? vi.AlliedVariants : vi.SovietVariants;
|
||||
|
||||
var variant = variants[voicedUnit.ActorID % variants.Length];
|
||||
|
||||
Play(clip + variant);
|
||||
|
||||
var variantext = (vi.Variants.ContainsKey(variant) && !vi.DisableVariants.Contains(phrase))?
|
||||
vi.Variants[variant][voicedUnit.ActorID % vi.Variants.Count] : vi.DefaultVariant;
|
||||
Play(clip + variantext);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -175,13 +246,15 @@ namespace OpenRA
|
||||
void SetAllSoundsPaused(bool paused);
|
||||
void StopAllSounds();
|
||||
void SetListenerPosition(float2 position);
|
||||
void SetSoundVolume(float volume, ISound music);
|
||||
void SetSoundVolume(float volume, ISound music, ISound video);
|
||||
}
|
||||
|
||||
interface ISoundSource {}
|
||||
interface ISound
|
||||
{
|
||||
float Volume { get; set; }
|
||||
float SeekPosition { get; }
|
||||
bool Playing { get; }
|
||||
}
|
||||
|
||||
class OpenAlSoundEngine : ISoundEngine
|
||||
@@ -288,14 +361,15 @@ namespace OpenRA
|
||||
}
|
||||
}
|
||||
|
||||
public void SetSoundVolume(float volume, ISound music)
|
||||
public void SetSoundVolume(float volume, ISound music, ISound video)
|
||||
{
|
||||
var sounds = sourcePool.Select(s => s.Key).Where( b =>
|
||||
{
|
||||
int state;
|
||||
Al.alGetSourcei(b, Al.AL_SOURCE_STATE, out state);
|
||||
return ((state == Al.AL_PLAYING || state == Al.AL_PAUSED) &&
|
||||
((music != null)? b != ((OpenAlSound) music).source : true));
|
||||
((music != null)? b != ((OpenAlSound) music).source : true) &&
|
||||
((video != null)? b != ((OpenAlSound) video).source : true));
|
||||
}).ToList();
|
||||
foreach (var s in sounds)
|
||||
{
|
||||
@@ -371,7 +445,6 @@ namespace OpenRA
|
||||
Al.alSourcef(source, Al.AL_REFERENCE_DISTANCE, 200);
|
||||
Al.alSourcef(source, Al.AL_MAX_DISTANCE, 1500);
|
||||
Volume = volume;
|
||||
|
||||
Al.alSourcePlay(source);
|
||||
}
|
||||
|
||||
@@ -384,5 +457,25 @@ namespace OpenRA
|
||||
Al.alSourcef(source, Al.AL_GAIN, volume = value);
|
||||
}
|
||||
}
|
||||
|
||||
public float SeekPosition
|
||||
{
|
||||
get
|
||||
{
|
||||
float pos;
|
||||
Al.alGetSourcef(source, Al.AL_SAMPLE_OFFSET, out pos);
|
||||
return pos/22050f;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Playing
|
||||
{
|
||||
get
|
||||
{
|
||||
int state;
|
||||
Al.alGetSourcei(source, Al.AL_SOURCE_STATE, out state);
|
||||
return state == Al.AL_PLAYING;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,11 +13,11 @@ using System.Text.RegularExpressions;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public class Settings
|
||||
public class Arguments
|
||||
{
|
||||
Dictionary<string, string> settings = new Dictionary<string, string>();
|
||||
Dictionary<string, string> args = new Dictionary<string, string>();
|
||||
|
||||
public Settings(IEnumerable<string> src)
|
||||
public Arguments(IEnumerable<string> src)
|
||||
{
|
||||
Regex regex = new Regex("([^=]+)=(.*)");
|
||||
foreach (string s in src)
|
||||
@@ -26,13 +26,13 @@ namespace OpenRA
|
||||
if (m == null || !m.Success)
|
||||
continue;
|
||||
|
||||
settings.Add(m.Groups[1].Value, m.Groups[2].Value);
|
||||
args.Add(m.Groups[1].Value, m.Groups[2].Value);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Contains(string key) { return settings.ContainsKey(key); }
|
||||
public bool Contains(string key) { return args.ContainsKey(key); }
|
||||
|
||||
public string GetValue(string key, string defaultValue) { return Contains(key) ? settings[key] : defaultValue; }
|
||||
public string GetValue(string key, string defaultValue) { return Contains(key) ? args[key] : defaultValue; }
|
||||
|
||||
public int GetValue(string key, int defaultValue)
|
||||
{
|
||||
@@ -36,17 +36,16 @@ namespace OpenRA
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
Log.AddChannel("exception", "openra.exception.txt", true, false);
|
||||
Log.AddChannel("exception", "exception.log");
|
||||
Log.Write("exception", "{0}", e.ToString());
|
||||
if (!Game.Settings.DeveloperMode || ( Game.Settings.DeveloperMode && Game.GetGameId() != 0) )
|
||||
Log.Upload(Game.GetGameId());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
static void Run( string[] args )
|
||||
{
|
||||
Game.Initialize( new Settings( args ) );
|
||||
Game.Initialize( new Arguments(args) );
|
||||
GC.Collect();
|
||||
Game.Run();
|
||||
}
|
||||
}
|
||||
|
||||
175
OpenRA.Game/TraitDictionary.cs
Executable file
175
OpenRA.Game/TraitDictionary.cs
Executable file
@@ -0,0 +1,175 @@
|
||||
#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.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
class TraitDictionary
|
||||
{
|
||||
Dictionary<Type, ITraitContainer> traits = new Dictionary<Type, ITraitContainer>();
|
||||
|
||||
ITraitContainer InnerGet( Type t )
|
||||
{
|
||||
return traits.GetOrAdd( t, CreateTraitContainer );
|
||||
}
|
||||
|
||||
static ITraitContainer CreateTraitContainer( Type t )
|
||||
{
|
||||
return (ITraitContainer)typeof( TraitContainer<> ).MakeGenericType( t )
|
||||
.GetConstructor( new Type[ 0 ] ).Invoke( new object[ 0 ] );
|
||||
}
|
||||
|
||||
public void AddTrait( Actor actor, object val )
|
||||
{
|
||||
var t = val.GetType();
|
||||
|
||||
foreach( var i in t.GetInterfaces() )
|
||||
InnerAdd( actor, i, val );
|
||||
foreach( var tt in t.BaseTypes() )
|
||||
InnerAdd( actor, tt, val );
|
||||
}
|
||||
|
||||
void InnerAdd( Actor actor, Type t, object val )
|
||||
{
|
||||
InnerGet( t ).Add( actor, val );
|
||||
}
|
||||
|
||||
public bool Contains<T>( Actor actor )
|
||||
{
|
||||
if( actor.Destroyed )
|
||||
throw new InvalidOperationException( "Attempted to get trait from destroyed object ({0})".F( actor.ToString() ) );
|
||||
return ( (TraitContainer<T>)InnerGet( typeof( T ) ) ).GetMultiple( actor.ActorID ).Count() != 0;
|
||||
}
|
||||
|
||||
public T Get<T>( Actor actor )
|
||||
{
|
||||
if( actor.Destroyed )
|
||||
throw new InvalidOperationException( "Attempted to get trait from destroyed object ({0})".F( actor.ToString() ) );
|
||||
return ( (TraitContainer<T>)InnerGet( typeof( T ) ) ).Get( actor.ActorID );
|
||||
}
|
||||
|
||||
public T GetOrDefault<T>( Actor actor )
|
||||
{
|
||||
if( actor.Destroyed )
|
||||
throw new InvalidOperationException( "Attempted to get trait from destroyed object ({0})".F( actor.ToString() ) );
|
||||
return ( (TraitContainer<T>)InnerGet( typeof( T ) ) ).GetOrDefault( actor.ActorID );
|
||||
}
|
||||
|
||||
public IEnumerable<T> WithInterface<T>( Actor actor )
|
||||
{
|
||||
if( actor.Destroyed )
|
||||
throw new InvalidOperationException( "Attempted to get trait from destroyed object ({0})".F( actor.ToString() ) );
|
||||
return ( (TraitContainer<T>)InnerGet( typeof( T ) ) ).GetMultiple( actor.ActorID );
|
||||
}
|
||||
|
||||
public IEnumerable<TraitPair<T>> ActorsWithTraitMultiple<T>( World world )
|
||||
{
|
||||
return ( (TraitContainer<T>)InnerGet( typeof( T ) ) ).All();//.Where( x => x.Actor.IsInWorld );
|
||||
}
|
||||
|
||||
public void RemoveActor( Actor a )
|
||||
{
|
||||
foreach( var t in traits )
|
||||
t.Value.RemoveActor( a.ActorID );
|
||||
}
|
||||
|
||||
interface ITraitContainer
|
||||
{
|
||||
void Add( Actor actor, object trait );
|
||||
void RemoveActor( uint actor );
|
||||
}
|
||||
|
||||
class TraitContainer<T> : ITraitContainer
|
||||
{
|
||||
List<Actor> actors = new List<Actor>();
|
||||
List<T> traits = new List<T>();
|
||||
|
||||
public void Add( Actor actor, object trait )
|
||||
{
|
||||
var insertIndex = actors.BinarySearchMany( actor.ActorID + 1 );
|
||||
actors.Insert( insertIndex, actor );
|
||||
traits.Insert( insertIndex, (T)trait );
|
||||
}
|
||||
|
||||
public T Get( uint actor )
|
||||
{
|
||||
var index = actors.BinarySearchMany( actor );
|
||||
if( index >= actors.Count || actors[ index ].ActorID != actor )
|
||||
throw new InvalidOperationException( string.Format( "TraitDictionary does not contain instance of type `{0}`", typeof( T ) ) );
|
||||
else if( index + 1 < actors.Count && actors[ index + 1 ].ActorID == actor )
|
||||
throw new InvalidOperationException( string.Format( "TraitDictionary contains multiple instance of type `{0}`", typeof( T ) ) );
|
||||
else
|
||||
return traits[ index ];
|
||||
}
|
||||
|
||||
public T GetOrDefault( uint actor )
|
||||
{
|
||||
var index = actors.BinarySearchMany( actor );
|
||||
if( index >= actors.Count || actors[ index ].ActorID != actor )
|
||||
return default( T );
|
||||
else if( index + 1 < actors.Count && actors[ index + 1 ].ActorID == actor )
|
||||
throw new InvalidOperationException( string.Format( "TraitDictionary contains multiple instance of type `{0}`", typeof( T ) ) );
|
||||
else return traits[ index ];
|
||||
}
|
||||
|
||||
public IEnumerable<T> GetMultiple( uint actor )
|
||||
{
|
||||
var index = actors.BinarySearchMany( actor );
|
||||
while( index < actors.Count && actors[ index ].ActorID == actor )
|
||||
{
|
||||
yield return traits[ index ];
|
||||
++index;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<TraitPair<T>> All()
|
||||
{
|
||||
for( int i = 0 ; i < actors.Count ; i++ )
|
||||
yield return new TraitPair<T> { Actor = actors[ i ], Trait = traits[ i ] };
|
||||
}
|
||||
|
||||
public void RemoveActor( uint actor )
|
||||
{
|
||||
for( int i = actors.Count - 1 ; i >= 0 ; i-- )
|
||||
{
|
||||
if( actors[ i ].ActorID == actor )
|
||||
{
|
||||
actors.RemoveAt( i );
|
||||
traits.RemoveAt( i );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class ListExts
|
||||
{
|
||||
public static int BinarySearchMany( this List<Actor> list, uint searchFor )
|
||||
{
|
||||
int start = 0;
|
||||
int end = list.Count;
|
||||
int mid = 0;
|
||||
while( start != end )
|
||||
{
|
||||
mid = ( start + end ) / 2;
|
||||
var c = list[ mid ].ActorID.CompareTo( searchFor );
|
||||
if( c < 0 )
|
||||
start = mid + 1;
|
||||
else
|
||||
end = mid;
|
||||
}
|
||||
return start;
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user