Compare commits

...

245 Commits

Author SHA1 Message Date
Chris Forbes
c0c4e7299b log changes to synced parameters in Mobile 2010-09-20 22:07:16 +12:00
Bob
afda1647fd moved more traits from engine into mods 2010-09-20 21:17:50 +12:00
Bob
aff6889995 moved traits from engine into mod 2010-09-20 20:58:42 +12:00
Bob
65515d54af fix crash where harv and linked proc get destroyed by the same bullet 2010-09-20 20:58:39 +12:00
Chris Forbes
c5b7c43d23 add pathspam in debug 2010-09-20 19:06:43 +12:00
Chris Forbes
dba5adc91c more debug 2010-09-20 18:33:48 +12:00
Chris Forbes
0073a03ca4 add debug for nudges 2010-09-20 18:27:31 +12:00
Chris Forbes
5509d0d2e9 suspecting drag instead 2010-09-20 17:55:16 +12:00
Chris Forbes
fe52e3722e more debug 2010-09-20 17:45:27 +12:00
Chris Forbes
3ddd1581f1 add debug for this desync 2010-09-20 17:28:06 +12:00
Iran
56efc3930b Pretty up HACKING and add some info 2010-09-19 23:10:33 +02:00
Iran
2f8d81a0f7 Fix OnFormClosing's MessageBox.Show under mono, unix newline and Environment.Newline didn't work, but Windows newline does work 2010-09-19 22:39:00 +02:00
Iran
46486073ab Display icon while running the Editor under mono, cant test it on windows 2010-09-19 19:31:10 +02:00
Chris Forbes
3dc11eaa05 fix crash in cnc when placing WEAP 2010-09-19 20:13:19 +12:00
Caleb Anderson
b62ee4d37c Fixed sequence crash 2010-09-19 19:13:15 +12:00
Paul Chote
532afc3ff8 Fix random logging 2010-09-19 19:03:18 +12:00
Paul Chote
9ddb2beced Apply the same to bibs and smudges 2010-09-19 18:57:42 +12:00
Matthew Bowra-Dean
1e758ec3e0 Removed website from main repository.
Moved to http://github.com/beedee/OpenRAWebsite/
2010-09-19 18:53:55 +12:00
Chris Forbes
aa1d44428d fix prev 2010-09-19 18:50:34 +12:00
Paul Chote
23da8a24bd Only render shroud/ore that is in the current viewport 2010-09-19 18:34:23 +12:00
Iran
fef291a27e don't switch production tab while selecting building not owned by you 2010-09-19 18:12:22 +12:00
Paul Chote
f49e56d660 3x faster syncreport 2010-09-19 17:13:44 +12:00
Paul Chote
927ab00f4d Use the correct number of players in the lobby team selector 2010-09-18 22:33:41 +12:00
Paul Chote
3f870e7e48 Remove yaml cruft; rename music repeat -> loop. 2010-09-18 22:19:57 +12:00
Paul Chote
f2a321186f Fix osx packaging 2010-09-18 21:53:22 +12:00
Paul Chote
410daecab6 sync SharedRandom 2010-09-18 21:53:10 +12:00
Paul Chote
966e3bb71a Remove debug spam 2010-09-18 20:47:24 +12:00
Paul Chote
652f06f604 Route the power check for support powers via the tech tree 2010-09-18 20:46:01 +12:00
Paul Chote
2a10af2007 Fix z-offset 2010-09-18 20:46:00 +12:00
Paul Chote
4cb26c0e3c Try again, with less fail. 2010-09-18 20:46:00 +12:00
Paul Chote
8455dadb3c Powerdown etc... untested 2010-09-18 20:46:00 +12:00
Paul Chote
3c19b3df73 Update power on damage 2010-09-18 20:46:00 +12:00
Paul Chote
c796e155e7 Fix UpdateTotals(); add debug info. 2010-09-18 20:46:00 +12:00
Paul Chote
ce9caec291 Begin splitting power into its own trait; incomplete and non-working. 2010-09-18 20:46:00 +12:00
Chris Forbes
0330ef2b9e blah 2010-09-18 19:57:45 +12:00
Chris Forbes
872a304714 all traits can contribute to the synchash 2010-09-18 18:34:57 +12:00
Chris Forbes
59cc50df4c hack synchash to sync the traitdict contents (just ITick impls for now) 2010-09-18 18:31:36 +12:00
Chris Forbes
a1fd84fb15 make actors collection sync order-dependent, since the actors themselves are. 2010-09-18 18:26:03 +12:00
Chris Forbes
317007f7ce temporarily disable crates (stability problem) 2010-09-18 17:23:47 +12:00
Matthew
387212d9ea Fixed RPM build script file listing 2010-09-18 16:07:10 +12:00
Matthew
c9ca5e207b Updated RPM build script to include menu, desktop and icon files. 2010-09-18 14:10:48 +12:00
Chris Forbes
ce78944a9e more editor hax 2010-09-18 13:30:12 +12:00
Chris Forbes
1fb336b7da unwtf the editor a bit 2010-09-18 13:26:45 +12:00
katzsmile
e4d05407d9 Added export minimap to PNG. Hided unfinished Tools and Bitmap import menus.
Added hack to render building roofs of they have same name but have "2" in name. (weap and weap2)

Signed-off-by: katzsmile <katzsmile@lead-games.com>
2010-09-18 12:56:08 +12:00
Chris Forbes
f7eca1157e fix walkability of sh30 template in RA temperate and snow 2010-09-18 11:56:22 +12:00
Chris Forbes
a64245fc10 fix it so it compiles with VS again 2010-09-18 11:52:51 +12:00
Paul Chote
ad8038867d PlayerProductionQueue -> ClassicProductionQueue. 2010-09-18 11:28:50 +12:00
Paul Chote
fb90400524 Rename TechTreeCache -> TechTree 2010-09-18 11:28:48 +12:00
Paul Chote
08b25d10c1 Remove dead TechTree code 2010-09-18 11:28:46 +12:00
Paul Chote
ba09bbba8e Remove TechLevel from special powers, and identify the performance problem. 2010-09-18 11:28:43 +12:00
Paul Chote
0d2e1d7de5 Hidden debug parameter for perf tick logging 2010-09-18 11:28:39 +12:00
Paul Chote
22861fca5a Sanitize ProductionQueue and fix bugs in TechTreeCache.
Gives perf win on every tick, and fixes bugs where you lose prereqs when buildings are low power.
2010-09-18 11:28:33 +12:00
Chris Forbes
692ef539f9 fix timings of infantry idle anims 2010-09-18 11:25:45 +12:00
Matthew
d07b0e4400 Linux desktop/menu entries. 2010-09-17 20:21:16 +12:00
Chris Forbes
9848d1f403 hack WEAP door z 2010-09-17 20:21:22 +12:00
Chris Forbes
83eae029b7 add explicit Z to Renderable. eating my hat, etc. 2010-09-17 20:21:21 +12:00
Paul Chote
99e225c279 Fix cnc fact footprint 2010-09-17 20:18:21 +12:00
Paul Chote
1785c4e4a8 Support for arbitrary building art offset relative to footprint 2010-09-17 20:18:14 +12:00
Chris Forbes
69753f8a08 ffs 2010-09-17 19:54:20 +12:00
Chris Forbes
5593b9ffdd start splitting up tsb; fix a wtf in the save code 2010-09-17 19:00:09 +12:00
Chris Forbes
1b66635670 fix A10 exploit 2010-09-17 19:00:08 +12:00
Chris Forbes
f1b1f3bd52 make hackyAI less of a tard 2010-09-17 19:00:08 +12:00
Chris Forbes
ff611dac32 hack BelowUnits z 2010-09-17 19:00:07 +12:00
Chris Forbes
e0a4cb4763 hack around some more z-glitches 2010-09-17 19:00:07 +12:00
Paul Chote
a3246866fb Better perf logging 2010-09-17 10:02:24 +12:00
Paul Chote
b94c2fc7c4 Fix d2k colour picker (fact doesn't exist yet) 2010-09-17 09:21:14 +12:00
Paul Chote
d530cf22da Include resources in the editor preview. 2010-09-17 09:09:36 +12:00
Chris Forbes
94e5b02a39 fix some editor weirdness (2/2) 2010-09-17 07:58:06 +12:00
Chris Forbes
40533a50c1 fix some editor weirdness (1/2) 2010-09-17 07:57:57 +12:00
Paul Chote
d4182b1929 Tweaks to minimap preview 2010-09-16 22:54:49 +12:00
Paul Chote
482129499d Fix editor makefile 2010-09-16 22:32:35 +12:00
katzsmile
366cd02761 Changed path text box to editable on save 2010-09-16 22:32:35 +12:00
katzsmile
f549e7e5a8 added map preview image on save and on load 2010-09-16 22:32:35 +12:00
katzsmile
4cab7c7fc4 added minimap preview 2010-09-16 22:32:35 +12:00
katzsmile
e3939d4805 Fixed most of bugs. Redone open/save dialog 2010-09-16 22:32:35 +12:00
katzsmile
2ae6983bc2 floater window changes 2010-09-16 22:32:34 +12:00
katzsmile
ad00193a17 Little fix for "indian" code
Signed-off-by: katzsmile <katzsmile@lead-games.com>
2010-09-16 22:32:34 +12:00
katzsmile
810667abbc changed border in open/save dialog 2010-09-16 22:32:34 +12:00
katzsmile
a66efd56f2 Title display in open/save dialogs
Signed-off-by: katzsmile <katzsmile@lead-games.com>
2010-09-16 22:32:34 +12:00
katzsmile
36ba15e7f9 Displaying map theater name in open/save dialogs 2010-09-16 22:32:34 +12:00
katzsmile
d809fb1e7b Updated Map Editor:
New Open/Save dialogs
Added icon for program
Hacked Actors Tab.
Started work on floater with tools

Signed-off-by: katzsmile <katzsmile@lead-games.com>
2010-09-16 22:32:34 +12:00
Chris Forbes
d0bc834a57 #151 fixed 2010-09-16 18:32:03 +12:00
Chris Forbes
483ca8cc4c #82 deliver to allied proc -- fixed 2010-09-16 18:22:45 +12:00
Chris Forbes
06aba5da46 fix remote engineer repair exploit 2010-09-16 18:19:06 +12:00
Chris Forbes
106fbcd5af remove some crashes 2010-09-16 18:18:16 +12:00
Chris Forbes
f456e41a45 check if a passenger is appropriate for reverse-enter-transport 2010-09-16 18:07:42 +12:00
Chris Forbes
7dc3aee4a2 #68 dog attacking ground fixed 2010-09-16 17:56:19 +12:00
Chris Forbes
c91bee8091 add option to ban attacking ground 2010-09-16 17:53:59 +12:00
Chris Forbes
82875e15f9 remove some bogosity; there will likely be regressions, but not a huge deal. 2010-09-16 17:50:52 +12:00
Chris Forbes
d6f8b7d850 fix z-order bug 2010-09-16 17:43:17 +12:00
Chris Forbes
72fe873b26 #105 fixed 2010-09-16 10:23:37 +12:00
Paul Chote
e9f34b1e21 Quick fix for #87, #88. Real fix will come when we nest activities. 2010-09-16 07:45:29 +12:00
Paul Chote
d15ab79370 Add new tileset source 2010-09-15 20:54:39 +12:00
Paul Chote
303613b052 Create valid maps for custom tilesets 2010-09-15 19:31:21 +12:00
Paul Chote
051c451867 Support custom tile size ingame 2010-09-15 19:31:21 +12:00
Paul Chote
ac8a3526a4 Custom tilesize support for editor 2010-09-15 19:31:21 +12:00
Paul Chote
be47fb55e8 Initial support for custom tile sizes 2010-09-15 19:31:21 +12:00
Paul Chote
5b8fc75d4a d2k shadows 2010-09-15 19:31:20 +12:00
Paul Chote
629e73ac29 support d2k remap range 2010-09-15 19:31:20 +12:00
Paul Chote
7e5b861caf Hacky beginnings of a standalone d2k mod 2010-09-15 19:31:20 +12:00
Chris Forbes
f3dcc14fca remove JEEP from soviet 2010-09-15 07:50:57 +12:00
Matthew
fee68d0231 Fixing permissions in deb scripts 2010-09-14 22:03:25 +12:00
Matthew Bowra-Dean
83f56d152f Updated web site for deb package 2010-09-14 21:30:55 +12:00
Matthew Bowra-Dean
a04ea789f5 Deb package building working and wired up. 2010-09-14 21:30:54 +12:00
Matthew Bowra-Dean
94becc3ddc More work on debian package 2010-09-14 21:30:53 +12:00
Matthew Bowra-Dean
8452e1bdf0 Beginning work on tying debian package together. 2010-09-14 21:30:52 +12:00
Matthew Bowra-Dean
5a513bc69d Fixing #129 and another issue with cnc packages in RPM script. 2010-09-14 21:30:52 +12:00
Paul Chote
5a173a2bd3 Fix #137 (selection cursor on non-selectable actors) 2010-09-13 17:48:05 +12:00
Chris Forbes
d29b068d59 #140 2010-09-13 07:44:11 +12:00
Chris Forbes
8dbbaca8da fix repair semantics for vehicles on FIX; fix #138 2010-09-13 07:36:53 +12:00
Paul Chote
10a1f7ec1e Fix #65; allow aircraft to receive move orders over buildings 2010-09-13 03:28:00 +12:00
Paul Chote
8286dba919 Improve semantics of selection cursor, plus free perf. 2010-09-12 19:25:05 +12:00
Paul Chote
bd735059d0 Don't leak info about resources under shroud 2010-09-12 18:51:29 +12:00
Paul Chote
147acbf096 Improve behaviour of move orders wrt shroud/fog 2010-09-12 18:48:46 +12:00
Paul Chote
91aa5302a8 Fix c4 force-firing. TODO: remove magic numbers 2010-09-12 18:20:25 +12:00
Paul Chote
2b6328f0ee Begin imposing sanity on order ordering 2010-09-12 18:10:34 +12:00
Paul Chote
1bc2136771 Nicer behaviour for edgescroll in windowed mode 2010-09-10 22:23:27 +12:00
Paul Chote
4ad0a52104 Give dog a selection voice 2010-09-10 22:10:51 +12:00
Paul Chote
b9450b0f63 Don't die when no songs are available. 2010-09-10 22:09:18 +12:00
Paul Chote
03bb74ea84 Remove unnecessary digit. 2010-09-10 21:58:07 +12:00
Paul Chote
8b4551c605 Next track / repeat on song completion. 2010-09-10 21:51:11 +12:00
Paul Chote
f645049054 shuffle music (Author: alzeih) 2010-09-10 20:59:03 +12:00
Paul Chote
aa832244fb cnc musics 2010-09-10 20:36:42 +12:00
Paul Chote
190311c68c Let the game determine song length. 2010-09-10 20:24:56 +12:00
Chris Forbes
b8ed9d7da5 (katzsmile) Added: Soviet Flak Truck with new SHP and Cameo 2010-09-10 19:46:53 +12:00
Paul Chote
ca32d51375 Enable music player 2010-09-10 19:45:22 +12:00
Matthew Bowra-Dean
b0e5bb3718 Infantry idle sequences for RA. 2010-09-10 18:52:11 +12:00
Paul Chote
96ebbfe75c fix gitignore so this isn't a problem in the future 2010-09-10 11:52:52 +12:00
Paul Chote
5c6a6ee350 Add snow.mix 2010-09-10 11:51:05 +12:00
Matthew
bbf2d68e9d Small fix to Windows installer. 2010-09-10 11:34:57 +12:00
Matthew
59cf76b4ae Retry dependency downloads in Windows installer. 2010-09-10 11:34:54 +12:00
Matthew
e97440819d Bring makefile and Windows installer in to line with pchote's mod folder structure changes. 2010-09-10 11:34:50 +12:00
Matthew
87cd37a30b Back up packages and remove mods dirs before installing. 2010-09-10 11:34:47 +12:00
Paul Chote
f406dfa277 scores.mix is optional 2010-09-10 11:27:58 +12:00
Paul Chote
24039f593c Copy the RA loadscreen for cnc 2010-09-09 23:43:29 +12:00
Paul Chote
cceb4401aa Disable unfinished default test map. 2010-09-09 23:36:30 +12:00
Paul Chote
f9445cb282 Pathfinder uses a MobileInfo instead of a specific actor 2010-09-09 23:25:58 +12:00
Paul Chote
706adb6d0b Remove cruft 2010-09-09 23:10:14 +12:00
Chris Forbes
dd7e578fe6 nearly finished laying out shellmap 2010-09-09 23:02:54 +12:00
Chris Forbes
83d1df19ba half a sensible cnc shellmap (no script yet) 2010-09-09 23:02:53 +12:00
Chris Forbes
975fa28f62 start of shellmap (dropped its actors :(); fix saving of actors from the editor 2010-09-09 23:02:52 +12:00
Paul Chote
452f7f7bff Add a local packaging script for osx 2010-09-09 20:51:10 +12:00
Paul Chote
626db661ab Remove syntax cruft and redundant comments from manifests 2010-09-09 20:48:02 +12:00
Paul Chote
9ea3a404a3 Tidy ra dir 2010-09-09 20:31:54 +12:00
Paul Chote
55c3e9d5bb Package the bits into a mix 2010-09-09 20:31:54 +12:00
Paul Chote
f616a527ee Reorganise cnc mod dir. Exposes a bug in folder/package priority. 2010-09-09 20:31:54 +12:00
Paul Chote
a594e9f830 Move the sequences files into their own dir. 2010-09-09 20:31:53 +12:00
Paul Chote
45d712d390 Fix defaultmod. 2010-09-09 20:31:53 +12:00
Paul Chote
dbbdc171d2 Use the new-format sequences. 2010-09-09 20:31:53 +12:00
Paul Chote
befe22e170 Convert sequences to yaml 2010-09-09 20:31:53 +12:00
Caleb Anderson
b284e82aa7 Added zoom to editor. Fixed crashes. Added sane tabbing to new map dialog. Added selection on tab - new map dialog 2010-09-09 20:29:42 +12:00
Matthew Bowra-Dean
ed5a3338fe Minor Windows installer fixes. 2010-09-09 20:29:40 +12:00
Bob
68dcec87c7 right-clicking a passenger with a transport loads cargo 2010-09-09 20:26:03 +12:00
Chris Forbes
39d7e54e7f fix one crash when server drops 2010-09-09 18:59:49 +12:00
Chris Forbes
404a4ad578 kill cargo when the transport dies 2010-09-09 18:52:12 +12:00
Chris Forbes
c9d0a7a301 tighten bounds on ra vehicles 2010-09-09 18:52:11 +12:00
Paul Chote
54ffdc51b4 Fix crashes with actors dying mid-projectile-flight 2010-09-09 17:20:05 +12:00
Bob
9e53774299 fix bug wrt tiberium infantry damage splashing; fix bug where Mobile+Production units didn't work right 2010-09-09 15:26:12 +12:00
Bob
f70a6aafb1 fix actor leak bug 2010-09-09 13:40:24 +12:00
Chris Forbes
c3fa9f7aa8 #120 fixed: crash in DeliverResources.Tick 2010-09-09 12:34:35 +12:00
Matthew Bowra-Dean
a73ef3affd Windows installer remembers previous install location. 2010-09-08 22:22:28 +12:00
Matthew Bowra-Dean
4e5d26a2d1 Windows installer launches browser to download .NET with user's consent. 2010-09-08 22:22:27 +12:00
Chris Forbes
4b1bc7acd4 fix bounding boxes on cnc vehicles 2010-09-08 22:19:33 +12:00
Chris Forbes
95d29c6910 fix toplevel exception handler in ralint; update cnc to use new armortypes 2010-09-08 22:11:19 +12:00
alzeih
c88ea2bd7c Fix #51 2010-09-08 21:30:32 +12:00
Paul Chote
af157867d8 merge the two INSTALL files 2010-09-08 12:24:09 +12:00
Paul Chote
9476e16df6 Update INSTALL.Ubuntu (fixes bugs 116, 117) 2010-09-08 12:19:55 +12:00
Paul Chote
9c148bf3f0 Remove unused mix files from cnc 2010-09-08 12:19:26 +12:00
Paul Chote
c8c96b9f6b Fix crash when losing fact with building ready to place 2010-09-08 03:22:05 +12:00
Paul Chote
108d7764ec Add nuke flash to cnc 2010-09-08 03:16:44 +12:00
Paul Chote
5396cad2b9 Beefier building explosions (replicates real-cnc) 2010-09-08 03:13:26 +12:00
Paul Chote
2bae3d9d2f Remove cruft from yaml; disable video player by default 2010-09-08 02:40:50 +12:00
Paul Chote
9cbaa9679d Revert to the old proc model - has 1500 local tib storage. Silos moved to defence queue. (fixes "can build on / drive through proc" bug). 2010-09-08 02:10:14 +12:00
Paul Chote
6228a962f6 Idle animations for the rest of the cnc infantry; fix a potential desync. 2010-09-08 01:55:50 +12:00
Paul Chote
1baff27553 Added snow theater for cnc mode by Jafet Kackur, aka 'Jk' and Nyerguds (katzsmile) 2010-09-08 00:49:37 +12:00
Paul Chote
4855b6bca6 Use the correct palette for sidebar icons (fixes icon glitch in cnc desert). 2010-09-08 00:34:04 +12:00
Paul Chote
ff0c66e38c Idle animations for infantry. Enabled for cnc e3. 2010-09-07 23:30:49 +12:00
alzeih
83d2ca07f1 update mirror lists 2010-09-07 21:26:15 +12:00
Chris Forbes
26152489f3 #66 fixed: attacking helipads 2010-09-07 20:57:26 +12:00
Caleb Anderson
4ca4d7b5dd GL error logging 2010-09-07 20:22:40 +12:00
Chris Forbes
0dddf12831 give gtwr and gun to both sides in cnc 2010-09-07 20:20:39 +12:00
Chris Forbes
25c098bad6 fix tesla accuracy 2010-09-07 20:17:08 +12:00
Chris Forbes
be9528dcb2 beef up hind; give it muzzle flashes 2010-09-07 20:08:45 +12:00
Chris Forbes
965385980f add muzzle flashes to yak 2010-09-07 20:01:43 +12:00
Chris Forbes
ca92cd03db slightly increase yak ammo 2010-09-07 19:23:58 +12:00
Chris Forbes
cdec95b73a fix dodgy targeting of FIX 2010-09-07 19:23:13 +12:00
Chris Forbes
76bf3077e9 give mig a sensible bounding box 2010-09-07 19:17:57 +12:00
Chris Forbes
53858a7789 give hind a sensible bounding box 2010-09-07 19:14:15 +12:00
Chris Forbes
b98e25c9a7 reduce pip counts on some units 2010-09-07 19:10:32 +12:00
Chris Forbes
be46f44bc9 polish multiple rows of pips (RA proc) 2010-09-07 19:09:18 +12:00
Chris Forbes
fee6d450e4 add ability to emit a muzzleflash from multiple weapons; make ftnk somewhat nicer 2010-09-07 19:05:14 +12:00
Chris Forbes
173dc59039 fix crash on engineer repair if the target building goes away 2010-09-07 17:37:18 +12:00
Chris Forbes
950dd4e85c fix #99 chronoshift-deploy didnt need to be charged 2010-09-07 17:33:11 +12:00
Paul Chote
6632feb696 Less perf, but avoids reinventing the wheel and searches a wider area 2010-09-07 15:58:04 +12:00
Paolo Chiodi
7b2622e67b if ordered to move to unreachable cell, find a new nearby target location 2010-09-07 15:32:28 +12:00
Chris Forbes
9e5528ef83 fix crash on shooting down aircraft which have an afld reserved. 2010-09-07 08:16:40 +12:00
Chris Forbes
3d920670e5 delay mig until afld+stek 2010-09-07 00:00:46 +12:00
Chris Forbes
4d2afd827f (for now) cut kenn, shift dog to barr 2010-09-07 00:00:45 +12:00
Matthew Bowra-Dean
9a4d0dfe5e Fix RPM package build. 2010-09-06 22:41:26 +12:00
Matthew Bowra-Dean
2a240e62aa VERSION file generation and distribution. 2010-09-06 22:20:11 +12:00
Chris Forbes
7a88adcf96 include the VERSION file in the package. 2010-09-06 21:57:14 +12:00
Paul Chote
b84d2f2c29 Allow a small amount of over-scroll so ui doesn't get in the way 2010-09-06 20:12:47 +12:00
Paolo Chiodi
2945838eef some more locking into map borders 2010-09-06 20:12:47 +12:00
Matthew Bowra-Dean
43aa8812b3 Windows installer checks for .NET v3.5 SP1 2010-09-06 20:09:27 +12:00
Matthew Bowra-Dean
9a2467dc21 .NET framework detection added to Windows install script. 2010-09-06 20:09:26 +12:00
Chris Forbes
5a75625eef don't thrash the GC quite so hard in SpatialBins 2010-09-06 18:46:47 +12:00
Chris Forbes
2f2890596d fix bug in HackyAI debug 2010-09-06 18:44:12 +12:00
Chris Forbes
01fa0b357e fix crash in prev on destroying a building (oops) 2010-09-06 18:16:32 +12:00
Chris Forbes
c5f0dad84e fix smudgelayer deepening; make biblayer work the same way (not optimal, but better) 2010-09-06 18:11:58 +12:00
Chris Forbes
7f7f4e81a5 add Give Exploration devmode option 2010-09-06 17:56:12 +12:00
Matthew Bowra-Dean
8b423908ca Added forum links. 2010-09-06 17:43:41 +12:00
Paul Chote
598fe9f956 gut perf logging - only record expensive ticks. perf.log is small enough to be useful now. 2010-09-06 15:29:34 +12:00
Paul Chote
06e8b530ea Use a dictionary for smudges 2010-09-06 14:40:22 +12:00
Matthew Bowra-Dean
d5c25f73bd Mods page. 2010-09-05 21:57:20 +12:00
Matthew
73fa306719 Bringing the docs up to date. 2010-09-05 21:52:47 +12:00
Chris Forbes
8d0cea6fe4 (RobotCaleb) fix shok death crash 2010-09-05 18:32:06 +12:00
Matthew
273b57ee69 Fixing screenshots on index page. 2010-09-05 17:36:32 +12:00
Matthew
c1578b92e1 Made mirroring script parameters more specific. 2010-09-05 16:42:30 +12:00
Matthew
c69a741c90 Expanded mirroring script to all dependencies, added new mirror (mirumu.jp) and updated download scripts. 2010-09-05 16:34:44 +12:00
Chris Forbes
f8d537c0c5 notes 2010-09-05 16:18:10 +12:00
Chris Forbes
e371159826 minor tidy-up in CrateAction 2010-09-05 16:07:35 +12:00
Chris Forbes
7d912715bc add ToString() for Pair, to make debug saner. 2010-09-05 15:20:01 +12:00
Matthew
d6449c2902 Stupid arguments ordering. 2010-09-05 00:27:28 +12:00
Matthew Bowra-Dean
8a3868abd0 Updated web pages and fixed OS X download script. 2010-09-05 00:10:07 +12:00
Matthew
112047d2b3 Changed downloading scripts to point to mirror script. Added open-ra.org to mirror list. 2010-09-04 22:42:55 +12:00
Matthew
cd9f584729 Mod package mirroring scripts. 2010-09-04 22:26:11 +12:00
Matthew
31741a1ab3 Fix rebuilding of project in packaging. 2010-09-04 20:57:34 +12:00
Matthew
eb6440694a Packaging script updated to use sub-packaging scripts in freshly checkedout copy of repo. 2010-09-04 20:57:34 +12:00
Paolo Chiodi
2c388308c7 avoid calling Viewport.Scroll on every ScreenShaker.Tick 2010-09-04 10:45:09 +02:00
Paolo Chiodi
1c8f744719 allow camera shaking to exit map borders 2010-09-04 10:45:09 +02:00
Paul Chote
dfdc893d63 Fix incorrect sequence + cnc support 2010-09-04 11:46:15 +12:00
Paolo Chiodi
669aaab6b4 change mouse sequence to blocked whene map borders are reached 2010-09-04 11:46:14 +12:00
Paolo Chiodi
73017d3f5c lock viewport scrolling into map size 2010-09-04 11:46:14 +12:00
Paolo Chiodi
38fa809656 added .DS_Store to gitignore 2010-09-04 11:46:13 +12:00
Paul Chote
0ed21a4acb Fix ra defenses 2010-09-03 21:47:25 +12:00
Paul Chote
9ae7d98193 Fix ra spawns 2010-09-03 21:47:25 +12:00
Paul Chote
07e60286f2 whoops 2010-09-03 21:47:25 +12:00
Paul Chote
7f918b8a69 fix FIX footprint 2010-09-03 21:47:24 +12:00
Paul Chote
4e0ace6ec5 Tidy production exits, cnc only 2010-09-03 21:47:24 +12:00
Paul Chote
dca5f8d27b Tidy up Mobile yaml / loading 2010-09-03 21:47:24 +12:00
alzeih
6478276064 make cnc nuke leave full area of smudge 2010-09-03 21:47:24 +12:00
alzeih
7d603f97fe cnc bib and footprint fixes (some of #83) 2010-09-03 21:47:24 +12:00
Paul Chote
112fdb32af Another dead actor crashfix 2010-09-03 17:20:30 +12:00
Paul Chote
5a78df0318 Fix flashtarget crash 2010-09-03 16:37:02 +12:00
Paul Chote
6ac4266847 Allow people to join mp games 2010-09-03 16:13:03 +12:00
385 changed files with 18471 additions and 8706 deletions

5
.gitignore vendored
View File

@@ -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
@@ -44,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

75
HACKING
View File

@@ -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
View File

@@ -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 games 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 shouldnt
be too hard to find a legal copy of the CD images. Unfortunately the
installer is 16-bit and so wont 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 wont 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

View File

@@ -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 games 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 shouldnt
be too hard to find a legal copy of the CD images. Unfortunately the
installer is 16-bit and so wont 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-*

View File

@@ -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,18 +103,27 @@ 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 --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
@@ -123,8 +132,8 @@ install: all
@$(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."
@@ -141,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:

View File

@@ -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;
}
}

View File

@@ -11,12 +11,11 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using OpenRA.FileFormats;
using OpenRA.GameRules;
using OpenRA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Editor
@@ -32,18 +31,17 @@ namespace OpenRA.Editor
Text = "OpenRA Editor (mod:{0})".F(currentMod);
Game.modData = new ModData( currentMod );
Game.modData = new ModData(currentMod);
Rules.LoadRules(Game.modData.Manifest, new Map());
folderBrowser.SelectedPath = new string[] { Environment.CurrentDirectory, "mods", currentMod, "maps" }
.Aggregate(Path.Combine);
surface1.AfterChange += MakeDirty;
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;
@@ -57,7 +55,7 @@ namespace OpenRA.Editor
loadedMapName = mapname;
Game.modData = new ModData( currentMod );
Game.modData = new ModData(currentMod);
// load the map
var map = new Map(new Folder(mapname));
@@ -81,31 +79,31 @@ namespace OpenRA.Editor
loadedMapName = null;
Game.modData = new ModData( currentMod );
Game.modData = new ModData(currentMod);
PrepareMapResources(Game.modData.Manifest, map);
MakeDirty();
}
// this code is insanely stupid, and mostly my fault -- chrisf
void PrepareMapResources(Manifest manifest, Map map)
{
Rules.LoadRules(manifest, map);
Rules.LoadRules(manifest, map);
tileset = Rules.TileSets[map.Theater];
tileset.LoadTiles();
var palette = new Palette(FileSystem.Open(tileset.Palette), true);
surface1.Bind(map, tileset, palette);
surface1.Bind(map, tileset, palette);
// construct the palette of tiles
var palettes = new[] { tilePalette, actorPalette, resourcePalette };
foreach (var p in palettes) { p.Visible = false; p.SuspendLayout(); }
foreach (var t in tileset.Templates)
{
try
{
var bitmap = RenderTemplate(tileset, (ushort)t.Key, palette);
var bitmap = RenderUtils.RenderTemplate(tileset, (ushort)t.Key, palette);
var ibox = new PictureBox
{
Image = bitmap,
@@ -119,7 +117,6 @@ namespace OpenRA.Editor
var template = t.Value;
tilePalette.Controls.Add(ibox);
tt.SetToolTip(ibox,
"{1}:{0} ({2}x{3})".F(
template.Image,
@@ -137,16 +134,18 @@ 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);
@@ -168,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);
@@ -193,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)
@@ -318,7 +229,7 @@ namespace OpenRA.Editor
surface1.Invalidate();
}
}
void SaveClicked(object sender, EventArgs e)
{
if (loadedMapName == null)
@@ -328,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)
@@ -362,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);
}
@@ -416,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 */
@@ -432,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;
@@ -440,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 { }
}
}
}
}

View File

@@ -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>

360
OpenRA.Editor/MapSelect.Designer.cs generated Normal file
View 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;
}
}

View 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;
}
}
}

View 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
View 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
View 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);
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -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
View 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;
}
}

View 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();
}
}
}

View 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>

View 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
View 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)
{

View File

@@ -144,6 +144,18 @@ 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;

View File

@@ -102,6 +102,20 @@ namespace OpenRA.FileFormats
return output;
}
public static float SoundLength(Stream s)
{
var br = new BinaryReader(s);
var sampleRate = br.ReadUInt16();
/*var dataSize = */ br.ReadInt32();
var outputSize = br.ReadInt32();
var flags = (SoundFlags) br.ReadByte();
var samples = outputSize;
if (0 != (flags & SoundFlags.Stereo)) samples /= 2;
if (0 != (flags & SoundFlags._16Bit)) samples /= 2;
return samples / sampleRate;
}
public static byte[] LoadSound(Stream s)
{
var br = new BinaryReader(s);

View File

@@ -19,21 +19,24 @@ namespace OpenRA.FileFormats
{
public readonly string[]
Folders, Packages, Rules,
Sequences, Chrome, Assemblies, ChromeLayout,
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");
@@ -45,6 +48,9 @@ namespace OpenRA.FileFormats
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)

View File

@@ -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);

View File

@@ -74,11 +74,12 @@ namespace OpenRA.FileFormats
public string Name;
public string Id;
public string Palette;
public int TileSize = 24;
public string[] Extensions;
public Dictionary<string, TerrainTypeInfo> Terrain = new Dictionary<string, TerrainTypeInfo>();
public Dictionary<ushort, Terrain> Tiles = new Dictionary<ushort, Terrain>();
public Dictionary<ushort, TileTemplate> Templates = new Dictionary<ushort, TileTemplate>();
static List<string> fields = new List<string>() {"Name", "Id", "Palette", "Extensions"};
static List<string> fields = new List<string>() {"Name", "TileSize", "Id", "Palette", "Extensions"};
public TileSet() {}
public TileSet( string filepath )
@@ -103,20 +104,13 @@ namespace OpenRA.FileFormats
using( Stream s = FileSystem.OpenWithExts(t.Value.Image, Extensions) )
{
if( !Tiles.ContainsKey( t.Key ) )
Tiles.Add( t.Key, new Terrain( s ) );
Tiles.Add( t.Key, new Terrain( s, TileSize ) );
}
}
public void Save(string filepath)
{
var root = new List<MiniYamlNode>();
foreach (var field in fields)
{
FieldInfo f = this.GetType().GetField(field);
if (f.GetValue(this) == null) continue;
root.Add( new MiniYamlNode( field, FieldSaver.FormatValue( this, f ) ) );
}
var gen = new List<MiniYamlNode>();
foreach (var field in fields)
{
@@ -144,7 +138,7 @@ namespace OpenRA.FileFormats
if( Tiles.TryGetValue( r.type, out tile ) )
return tile.TileBitmapBytes[ r.image ];
byte[] missingTile = new byte[ 24 * 24 ];
byte[] missingTile = new byte[ TileSize * TileSize ];
for( int i = 0 ; i < missingTile.Length ; i++ )
missingTile[ i ] = 0x36;

View File

@@ -57,6 +57,7 @@ namespace OpenRA.FileFormats
colors[0] = 0;
if (remapTransparent)
{
colors[1] = 178u << 24; // Hack for d2k; may have side effects
colors[3] = 178u << 24;
colors[4] = 140u << 24;
}

View File

@@ -15,15 +15,16 @@ using System.Linq;
namespace OpenRA.FileFormats
{
// TODO: ship this out of here.
public enum PaletteFormat { ra, cnc, d2k }
public class PlayerColorRemap : IPaletteRemap
{
Dictionary<int, Color> remapColors;
public PlayerColorRemap(Color c1, Color c2, bool useSplitRamp)
public PlayerColorRemap(Color c1, Color c2, PaletteFormat fmt)
{
var baseIndex = useSplitRamp ? 0xb0 : 80;
var ramp = useSplitRamp
var baseIndex = (fmt == PaletteFormat.cnc) ? 0xb0 : (fmt == PaletteFormat.d2k) ? 240 : 80;
var ramp = (fmt == PaletteFormat.cnc)
? new[] { 0, 2, 4, 6, 8, 10, 13, 15, 1, 3, 5, 7, 9, 11, 12, 14 }
: new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };

View File

@@ -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

View File

@@ -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); }

View File

@@ -6,15 +6,15 @@
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.GameRules;
using OpenRA.Traits;
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Support;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA
@@ -74,8 +74,13 @@ namespace OpenRA
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)
@@ -105,7 +110,7 @@ namespace OpenRA
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;
@@ -115,13 +120,9 @@ namespace OpenRA
if (Destroyed)
return null;
var underCursor = World.FindUnitsAtMouse(mi.Location)
.Where(a => a.Info.Traits.Contains<TargetableInfo>())
.OrderByDescending(a => a.Info.Traits.Contains<SelectableInfo>() ? a.Info.Traits.Get<SelectableInfo>().Priority : int.MinValue)
.FirstOrDefault();
return TraitsImplementing<IIssueOrder>()
return TraitsImplementing<IIssueOrder>()
.OrderByDescending( x => x.OrderPriority( this, xy, mi, underCursor ) )
.Select( x => x.IssueOrder( this, xy, mi, underCursor ) )
.FirstOrDefault( x => x != null );
}

View File

@@ -8,8 +8,8 @@
*/
#endregion
using System.Collections.Generic;
using System.Collections;
using System.Collections.Generic;
using System.IO;
namespace OpenRA.FileFormats
@@ -45,7 +45,7 @@ namespace OpenRA.FileFormats
foreach( var init in InitDict )
{
var initName = init.GetType().Name;
ret.NodesDict.Add( initName.Substring( 0, initName.Length - 4 ), FieldSaver.Save( init ) );
ret.Nodes.Add( new MiniYamlNode( initName.Substring( 0, initName.Length - 4 ), FieldSaver.Save( init ) ) );
}
return ret;
}

View File

@@ -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)

View File

@@ -34,6 +34,9 @@ namespace OpenRA.Effects
public IEnumerable<Renderable> Render()
{
if (!target.IsInWorld)
yield break;
if (remainingTicks % 2 == 0)
foreach (var r in target.Render())
yield return r.WithPalette("highlight");

View File

@@ -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);
}
}
}

View File

@@ -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);
} );
}
}

View File

@@ -18,18 +18,16 @@ 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;
@@ -42,6 +40,7 @@ namespace OpenRA
public static Renderer Renderer;
public static Session LobbyInfo = new Session();
public static bool HasInputFocus = false;
static void LoadMap(string uid)
{
@@ -49,9 +48,7 @@ namespace OpenRA
viewport = new Viewport(new float2(Renderer.Resolution), map.TopLeft, map.BottomRight, Renderer);
world = null; // trying to access the old world will NRE, rather than silently doing it wrong.
Timer.Time("viewport: {0}");
world = new World(modData.Manifest, map);
Timer.Time("world: {0}");
}
public static void MoveViewport(int2 loc)
@@ -120,7 +117,7 @@ namespace OpenRA
{
lastTime += Settings.Game.Timestep;
Widget.DoTick(world);
Sound.Tick();
orderManager.TickImmediate(world);
var isNetTick = LocalTick % NetTickScale == 0;
@@ -295,9 +292,9 @@ namespace OpenRA
public static void Exit() { quit = true; }
public static Action<Color,string,string> AddChatLine = (c,n,s) => {};
public static void Debug(string s, params object[] args)
{
{
AddChatLine(Color.White, "Debug", String.Format(s,args));
}

View File

@@ -14,15 +14,21 @@ namespace OpenRA.GameRules
{
public class MusicInfo
{
[FieldLoader.Load] public readonly string Filename = null;
[FieldLoader.Load] public readonly string Title = null;
[FieldLoader.Load] public readonly int Length = 0; // seconds
public readonly string Filename = null;
public readonly string Title = null;
public readonly int Length = 0; // seconds
public readonly bool Exists = false;
public MusicInfo( string key, MiniYaml value )
{
FieldLoader.Load(this, value);
if (Filename == null)
Filename = key+".aud";
Filename = key+".aud";
Title = value.Value;
if (!FileSystem.Exists(Filename))
return;
Exists = true;
Length = (int)AudLoader.SoundLength(FileSystem.Open(Filename));
}
}
}

View File

@@ -18,8 +18,6 @@ namespace OpenRA
{
public static class Rules
{
public static TechTree TechTree;
public static Dictionary<string, ActorInfo> Info;
public static Dictionary<string, WeaponInfo> Weapons;
public static Dictionary<string, VoiceInfo> Voices;
@@ -41,8 +39,6 @@ namespace OpenRA
var t = new TileSet(file);
TileSets.Add(t.Id,t);
}
TechTree = new TechTree();
}
static Dictionary<string, T> LoadYamlRules<T>(string[] files, List<MiniYamlNode> dict, Func<MiniYamlNode, Dictionary<string, MiniYaml>, T> f)

View File

@@ -33,6 +33,7 @@ namespace OpenRA.GameRules
public bool PerfGraph = false;
public bool RecordSyncReports = true;
public bool ShowCollisions = false;
public float LongTickThreshold = 0.001f;
}
public class GraphicSettings
@@ -48,6 +49,8 @@ namespace OpenRA.GameRules
public float SoundVolume = 0.5f;
public float MusicVolume = 0.5f;
public float VideoVolume = 0.5f;
public bool Shuffle = false;
public bool Repeat = false;
}
public class PlayerSettings

View File

@@ -1,100 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
using System.Collections.Generic;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Traits;
namespace OpenRA.GameRules
{
public class TechTree
{
readonly Cache<string, List<ActorInfo>> producesIndex = new Cache<string, List<ActorInfo>>(x => new List<ActorInfo>());
public TechTree()
{
foreach( var info in Rules.Info.Values )
{
var pi = info.Traits.GetOrDefault<ProductionInfo>();
if (pi != null)
foreach( var p in pi.Produces )
producesIndex[ p ].Add( info );
}
}
public Cache<string, List<Actor>> GatherBuildings( Player player )
{
var ret = new Cache<string, List<Actor>>( x => new List<Actor>() );
if (player == null)
return ret;
foreach( var b in player.World.Queries.OwnedBy[player].Where( x=>x.Info.Traits.Contains<BuildingInfo>() ) )
{
ret[ b.Info.Name ].Add( b );
var tt = b.Info.Traits.GetOrDefault<TooltipInfo>();
if( tt != null )
foreach( var alt in tt.AlternateName )
ret[ alt ].Add( b );
}
return ret;
}
public bool CanBuild( ActorInfo info, Player player, Cache<string, List<Actor>> playerBuildings )
{
if (player == null)
return false;
var bi = info.Traits.GetOrDefault<BuildableInfo>();
if( bi == null ) return false;
if( !bi.Owner.Contains( player.Country.Race ) )
return false;
foreach( var p in bi.Prerequisites )
if( playerBuildings[ p ].Count == 0 )
return false;
if( producesIndex[ bi.Queue ].All( x => playerBuildings[ x.Name ].Count == 0 ) )
return false;
return true;
}
public IEnumerable<string> BuildableItems( Player player, params string[] categories )
{
if (player == null)
yield break;
var playerBuildings = GatherBuildings( player );
foreach (var unit in AllBuildables(categories))
if( CanBuild( unit, player, playerBuildings ) )
yield return unit.Name;
}
public IEnumerable<ActorInfo> AllBuildables(params string[] categories)
{
return Rules.Info.Values
.Where( x => x.Name[ 0 ] != '^' )
.Where( x => x.Traits.Contains<BuildableInfo>() )
.Where( x => categories.Contains(x.Traits.Get<BuildableInfo>().Queue) );
}
public IEnumerable<ActorInfo> UnitBuiltAt( ActorInfo info )
{
var bi = info.Traits.Get<BuildableInfo>();
var builtAt = bi.BuiltAt;
if( builtAt.Length != 0 )
return builtAt.Select( x => Rules.Info[ x.ToLowerInvariant() ] );
else
return producesIndex[ bi.Queue ];
}
}
}

View File

@@ -12,47 +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
{

View 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));
}
}
}
}

View File

@@ -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();
}
}

View File

@@ -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 );

View File

@@ -20,53 +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)
{
XmlDocument document = new XmlDocument();
document.Load(FileSystem.Open(filename));
foreach (XmlElement eUnit in document.SelectNodes("/sequences/unit"))
LoadSequencesForUnit(eUnit);
foreach (XmlElement eCursor in document.SelectNodes("/sequences/cursor"))
LoadSequencesForCursor(eCursor);
}
static void LoadSequencesForCursor(XmlElement eCursor)
static void LoadSequencesForUnit(string unit, MiniYaml sequences)
{
Game.modData.LoadScreen.Display();
string cursorSrc = eCursor.GetAttribute("src");
string palette = eCursor.GetAttribute("palette");
foreach (XmlElement eSequence in eCursor.SelectNodes("./sequence"))
cursors.Add(eSequence.GetAttribute("name"), new CursorSequence(cursorSrc, palette, eSequence));
}
static void LoadSequencesForUnit(XmlElement eUnit)
{
Game.modData.LoadScreen.Display();
string unitName = eUnit.GetAttribute("name");
try {
var sequences = eUnit.SelectNodes("./sequence").OfType<XmlElement>()
.Select(e => new Sequence(unitName, e))
.ToDictionary(s => s.Name);
units.Add(unitName, sequences);
var seq = sequences.NodesDict.ToDictionary(x => x.Key, x => new Sequence(unit,x.Key,x.Value));
units.Add(unit, seq);
} catch (FileNotFoundException) {} // Do nothing; we can crash later if we actually wanted art
}
public static MiniYaml SaveSequencesForUnit(string unitname)
{
var ret = new List<MiniYamlNode>();
foreach (var s in units[unitname])
ret.Add(new MiniYamlNode(s.Key, s.Value.Save()));
return new MiniYaml(null, ret);
}
public static Sequence GetSequence(string unitName, string sequenceName)
{
try { return units[unitName][sequenceName]; }
@@ -81,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));
}
}
}
}

View File

@@ -31,7 +31,6 @@ namespace OpenRA.Graphics
this.map = world.Map;
Size tileSize = new Size( Game.CellSize, Game.CellSize );
var tileMapping = new Cache<TileReference<ushort,byte>, Sprite>(
x => Game.modData.SheetBuilder.Add(world.TileSet.GetBytes(x), tileSize));
@@ -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)

View File

@@ -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,39 +37,81 @@ 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" );
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()
@@ -93,7 +137,7 @@ namespace OpenRA.Graphics
public void Center(int2 loc)
{
scrollPosition = (Game.CellSize*loc - .5f * new float2(Width, Height));
scrollPosition = this.NormalizeScrollPosition(Game.CellSize*loc - .5f * new float2(Width, Height));
}
public void Center(IEnumerable<Actor> actors)
@@ -104,7 +148,7 @@ namespace OpenRA.Graphics
.Select(a => a.CenterLocation)
.Aggregate((a, b) => a + b);
scrollPosition = (avgPos - .5f * new float2(Width, Height));
scrollPosition = this.NormalizeScrollPosition((avgPos - .5f * new float2(Width, Height)));
}
public Rectangle? ShroudBounds()
@@ -114,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);
}
}
}
}

View File

@@ -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)
@@ -41,11 +41,7 @@ namespace OpenRA.Graphics
{
public int Compare(Renderable x, Renderable y)
{
var result = x.ZOffset.CompareTo(y.ZOffset);
if (result == 0)
result = x.Pos.Y.CompareTo(y.Pos.Y);
return result;
return (x.Z + x.ZOffset).CompareTo(y.Z + y.ZOffset);
}
}
@@ -142,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);
}
}

View File

@@ -62,14 +62,22 @@ namespace OpenRA
public Rectangle Bounds { get { return Rectangle.FromLTRB(TopLeft.X, TopLeft.Y, BottomRight.X, BottomRight.Y); } }
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);

View File

@@ -59,21 +59,16 @@ namespace OpenRA
if (!AvailableMaps.ContainsKey(uid))
throw new InvalidDataException("Invalid map uid: {0}".F(uid));
Timer.Time("----PrepareMap");
var map = new Map(AvailableMaps[uid].Package);
Timer.Time( "Map: {0}" );
Rules.LoadRules(Manifest, map);
Timer.Time( "Rules: {0}" );
if (map.Theater != cachedTheatre)
{
SpriteSheetBuilder.Initialize( Rules.TileSets[map.Tileset] );
SequenceProvider.Initialize(Manifest.Sequences);
Timer.Time("SSB, SeqProv: {0}");
CursorProvider.Initialize(Manifest.Cursors);
cachedTheatre = map.Theater;
}
Timer.Time("----end PrepareMap");
return map;
}
}

View File

@@ -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;

View File

@@ -3,61 +3,87 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenRA.FileFormats;
using OpenRA.Support;
namespace OpenRA.Network
{
class SyncReport
{
Queue<Pair<int, string>> syncReports = new Queue<Pair<int, string>>();
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;
while (syncReports.Count >= numSyncReports) syncReports.Dequeue();
syncReports.Enqueue(Pair.New(Game.orderManager.FrameNumber, GenerateSyncReport()));
GenerateSyncReport(syncReports[curIndex]);
curIndex = ++curIndex % numSyncReports;
}
string GenerateSyncReport()
void GenerateSyncReport(Report report)
{
var sb = new StringBuilder();
sb.AppendLine("Actors:");
foreach (var a in Game.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:");
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)
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));
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
});
}
return sb.ToString();
}
internal 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);
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;
}
}
}

View File

@@ -1,10 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenRA.FileFormats;
using System.Reflection;
using System.IO;
using System.Linq;
using System.Reflection;
using OpenRA.FileFormats;
namespace OpenRA
{

View File

@@ -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,7 +97,6 @@
<Compile Include="Effects\MoveFlash.cs" />
<Compile Include="Exts.cs" />
<Compile Include="GameRules\ActorInfo.cs" />
<Compile Include="GameRules\TechTree.cs" />
<Compile Include="GameRules\VoiceInfo.cs" />
<Compile Include="Effects\IEffect.cs" />
<Compile Include="Graphics\ChromeProvider.cs" />
@@ -137,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" />
@@ -157,23 +153,15 @@
<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" />
@@ -193,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" />
@@ -202,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" />
@@ -217,14 +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="Traits\MPStartLocations.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">
@@ -239,7 +226,9 @@
<Compile Include="ObjectCreator.cs" />
<Compile Include="Network\SyncReport.cs" />
<Compile Include="TraitDictionary.cs" />
<Compile Include="Traits\PrimaryBuilding.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>
@@ -270,4 +259,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>

View File

@@ -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();
@@ -56,16 +61,23 @@ namespace OpenRA.Orders
}
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.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";
}
}
}

View File

@@ -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.Trait<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();

View File

@@ -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.Trait<Mobile>();
this.mobileInfo = mobileInfo;
queue = new PriorityQueue<PathDistance>();
}
@@ -69,7 +72,7 @@ namespace OpenRA
public PathSearch FromPoint(int2 from)
{
AddInitialCell( self.World, from );
AddInitialCell( world, from );
return this;
}
@@ -86,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;
@@ -99,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))
@@ -160,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;
}

View File

@@ -46,8 +46,6 @@ namespace OpenRA
{
World = world;
Shroud = new ShroudRenderer(this, world.Map);
PlayerActor = world.CreateActor("Player", new TypeDictionary{ new OwnerInit( this ) });
Index = index;
Palette = "player"+index;
@@ -63,15 +61,14 @@ namespace OpenRA
PlayerRef = pr;
RegisterPlayerColor(world, Palette);
RegisterPlayerColor(world, Palette);
PlayerActor = world.CreateActor("Player", new TypeDictionary{ new OwnerInit( this ) });
}
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 = index;
Palette = "player"+index;
@@ -86,14 +83,15 @@ namespace OpenRA
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);
}

View File

@@ -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;

View File

@@ -102,9 +102,27 @@ namespace OpenRA
soundEngine.StopSound(video);
}
public static void Tick()
{
// Song finished
if (MusicPlaying && !music.Playing)
{
StopMusic();
OnMusicComplete();
}
}
static Action OnMusicComplete;
public static bool MusicPlaying { get; private set; }
public static void PlayMusic(string name)
{
PlayMusicThen(name, () => {});
}
public static void PlayMusicThen(string name, Action then)
{
OnMusicComplete = then;
if (name == "" || name == null)
return;
@@ -114,11 +132,11 @@ namespace OpenRA
return;
}
StopMusic();
currentMusic = name;
MusicPlaying = true;
var sound = sounds[name];
music = soundEngine.Play2D(sound, true, true, float2.Zero, MusicVolume);
music = soundEngine.Play2D(sound, false, true, float2.Zero, MusicVolume);
}
public static void PlayMusic()
@@ -236,6 +254,7 @@ namespace OpenRA
{
float Volume { get; set; }
float SeekPosition { get; }
bool Playing { get; }
}
class OpenAlSoundEngine : ISoundEngine
@@ -448,5 +467,15 @@ namespace OpenRA
return pos/22050f;
}
}
public bool Playing
{
get
{
int state;
Al.alGetSourcei(source, Al.AL_SOURCE_STATE, out state);
return state == Al.AL_PLAYING;
}
}
}
}

View File

@@ -30,7 +30,8 @@ namespace OpenRA.Traits.Activities
int ticks = 0;
public IActivity Tick( Actor self )
{
self.CenterLocation = float2.Lerp(startLocation, endLocation, (float)ticks/(length-1));
self.CenterLocation = float2.Lerp(startLocation, endLocation, (float)ticks/(length-1));
Log.Write("debug", "drag #{0} {1} {2}", self.ActorID, ticks, self.CenterLocation);
if (++ticks >= length)
return NextActivity;

View File

@@ -45,7 +45,7 @@ namespace OpenRA.Traits.Activities
{
this.getPath = (self,mobile) =>
self.World.PathFinder.FindPath(
PathSearch.FromPoint( self, mobile.toCell, destination, false )
PathSearch.FromPoint( self.World, mobile.Info, mobile.toCell, destination, false )
.WithoutLaneBias());
this.destination = destination;
this.nearEnough = 0;
@@ -55,8 +55,7 @@ namespace OpenRA.Traits.Activities
public Move( int2 destination, int nearEnough )
: this()
{
this.getPath = (self,mobile) => self.World.PathFinder.FindUnitPath(
mobile.toCell, destination, self );
this.getPath = (self,mobile) => self.World.PathFinder.FindUnitPath( mobile.toCell, destination, self );
this.destination = destination;
this.nearEnough = nearEnough;
}
@@ -66,7 +65,7 @@ namespace OpenRA.Traits.Activities
{
this.getPath = (self,mobile) =>
self.World.PathFinder.FindPath(
PathSearch.FromPoint( self, mobile.toCell, destination, false )
PathSearch.FromPoint( self.World, mobile.Info, mobile.toCell, destination, false )
.WithCustomBlocker( self.World.PathFinder.AvoidUnitsNear( mobile.toCell, 4, self ))
.WithIgnoredBuilding( ignoreBuilding ));
@@ -103,6 +102,16 @@ namespace OpenRA.Traits.Activities
this.nearEnough = 0;
}
List<int2> EvalPath( Actor self, Mobile mobile )
{
var path = getPath(self, mobile).TakeWhile(a => a != mobile.toCell).ToList();
Log.Write("debug", "EvalPath #{0} {1}",
self.ActorID, string.Join(" ", path.Select(a => a.ToString()).ToArray()));
return path;
}
public IActivity Tick( Actor self )
{
var mobile = self.Trait<Mobile>();
@@ -124,7 +133,7 @@ namespace OpenRA.Traits.Activities
return this;
}
path = getPath( self, mobile ).TakeWhile( a => a != mobile.toCell ).ToList();
path = EvalPath(self, mobile);
SanityCheckPath( mobile );
}
@@ -145,6 +154,8 @@ namespace OpenRA.Traits.Activities
if( firstFacing != mobile.Facing )
{
path.Add( nextCell.Value );
Log.Write("debug", "Turn: #{0} from {1} to {2}",
self.ActorID, mobile.Facing, firstFacing);
return new Turn( firstFacing ) { NextActivity = this };
}
@@ -183,6 +194,9 @@ namespace OpenRA.Traits.Activities
var blocker = self.World.WorldActor.Trait<UnitInfluence>().GetUnitsAt(nextCell).FirstOrDefault();
if (blocker == null) return;
Log.Write("debug", "NudgeBlocker #{0} nudges #{1} at {2} from {3}",
self.ActorID, blocker.ActorID, nextCell, self.Location);
var nudge = blocker.TraitOrDefault<INudge>();
if (nudge != null)
nudge.OnNudge(blocker, self);
@@ -217,7 +231,7 @@ namespace OpenRA.Traits.Activities
return null;
mobile.RemoveInfluence();
var newPath = getPath( self, mobile ).TakeWhile(a => a != mobile.toCell).ToList();
var newPath = EvalPath(self, mobile);
mobile.AddInfluence();
if (newPath.Count != 0)

View File

@@ -0,0 +1,26 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
using System;
using OpenRA.Traits;
using OpenRA.GameRules;
using System.Collections.Generic;
using OpenRA.FileFormats;
namespace OpenRA.Traits
{
public class ArmorInfo : ITraitInfo
{
public readonly string Type = null;
public object Create (ActorInitializer init) { return new Armor(); }
}
public class Armor {}
}

View File

@@ -38,17 +38,14 @@ namespace OpenRA.Traits
public object Create(ActorInitializer init) { return new Building(init); }
}
public class Building : INotifyDamage, IResolveOrder, IRenderModifier, IOccupySpace
public class Building : INotifyDamage, IResolveOrder, IOccupySpace
{
readonly Actor self;
public readonly BuildingInfo Info;
[Sync]
readonly int2 topLeft;
public bool Disabled
{
get { return self.TraitsImplementing<IDisable>().Any(t => t.Disabled); }
}
readonly PowerManager PlayerPower;
public Building(ActorInitializer init)
{
@@ -57,27 +54,30 @@ namespace OpenRA.Traits
Info = self.Info.Traits.Get<BuildingInfo>();
self.CenterLocation = Game.CellSize
* ((float2)topLeft + .5f * (float2)Info.Dimensions);
PlayerPower = init.self.Owner.PlayerActor.Trait<PowerManager>();
}
public int GetPowerUsage()
{
var modifier = self
.TraitsImplementing<IPowerModifier>()
.Select(t => t.GetPowerModifier())
.Product();
if (Info.Power <= 0)
return Info.Power;
if (Info.Power > 0)
{
var health = self.TraitOrDefault<Health>();
var healthFraction = (health == null) ? 1f : health.HPFraction;
return (int)(modifier * healthFraction * Info.Power);
}
else
return (int)(modifier * Info.Power);
var health = self.TraitOrDefault<Health>();
var healthFraction = (health == null) ? 1f : health.HPFraction;
return (int)(healthFraction * Info.Power);
}
public void Damaged(Actor self, AttackInfo e)
{
// Power plants lose power with damage
if (Info.Power > 0)
{
var health = self.TraitOrDefault<Health>();
var healthFraction = (health == null) ? 1f : health.HPFraction;
PlayerPower.UpdateActor(self, (int)(healthFraction * Info.Power));
}
if (e.DamageState == DamageState.Dead)
{
self.World.WorldActor.Trait<ScreenShaker>().AddEffect(10, self.CenterLocation, 1);
@@ -94,16 +94,6 @@ namespace OpenRA.Traits
}
}
public IEnumerable<Renderable> ModifyRender(Actor self, IEnumerable<Renderable> r)
{
foreach (var a in r)
{
yield return a;
if (Disabled)
yield return a.WithPalette("disabled");
}
}
public int2 TopLeft
{
get { return topLeft; }

View File

@@ -22,7 +22,6 @@ namespace OpenRA.Traits
public class HealthInfo : ITraitInfo
{
public readonly int HP = 0;
public readonly ArmorType Armor = ArmorType.none;
public virtual object Create(ActorInitializer init) { return new Health(init, this); }
}

View File

@@ -14,76 +14,103 @@ using System.Drawing;
using System.Linq;
using OpenRA.Effects;
using OpenRA.Traits.Activities;
using OpenRA.FileFormats;
namespace OpenRA.Traits
{
public class MobileInfo : ITraitInfo
{
public readonly string[] TerrainTypes;
public readonly float[] TerrainSpeeds;
public readonly string[] TerrainCostOverrides;
public readonly float[] TerrainCosts;
public readonly string[] Crushes;
public readonly int WaitAverage = 60;
public readonly int WaitSpread = 20;
public readonly int InitialFacing = 128;
public readonly int ROT = 255;
public readonly int Speed = 1;
public readonly bool OnRails = false;
[FieldLoader.LoadUsing( "LoadSpeeds" )]
public readonly Dictionary<string, TerrainInfo> TerrainSpeeds;
[FieldLoader.Load] public readonly string[] Crushes;
[FieldLoader.Load] public readonly int WaitAverage = 60;
[FieldLoader.Load] public readonly int WaitSpread = 20;
[FieldLoader.Load] public readonly int InitialFacing = 128;
[FieldLoader.Load] public readonly int ROT = 255;
[FieldLoader.Load] public readonly int Speed = 1;
[FieldLoader.Load] public readonly bool OnRails = false;
public virtual object Create(ActorInitializer init) { return new Mobile(init, this); }
static object LoadSpeeds( MiniYaml y )
{
Dictionary<string,TerrainInfo> ret = new Dictionary<string, TerrainInfo>();
foreach (var t in y.NodesDict["TerrainSpeeds"].Nodes)
{
var speed = (float)FieldLoader.GetValue("speed", typeof(float),t.Value.Value);
var cost = t.Value.NodesDict.ContainsKey("PathingCost") ? (float)FieldLoader.GetValue("cost", typeof(float), t.Value.NodesDict["PathingCost"].Value) : 1f/speed;
ret.Add(t.Key, new TerrainInfo{Speed = speed, Cost = cost});
}
return ret;
}
public class TerrainInfo
{
public float Cost = float.PositiveInfinity;
public float Speed = 0;
}
}
public class Mobile : IIssueOrder, IResolveOrder, IOrderCursor, IOrderVoice, IOccupySpace, IMove, IFacing, INudge
{
public readonly Actor self;
public readonly MobileInfo Info;
public readonly Dictionary<string,float> TerrainCost;
public readonly Dictionary<string,float> TerrainSpeed;
int __facing;
int2 __fromCell, __toCell;
int __altitude;
[Sync]
public int Facing { get; set; }
[Sync]
public int Altitude { get; set; }
public int Facing
{
get { return __facing; }
set { __facing = value; Log.Write("debug", "#{0} set Facing={1}", self.ActorID, value); }
}
[Sync]
public int Altitude
{
get { return __altitude; }
set { __altitude = value; Log.Write("debug", "#{0} set Altitude={1}", self.ActorID, value); }
}
public int ROT { get { return Info.ROT; } }
public int InitialFacing { get { return Info.InitialFacing; } }
int2 __fromCell, __toCell;
[Sync]
public int2 fromCell
{
get { return __fromCell; }
set { SetLocation( value, __toCell ); }
}
[Sync]
public int2 toCell
{
get { return __toCell; }
set { SetLocation( __fromCell, value ); }
}
void SetLocation( int2 from, int2 to )
void SetLocation(int2 from, int2 to)
{
if( fromCell == from && toCell == to ) return;
if (fromCell == from && toCell == to) return;
RemoveInfluence();
__fromCell = from;
__toCell = to;
AddInfluence();
Log.Write("debug", "#{0} set location = {1} {2}", self.ActorID, from, to);
}
Shroud shroud;
UnitInfluence uim;
BuildingInfluence bim;
bool canShareCell;
public Mobile(ActorInitializer init, MobileInfo info)
{
this.self = init.self;
this.Info = info;
shroud = self.World.WorldActor.Trait<Shroud>();
uim = self.World.WorldActor.Trait<UnitInfluence>();
bim = self.World.WorldActor.Trait<BuildingInfluence>();
canShareCell = self.HasTrait<SharesCell>();
if (init.Contains<LocationInit>())
{
@@ -93,26 +120,6 @@ namespace OpenRA.Traits
this.Facing = init.Contains<FacingInit>() ? init.Get<FacingInit,int>() : info.InitialFacing;
this.Altitude = init.Contains<AltitudeInit>() ? init.Get<AltitudeInit,int>() : 0;
TerrainCost = new Dictionary<string, float>();
TerrainSpeed = new Dictionary<string, float>();
if (info.TerrainTypes.Count() != info.TerrainSpeeds.Count())
throw new InvalidOperationException("Mobile TerrainType/TerrainSpeed length mismatch");
if (info.TerrainCostOverrides != null)
for (int i = 0; i < info.TerrainCostOverrides.Count(); i++)
{
TerrainCost.Add(info.TerrainCostOverrides[i], info.TerrainCosts[i]);
}
for (int i = 0; i < info.TerrainTypes.Count(); i++)
{
if (!TerrainCost.ContainsKey(info.TerrainTypes[i]))
TerrainCost.Add(info.TerrainTypes[i], 1f/info.TerrainSpeeds[i]);
TerrainSpeed.Add(info.TerrainTypes[i], info.TerrainSpeeds[i]);
}
}
public void SetPosition(Actor self, int2 cell)
@@ -121,66 +128,86 @@ namespace OpenRA.Traits
self.CenterLocation = Util.CenterOfCell(fromCell);
}
public int OrderPriority(Actor self, int2 xy, MouseInput mi, Actor underCursor)
{
// Force move takes precedence
return mi.Modifiers.HasModifier(Modifiers.Alt) ? int.MaxValue : 0;
}
// Note: Returns a valid order even if the unit can't move to the target
public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor)
{
if (Info.OnRails) return null;
if (mi.Button == MouseButton.Left) return null;
// force-fire should *always* take precedence over move.
if (mi.Modifiers.HasModifier(Modifiers.Ctrl)) return null;
if (underCursor != null && underCursor.Owner != null)
{
// force-move
if (!mi.Modifiers.HasModifier(Modifiers.Alt)) return null;
if (!CanEnterCell(underCursor.Location, null, true)) return null;
}
if (MovementSpeedForCell(self, toCell) == 0) return null; /* allow disabling move orders from modifiers */
if (xy == toCell) return null;
return new Order("Move", self, xy, mi.Modifiers.HasModifier(Modifiers.Shift));
var type = (!self.World.LocalPlayer.Shroud.IsVisible(xy) || CanEnterCell(xy)) ? "Move" : "Move-Blocked";
return new Order(type, self, xy, mi.Modifiers.HasModifier(Modifiers.Shift));
}
public int2 NearestMoveableCell(int2 target)
{
if (CanEnterCell(target))
return target;
var searched = new List<int2>(){};
// Limit search to a radius of 10 tiles
for (int r = 1; r < 10; r++)
foreach (var tile in self.World.FindTilesInCircle(target,r).Except(searched))
{
if (CanEnterCell(tile))
return tile;
searched.Add(tile);
}
// Couldn't find a cell
return target;
}
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "Move")
if (order.OrderString == "Move" || order.OrderString == "Move-Blocked")
{
if (CanEnterCell(order.TargetLocation))
{
if (self.Owner == self.World.LocalPlayer)
self.World.AddFrameEndTask(w =>
{
w.Add(new MoveFlash(self.World, order.TargetLocation));
var line = self.TraitOrDefault<DrawLineToTarget>();
if (line != null)
line.SetTarget(self, Target.FromOrder(order), Color.Green);
});
if( !order.Queued ) self.CancelActivity();
self.QueueActivity(new Activities.Move(order.TargetLocation, 8));
}
int2 currentLocation = NearestMoveableCell(order.TargetLocation);
if (!CanEnterCell(currentLocation))
return;
if( !order.Queued ) self.CancelActivity();
self.QueueActivity(new Activities.Move(currentLocation, 8));
if (self.Owner == self.World.LocalPlayer)
self.World.AddFrameEndTask(w =>
{
w.Add(new MoveFlash(self.World, order.TargetLocation));
var line = self.TraitOrDefault<DrawLineToTarget>();
if (line != null)
line.SetTarget(self, Target.FromCell(currentLocation), Color.Green);
});
}
}
public string CursorForOrder(Actor self, Order order)
{
if (order.OrderString != "Move")
return null;
if (order.OrderString == "Move")
return "move";
var xy = order.TargetLocation;
return (!shroud.exploredCells[xy.X, xy.Y] || CanEnterCell(xy)) ? "move" : "move-blocked";
if (order.OrderString == "Move-Blocked")
return "move-blocked";
return null;
}
public string VoicePhraseForOrder(Actor self, Order order)
{
var xy = order.TargetLocation;
return (order.OrderString == "Move" && (!shroud.exploredCells[xy.X, xy.Y] || CanEnterCell(xy))) ? "Move" : null;
if (order.OrderString == "Move" || order.OrderString == "Move-Blocked")
return "Move";
return null;
}
public int2 TopLeft { get { return toCell; } }
public virtual IEnumerable<int2> OccupiedCells()
public IEnumerable<int2> OccupiedCells()
{
return (fromCell == toCell)
? new[] { fromCell }
@@ -191,58 +218,60 @@ namespace OpenRA.Traits
public bool CanEnterCell(int2 p)
{
return CanEnterCell(p, null, true);
return CanEnterCell( p, null, true);
}
public virtual bool CanEnterCell(int2 cell, Actor ignoreActor, bool checkTransientActors)
public static bool CanEnterCell( World world, MobileInfo mi, int2 cell, Actor ignoreActor, bool checkTransientActors )
{
if (MovementCostForCell(self, cell) == float.PositiveInfinity)
var bim = world.WorldActor.Trait<BuildingInfluence>();
var uim = world.WorldActor.Trait<UnitInfluence>();
return Mobile.CanEnterCell( mi, world, uim, bim, cell, ignoreActor, checkTransientActors );
}
public bool CanEnterCell( int2 cell, Actor ignoreActor, bool checkTransientActors )
{
var bim = self.World.WorldActor.Trait<BuildingInfluence>();
var uim = self.World.WorldActor.Trait<UnitInfluence>();
return CanEnterCell( Info, self.World, uim, bim, cell, ignoreActor, checkTransientActors );
}
public static bool CanEnterCell( MobileInfo mobileInfo, World world, UnitInfluence uim, BuildingInfluence bim, int2 cell, Actor ignoreActor, bool checkTransientActors )
{
if (MovementCostForCell(mobileInfo, world, cell) == float.PositiveInfinity)
return false;
// Check for buildings
var building = bim.GetBuildingBlocking(cell);
if (building != null && building != ignoreActor)
{
if (Info.Crushes == null)
if (mobileInfo.Crushes == null)
return false;
var crushable = building.TraitsImplementing<ICrushable>();
if (crushable.Count() == 0)
return false;
if (!crushable.Any(b => b.CrushClasses.Intersect(Info.Crushes).Any()))
if (!crushable.Any(b => b.CrushClasses.Intersect(mobileInfo.Crushes).Any()))
return false;
}
// Check mobile actors
if (checkTransientActors && uim.AnyUnitsAt(cell))
var blockingActors = uim.GetUnitsAt( cell ).Where( x => x != ignoreActor ).ToList();
if (checkTransientActors && blockingActors.Count > 0)
{
var actors = uim.GetUnitsAt(cell).Where(a => a != self && a != ignoreActor).ToArray();
var nonshareable = canShareCell ? actors : actors.Where(a => !a.HasTrait<SharesCell>()).ToArray();
if (canShareCell)
{
var shareable = actors.Where(a => a.HasTrait<SharesCell>());
// only allow 5 in a cell
if (shareable.Count() >= 5)
return false;
}
// We can enter a cell with nonshareable units only if we can crush all of them
if (Info.Crushes == null && nonshareable.Length > 0)
if (mobileInfo.Crushes == null)
return false;
if (nonshareable.Length > 0 && nonshareable.Any(a => !(a.HasTrait<ICrushable>() &&
a.TraitsImplementing<ICrushable>().Any(b => b.CrushClasses.Intersect(Info.Crushes).Any()))))
if (blockingActors.Any(a => !(a.HasTrait<ICrushable>() &&
a.TraitsImplementing<ICrushable>().Any(b => b.CrushClasses.Intersect(mobileInfo.Crushes).Any()))))
return false;
}
return true;
}
public virtual void FinishedMoving(Actor self)
public void FinishedMoving(Actor self)
{
var crushable = uim.GetUnitsAt(toCell).Where(a => a != self && a.HasTrait<ICrushable>());
foreach (var a in crushable)
@@ -252,25 +281,36 @@ namespace OpenRA.Traits
b.OnCrush(self);
}
}
public virtual float MovementCostForCell(Actor self, int2 cell)
{
if (!self.World.Map.IsInMap(cell.X,cell.Y))
return float.PositiveInfinity;
var type = self.World.GetTerrainType(cell);
return TerrainCost[type];
public float MovementCostForCell( Actor self, int2 cell )
{
return MovementCostForCell( Info, self.World, cell );
}
public virtual float MovementSpeedForCell(Actor self, int2 cell)
public static float MovementCostForCell(MobileInfo info, World world, int2 cell)
{
if (!world.Map.IsInMap(cell.X,cell.Y))
return float.PositiveInfinity;
var type = world.GetTerrainType(cell);
if (!info.TerrainSpeeds.ContainsKey(type))
return float.PositiveInfinity;
return info.TerrainSpeeds[type].Cost;
}
public float MovementSpeedForCell(Actor self, int2 cell)
{
var type = self.World.GetTerrainType(cell);
if (!Info.TerrainSpeeds.ContainsKey(type))
return 0;
var modifier = self
.TraitsImplementing<ISpeedModifier>()
.Select(t => t.GetSpeedModifier())
.Product();
return Info.Speed * TerrainSpeed[type] * modifier;
return Info.Speed * Info.TerrainSpeeds[type].Speed * modifier;
}
public IEnumerable<float2> GetCurrentPath(Actor self)
@@ -281,12 +321,12 @@ namespace OpenRA.Traits
return Enumerable.Reverse(move.path).Select( c => Util.CenterOfCell(c) );
}
public virtual void AddInfluence()
public void AddInfluence()
{
uim.Add( self, this );
}
public virtual void RemoveInfluence()
public void RemoveInfluence()
{
uim.Remove( self, this );
}
@@ -331,7 +371,13 @@ namespace OpenRA.Traits
line.SetTargetSilently(self, Target.FromCell(moveTo.Value), Color.Green);
});
self.QueueActivity(new Move(moveTo.Value, 0));
Log.Write("debug", "OnNudge #{0} from {1} to {2}",
self.ActorID, self.Location, moveTo.Value);
}
else
Log.Write("debug", "OnNudge #{0} refuses at {1}",
self.ActorID, self.Location);
}
}
}

View File

@@ -86,8 +86,19 @@ namespace OpenRA.Traits
if (self.World.LocalPlayer == self.Owner)
Game.Settings.Debug.ShowCollisions ^= true;
break;
}
case "DevGiveExploration":
{
if (self.World.LocalPlayer == self.Owner)
self.World.WorldActor.Trait<Shroud>().ExploreAll(self.World);
break;
}
}
default:
return;
}
Game.Debug("Cheat used: {0} by {1}"
.F(order.OrderString, self.Owner.PlayerName));
}
}
}

View File

@@ -13,7 +13,7 @@ using System.Linq;
namespace OpenRA.Traits
{
class PlayerResourcesInfo : ITraitInfo
public class PlayerResourcesInfo : ITraitInfo
{
public readonly int InitialCash = 10000;
public readonly int InitialOre = 0;
@@ -45,17 +45,53 @@ namespace OpenRA.Traits
public int OreCapacity;
[Sync]
public int DisplayOre;
public float GetSiloFullness() { return (float)Ore / OreCapacity; }
public void GiveOre(int num)
{
Ore += num;
if (Ore > OreCapacity)
{
nextSiloAdviceTime = 0;
Ore = OreCapacity;
}
}
[Sync]
public int PowerProvided;
[Sync]
public int PowerDrained;
public bool TakeOre(int num)
{
if (Ore < num) return false;
Ore -= num;
return true;
}
public void GiveCash(int num)
{
Cash += num;
}
public bool TakeCash(int num)
{
if (Cash + Ore < num) return false;
// Spend ore before cash
Ore -= num;
if (Ore < 0)
{
Cash += Ore;
Ore = 0;
}
return true;
}
const float displayCashFracPerFrame = .07f;
const int displayCashDeltaPerFrame = 37;
int nextSiloAdviceTime = 0;
void TickOre(Actor self)
public void Tick(Actor self)
{
OreCapacity = self.World.Queries.OwnedBy[Owner].WithTrait<IStoreOre>()
.Sum(a => a.Trait.Capacity);
@@ -102,91 +138,5 @@ namespace OpenRA.Traits
Sound.PlayToPlayer(self.Owner, eva.CashTickDown);
}
}
int nextPowerAdviceTime = 0;
void TickPower()
{
var oldBalance = PowerProvided - PowerDrained;
PowerProvided = 0;
PowerDrained = 0;
var myBuildings = Owner.World.Queries.OwnedBy[Owner].WithTrait<Building>();
foreach (var a in myBuildings)
{
var q = a.Trait.GetPowerUsage();
if (q > 0)
PowerProvided += q;
else
PowerDrained -= q;
}
if (PowerProvided - PowerDrained < 0)
if (PowerProvided - PowerDrained != oldBalance)
nextPowerAdviceTime = 0;
if (--nextPowerAdviceTime <= 0)
{
if (PowerProvided - PowerDrained < 0)
Owner.GiveAdvice(Rules.Info["world"].Traits.Get<EvaAlertsInfo>().LowPower);
nextPowerAdviceTime = AdviceInterval;
}
}
public PowerState GetPowerState()
{
if (PowerProvided >= PowerDrained) return PowerState.Normal;
if (PowerProvided > PowerDrained / 2) return PowerState.Low;
return PowerState.Critical;
}
public float GetSiloFullness() { return (float)Ore / OreCapacity; }
public void GiveOre(int num)
{
Ore += num;
if (Ore > OreCapacity)
{
nextSiloAdviceTime = 0;
Ore = OreCapacity;
}
}
public bool TakeOre(int num)
{
if (Ore < num) return false;
Ore -= num;
return true;
}
public void GiveCash(int num)
{
Cash += num;
}
public bool TakeCash(int num)
{
if (Cash + Ore < num) return false;
// Spend ore before cash
Ore -= num;
if (Ore < 0)
{
Cash += Ore;
Ore = 0;
}
return true;
}
public void Tick(Actor self)
{
TickPower();
TickOre(self);
}
}
}

View File

@@ -0,0 +1,111 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
using System;
using System.Linq;
using System.Collections.Generic;
using OpenRA.FileFormats;
namespace OpenRA.Traits
{
public class PowerManagerInfo : ITraitInfo
{
public readonly int AdviceInterval = 250;
public object Create(ActorInitializer init) { return new PowerManager(init, this); }
}
public class PowerManager : ITick
{
PowerManagerInfo Info;
Player Player;
Dictionary<Actor, int> PowerDrain = new Dictionary<Actor, int>();
[Sync] int totalProvided;
public int PowerProvided { get { return totalProvided; } }
[Sync] int totalDrained;
public int PowerDrained { get { return totalDrained; } }
public PowerManager(ActorInitializer init, PowerManagerInfo info)
{
Info = info;
Player = init.self.Owner;
init.world.ActorAdded += ActorAdded;
init.world.ActorRemoved += ActorRemoved;
}
void ActorAdded(Actor a)
{
if (a.Owner != Player || !a.HasTrait<Building>())
return;
PowerDrain.Add(a, a.Trait<Building>().GetPowerUsage());
UpdateTotals();
}
void ActorRemoved(Actor a)
{
if (a.Owner != Player || !a.HasTrait<Building>())
return;
PowerDrain.Remove(a);
UpdateTotals();
}
void UpdateTotals()
{
totalProvided = 0;
totalDrained = 0;
foreach (var kv in PowerDrain)
{
var p = kv.Value;
if (p > 0)
totalProvided += p;
else
totalDrained -= p;
}
}
public void UpdateActor(Actor a, int newPower)
{
if (a.Owner != Player || !a.HasTrait<Building>())
return;
PowerDrain[a] = newPower;
UpdateTotals();
}
int nextPowerAdviceTime = 0;
bool wasLowPower = false;
public void Tick(Actor self)
{
var lowPower = totalProvided < totalDrained;
if (lowPower && !wasLowPower)
nextPowerAdviceTime = 0;
wasLowPower = lowPower;
if (--nextPowerAdviceTime <= 0)
{
if (lowPower)
Player.GiveAdvice(Rules.Info["world"].Traits.Get<EvaAlertsInfo>().LowPower);
nextPowerAdviceTime = Info.AdviceInterval;
}
}
public PowerState PowerState
{
get {
if (PowerProvided >= PowerDrained) return PowerState.Normal;
if (PowerProvided > PowerDrained / 2) return PowerState.Low;
return PowerState.Critical;
}
}
}
}

View File

@@ -0,0 +1,124 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
using System.Collections.Generic;
using System.Linq;
using OpenRA.FileFormats;
namespace OpenRA.Traits
{
public class TechTreeInfo : ITraitInfo
{
public object Create(ActorInitializer init) { return new TechTree(init);}
}
public class TechTree
{
readonly List<Watcher> watchers = new List<Watcher>();
readonly Player player;
public TechTree(ActorInitializer init)
{
player = init.self.Owner;
init.world.ActorAdded += ActorChanged;
init.world.ActorRemoved += ActorChanged;
}
public void ActorChanged(Actor a)
{
if (a.Owner == player && a.HasTrait<Building>())
Update();
}
public void Update()
{
var buildings = GatherBuildings(player);
foreach(var w in watchers)
w.Update(buildings);
}
public void Add(string key, List<string> prerequisites, ITechTreeElement tte)
{
Add(key, prerequisites, false, tte);
}
// set requiresPowered = true to discard buildings that have an IDisabled active (eg manually powered down)
public void Add(string key, List<string> prerequisites, bool requiresPowered, ITechTreeElement tte)
{
watchers.Add(new Watcher( key, prerequisites, requiresPowered, tte ));
}
public void Remove(string key)
{
watchers.RemoveAll(x => x.key == key);
}
static Cache<string, List<Actor>> GatherBuildings( Player player )
{
var ret = new Cache<string, List<Actor>>( x => new List<Actor>() );
if (player == null)
return ret;
foreach( var b in player.World.Queries.OwnedBy[player].Where( x=>x.Info.Traits.Contains<BuildingInfo>() ) )
{
ret[ b.Info.Name ].Add( b );
var tt = b.Info.Traits.GetOrDefault<TooltipInfo>();
if( tt != null )
foreach( var alt in tt.AlternateName )
ret[ alt ].Add( b );
}
return ret;
}
class Watcher
{
public readonly string key;
// strings may be either actor type, or "alternate name" key
public readonly List<string> prerequisites;
public readonly ITechTreeElement watcher;
bool hasPrerequisites;
bool requiresPowered;
public Watcher(string key, List<string> prerequisites, bool requiresPowered, ITechTreeElement watcher)
{
this.key = key;
this.prerequisites = prerequisites;
this.watcher = watcher;
this.hasPrerequisites = false;
this.requiresPowered = requiresPowered;
}
public void Update(Cache<string, List<Actor>> buildings)
{
var nowHasPrerequisites = true;
foreach (var p in prerequisites)
if (!buildings.Keys.Contains(p) ||
(requiresPowered && buildings[p].All(b => b.TraitsImplementing<IDisable>().Any(d => d.Disabled))))
{
nowHasPrerequisites = false;
break;
}
if( nowHasPrerequisites && !hasPrerequisites )
watcher.PrerequisitesAvailable(key);
if( !nowHasPrerequisites && hasPrerequisites )
watcher.PrerequisitesUnavailable(key);
hasPrerequisites = nowHasPrerequisites;
}
}
}
public interface ITechTreeElement
{
void PrerequisitesAvailable(string key);
void PrerequisitesUnavailable(string key);
}
}

View File

@@ -1,78 +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.GameRules;
namespace OpenRA.Traits
{
class TechTreeCacheInfo : TraitInfo<TechTreeCache> { }
class TechTreeCache : ITick
{
class Watcher
{
public readonly string key;
// strings may be either actor type, or "alternate name" key
public readonly List<string> prerequisites;
public readonly ITechTreeElement watcher;
bool hasPrerequisites;
public Watcher(string key, List<string> prerequisites, ITechTreeElement watcher)
{
this.key = key;
this.prerequisites = prerequisites;
this.watcher = watcher;
this.hasPrerequisites = false;
}
public void Tick( Player owner, Cache<string, List<Actor>> buildings )
{
var nowHasPrerequisites = prerequisites.All( a => buildings[ a ].Any( b => !b.Trait<Building>().Disabled ) );
if( nowHasPrerequisites && !hasPrerequisites )
watcher.PrerequisitesAvailable(key);
if( !nowHasPrerequisites && hasPrerequisites )
watcher.PrerequisitesUnavailable(key);
hasPrerequisites = nowHasPrerequisites;
}
}
readonly List<Watcher> watchers = new List<Watcher>();
public void Tick( Actor self )
{
var buildings = Rules.TechTree.GatherBuildings( self.Owner );
foreach( var w in watchers )
w.Tick( self.Owner, buildings );
}
public void Add( string key, List<string> prerequisites, ITechTreeElement tte )
{
watchers.Add( new Watcher( key, prerequisites, tte ) );
}
public void Remove( string key )
{
watchers.RemoveAll( x => x.key == key );
}
}
interface ITechTreeElement
{
void PrerequisitesAvailable(string key);
void PrerequisitesUnavailable(string key);
}
}

12
OpenRA.Game/Traits/Render/RenderSimple.cs Normal file → Executable file
View File

@@ -62,16 +62,20 @@ namespace OpenRA.Traits
a.Animation.Tick();
}
protected virtual string GetPrefix(Actor self)
protected virtual string NormalizeSequence(Actor self, string baseSequence)
{
return self.GetDamageState() >= DamageState.Heavy ? "damaged-" : "";
string damageState = self.GetDamageState() >= DamageState.Heavy ? "damaged-" : "";
if (anim.HasSequence(damageState + baseSequence))
return damageState + baseSequence;
else
return baseSequence;
}
public void PlayCustomAnim(Actor self, string name)
{
if (anim.HasSequence(name))
anim.PlayThen(GetPrefix(self) + name,
() => anim.PlayRepeating(GetPrefix(self) + "idle"));
anim.PlayThen(NormalizeSequence(self, name),
() => anim.PlayRepeating(NormalizeSequence(self, "idle")));
}
public class AnimationWithOffset

View File

@@ -28,7 +28,7 @@ namespace OpenRA.Traits
public void Tick(Actor self)
{
if (!self.IsIdle && previousLocation != self.Location)
if (previousLocation != self.Location)
{
previousLocation = self.Location;
self.World.WorldActor.Trait<Shroud>().UpdateActor(self);

View File

@@ -109,7 +109,11 @@ namespace OpenRA.Traits
foreach (var pips in self.TraitsImplementing<IPips>())
{
foreach (var pip in pips.GetPips(self))
var thisRow = pips.GetPips(self);
if (thisRow == null)
continue;
foreach (var pip in thisRow)
{
if (pipxyOffset.X+5 > self.GetBounds(false).Width)
{

0
OpenRA.Game/Traits/SharesCell.cs Normal file → Executable file
View File

View File

@@ -33,7 +33,11 @@ namespace OpenRA.Traits
public interface ITick { void Tick(Actor self); }
public interface IRender { IEnumerable<Renderable> Render(Actor self); }
public interface IIssueOrder { Order IssueOrder( Actor self, int2 xy, MouseInput mi, Actor underCursor ); }
public interface IIssueOrder
{
Order IssueOrder( Actor self, int2 xy, MouseInput mi, Actor underCursor );
int OrderPriority( Actor self, int2 xy, MouseInput mi, Actor underCursor );
}
public interface IResolveOrder { void ResolveOrder(Actor self, Order order); }
public interface IOrderCursor { string CursorForOrder(Actor self, Order order); }
public interface IOrderVoice { string VoicePhraseForOrder(Actor self, Order order); }
@@ -95,7 +99,6 @@ namespace OpenRA.Traits
public interface IRenderModifier { IEnumerable<Renderable> ModifyRender(Actor self, IEnumerable<Renderable> r); }
public interface IDamageModifier { float GetDamageModifier( WarheadInfo warhead ); }
public interface ISpeedModifier { float GetSpeedModifier(); }
public interface IPowerModifier { float GetPowerModifier(); }
public interface IFirepowerModifier { float GetFirepowerModifier(); }
public interface IPaletteModifier { void AdjustPalette(Dictionary<string,Palette> b); }
public interface IPips { IEnumerable<PipType> GetPips(Actor self); }
@@ -134,22 +137,24 @@ namespace OpenRA.Traits
public readonly Sprite Sprite;
public readonly float2 Pos;
public readonly string Palette;
public readonly int Z;
public readonly int ZOffset;
public Renderable(Sprite sprite, float2 pos, string palette, int zOffset)
public Renderable(Sprite sprite, float2 pos, string palette, int z, int zOffset)
{
Sprite = sprite;
Pos = pos;
Palette = palette;
Z = z;
ZOffset = zOffset;
}
public Renderable(Sprite sprite, float2 pos, string palette)
: this(sprite, pos, palette, 0) { }
public Renderable(Sprite sprite, float2 pos, string palette, int z)
: this(sprite, pos, palette, z, 0) { }
public Renderable WithPalette(string newPalette) { return new Renderable(Sprite, Pos, newPalette, ZOffset); }
public Renderable WithZOffset(int newOffset) { return new Renderable(Sprite, Pos, Palette, newOffset); }
public Renderable WithPos(float2 newPos) { return new Renderable(Sprite, newPos, Palette, ZOffset); }
public Renderable WithPalette(string newPalette) { return new Renderable(Sprite, Pos, newPalette, Z, ZOffset); }
public Renderable WithZOffset(int newOffset) { return new Renderable(Sprite, Pos, Palette, Z, newOffset); }
public Renderable WithPos(float2 newPos) { return new Renderable(Sprite, newPos, Palette, Z, ZOffset); }
}
public interface ITraitInfo { object Create(ActorInitializer init); }

View File

@@ -100,7 +100,7 @@ namespace OpenRA.Traits
{
var pal = self.Owner == null ? "player0" : self.Owner.Palette;
var loc = location - 0.5f * s.size;
return new Renderable(s, loc.Round(), pal);
return new Renderable(s, loc.Round(), pal, (int)self.CenterLocation.Y);
}
public static IActivity SequenceActivities(params IActivity[] acts)

23
OpenRA.Game/Traits/Valued.cs Executable file
View File

@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OpenRA.Traits
{
public class ValuedInfo : TraitInfo<Valued>
{
public readonly int Cost = 0;
}
public class TooltipInfo : TraitInfo<Tooltip>
{
public readonly string Description = "";
public readonly string Name = "";
public readonly string Icon = null;
public readonly string[] AlternateName = { };
}
public class Valued { }
public class Tooltip { }
}

50
OpenRA.Game/Traits/World/BibLayer.cs Normal file → Executable file
View File

@@ -12,7 +12,8 @@ using System;
using System.Drawing;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Graphics;
using OpenRA.Graphics;
using System.Collections.Generic;
namespace OpenRA.Traits
{
@@ -26,9 +27,8 @@ namespace OpenRA.Traits
class BibLayer: IRenderOverlay, IWorldLoaded
{
World world;
BibLayerInfo info;
TileReference<byte,byte>[,] tiles;
BibLayerInfo info;
Dictionary<int2, TileReference<byte, byte>> tiles;
Sprite[][] bibSprites;
public BibLayer(Actor self, BibLayerInfo info)
@@ -44,8 +44,8 @@ namespace OpenRA.Traits
public void WorldLoaded(World w)
{
world = w;
tiles = new TileReference<byte,byte>[w.Map.MapSize.X,w.Map.MapSize.Y];
world = w;
tiles = new Dictionary<int2, TileReference<byte, byte>>();
}
public void DoBib(Actor b, bool isAdd)
@@ -63,11 +63,11 @@ namespace OpenRA.Traits
for (int i = 0; i < 2 * size; i++)
{
var p = b.Location + new int2(i % size, i / size + bibOffset);
byte type = (byte)((isAdd) ? bib+1 : 0);
byte index = (byte)i;
tiles[p.X,p.Y] = new TileReference<byte,byte>(type,index);
var p = b.Location + new int2(i % size, i / size + bibOffset);
if (isAdd)
tiles[p] = new TileReference<byte, byte>((byte)((isAdd) ? bib + 1 : 0), (byte)i);
else
tiles.Remove(p);
}
}
@@ -75,22 +75,18 @@ namespace OpenRA.Traits
{
var cliprect = Game.viewport.ShroudBounds().HasValue
? Rectangle.Intersect(Game.viewport.ShroudBounds().Value, world.Map.Bounds) : world.Map.Bounds;
var minx = cliprect.Left;
var maxx = cliprect.Right;
var miny = cliprect.Top;
var maxy = cliprect.Bottom;
for (int x = minx; x < maxx; x++)
for (int y = miny; y < maxy; y++)
{
var t = new int2(x, y);
if (world.LocalPlayer != null && !world.LocalPlayer.Shroud.IsExplored(t) || tiles[x,y].type == 0) continue;
Game.Renderer.SpriteRenderer.DrawSprite(bibSprites[tiles[x, y].type - 1][tiles[x, y].image],
Game.CellSize * t, "terrain");
}
cliprect = Rectangle.Intersect(Game.viewport.ViewBounds(), cliprect);
foreach (var kv in tiles)
{
if (!cliprect.Contains(kv.Key.X, kv.Key.Y))
continue;
if (world.LocalPlayer != null && !world.LocalPlayer.Shroud.IsExplored(kv.Key))
continue;
Game.Renderer.SpriteRenderer.DrawSprite(bibSprites[kv.Value.type - 1][kv.Value.image],
Game.CellSize * kv.Key, "terrain");
}
}
}

View File

@@ -8,12 +8,13 @@
*/
#endregion
using OpenRA.FileFormats;
namespace OpenRA.Traits
{
{
public class PlayerColorPaletteInfo : TraitInfo<PlayerColorPalette>
{
public readonly string BasePalette = null;
public readonly bool SplitRamp = false;
public readonly PaletteFormat PaletteFormat = PaletteFormat.ra;
}
public class PlayerColorPalette {}

View File

@@ -29,6 +29,8 @@ namespace OpenRA.Traits
var cliprect = Game.viewport.ShroudBounds().HasValue
? Rectangle.Intersect(Game.viewport.ShroudBounds().Value, world.Map.Bounds) : world.Map.Bounds;
cliprect = Rectangle.Intersect(Game.viewport.ViewBounds(), cliprect);
var minx = cliprect.Left;
var maxx = cliprect.Right;

View File

@@ -22,9 +22,12 @@ namespace OpenRA.Traits
List<ShakeEffect> shakeEffects = new List<ShakeEffect>();
public void Tick (Actor self)
{
Game.viewport.Scroll(GetScrollOffset());
shakeEffects.RemoveAll(t => t.ExpiryTime == ticks);
{
if(shakeEffects.Any())
{
Game.viewport.Scroll(GetScrollOffset(), true);
shakeEffects.RemoveAll(t => t.ExpiryTime == ticks);
}
ticks++;
}
@@ -48,7 +51,7 @@ namespace OpenRA.Traits
var cp = Game.viewport.Location
+ .5f * new float2(Game.viewport.Width, Game.viewport.Height);
var intensity = 24 * 24 * 100 * shakeEffects.Sum(
var intensity = Game.CellSize * Game.CellSize * 100 * shakeEffects.Sum(
e => e.Intensity / (e.Position - cp).LengthSquared);
return Math.Min(intensity, 10);

View File

@@ -33,13 +33,17 @@ namespace OpenRA.Traits
self.World.Map.MapSize.Y / info.BinSize];
scale = Game.CellSize * info.BinSize;
for (var j = 0; j <= bins.GetUpperBound(1); j++)
for (var i = 0; i <= bins.GetUpperBound(0); i++)
bins[i, j] = new List<Actor>();
}
public void Tick(Actor self)
{
for (var j = 0; j <= bins.GetUpperBound(1); j++)
for (var i = 0; i <= bins.GetUpperBound(0); i++)
bins[i, j] = new List<Actor>();
bins[i, j].Clear();
foreach (var a in self.World.Actors)
{
@@ -63,8 +67,6 @@ namespace OpenRA.Traits
IEnumerable<Actor> ActorsInBins(int i1, int i2, int j1, int j2)
{
if (bins[0, 0] == null) yield break; // hack
j1 = Math.Max(0, j1); j2 = Math.Min(j2, bins.GetUpperBound(1));
i1 = Math.Max(0, i1); i2 = Math.Min(i2, bins.GetUpperBound(0));
for (var j = j1; j <= j2; j++)

View File

@@ -18,7 +18,7 @@ using OpenRA.Widgets;
namespace OpenRA
{
class UiOverlay
public class UiOverlay
{
Sprite buildOk, buildBlocked, unitDebug;
@@ -79,7 +79,7 @@ namespace OpenRA
}
}
static class LineBuildUtils
public static class LineBuildUtils
{
public static IEnumerable<int2> GetLineBuildCells(World world, int2 location, string name, BuildingInfo bi)
{

View File

@@ -34,7 +34,7 @@ namespace OpenRA.Widgets.Delegates
cs.GetWidget("BUTTON_START").OnMouseUp = mi => {
r.OpenWindow("SERVER_LOBBY");
var map = Game.modData.AvailableMaps.Keys.FirstOrDefault();
var map = Game.modData.AvailableMaps.FirstOrDefault(m => m.Value.Selectable).Key;
settings.Server.Name = cs.GetWidget<TextFieldWidget>("GAME_TITLE").Text;
settings.Server.ListenPort = int.Parse(cs.GetWidget<TextFieldWidget>("LISTEN_PORT").Text);

View File

@@ -92,6 +92,12 @@ namespace OpenRA.Widgets.Delegates
{
Game.IssueOrder(new Order("DevEnableTech", Game.world.LocalPlayer.PlayerActor));
return true;
};
devmodeBG.GetWidget<ButtonWidget>("GIVE_EXPLORATION").OnMouseUp = mi =>
{
Game.IssueOrder(new Order("DevGiveExploration", Game.world.LocalPlayer.PlayerActor));
return true;
};
devModeButton.IsVisible = () => { return Game.LobbyInfo.GlobalSettings.AllowCheats; };

View File

@@ -281,7 +281,7 @@ namespace OpenRA.Widgets.Delegates
else
{
template = EmptySlotTemplate.Clone();
var name = template.GetWidget<ButtonWidget>("NAME");
var name = template.GetWidget<LabelWidget>("NAME");
name.GetText = () => s.Closed ? "Closed" : "Open";
}
@@ -416,10 +416,9 @@ namespace OpenRA.Widgets.Delegates
bool CycleTeam(MouseInput mi)
{
var d = (mi.Button == MouseButton.Left) ? +1 : Game.world.Map.PlayerCount;
var newIndex = (Game.LocalClient.Team + d) % (Game.world.Map.PlayerCount + 1);
var d = (mi.Button == MouseButton.Left) ? +1 : Map.PlayerCount;
var newIndex = (Game.LocalClient.Team + d) % (Map.PlayerCount + 1);
Game.IssueOrder(
Order.Command("team " + newIndex));
return true;

View File

@@ -74,7 +74,7 @@ namespace OpenRA.Widgets.Delegates
if (uid != null)
Map = Game.modData.AvailableMaps[uid];
else
Map = Game.modData.AvailableMaps.FirstOrDefault().Value;
Map = Game.modData.AvailableMaps.FirstOrDefault(m => m.Value.Selectable).Value;
}
}
}

View File

@@ -19,16 +19,27 @@ namespace OpenRA.Widgets.Delegates
string CurrentSong = null;
public MusicPlayerDelegate()
{
var bg = Widget.RootWidget.GetWidget("MUSIC_BG");
//bg.Visible = Game.Settings.MusicPlayer;
var bg = Widget.RootWidget.GetWidget("MUSIC_MENU");
CurrentSong = GetNextSong();
bg.GetWidget("BUTTON_CLOSE").OnMouseUp = mi => {
Game.Settings.Save();
Widget.RootWidget.CloseWindow();
return true;
};
Widget.RootWidget.GetWidget("MAINMENU_BUTTON_MUSIC").OnMouseUp = mi => {
Widget.RootWidget.OpenWindow("MUSIC_MENU");
return true;
};
bg.GetWidget("BUTTON_PLAY").OnMouseUp = mi =>
{
if (CurrentSong == null)
return true;
Sound.PlayMusic(Rules.Music[CurrentSong].Filename);
Sound.PlayMusicThen(Rules.Music[CurrentSong].Filename,
() => bg.GetWidget(Game.Settings.Sound.Repeat ? "BUTTON_PLAY" : "BUTTON_NEXT").OnMouseUp(new MouseInput()));
bg.GetWidget("BUTTON_PLAY").Visible = false;
bg.GetWidget("BUTTON_PAUSE").Visible = true;
@@ -64,19 +75,44 @@ namespace OpenRA.Widgets.Delegates
return bg.GetWidget("BUTTON_PLAY").OnMouseUp(mi);
};
bg.GetWidget<LabelWidget>("TIME").GetText = () => "{0:D2}:{1:D2} / {2:D2}:{3:D2}".F((int)Sound.MusicSeekPosition / 60, (int)Sound.MusicSeekPosition % 60,
var shuffle = bg.GetWidget<CheckboxWidget>("SHUFFLE");
shuffle.OnMouseDown = mi =>
{
Game.Settings.Sound.Shuffle ^= true;
return true;
};
shuffle.Checked = () => Game.Settings.Sound.Shuffle;
var repeat = bg.GetWidget<CheckboxWidget>("REPEAT");
repeat.OnMouseDown = mi =>
{
Game.Settings.Sound.Repeat ^= true;
return true;
};
repeat.Checked = () => Game.Settings.Sound.Repeat;
bg.GetWidget<LabelWidget>("TIME").GetText = () =>
{
if (CurrentSong == null)
return "";
return "{0:D2}:{1:D2} / {2:D2}:{3:D2}".F((int)Sound.MusicSeekPosition / 60, (int)Sound.MusicSeekPosition % 60,
Rules.Music[CurrentSong].Length / 60, Rules.Music[CurrentSong].Length % 60);
};
var ml = bg.GetWidget<ListBoxWidget>("MUSIC_LIST");
var itemTemplate = ml.GetWidget<LabelWidget>("MUSIC_TEMPLATE");
int offset = itemTemplate.Bounds.Y;
foreach (var kv in Rules.Music)
if (!Rules.Music.Where(m => m.Value.Exists).Any())
{
itemTemplate.IsVisible = () => true;
itemTemplate.GetWidget<LabelWidget>("TITLE").GetText = () => "No Music Installed";
itemTemplate.GetWidget<LabelWidget>("TITLE").Align = LabelWidget.TextAlign.Center;
}
foreach (var kv in Rules.Music.Where(m => m.Value.Exists))
{
var song = kv.Key;
if (!FileSystem.Exists(Rules.Music[song].Filename))
continue;
if (CurrentSong == null)
CurrentSong = song;
@@ -95,7 +131,7 @@ namespace OpenRA.Widgets.Delegates
template.IsVisible = () => true;
template.GetWidget<LabelWidget>("TITLE").GetText = () => " " + Rules.Music[song].Title;
template.GetWidget<LabelWidget>("LENGTH").GetText = () => "{0:D2}:{1:D2}".F(Rules.Music[song].Length / 60, Rules.Music[song].Length % 60);
template.GetWidget<LabelWidget>("LENGTH").GetText = () => "{0:D1}:{1:D2}".F(Rules.Music[song].Length / 60, Rules.Music[song].Length % 60);
ml.AddChild(template);
@@ -106,35 +142,33 @@ namespace OpenRA.Widgets.Delegates
string GetNextSong()
{
var songs = Rules.Music.Select(a => a.Key)
.Where(a => FileSystem.Exists(Rules.Music[a].Filename));
var songs = Rules.Music.Where(a => a.Value.Exists)
.Select(a => a.Key);
var nextSong = songs
.SkipWhile(m => m != CurrentSong)
.Skip(1)
.FirstOrDefault();
if (!songs.Any())
return null;
if (nextSong == null)
nextSong = songs.FirstOrDefault();
if (Game.Settings.Sound.Shuffle)
return songs.Random(Game.CosmeticRandom);
return nextSong;
return songs.SkipWhile(m => m != CurrentSong)
.Skip(1).FirstOrDefault() ?? songs.FirstOrDefault();
}
string GetPrevSong()
{
var songs = Rules.Music.Select(a => a.Key)
.Where(a => FileSystem.Exists(Rules.Music[a].Filename))
.Reverse();
var songs = Rules.Music.Where(a => a.Value.Exists)
.Select(a => a.Key).Reverse();
var nextSong = songs
.SkipWhile(m => m != CurrentSong)
.Skip(1)
.FirstOrDefault();
if (!songs.Any())
return null;
if (nextSong == null)
nextSong = songs.FirstOrDefault();
if (Game.Settings.Sound.Shuffle)
return songs.Random(Game.CosmeticRandom);
return nextSong;
return songs.SkipWhile(m => m != CurrentSong)
.Skip(1).FirstOrDefault() ?? songs.FirstOrDefault();
}
}
}

84
OpenRA.Game/Widgets/ViewportScrollControllerWidget.cs Normal file → Executable file
View File

@@ -50,24 +50,56 @@ namespace OpenRA.Widgets
{
if (!Game.Settings.Game.ViewportEdgeScroll)
return null;
if (Edge.Includes(ScrollDirection.Up) && Edge.Includes(ScrollDirection.Left))
return "scroll-tl";
if (Edge.Includes(ScrollDirection.Up) && Edge.Includes(ScrollDirection.Right))
return "scroll-tr";
if (Edge.Includes(ScrollDirection.Down) && Edge.Includes(ScrollDirection.Left))
return "scroll-bl";
if (Edge.Includes(ScrollDirection.Down) && Edge.Includes(ScrollDirection.Right))
return "scroll-br";
if (Edge.Includes(ScrollDirection.Up) && Edge.Includes(ScrollDirection.Left)){
ScrollDirection BlockedDirections = Game.viewport.GetBlockedDirections();
if(BlockedDirections.Includes(ScrollDirection.Up) && BlockedDirections.Includes(ScrollDirection.Left))
return "scroll-tl-blocked";
else
return "scroll-tl";
}
if (Edge.Includes(ScrollDirection.Up) && Edge.Includes(ScrollDirection.Right)){
ScrollDirection BlockedDirections = Game.viewport.GetBlockedDirections();
if (BlockedDirections.Includes(ScrollDirection.Up) && BlockedDirections.Includes(ScrollDirection.Right))
return "scroll-tr-blocked";
else
return "scroll-tr";
}
if (Edge.Includes(ScrollDirection.Down) && Edge.Includes(ScrollDirection.Left)){
ScrollDirection BlockedDirections = Game.viewport.GetBlockedDirections();
if (BlockedDirections.Includes(ScrollDirection.Down) && BlockedDirections.Includes(ScrollDirection.Left))
return "scroll-bl-blocked";
else
return "scroll-bl";
}
if (Edge.Includes(ScrollDirection.Down) && Edge.Includes(ScrollDirection.Right)){
ScrollDirection BlockedDirections = Game.viewport.GetBlockedDirections();
if (BlockedDirections.Includes(ScrollDirection.Down) && BlockedDirections.Includes(ScrollDirection.Right))
return "scroll-br-blocked";
else
return "scroll-br";
}
if (Edge.Includes(ScrollDirection.Up))
return "scroll-t";
if (Game.viewport.GetBlockedDirections().Includes(ScrollDirection.Up))
return "scroll-t-blocked";
else
return "scroll-t";
if (Edge.Includes(ScrollDirection.Down))
return "scroll-b";
if (Game.viewport.GetBlockedDirections().Includes(ScrollDirection.Down))
return "scroll-b-blocked";
else
return "scroll-b";
if (Edge.Includes(ScrollDirection.Left))
return "scroll-l";
if (Game.viewport.GetBlockedDirections().Includes(ScrollDirection.Left))
return "scroll-l-blocked";
else
return "scroll-l";
if (Edge.Includes(ScrollDirection.Right))
return "scroll-r";
if (Game.viewport.GetBlockedDirections().Includes(ScrollDirection.Right))
return "scroll-r-blocked";
else
return "scroll-r";
return null;
}
@@ -93,7 +125,7 @@ namespace OpenRA.Widgets
public override void Tick(World world)
{
Edge = ScrollDirection.None;
if (Game.Settings.Game.ViewportEdgeScroll)
if (Game.Settings.Game.ViewportEdgeScroll && Game.HasInputFocus)
{
// Check for edge-scroll
if (Viewport.LastMousePos.X < EdgeScrollThreshold)
@@ -105,17 +137,21 @@ namespace OpenRA.Widgets
if (Viewport.LastMousePos.Y >= Game.viewport.Height - EdgeScrollThreshold)
Edge = Edge.Set(ScrollDirection.Down, true);
}
var scroll = new float2(0,0);
if (Keyboard.Includes(ScrollDirection.Up) || Edge.Includes(ScrollDirection.Up))
scroll += new float2(0, -10);
if (Keyboard.Includes(ScrollDirection.Right) || Edge.Includes(ScrollDirection.Right))
scroll += new float2(10, 0);
if (Keyboard.Includes(ScrollDirection.Down) || Edge.Includes(ScrollDirection.Down))
scroll += new float2(0, 10);
if (Keyboard.Includes(ScrollDirection.Left) || Edge.Includes(ScrollDirection.Left))
scroll += new float2(-10, 0);
Game.viewport.Scroll(scroll);
if(Keyboard != ScrollDirection.None || Edge != ScrollDirection.None)
{
var scroll = new float2(0,0);
if (Keyboard.Includes(ScrollDirection.Up) || Edge.Includes(ScrollDirection.Up))
scroll += new float2(0, -10);
if (Keyboard.Includes(ScrollDirection.Right) || Edge.Includes(ScrollDirection.Right))
scroll += new float2(10, 0);
if (Keyboard.Includes(ScrollDirection.Down) || Edge.Includes(ScrollDirection.Down))
scroll += new float2(0, 10);
if (Keyboard.Includes(ScrollDirection.Left) || Edge.Includes(ScrollDirection.Left))
scroll += new float2(-10, 0);
Game.viewport.Scroll(scroll);
}
}
public override Widget Clone() { return new ViewportScrollControllerWidget(this); }

View File

@@ -29,7 +29,7 @@ namespace OpenRA.Widgets
public static void DrawSHP(Sprite s, float2 pos)
{
Game.Renderer.WorldSpriteRenderer.DrawSprite(s,pos);
Game.Renderer.WorldSpriteRenderer.DrawSprite(s,pos, "chrome");
}
public static void DrawPanel(string collection, Rectangle Bounds)

View File

@@ -10,13 +10,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Collections;
using OpenRA.Effects;
using OpenRA.FileFormats;
using OpenRA.Graphics;
using OpenRA.Orders;
using OpenRA.Support;
using OpenRA.Traits;
using XRandom = OpenRA.Thirdparty.Random;
@@ -78,15 +76,12 @@ namespace OpenRA
public World(Manifest manifest, Map map)
{
Timer.Time( "----World.ctor" );
Map = map;
TileSet = Rules.TileSets[Map.Tileset];
TileSet.LoadTiles();
Timer.Time( "Tileset: {0}" );
WorldRenderer = new WorldRenderer(this);
Timer.Time("renderer: {0}");
WorldActor = CreateActor( "World", new TypeDictionary() );
Queries = new AllQueries(this);
@@ -101,16 +96,10 @@ namespace OpenRA
if (!p.Stances.ContainsKey(q))
p.Stances[q] = Stance.Neutral;
Timer.Time( "worldActor, players: {0}" );
PathFinder = new PathFinder(this);
foreach (var wlh in WorldActor.TraitsImplementing<IWorldLoaded>())
wlh.WorldLoaded(this);
Timer.Time( "hooks, pathing: {0}" );
Timer.Time( "----end World.ctor" );
}
public Actor CreateActor( string name, TypeDictionary initDict )
@@ -155,31 +144,18 @@ namespace OpenRA
if (DisableTick)
return;
Timer.Time("----World Tick");
actors.DoTimed( x => x.Tick(), "expensive actor tick: {0} ({1:0.000})", 0.001 );
Timer.Time(" actors: {0:0.000}");
actors.Do( x => x.Tick() );
Queries.WithTraitMultiple<ITick>().DoTimed( x =>
{
x.Trait.Tick( x.Actor );
Timer.Time( "trait tick \"{0}\": {{0}}".F( x.Trait.GetType().Name ) );
}, "expensive trait tick: {0} ({1:0.000})", 0.001 );
Timer.Time(" traits: {0:0.000}");
effects.DoTimed( e => e.Tick( this ), "expensive effect tick: {0} ({1:0.000})", 0.001 );
Timer.Time(" effects: {0:0.000}");
}, "[{2}] Trait: {0} ({1:0.000} ms)", Game.Settings.Debug.LongTickThreshold );
effects.DoTimed( e => e.Tick( this ), "[{2}] Effect: {0} ({1:0.000} ms)", Game.Settings.Debug.LongTickThreshold );
Game.viewport.Tick();
Timer.Time(" viewport: {0:0.000}");
while (frameEndActions.Count != 0)
frameEndActions.Dequeue()(this);
Timer.Time(" frameEndActions: {0:0.000}");
WorldRenderer.Tick();
Timer.Time(" worldrenderer: {0:0.000}");
}
public IEnumerable<Actor> Actors { get { return actors; } }
@@ -195,10 +171,20 @@ namespace OpenRA
{
//using (new PerfSample("synchash"))
{
int n = 0;
int ret = 0;
foreach (var a in Actors)
ret += (int)a.ActorID * Sync.CalculateSyncHash(a);
// hash all the actors
foreach (var a in Actors)
ret += n++ * (int)a.ActorID * Sync.CalculateSyncHash(a);
// hash all the traits that tick
foreach (var x in traitDict.ActorsWithTraitMultiple<object>(this))
ret += n++ * (int)x.Actor.ActorID * Sync.CalculateSyncHash(x.Trait);
// Hash the shared rng
ret += SharedRandom.Last;
return ret;
}
}

520
OpenRA.Gl/GraphicsDevice.cs Normal file → Executable file
View File

@@ -6,252 +6,264 @@
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
using System;
#endregion
using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using OpenRA.FileFormats.Graphics;
using Tao.Cg;
using Tao.OpenGl;
using Tao.Sdl;
[assembly: Renderer( typeof( OpenRA.GlRenderer.GraphicsDevice ))]
using System.Windows.Forms;
using OpenRA.FileFormats.Graphics;
using Tao.Cg;
using Tao.OpenGl;
using Tao.Sdl;
[assembly: Renderer(typeof(OpenRA.GlRenderer.GraphicsDevice))]
namespace OpenRA.GlRenderer
{
public class GraphicsDevice : IGraphicsDevice
{
Size windowSize;
internal IntPtr cgContext;
internal int vertexProfile, fragmentProfile;
public class GraphicsDevice : IGraphicsDevice
{
Size windowSize;
internal IntPtr cgContext;
internal int vertexProfile, fragmentProfile;
IntPtr surf;
IntPtr surf;
public Size WindowSize { get { return windowSize; } }
public Size WindowSize { get { return windowSize; } }
internal static void CheckGlError()
{
var n = Gl.glGetError();
if (n != Gl.GL_NO_ERROR)
throw new InvalidOperationException("GL Error");
}
public enum GlError
{
GL_NO_ERROR = Gl.GL_NO_ERROR,
GL_INVALID_ENUM = Gl.GL_INVALID_ENUM,
GL_INVALID_VALUE = Gl.GL_INVALID_VALUE,
GL_STACK_OVERFLOW = Gl.GL_STACK_OVERFLOW,
GL_STACK_UNDERFLOW = Gl.GL_STACK_UNDERFLOW,
GL_OUT_OF_MEMORY = Gl.GL_OUT_OF_MEMORY,
GL_TABLE_TOO_LARGE = Gl.GL_TABLE_TOO_LARGE,
}
public GraphicsDevice(int width, int height, WindowMode window, bool vsync)
{
Sdl.SDL_Init(Sdl.SDL_INIT_NOPARACHUTE | Sdl.SDL_INIT_VIDEO);
Sdl.SDL_GL_SetAttribute(Sdl.SDL_GL_DOUBLEBUFFER, 1);
Sdl.SDL_GL_SetAttribute(Sdl.SDL_GL_RED_SIZE, 8);
Sdl.SDL_GL_SetAttribute(Sdl.SDL_GL_GREEN_SIZE, 8);
Sdl.SDL_GL_SetAttribute(Sdl.SDL_GL_BLUE_SIZE, 8);
Sdl.SDL_GL_SetAttribute(Sdl.SDL_GL_ALPHA_SIZE, 0);
int windowFlags = 0;
switch( window )
{
case WindowMode.Fullscreen:
windowFlags |= Sdl.SDL_FULLSCREEN;
break;
case WindowMode.PseudoFullscreen:
// pseudo-fullscreen only reliably works on windows; fall back to fullscreen for everyone else
windowFlags |= ( Environment.OSVersion.Platform == PlatformID.Win32NT ) ? Sdl.SDL_NOFRAME : Sdl.SDL_FULLSCREEN;
Environment.SetEnvironmentVariable( "SDL_VIDEO_WINDOW_POS", "0,0" );
break;
default:
break;
}
surf = Sdl.SDL_SetVideoMode(width, height, 0, Sdl.SDL_OPENGL | windowFlags);
internal static void CheckGlError()
{
var n = Gl.glGetError();
if (n != Gl.GL_NO_ERROR)
throw new InvalidOperationException("GL Error: " + ((GlError)n).ToString());
}
public GraphicsDevice(int width, int height, WindowMode window, bool vsync)
{
Sdl.SDL_Init(Sdl.SDL_INIT_NOPARACHUTE | Sdl.SDL_INIT_VIDEO);
Sdl.SDL_GL_SetAttribute(Sdl.SDL_GL_DOUBLEBUFFER, 1);
Sdl.SDL_GL_SetAttribute(Sdl.SDL_GL_RED_SIZE, 8);
Sdl.SDL_GL_SetAttribute(Sdl.SDL_GL_GREEN_SIZE, 8);
Sdl.SDL_GL_SetAttribute(Sdl.SDL_GL_BLUE_SIZE, 8);
Sdl.SDL_GL_SetAttribute(Sdl.SDL_GL_ALPHA_SIZE, 0);
int windowFlags = 0;
switch (window)
{
case WindowMode.Fullscreen:
windowFlags |= Sdl.SDL_FULLSCREEN;
break;
case WindowMode.PseudoFullscreen:
// pseudo-fullscreen only reliably works on windows; fall back to fullscreen for everyone else
windowFlags |= (Environment.OSVersion.Platform == PlatformID.Win32NT) ? Sdl.SDL_NOFRAME : Sdl.SDL_FULLSCREEN;
Environment.SetEnvironmentVariable("SDL_VIDEO_WINDOW_POS", "0,0");
break;
default:
break;
}
surf = Sdl.SDL_SetVideoMode(width, height, 0, Sdl.SDL_OPENGL | windowFlags);
Sdl.SDL_WM_SetCaption("OpenRA", "OpenRA");
Sdl.SDL_ShowCursor(0);
Sdl.SDL_EnableUNICODE(1);
Sdl.SDL_EnableKeyRepeat(Sdl.SDL_DEFAULT_REPEAT_DELAY, Sdl.SDL_DEFAULT_REPEAT_INTERVAL);
CheckGlError();
windowSize = new Size(width, height);
cgContext = Cg.cgCreateContext();
Cg.cgSetErrorCallback(CgErrorCallback);
CgGl.cgGLRegisterStates(cgContext);
CgGl.cgGLSetManageTextureParameters(cgContext, true);
vertexProfile = CgGl.cgGLGetLatestProfile(CgGl.CG_GL_VERTEX);
fragmentProfile = CgGl.cgGLGetLatestProfile(CgGl.CG_GL_FRAGMENT);
//Console.WriteLine("VP Profile: " + vertexProfile);
//Console.WriteLine("FP Profile: " + fragmentProfile);
Gl.glEnableClientState(Gl.GL_VERTEX_ARRAY);
CheckGlError();
Gl.glEnableClientState(Gl.GL_TEXTURE_COORD_ARRAY);
CheckGlError();
Sdl.SDL_SetModState(0); // i have had enough.
}
static Cg.CGerrorCallbackFuncDelegate CgErrorCallback = () =>
{
var err = Cg.cgGetError();
var str = Cg.cgGetErrorString(err);
throw new InvalidOperationException(
string.Format("CG Error: {0}: {1}", err, str));
};
public void EnableScissor(int left, int top, int width, int height)
{
if (width < 0) width = 0;
if (height < 0) height = 0;
Gl.glScissor(left, windowSize.Height - (top + height), width, height);
CheckGlError();
Gl.glEnable(Gl.GL_SCISSOR_TEST);
CheckGlError();
}
public void DisableScissor()
{
Gl.glDisable(Gl.GL_SCISSOR_TEST);
CheckGlError();
}
public void Begin() { }
public void End() { }
public void Clear(Color c)
{
Gl.glClearColor(0, 0, 0, 0);
CheckGlError();
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT);
CheckGlError();
}
MouseButtons lastButtonBits = (MouseButtons)0;
static MouseButtons MakeButton(byte b)
{
return b == Sdl.SDL_BUTTON_LEFT ? MouseButtons.Left
: b == Sdl.SDL_BUTTON_RIGHT ? MouseButtons.Right
: b == Sdl.SDL_BUTTON_MIDDLE ? MouseButtons.Middle
: 0;
}
static Modifiers MakeModifiers(int raw)
{
return ((raw & Sdl.KMOD_ALT) != 0 ? Modifiers.Alt : 0)
| ((raw & Sdl.KMOD_CTRL) != 0 ? Modifiers.Ctrl : 0)
| ((raw & Sdl.KMOD_SHIFT) != 0 ? Modifiers.Shift : 0);
}
bool HandleSpecialKey(KeyInput k)
{
switch (k.VirtKey)
{
case Sdl.SDLK_F13:
var path = Environment.GetFolderPath(Environment.SpecialFolder.Personal)
+ Path.DirectorySeparatorChar + DateTime.UtcNow.ToString("OpenRA-yyyy-MM-ddThhmmssZ") + ".bmp";
Sdl.SDL_SaveBMP(surf, path);
return true;
case Sdl.SDLK_F4:
if (k.Modifiers.HasModifier(Modifiers.Alt))
{
OpenRA.Game.Exit();
return true;
}
return false;
default:
return false;
}
}
public void Present()
{
Sdl.SDL_GL_SwapBuffers();
Game.HasInputFocus = 0 != (Sdl.SDL_GetAppState() & Sdl.SDL_APPINPUTFOCUS);
Sdl.SDL_WM_SetCaption("OpenRA", "OpenRA");
Sdl.SDL_ShowCursor(0);
Sdl.SDL_EnableUNICODE(1);
Sdl.SDL_EnableKeyRepeat(Sdl.SDL_DEFAULT_REPEAT_DELAY, Sdl.SDL_DEFAULT_REPEAT_INTERVAL);
CheckGlError();
windowSize = new Size(width, height);
cgContext = Cg.cgCreateContext();
Cg.cgSetErrorCallback(CgErrorCallback);
CgGl.cgGLRegisterStates(cgContext);
CgGl.cgGLSetManageTextureParameters(cgContext, true);
vertexProfile = CgGl.cgGLGetLatestProfile(CgGl.CG_GL_VERTEX);
fragmentProfile = CgGl.cgGLGetLatestProfile(CgGl.CG_GL_FRAGMENT);
//Console.WriteLine("VP Profile: " + vertexProfile);
//Console.WriteLine("FP Profile: " + fragmentProfile);
Gl.glEnableClientState(Gl.GL_VERTEX_ARRAY);
CheckGlError();
Gl.glEnableClientState(Gl.GL_TEXTURE_COORD_ARRAY);
CheckGlError();
Sdl.SDL_SetModState(0); // i have had enough.
}
static Cg.CGerrorCallbackFuncDelegate CgErrorCallback = () =>
{
var err = Cg.cgGetError();
var str = Cg.cgGetErrorString(err);
throw new InvalidOperationException(
string.Format("CG Error: {0}: {1}", err, str));
};
public void EnableScissor(int left, int top, int width, int height)
{
if (width < 0) width = 0;
if (height < 0) height = 0;
Gl.glScissor(left, windowSize.Height - (top + height), width, height);
CheckGlError();
Gl.glEnable(Gl.GL_SCISSOR_TEST);
CheckGlError();
}
public void DisableScissor()
{
Gl.glDisable(Gl.GL_SCISSOR_TEST);
CheckGlError();
}
public void Begin() { }
public void End() { }
public void Clear(Color c)
{
Gl.glClearColor(0, 0, 0, 0);
CheckGlError();
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT);
CheckGlError();
}
MouseButtons lastButtonBits = (MouseButtons)0;
static MouseButtons MakeButton(byte b)
{
return b == Sdl.SDL_BUTTON_LEFT ? MouseButtons.Left
: b == Sdl.SDL_BUTTON_RIGHT ? MouseButtons.Right
: b == Sdl.SDL_BUTTON_MIDDLE ? MouseButtons.Middle
: 0;
}
static Modifiers MakeModifiers(int raw)
{
return ((raw & Sdl.KMOD_ALT) != 0 ? Modifiers.Alt : 0)
| ((raw & Sdl.KMOD_CTRL) != 0 ? Modifiers.Ctrl : 0)
| ((raw & Sdl.KMOD_SHIFT) != 0 ? Modifiers.Shift : 0);
}
bool HandleSpecialKey(KeyInput k)
{
switch (k.VirtKey)
{
case Sdl.SDLK_F13:
var path = Environment.GetFolderPath(Environment.SpecialFolder.Personal)
+ Path.DirectorySeparatorChar + DateTime.UtcNow.ToString("OpenRA-yyyy-MM-ddThhmmssZ") + ".bmp";
Sdl.SDL_SaveBMP(surf, path);
return true;
case Sdl.SDLK_F4:
if (k.Modifiers.HasModifier(Modifiers.Alt))
{
OpenRA.Game.Exit();
return true;
}
return false;
default:
return false;
}
}
public void Present()
{
Sdl.SDL_GL_SwapBuffers();
var mods = MakeModifiers(Sdl.SDL_GetModState());
Game.HandleModifierKeys(mods);
var mods = MakeModifiers(Sdl.SDL_GetModState());
Game.HandleModifierKeys(mods);
MouseEventArgs pendingMotion = null;
Sdl.SDL_Event e;
while (Sdl.SDL_PollEvent(out e) != 0)
{
switch (e.type)
{
case Sdl.SDL_QUIT:
OpenRA.Game.Exit();
break;
Sdl.SDL_Event e;
while (Sdl.SDL_PollEvent(out e) != 0)
{
switch (e.type)
{
case Sdl.SDL_QUIT:
OpenRA.Game.Exit();
break;
case Sdl.SDL_MOUSEBUTTONDOWN:
{
case Sdl.SDL_MOUSEBUTTONDOWN:
{
if (pendingMotion != null)
{
Game.DispatchMouseInput(MouseInputEvent.Move, pendingMotion, mods);
pendingMotion = null;
}
var button = MakeButton(e.button.button);
lastButtonBits |= button;
var button = MakeButton(e.button.button);
lastButtonBits |= button;
Game.DispatchMouseInput(MouseInputEvent.Down,
new MouseEventArgs(button, 1, e.button.x, e.button.y, 0),
mods);
} break;
Game.DispatchMouseInput(MouseInputEvent.Down,
new MouseEventArgs(button, 1, e.button.x, e.button.y, 0),
mods);
} break;
case Sdl.SDL_MOUSEBUTTONUP:
{
case Sdl.SDL_MOUSEBUTTONUP:
{
if (pendingMotion != null)
{
Game.DispatchMouseInput(MouseInputEvent.Move, pendingMotion, mods);
pendingMotion = null;
}
var button = MakeButton(e.button.button);
lastButtonBits &= ~button;
var button = MakeButton(e.button.button);
lastButtonBits &= ~button;
Game.DispatchMouseInput(MouseInputEvent.Up,
new MouseEventArgs(button, 1, e.button.x, e.button.y, 0),
mods);
} break;
Game.DispatchMouseInput(MouseInputEvent.Up,
new MouseEventArgs(button, 1, e.button.x, e.button.y, 0),
mods);
} break;
case Sdl.SDL_MOUSEMOTION:
{
case Sdl.SDL_MOUSEMOTION:
{
pendingMotion = new MouseEventArgs(lastButtonBits, 0, e.motion.x, e.motion.y, 0);
} break;
} break;
case Sdl.SDL_KEYDOWN:
{
var keyEvent = new KeyInput
{
Event = KeyInputEvent.Down,
Modifiers = mods,
KeyChar = (char) e.key.keysym.unicode,
KeyName = Sdl.SDL_GetKeyName( e.key.keysym.sym ),
VirtKey = e.key.keysym.sym
};
case Sdl.SDL_KEYDOWN:
{
var keyEvent = new KeyInput
{
Event = KeyInputEvent.Down,
Modifiers = mods,
KeyChar = (char)e.key.keysym.unicode,
KeyName = Sdl.SDL_GetKeyName(e.key.keysym.sym),
VirtKey = e.key.keysym.sym
};
if (!HandleSpecialKey(keyEvent))
Game.HandleKeyEvent(keyEvent);
} break;
if (!HandleSpecialKey(keyEvent))
Game.HandleKeyEvent(keyEvent);
} break;
case Sdl.SDL_KEYUP:
{
var keyEvent = new KeyInput
{
Event = KeyInputEvent.Up,
Modifiers = mods,
KeyChar = (char) e.key.keysym.unicode,
KeyName = Sdl.SDL_GetKeyName( e.key.keysym.sym ),
VirtKey = e.key.keysym.sym
};
Game.HandleKeyEvent(keyEvent);
} break;
}
}
case Sdl.SDL_KEYUP:
{
var keyEvent = new KeyInput
{
Event = KeyInputEvent.Up,
Modifiers = mods,
KeyChar = (char)e.key.keysym.unicode,
KeyName = Sdl.SDL_GetKeyName(e.key.keysym.sym),
VirtKey = e.key.keysym.sym
};
Game.HandleKeyEvent(keyEvent);
} break;
}
}
if (pendingMotion != null)
{
@@ -259,49 +271,49 @@ namespace OpenRA.GlRenderer
pendingMotion = null;
}
CheckGlError();
}
CheckGlError();
}
public void DrawIndexedPrimitives(PrimitiveType pt, Range<int> vertices, Range<int> indices)
{
Gl.glDrawElements(ModeFromPrimitiveType(pt), indices.End - indices.Start,
Gl.GL_UNSIGNED_SHORT, new IntPtr(indices.Start * 2));
CheckGlError();
}
public void DrawIndexedPrimitives(PrimitiveType pt, Range<int> vertices, Range<int> indices)
{
Gl.glDrawElements(ModeFromPrimitiveType(pt), indices.End - indices.Start,
Gl.GL_UNSIGNED_SHORT, new IntPtr(indices.Start * 2));
CheckGlError();
}
public void DrawIndexedPrimitives(PrimitiveType pt, int numVerts, int numPrimitives)
{
Gl.glDrawElements(ModeFromPrimitiveType(pt), numPrimitives * IndicesPerPrimitive(pt),
Gl.GL_UNSIGNED_SHORT, IntPtr.Zero);
CheckGlError();
}
public void DrawIndexedPrimitives(PrimitiveType pt, int numVerts, int numPrimitives)
{
Gl.glDrawElements(ModeFromPrimitiveType(pt), numPrimitives * IndicesPerPrimitive(pt),
Gl.GL_UNSIGNED_SHORT, IntPtr.Zero);
CheckGlError();
}
static int ModeFromPrimitiveType(PrimitiveType pt)
{
switch (pt)
{
case PrimitiveType.PointList: return Gl.GL_POINTS;
case PrimitiveType.LineList: return Gl.GL_LINES;
case PrimitiveType.TriangleList: return Gl.GL_TRIANGLES;
}
throw new NotImplementedException();
}
static int ModeFromPrimitiveType(PrimitiveType pt)
{
switch (pt)
{
case PrimitiveType.PointList: return Gl.GL_POINTS;
case PrimitiveType.LineList: return Gl.GL_LINES;
case PrimitiveType.TriangleList: return Gl.GL_TRIANGLES;
}
throw new NotImplementedException();
}
static int IndicesPerPrimitive(PrimitiveType pt)
{
switch (pt)
{
case PrimitiveType.PointList: return 1;
case PrimitiveType.LineList: return 2;
case PrimitiveType.TriangleList: return 3;
}
throw new NotImplementedException();
}
static int IndicesPerPrimitive(PrimitiveType pt)
{
switch (pt)
{
case PrimitiveType.PointList: return 1;
case PrimitiveType.LineList: return 2;
case PrimitiveType.TriangleList: return 3;
}
throw new NotImplementedException();
}
public IVertexBuffer<Vertex> CreateVertexBuffer(int size) { return new VertexBuffer<Vertex>(this, size); }
public IIndexBuffer CreateIndexBuffer(int size) { return new IndexBuffer(this, size); }
public ITexture CreateTexture() { return new Texture(this); }
public ITexture CreateTexture(Bitmap bitmap) { return new Texture(this, bitmap); }
public IShader CreateShader(Stream stream) { return new Shader(this, stream); }
}
}
public IVertexBuffer<Vertex> CreateVertexBuffer(int size) { return new VertexBuffer<Vertex>(this, size); }
public IIndexBuffer CreateIndexBuffer(int size) { return new IndexBuffer(this, size); }
public ITexture CreateTexture() { return new Texture(this); }
public ITexture CreateTexture(Bitmap bitmap) { return new Texture(this, bitmap); }
public IShader CreateShader(Stream stream) { return new Shader(this, stream); }
}
}

View File

@@ -0,0 +1,73 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Support;
using OpenRA.Graphics;
using OpenRA.Widgets;
namespace OpenRA.Mods.Cnc
{
public class CncLoadScreen : ILoadScreen
{
static string[] Comments = new[] { "Filling Crates...", "Charging Capacitors...", "Reticulating Splines...",
"Planting Trees...", "Building Bridges...", "Aging Empires...",
"Compiling EVA...", "Constructing Pylons...", "Activating Skynet...",
"Splitting Atoms..."
};
Stopwatch lastLoadScreen = new Stopwatch();
Rectangle StripeRect;
Sprite Stripe, Logo;
float2 LogoPos;
Renderer r;
SpriteFont Font;
public void Init()
{
// Avoid standard loading mechanisms so we
// can display loadscreen as early as possible
r = Game.Renderer;
if (r == null) return;
Font = r.BoldFont;
var s = new Sheet("mods/cnc/uibits/loadscreen.png");
Logo = new Sprite(s, new Rectangle(0,0,256,256), TextureChannel.Alpha);
Stripe = new Sprite(s, new Rectangle(256,0,256,256), TextureChannel.Alpha);
StripeRect = new Rectangle(0, Renderer.Resolution.Height/2 - 128, Renderer.Resolution.Width, 256);
LogoPos = new float2(Renderer.Resolution.Width/2 - 128, Renderer.Resolution.Height/2 - 128);
}
public void Display()
{
if (r == null)
return;
// Update text at most every 0.5 seconds
if (lastLoadScreen.ElapsedTime() < 0.5)
return;
lastLoadScreen.Reset();
var text = Comments.Random(Game.CosmeticRandom);
var textSize = Font.Measure(text);
r.BeginFrame(float2.Zero);
WidgetUtils.FillRectWithSprite(StripeRect, Stripe);
r.RgbaSpriteRenderer.DrawSprite(Logo, LogoPos);
Font.DrawText(text, new float2(Renderer.Resolution.Width - textSize.X - 20, Renderer.Resolution.Height - textSize.Y - 20), Color.White);
r.RgbaSpriteRenderer.Flush();
r.EndFrame();
}
}
}

View File

@@ -36,7 +36,7 @@ namespace OpenRA.Mods.Cnc.Effects
{
yield return new Renderable(anim.Image,
target.CenterLocation - new float2(.5f * anim.Image.size.X, anim.Image.size.Y - Game.CellSize),
"effect");
"effect", (int)target.CenterLocation.Y);
}
void Finish( World world )

View File

@@ -9,6 +9,7 @@
#endregion
using OpenRA.Mods.Cnc.Effects;
using OpenRA.Mods.RA;
using OpenRA.Orders;
using OpenRA.Traits;

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -62,6 +62,7 @@
<Compile Include="Missions\Gdi01Script.cs" />
<Compile Include="RenderGunboat.cs" />
<Compile Include="RenderCargo.cs" />
<Compile Include="CncLoadScreen.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">
@@ -91,10 +92,6 @@
<PropertyGroup>
<PostBuildEvent>mkdir "$(SolutionDir)mods/cnc/"
copy "$(TargetPath)" "$(SolutionDir)mods/cnc/"
cd "$(SolutionDir)"
ralint cnc</PostBuildEvent>
cd "$(SolutionDir)"</PostBuildEvent>
</PropertyGroup>
<ItemGroup>
<Folder Include="Missions\" />
</ItemGroup>
</Project>

View File

@@ -33,26 +33,17 @@ namespace OpenRA.Mods.Cnc
public void Tick(Actor self)
{
if (--poisonTicks <= 0)
{
var rl = self.World.WorldActor.Trait<ResourceLayer>();
var r = rl.GetResource(self.Location);
if (--poisonTicks > 0) return;
if (r != null && info.Resources.Contains(r.info.Name))
Combat.DoImpacts(new ProjectileArgs
{
src = self.CenterLocation.ToInt2(),
dest = self.CenterLocation.ToInt2(),
srcAltitude = 0,
destAltitude = 0,
facing = 0,
firedBy = self,
target = Target.FromActor(self),
weapon = Rules.Weapons[info.Weapon.ToLowerInvariant()]
});
var rl = self.World.WorldActor.Trait<ResourceLayer>();
var r = rl.GetResource(self.Location);
if( r == null ) return;
if( !info.Resources.Contains(r.info.Name) ) return;
poisonTicks = Rules.Weapons[info.Weapon.ToLowerInvariant()].ROF;
}
var weapon = Rules.Weapons[info.Weapon.ToLowerInvariant()];
self.InflictDamage( self.World.WorldActor, weapon.Warheads[ 0 ].Damage, weapon.Warheads[ 0 ] );
poisonTicks = weapon.ROF;
}
}
}

View File

@@ -37,8 +37,7 @@ namespace OpenRA.Mods.Cnc
// Assume a single exit point for simplicity
var spawn = self.CenterLocation + Spawns.First().First;
var exit = self.Location + Spawns.First().Second;
var exit = self.Info.Traits.WithInterface<ExitInfo>().First();
var rb = self.Trait<RenderBuilding>();
rb.PlayCustomAnimRepeating(self, "active");
@@ -52,12 +51,6 @@ namespace OpenRA.Mods.Cnc
new AltitudeInit( Rules.Info["c17"].Traits.Get<PlaneInfo>().CruiseAltitude ),
});
var cargo = a.Trait<Cargo>();
var newUnit = self.World.CreateActor(false, producee.Name, new TypeDictionary
{
new OwnerInit( self.Owner ),
});
cargo.Load(a, newUnit);
a.QueueActivity(new Fly(self.Location + new int2(6,0)));
a.QueueActivity(new Land(Target.FromActor(self)));
a.QueueActivity(new CallFunc(() =>
@@ -65,7 +58,7 @@ namespace OpenRA.Mods.Cnc
if (self.IsDead())
return;
rb.PlayCustomAnimRepeating(self, "idle");
self.World.AddFrameEndTask(ww => DoProduction(self, cargo.Unload(self), exit, spawn));
self.World.AddFrameEndTask(ww => DoProduction(self, producee, exit));
}));
a.QueueActivity(new Fly(endPos));
a.QueueActivity(new RemoveSelf());

View File

@@ -14,32 +14,34 @@ namespace OpenRA.Mods.RA.Activities
{
class CaptureBuilding : IActivity
{
Actor target;
Target target;
public CaptureBuilding(Actor target) { this.target = target; }
public CaptureBuilding(Actor target) { this.target = Target.FromActor(target); }
public IActivity NextActivity { get; set; }
public IActivity Tick(Actor self)
{
if (target == null || target.IsDead()) return NextActivity;
target.World.AddFrameEndTask(w =>
if (!target.IsValid) return NextActivity;
if ((target.Actor.Location - self.Location).Length > 1)
return NextActivity;
self.World.AddFrameEndTask(w =>
{
// momentarily remove from world so the ownership queries don't get confused
var oldOwner = target.Owner;
w.Remove(target);
target.Owner = self.Owner;
w.Add(target);
var oldOwner = target.Actor.Owner;
w.Remove(target.Actor);
target.Actor.Owner = self.Owner;
w.Add(target.Actor);
foreach (var t in target.TraitsImplementing<INotifyCapture>())
t.OnCapture(target, self, oldOwner, self.Owner);
foreach (var t in target.Actor.TraitsImplementing<INotifyCapture>())
t.OnCapture(target.Actor, self, oldOwner, self.Owner);
self.Destroy();
});
return NextActivity;
}
public void Cancel(Actor self) { target = null; NextActivity = null; }
public void Cancel(Actor self) { target = Target.None; NextActivity = null; }
}
}

Some files were not shown because too many files have changed in this diff Show More