Compare commits

...

627 Commits

Author SHA1 Message Date
ScottNZ
ad5e1cbe3a Merge pull request #6027 from OpenRA/revert-5763-build-shift+keypress
Revert "Make Shift+<Hotkey> queue five units/buildings. Fixes #5544."
2014-07-22 22:36:43 +12:00
Paul Chote
3744a1af25 Revert "Make Shift+<Hotkey> queue five units/buildings. Fixes #5544." 2014-07-22 20:16:47 +12:00
Chris Forbes
3780a70045 Merge pull request #6021 from pchote/gtwr-fix
Give GTWR back to both factions.
2014-07-22 11:25:08 +12:00
Paul Chote
5d0282188c Give GTWR back to both factions. 2014-07-22 10:19:20 +12:00
Chris Forbes
8174cbc88f Merge pull request #5994 from deniz1a/prod_order
Reordered production palette according to prerequisites.
2014-07-21 13:50:49 +12:00
reaperrr
582c1016e9 Merge pull request #5998 from Mailaender/ts-bibs
Added bibs to Tiberian Sun refinery and factories
2014-07-20 12:48:53 +02:00
Matthias Mailänder
702b3f7d20 these are already fixed with the addition of isometry 2014-07-20 11:29:12 +02:00
Matthias Mailänder
dbe64f496b add bibs to refinery and factories 2014-07-20 11:28:06 +02:00
Deniz Ayıkol
686c043151 Put Minelayer.AT before Minelayer.AP 2014-07-19 20:16:34 +03:00
Deniz Ayıkol
6e8a002dad Reordered production palette according to prerequisites. 2014-07-19 19:36:36 +03:00
Matthias Mailänder
6c1efac235 Merge pull request #5977 from pchote/oi-keep-moving
Don’t cancel MoveAdjacentTo / MoveWithinRange when target becomes invalid
2014-07-19 09:39:32 +02:00
Matthias Mailänder
d2aa97c1d1 Merge pull request #5990 from pchote/repair-fix
Play the correct race notification when repairing an ally’s structure.
2014-07-19 08:08:05 +02:00
Paul Chote
850fcd5100 Fix a typo. 2014-07-19 18:03:21 +12:00
Paul Chote
5b0cee78cf Calculate a new path (and possibly new target cell) if the original path is blocked. 2014-07-19 18:03:21 +12:00
Paul Chote
e805461be7 Don’t cancel MoveAdjacentTo / MoveWithinRange when target becomes invalid.
Move to the last known position instead.  Fixes #5968.
2014-07-19 15:42:52 +12:00
Paul Chote
c2ba2fe12b Play the correct race notification when repairing an ally’s structure. 2014-07-19 15:33:06 +12:00
obrakmann
312041b9c8 Merge pull request #5988 from pchote/shellmap-paradrop
Fix scripted paradrops.
2014-07-19 05:01:27 +02:00
Oliver Brakmann
0cf49ad49f Fix old-lua paradrop too. 2014-07-19 14:42:36 +12:00
Paul Chote
87e425042f Fix scripted paradrops. 2014-07-19 14:40:29 +12:00
obrakmann
54191039a9 Merge pull request #5989 from pchote/frozen-target-fix
Fix frozen actors being targetable under shroud.
2014-07-19 04:16:56 +02:00
Paul Chote
bcc32d15ed Fix frozen actors being targetable under shroud. Fixes #5979, #5978. 2014-07-19 12:56:52 +12:00
Paul Chote
0f03d6bee8 Merge pull request #5987 from reaperrr/gem-mine-palette
Fixes gem mine desert palette
2014-07-19 12:00:49 +12:00
reaperrr
a447e35695 Fixes gem mine desert palette. 2014-07-18 22:47:11 +02:00
Paul Chote
58abd45ed9 Merge pull request #5967 from obrakmann/fix5651
Fix aircraft losing selection outside the map borders
2014-07-18 20:36:02 +12:00
Paul Chote
8a65632851 Merge pull request #5965 from WolfGaming/CustomPrereqChange
Adds the RequiresPrerequisites field into ProvidesCustomPrerequisite
2014-07-18 20:29:11 +12:00
Oliver Brakmann
42f963d687 Fix aircraft losing selection outside the map borders
Fixes #5651
2014-07-18 10:03:57 +02:00
WolfGaming
7b10da6bde Adds the RequiresPrerequisites field into ProvidesCustomPrerequisite and all the logic behind it. 2014-07-18 06:11:03 +00:00
Chris Forbes
62820430de Merge pull request #5974 from pchote/cratefix
Fix unit collection crates and drop-zone maps.
2014-07-18 12:58:24 +12:00
abcdefg30
8f60b9b652 Fixed drop-zone units 2014-07-18 11:39:43 +12:00
Paul Chote
e3dae2edd0 Replace the obsolete race check from GiveUnitCrateAction. 2014-07-15 10:15:35 +12:00
Paul Chote
8bce37710b Merge pull request #5955 from Squiggles211/production_cancel_fix
Restored PlaceBuilding order's ProductionQueue checks.
2014-07-14 20:06:50 +12:00
Chris Forbes
709f29184a Merge pull request #5954 from abcdefg30/fixhijacker
Made Hijacker buildable by soviets
2014-07-14 08:45:51 +12:00
Squiggles211
006f7b888a Restored production queue current item checks
Fixes regression #5948 where you could freely build any building by
canceling the production before deploying by restoring the currentItem
checks in the PlaceBuilding order to ensure that the production is still
valid.
2014-07-13 14:06:30 -05:00
abcdefg30
1ef3099910 Hijacker again buildable by soviets 2014-07-13 20:39:54 +02:00
Matthias Mailänder
aca0b9d7dd Merge pull request #5932 from MustaphaTR/d2k-only-inf-fix
D2K - Fixed some tiles should be only infantry
2014-07-13 08:34:06 +02:00
Chris Forbes
e7cd4e07f9 Merge pull request #5946 from Phrohdoh/MoreTraitDocs
Added some trait [Desc()]s.
2014-07-13 17:51:55 +12:00
Taryn Hill
da001385ae Added some trait [Desc()]s. 2014-07-12 13:31:14 -05:00
Matthias Mailänder
a03d607878 Merge pull request #5930 from MustaphaTR/ra-oil-explode
RA - Explosive Oil Derricks
2014-07-12 11:25:30 +02:00
Chris Forbes
d8df332d97 Merge pull request #5940 from Mailaender/fort-lonestar-tech-disable
Fixed unbuildable high-tech on Fort Lonestar
2014-07-12 20:28:56 +12:00
Matthias Mailänder
e512799eeb disable tech properly 2014-07-12 09:47:42 +02:00
Matthias Mailänder
8afddd9497 Merge pull request #5938 from abcdefg30/fortlonestar
Fixed a bug in Fort Lonestar
2014-07-12 09:45:00 +02:00
abcdefg30
b87ea6ddef Update fort-lonestar.lua 2014-07-11 23:47:02 +02:00
Mustafa Alperen Seki
70af7f3595 Changed some tiles types 2014-07-11 16:34:16 +03:00
Mustafa Alperen Seki
b6a39c5993 Explosive Oil Derricks 2014-07-11 15:08:41 +03:00
Matthias Mailänder
a357bceb35 Merge pull request #5926 from pchote/ra-tabs
Fixes #5915
2014-07-11 13:42:21 +02:00
Matthias Mailänder
43242245b8 Merge pull request #5927 from MustaphaTR/ra-building-sort
Fixes #5914
2014-07-11 13:34:11 +02:00
Mustafa Alperen Seki
5fa4a5fa20 Sort Changes 2014-07-11 12:56:45 +03:00
Paul Chote
393702fe67 Fix bogus inconsistencies in the ra tab images:
- Soviet-normal tab glyphs were off by 1px.
- Allied-selected tabs had random semi-transparent pixels.
- Most tabs had a discoloured pixel near the left edge.
2014-07-11 20:04:03 +12:00
Paul Chote
1aacb21b04 Enable correct tab images for helicopters and aircraft. 2014-07-11 18:27:35 +12:00
Paul Chote
fc882437f0 Fix incorrect soviet tab image coordinates. 2014-07-11 18:26:00 +12:00
Daniel Hernandez
bac2b4f28e Add opposing-faction tab art for aircraft and navy, 2014-07-11 18:11:40 +12:00
Paul Chote
ee27b248d8 Remove bitrotted tab source artwork. 2014-07-11 18:09:32 +12:00
Paul Chote
fd2254f9db Merge pull request #5924 from Cr0s/patch-1
Fixed typo in HackyAI building placement code
2014-07-11 18:07:32 +12:00
Paul Chote
be2357f509 Merge pull request #5917 from pavlos256/deterministic-sort
Make tiles sorting deterministic in all cases
2014-07-11 17:53:08 +12:00
Cr0s
0f363d4c0f Fixed typo in HackAI building placement code 2014-07-11 05:44:45 +04:00
Matthias Mailänder
efeba3ec4f Merge pull request #5898 from MustaphaTR/d2k-techlevel
D2k Tech Level
2014-07-10 19:05:35 +02:00
Mustafa Alperen Seki
ec69e05433 Added D2K Tech Levels 2014-07-10 17:17:11 +03:00
Matthias Mailänder
6af834c436 Merge pull request #5901 from ScottNZ/techlevel
Add tech levels to ra
2014-07-10 15:07:46 +02:00
Matthias Mailänder
e8a7d4d93a Merge pull request #5911 from pchote/concrete-fix
Add AllowInvalidPlacement check to IsCellBuildable.
2014-07-10 13:41:02 +02:00
Pavlos Touboulidis
f45d063f1e Make tiles sorting deterministic in all cases
This may fix issue #5916.

In any case, it's wanted because this kind of sort is "unstable".
According to the docs:

    "This implementation performs an unstable sort; that is, if two
    elements are equal, their order might not be preserved."
2014-07-10 12:40:38 +03:00
Paul Chote
c6ed6dbeb9 Remove redundant overload and return early if outside map. 2014-07-10 20:34:17 +12:00
Matthias Mailänder
17310b7234 Merge pull request #5912 from pchote/powr-fix
Allow NormalizeSequence to remove existing damage prefixes.
2014-07-10 09:37:31 +02:00
Matthias Mailänder
d3128463c0 Merge pull request #5907 from reaperrr/misc-ts-fixes
More TS fixes & tuning
2014-07-10 09:04:22 +02:00
Paul Chote
2e9e4cff5c Allow NormalizeSequence to remove existing damage prefixes. Fixes #5909. 2014-07-10 17:16:46 +12:00
Paul Chote
05e1841e0e Add AllowInvalidPlacement check to IsCellBuildable. Fixes #5902. 2014-07-10 17:06:57 +12:00
reaperrr
69077629a7 Reduce infantry sequence tick values, fix Cyborg Commando idle shadow. 2014-07-09 20:14:21 +02:00
reaperrr
b09a301bb3 Added ^Tank default, adjusted movement penalties on terrain types. 2014-07-09 20:14:20 +02:00
reaperrr
1600b30fde Doubles Refinery storage capacity. 2014-07-09 20:14:19 +02:00
reaperrr
1973208694 Fixes Light Post. Closes #5903. 2014-07-09 20:13:38 +02:00
ScottNZ
f8ad69889c Add tech levels to ra 2014-07-10 01:23:29 +12:00
Matthias Mailänder
fd68c81b15 Update .travis.yml
remove failing auto-wiki-update
2014-07-09 14:11:01 +02:00
Matthias Mailänder
5f1a0ddb99 Merge pull request #5899 from obrakmann/blinky-blinky
Change the colour of the blinking READY to gold
2014-07-09 13:09:46 +02:00
Oliver Brakmann
ab4a9388ce Change defaults for the production palette's ready sign
Default is now to blink alternating between white and gold.
2014-07-09 12:09:44 +02:00
Matthias Mailänder
a816956b5e Merge pull request #5897 from pchote/disable-green
Restore blinking ready label in RA.
2014-07-09 11:37:04 +02:00
Paul Chote
8b01ed034b Restore blinking ready label in RA. 2014-07-09 21:08:00 +12:00
Paul Chote
4471891cae Merge pull request #5896 from Mailaender/d2k-parachute-corpse
Fixed missing parachute corpses in Dune 2000
2014-07-09 21:00:28 +12:00
Paul Chote
2524ead1c4 Merge pull request #5892 from Mailaender/destroyed-repair-building-nre
Added a check if the rearm host building is gone
2014-07-09 20:55:20 +12:00
Paul Chote
15ec2b40f2 Merge pull request #5890 from Mailaender/negative-spawns-crash-fix
Made GetSpawnOccupants more robust against invalid list queries
2014-07-09 20:48:12 +12:00
Matthias Mailänder
dc2880e047 bring it in line with Rearm 2014-07-09 09:35:36 +02:00
Matthias Mailänder
26ed4c24be check if the host building is gone
fixes #5670
2014-07-09 09:25:06 +02:00
Matthias Mailänder
befb11ce69 add parachute corpses
fixes #5893
2014-07-09 09:16:27 +02:00
Matthias Mailänder
971ec55679 Merge pull request #5833 from pchote/cnc-techlevels
Closes #3221
2014-07-09 08:51:29 +02:00
Matthias Mailänder
3491d3b9f8 Merge pull request #5894 from pchote/warhead-nre
Fix NRE if a unit is damaged without a warhead.
2014-07-09 08:12:08 +02:00
Paul Chote
83b559befc Fix NRE if a unit is damaged without a warhead. 2014-07-09 18:02:27 +12:00
Paul Chote
4e1f7dedba Fix the bogus D2K AI definitions. 2014-07-09 17:50:14 +12:00
Paul Chote
a46baeaf2b Reorganise AI base building logic.
- Now obeys defined structure percentages and limits.
- Faster.
- More readable and maintainable code.
2014-07-09 17:50:14 +12:00
Paul Chote
c8bd8336f7 Remove super-spammy debug messages. 2014-07-09 17:50:14 +12:00
Paul Chote
ff78b0f7ea Add tech levels to TD. 2014-07-09 17:50:14 +12:00
Matthias Mailänder
5a891daa59 make GetSpawnOccupants more robust against invalid list queries
fixes #5588
2014-07-09 06:21:59 +02:00
Paul Chote
5e96bb3f8c Merge pull request #5824 from reaperrr/pronedamage
Moved ProneDamage to Warhead
2014-07-09 11:02:02 +12:00
Paul Chote
e5b863f926 Merge pull request #5698 from Mailaender/sonar
Added the sonar pulse to reveal sub marines
2014-07-09 10:44:47 +12:00
Chris Forbes
c70087fdb2 Merge pull request #5885 from Mailaender/ra-capture-tech-oversights
Fixed captureable tech oversights in the Red Alert mod
2014-07-09 08:05:35 +12:00
Matthias Mailänder
c4dffa02da fix chronosphere being visible to soviets 2014-07-08 21:30:09 +02:00
Matthias Mailänder
5740faef21 fix Tanya being available to soviets 2014-07-08 21:27:34 +02:00
Matthias Mailänder
63d4df76a8 Merge pull request #5874 from pchote/revert-desyncs
Revert TickRender and PauseState changes
2014-07-08 21:21:49 +02:00
reaperrr
fa98eae2c3 Applies most TS prone damage values to TS mod. 2014-07-08 21:05:43 +02:00
reaperrr
fabca5dca6 Move ProneDamage modifier from TakeCover to Warhead.
Rename it to ProneModifier and convert it to integer.
2014-07-08 21:05:42 +02:00
Matthias Mailänder
b12c630e63 Merge pull request #5883 from reaperrr/ts-tib-heal
Fixes #5877
2014-07-08 21:03:50 +02:00
Matthias Mailänder
db7b7742a3 Merge pull request #5880 from MustaphaTR/ra-capturable-bio
Capturable Bio Lab
2014-07-08 20:54:53 +02:00
reaperrr
b765d5238c Add TiberiumHeal weapon and use it for healing mutants, cyborgs & critters. 2014-07-08 18:04:20 +02:00
reaperrr
343de6a244 Fix palette and add inaccuracy to Tiberian Fiend's weapon. 2014-07-08 18:02:44 +02:00
Mustafa Alperen Seki
101e57eade Capturable Bio Lab 2014-07-08 11:51:29 +03:00
Matthias Mailänder
1a81016bdc Merge pull request #5869 from reaperrr/ts-blue-tib
Added blue tiberium and blue large crystal to TS mod.
2014-07-08 08:12:12 +02:00
Paul Chote
3918c992c4 Fix D2K turret placement crash. 2014-07-08 17:12:51 +12:00
Paul Chote
1b222958d6 Don’t override custom animations if damaged. 2014-07-08 17:12:36 +12:00
Paul Chote
c639339a62 Remove the crumble overlay after it has completed. 2014-07-08 17:11:59 +12:00
Paul Chote
2b91a2363b Fix make animations. 2014-07-08 16:56:09 +12:00
Paul Chote
5650d5fc98 Revert "use TickRender() for RenderSprites and PaletteModifier"
This reverts commit 87fd576b26.
2014-07-08 11:09:54 +12:00
Paul Chote
802b6a652c Revert "new PauseState to differentiate game and editor pausing"
This reverts commit d1e18cad7a.
2014-07-08 10:42:00 +12:00
Paul Chote
18c9a25232 Revert "freeze animations during pause to visualize it better"
This reverts commit 960248fe44.
2014-07-08 10:40:06 +12:00
Paul Chote
3c2d9910e3 Revert "Undo changes to World::SetLocalPauseState to unbreak Lua"
This reverts commit 77e3d17527.
2014-07-08 10:39:18 +12:00
reaperrr
b279de1edb Fixes tiberium tree shadow frames, adds large blue crystal. 2014-07-07 22:53:24 +02:00
reaperrr
e27e7ce87c Adds blue tiberium to TS mod. 2014-07-07 22:51:00 +02:00
reaperrr
a3cb5d2d1d Renames interior tileset to temperate and adds BlueTiberium terrain type. 2014-07-07 22:49:50 +02:00
Matthias Mailänder
dfc722847a Merge pull request #5862 from obrakmann/fix-lua-pausestate
Old Lua: use the correct method to set the pause state
2014-07-07 21:57:14 +02:00
Oliver Brakmann
77e3d17527 Undo changes to World::SetLocalPauseState to unbreak Lua
Fixes #5864.
2014-07-07 21:50:37 +02:00
Matthias Mailänder
d2adc28a00 Merge pull request #5865 from obrakmann/fix5861
Fix RepairBuilding not working for AI and Lua scripts
2014-07-07 20:54:03 +02:00
Oliver Brakmann
33b916a713 Fix RepairBuilding not working for AI and Lua scripts
Fixes #5861
2014-07-07 19:43:52 +02:00
Matthias Mailänder
91a076728d generalize into SpawnActorPower
closes #5724
2014-07-07 15:27:54 +02:00
Matthias Mailänder
f60fefd5f5 add a ripple animation based on the move flash 2014-07-07 15:26:07 +02:00
Matthias Mailänder
43bca0e73d add the sonar pulse
closes #4729
2014-07-07 15:26:07 +02:00
Matthias Mailänder
5cdf0e6a67 generalize MoveFlash as parametrized SpriteEffect 2014-07-07 15:23:14 +02:00
Matthias Mailänder
4fb38c955b Merge pull request #5859 from pchote/paratrooper-cleanup
Improve paratroopers.
2014-07-07 15:19:41 +02:00
Paul Chote
e4f8816486 Fix the crate drop. 2014-07-08 00:30:55 +12:00
Paul Chote
ab26d4b0ad Overhaul ParatroopersPower:
- Adds support for multiple drop planes.
- Adds support a beacon and camera.
- Prevents the plane from circling if it can’t unload.
2014-07-08 00:30:38 +12:00
Matthias Mailänder
b8756d9de7 Merge pull request #5860 from pchote/news-fix
News fixes
2014-07-07 13:25:25 +02:00
Paul Chote
470dfa941a Merge pull request #5840 from Mailaender/map-download-isometry-nre
Fixed a NullReferenceException in auto map download.
2014-07-07 22:31:25 +12:00
Paul Chote
d0a972f3b7 Merge pull request #5835 from Squiggles211/wall-damage
Removed false damage states which caused invisible walls.  Fixes #5654
2014-07-07 22:27:25 +12:00
Paul Chote
ad375c5734 Reorganize news parsing. Fixes #5647. 2014-07-07 22:23:04 +12:00
Paul Chote
c352ff644f Use a shared url for news updates. Fixes #5603. 2014-07-07 21:48:07 +12:00
Matthias Mailänder
fa83507a62 Merge pull request #5854 from pchote/ra-poster
Add beacons to the RA spy plane and parabombs
2014-07-07 10:15:03 +02:00
Matthias Mailänder
17e41a7b79 Merge pull request #5856 from MustaphaTR/d2k-footprints
D2k Some Footprint Fixes
2014-07-07 09:33:41 +02:00
Mustafa Alperen Seki
96988fe563 Fixed ref and palace footprints. 2014-07-07 10:20:12 +03:00
Matthias Mailänder
d4627479b5 fix a NullReferenceException in preview.Map 2014-07-07 09:18:24 +02:00
Paul Chote
38a08c0967 Add a spy plane beacon, and quantise facings. 2014-07-07 17:40:51 +12:00
Paul Chote
59bea931a5 Use AirstrikePower for spy planes. 2014-07-07 17:40:51 +12:00
Paul Chote
a4ba7f7158 Remove the obsolete flare definition from AirstrikePower. 2014-07-07 17:40:51 +12:00
Paul Chote
c6299892e0 Remove obsolete BeaconDuration definitions. 2014-07-07 17:40:50 +12:00
Paul Chote
6f7816b653 Add beacon to parabombs, and quantise facings. 2014-07-07 17:40:44 +12:00
Paul Chote
e3e5de2b59 Merge pull request #5844 from Mailaender/ts-blossom-trees
Added Blossom Trees to Tiberian Sun
2014-07-07 11:23:04 +12:00
Chris Forbes
43ce9274e1 Merge pull request #5847 from Mailaender/sietch-bib
Fixed the sietch crashing the game when placed on a map
2014-07-07 09:42:06 +12:00
Chris Forbes
e3100171f0 Merge pull request #5848 from Mailaender/shellmap-category
Categorized shellmaps
2014-07-07 09:39:05 +12:00
Chris Forbes
c2a659f4d2 Merge pull request #5849 from Mailaender/active-animation-pause
Fixed active animations playing during paused games
2014-07-07 09:34:44 +12:00
Matthias Mailänder
dc63171e0e pause active animations 2014-07-06 23:11:56 +02:00
Matthias Mailänder
4fb7d4ef41 fix Unit sietch does not have a sequence named bib2x 2014-07-06 22:55:27 +02:00
Matthias Mailänder
a550febc94 categorize shellmaps 2014-07-06 21:04:03 +02:00
Matthias Mailänder
dac2314051 add blossom trees to Tiberian Sun 2014-07-06 19:00:43 +02:00
Matthias Mailänder
0262a946be add FrozenActorLayer to Tiberian Sun 2014-07-06 19:00:25 +02:00
Matthias Mailänder
b466a066a9 Merge pull request #5839 from ihptru/downloadingstatus
depend on proper status in auto-downloading
2014-07-06 17:46:04 +02:00
ihptru
305f76e300 depend on proper status in auto-downloading 2014-07-06 19:17:38 +04:00
Paul Chote
6ad5c99815 Merge pull request #5806 from Mailaender/seeds-resources-cleanup
Fixed SeedsResources messing with make animation
2014-07-07 01:05:17 +12:00
Matthias Mailänder
82a8fd329e don't play active animation when we sell it 2014-07-06 14:58:29 +02:00
Matthias Mailänder
69209cd340 split WithActiveAnimation from SeedsResource
closes #5300
2014-07-06 14:58:29 +02:00
Matthias Mailänder
59dcd297f5 Merge pull request #5828 from reaperrr/missile-shadow
Re-implement Shadow support for Missiles
2014-07-06 14:55:51 +02:00
Paul Chote
06039ce818 Merge pull request #5304 from Mailaender/music-downloads
Added Music downloads
2014-07-07 00:52:05 +12:00
reaperrr
5a645adb2d TS changes to improve missile test cases. 2014-07-06 14:46:07 +02:00
reaperrr
a69f5857e6 Removes Missile-shadow-related bitrot. 2014-07-06 14:46:05 +02:00
reaperrr
cb216aa345 Reimplement Shadow toggle for Missile projectile.
Enable Shadow by default.
2014-07-06 14:46:04 +02:00
Matthias Mailänder
fe41ac7fa3 @pchote breaks all the things 2014-07-06 14:45:05 +02:00
Matthias Mailänder
443b46ca64 fix Tiberian Sun installation from CD 2014-07-06 14:04:26 +02:00
Paul Chote
3f7293b206 Let FieldLoader do the hard work of loading fields. 2014-07-06 14:04:26 +02:00
Matthias Mailänder
352067eb48 consistent size for all install panels 2014-07-06 14:04:26 +02:00
Matthias Mailänder
038146abb3 prevent flickering 2014-07-06 14:04:26 +02:00
Matthias Mailänder
6a0c158ffa rename gameinit to install for consistency 2014-07-06 14:04:26 +02:00
Matthias Mailänder
585264d3ad remove non-existing "INIT_SETUP" chrome widget reference 2014-07-06 14:04:26 +02:00
Matthias Mailänder
a67e2290d1 fix the music list not being populated after CD asset install 2014-07-06 14:04:26 +02:00
Matthias Mailänder
1f4b780450 save a redirect 2014-07-06 14:04:26 +02:00
Matthias Mailänder
2f55768c1b restart the game instead of unmounting on the fly
avoid more redundancy between the load screens
2014-07-06 14:04:26 +02:00
Matthias Mailänder
334605287c Intro/Map music is also split across several files here 2014-07-06 14:04:26 +02:00
Matthias Mailänder
b2517b2c87 don't test for scores.mix as it is optional 2014-07-06 14:04:26 +02:00
Matthias Mailänder
178bf0643f don't check for general.mix as it stays unmounted
however still extract it
2014-07-06 14:04:26 +02:00
Matthias Mailänder
7b5e072994 unmount all to avoid write permission problems
fight the new caching mechanism and M$ WindowsTM file systems
2014-07-06 14:04:25 +02:00
Matthias Mailänder
dbb4132b66 add TrimOrEmpty to avoid NREs 2014-07-06 14:04:25 +02:00
Matthias Mailänder
cc64b41246 fix Tiberian Dawn CD rip logic
closes #4424
2014-07-06 14:04:25 +02:00
Matthias Mailänder
57a631c284 rebase bit rot crap 2014-07-06 14:04:25 +02:00
Matthias Mailänder
7783e988a7 unify music install and add a download option
closes #4759
2014-07-06 14:04:25 +02:00
Matthias Mailänder
14f71c55bf unify install from CD logic 2014-07-06 14:04:25 +02:00
Matthias Mailänder
351c759793 separate content install from loadscreen 2014-07-06 14:04:25 +02:00
Paul Chote
08b1c989d6 Merge pull request #5640 from Mailaender/editor-tick
Separated Tick and TickRender more cleanly
2014-07-07 00:03:04 +12:00
Matthias Mailänder
7e496f8db9 StyleCop and avoid redundancy 2014-07-06 12:48:47 +02:00
Matthias Mailänder
bf1743ac6e Merge pull request #5838 from obrakmann/fix5378
Fix non-infantry support units starting on subcells. Fixes #5378
2014-07-06 12:09:01 +02:00
Oliver Brakmann
bb38521d70 Add myself to AUTHORS 2014-07-06 12:04:15 +02:00
Oliver Brakmann
cb8ed251b2 Fix non-infantry support units starting on subcells.
Fixes #5378
2014-07-06 12:04:15 +02:00
Matthias Mailänder
cde7ec1948 disallow building placement when the game is paused
touches the most glitchy case of #3277
2014-07-06 09:39:16 +02:00
Matthias Mailänder
565ea05bd7 fix problem with cnc nuke leaking the long idle sequence Tick
and avoid magic numbers
2014-07-06 09:23:31 +02:00
Squiggles211
52bc05c1b5 Fixes #5654 by removing false damage states which caused invisible walls
Removes final set of 16 sequences for all walls as it appears that these
are not actually supposed to be used as damage states for the actual
wall, but as end pieces for each wall.  One of the pieces in particular
caused a single wall to be seen as invisible.  Fixes #5654
2014-07-06 02:09:10 -05:00
Matthias Mailänder
960248fe44 freeze animations during pause to visualize it better 2014-07-06 08:24:08 +02:00
Matthias Mailänder
d1e18cad7a new PauseState to differentiate game and editor pausing 2014-07-06 08:24:08 +02:00
Matthias Mailänder
d580ca6417 ActorMap is updated in Tick
so we can't search for adjacent actors in TickRender
2014-07-06 08:24:08 +02:00
Matthias Mailänder
394d635dae new trait WithMakeAnimation 2014-07-06 08:24:08 +02:00
Matthias Mailänder
87fd576b26 use TickRender() for RenderSprites and PaletteModifier 2014-07-06 08:24:08 +02:00
Matthias Mailänder
58cb603803 Merge pull request #5834 from Squiggles211/heli-turn
Increase Chinook landing speed and removed turn before landing.
2014-07-06 08:19:44 +02:00
Matthias Mailänder
9be8f4ce29 Merge pull request #5832 from obrakmann/fix-old-lua-breakage
Fix breakage of the old Lua API due to recent changes
2014-07-06 07:55:34 +02:00
Squiggles211
ebc6515d73 Fixes #5054 by removing chinook's turn before landing and increasing ascend/descend speed
Allows for any helicopter to enable or disable the turn before landing
but sets it to default off for the chinook.  (may be desireable for
single player missions visual effect like Allies01?)  Also gives the
chinook a faster ascend/descend speed.  Fixes #5054
2014-07-06 00:52:43 -05:00
Oliver Brakmann
3a67b3dec3 Fix breakage of the old Lua API due to recent changes
Specifically, the CPos::CenterPosition -> Map::CenterOfCell rename (#5758),
as well as the additional argument to Paradrop::SetLZ (#5695).
2014-07-06 01:21:22 +02:00
Chris Forbes
ee2dc60eb3 Merge pull request #5822 from Mailaender/voxel-walker-move
Moved specialized voxel render traits to Mods.TS library.
2014-07-06 10:52:35 +12:00
Chris Forbes
636f926184 Merge pull request #5821 from Mailaender/bye-scott
Removed Scott from the active maintainer list
2014-07-06 10:22:01 +12:00
Chris Forbes
1ca218182a Merge pull request #5831 from pchote/repair-crashfix
Don’t try to render the repair indicator if there are no repairers.
2014-07-06 10:19:36 +12:00
Paul Chote
cc14f5ef17 Don’t try to render the repair indicator if there are no repairers. Fixes #5823 2014-07-06 10:05:56 +12:00
Matthias Mailänder
b9d84cb422 Merge pull request #5829 from reaperrr/ts-fiendshard
Fixes TS FiendShard using wrong projectile
2014-07-05 18:14:29 +02:00
reaperrr
0d33aec9d9 Fix TS FiendShard using wrong projectile. 2014-07-05 17:30:39 +02:00
Matthias Mailänder
b5a514d868 move WithVoxelUnloadBody 2014-07-05 12:13:47 +02:00
Matthias Mailänder
07c75b5e27 move WithVoxelWalkerBody to Mods.TS 2014-07-05 12:12:56 +02:00
Matthias Mailänder
a0a5d10e4b remove Scott from the active maintainer list 2014-07-05 11:57:19 +02:00
Paul Chote
8743f39a79 Merge pull request #5814 from Mailaender/vamos-vamos
Fixed units not moving to the RallyPoint
2014-07-05 20:00:47 +12:00
Paul Chote
88cd454ce1 Merge pull request #5695 from Mailaender/parachute-dangers
Added the possibility for paratroopers to die on impact
2014-07-05 19:49:15 +12:00
Paul Chote
da66a9a6b3 Merge pull request #5797 from Mailaender/ts-harvester
Fixed the Tiberian Sun harvester
2014-07-05 19:14:47 +12:00
Matthias Mailänder
5e7e677ca9 fix shadow sprite not being rendered on the ground 2014-07-05 09:13:52 +02:00
Matthias Mailänder
8cdd7dce6c make the fallrate customizable 2014-07-05 09:13:52 +02:00
Matthias Mailänder
4a7687d7e4 add a customizable parachute shadow
closes #3335
2014-07-05 09:13:52 +02:00
Matthias Mailänder
18a77e0039 make the parachute palettes configurable 2014-07-05 09:13:52 +02:00
Matthias Mailänder
ef01fb289b make the parachute animation optional
instead of hard-coding default sprite sequences
2014-07-05 09:13:52 +02:00
Matthias Mailänder
ff1be8daea merge ParachuteAttachment and Parachutable 2014-07-05 09:13:52 +02:00
Matthias Mailänder
e04ff18060 @pchote's quest against legacy truth value definitions 2014-07-05 09:13:51 +02:00
Matthias Mailänder
a38d43019a new setting to allow unlucky paratroopers 2014-07-05 09:13:51 +02:00
Matthias Mailänder
2907273ef2 new trait Parachtuable that decides on the fate upon landing 2014-07-05 09:13:51 +02:00
Matthias Mailänder
1a0bb726e6 document for modders 2014-07-05 09:13:51 +02:00
Matthias Mailänder
8f805248ca StyleCop 2014-07-05 09:13:51 +02:00
Matthias Mailänder
d6c60f6436 tweak the DockOffset a bit 2014-07-05 09:08:50 +02:00
Matthias Mailänder
f4f127e3d1 spaces to tabs 2014-07-05 09:08:50 +02:00
Matthias Mailänder
7385fcbf3f fix VoxelAnimation.DisableFunc being ignored 2014-07-05 09:08:49 +02:00
Matthias Mailänder
6734cd96a4 add a voxel harvester unload animation 2014-07-05 09:08:47 +02:00
Matthias Mailänder
1e2e7bcf42 StyleCop 2014-07-05 09:00:20 +02:00
Matthias Mailänder
7b5f000ba0 stop pretending this is configurable and use MoveTo
fixes #5682
2014-07-05 08:58:21 +02:00
Matthias Mailänder
4fed3371d0 avoid an unneccessary conversion FieldLoader can do 2014-07-05 08:58:21 +02:00
Matthias Mailänder
9199cf4669 get to work automatically 2014-07-05 08:45:37 +02:00
Matthias Mailänder
270975a590 fix crash when docking with a voxel harvester 2014-07-05 08:45:34 +02:00
Paul Chote
bf50372f85 Merge pull request #5787 from Mailaender/input-sound-render-split
Sound and Input cleanup
2014-07-05 18:41:11 +12:00
Matthias Mailänder
b1ac961adc StyleCop 2014-07-05 08:35:38 +02:00
Matthias Mailänder
cf6f32fb96 split Sound.cs in smaller chunks 2014-07-05 08:35:38 +02:00
Matthias Mailänder
8cce30d472 sort into sub-folders Input and Graphics 2014-07-05 08:35:32 +02:00
Paul Chote
dbfd1eaaa3 Merge pull request #5808 from reaperrr/td-bluetib
Replaces glitchy blue tiberium art with TS-style remapable tiberium art
2014-07-05 18:34:18 +12:00
Paul Chote
6250c9df12 Merge pull request #5696 from Mailaender/emit-cargo-on-sell
Finished EmitCargoOnSell
2014-07-05 12:30:29 +12:00
Paul Chote
15d8fadb60 Merge pull request #5801 from Mailaender/building-influence-crash
Fixed a crash when trying to capture husks that have been destroyed.
2014-07-05 11:36:54 +12:00
Paul Chote
31aaaf26b5 Merge pull request #5812 from Mailaender/rallypoint-test-building-hack-removal
Fixed the AI choosing rallypoints on land for shipyards
2014-07-05 11:22:00 +12:00
Paul Chote
6deadd7658 Merge pull request #5798 from Mailaender/td-production-tooltip-nre
Fixed a crash in Tiberian Dawn when a production tooltip is being rendered while the last accompanying production queue is destroyed.
2014-07-05 10:58:13 +12:00
Paul Chote
8d6cd143d6 Merge pull request #5807 from Mailaender/building-influence-reslayer
Fixed resources growing on building bibs and behind trees
2014-07-05 10:53:10 +12:00
obrakmann
80f1dc6a56 Merge pull request #5818 from UberWaffe/bleed
Corrected d2k.sardaukar prone-shoot animation.
2014-07-04 22:08:01 +02:00
obrakmann
6d3edb8725 Merge pull request #5817 from Mailaender/chat-command-nre
Fixed chat commands crashing replays
2014-07-04 21:57:12 +02:00
UberWaffe
29df6866d0 Corrected d2k.sardaukar prone-shoot animation. 2014-07-04 20:10:40 +02:00
Matthias Mailänder
13e0dac141 execute chat commands only locally
fixes #5755
2014-07-04 18:18:33 +02:00
Matthias Mailänder
0572220cc3 Merge pull request #5768 from pchote/multirepair
Closes #3748
2014-07-04 16:12:46 +02:00
Matthias Mailänder
7428776e90 Merge pull request #5813 from pavlos256/asset-browser-search
Instant filtering by file name in the asset browser
2014-07-04 16:01:01 +02:00
Matthias Mailänder
65d61dff3e Merge pull request #5767 from pchote/isqrt
Add Exts.ISqrt to avoid fp sqrt calculations.
2014-07-04 15:48:20 +02:00
Pavlos Touboulidis
d1251d412f Instant filtering by file name in the asset browser 2014-07-04 16:33:26 +03:00
Matthias Mailänder
79dd9a9c6b get rid of the RallypointTestBuilding hack 2014-07-04 14:57:34 +02:00
Matthias Mailänder
7824564a44 fix System.Reflection.ReflectionTypeLoadException 2014-07-04 14:34:34 +02:00
Matthias Mailänder
3c502117a5 Merge pull request #5804 from MustaphaTR/d2k-shellmap
Better Shellmap to D2K
2014-07-04 11:44:17 +02:00
Mustapha
c842f1cbc1 High Resolution Fix 2014-07-04 12:37:47 +03:00
Matthias Mailänder
0feb5a7bdc check for building influence when growing resources
closes #5556
2014-07-04 09:22:14 +02:00
Ishan Bhargava
16df8322c6 Added repair bonus for multiple players
More than one player can now contribute to repairing a building.
Base repair amount is multiplied by value of array
Players who can't afford to contribute are ignored
Repair indicator cycles between each player's color.
2014-07-04 10:40:26 +12:00
Paul Chote
9e11e38005 Merge pull request #5781 from pavlos256/format80-write-rle
Implement Format80 RLE compression
2014-07-04 10:34:01 +12:00
Paul Chote
ce99f02ba6 Merge pull request #5678 from pavlos256/find-tiles-in-circle
Fix and optimize FindTilesInCircle
2014-07-04 10:27:37 +12:00
Matthias Mailänder
ae8b2cec74 Merge pull request #5792 from reaperrr/tib-tree-fixes
TD Tiberium tree fixes
2014-07-03 22:35:34 +02:00
reaperrr
7b5078c4f2 Remove bluetib.mix package. 2014-07-03 22:31:34 +02:00
reaperrr
739865062a Replaces glitchy blue tiberium art with TS-style remapable tiberium art. 2014-07-03 22:28:36 +02:00
reaperrr
9e8c7ee145 Remove duplicate split sequence.
Make blue tib tree more centered on cell (fixes #5744).

Remove obsolete splitblue art.
2014-07-03 22:17:01 +02:00
reaperrr
6fa3f4207a Fix editor position of TD tiberium trees. 2014-07-03 21:52:18 +02:00
Matthias Mailänder
b02ca7695f StyleCop 2014-07-03 18:35:11 +02:00
Pavlos Touboulidis
daed053a57 Fix and optimize FindTilesInCircle 2014-07-03 18:11:28 +03:00
Pavlos Touboulidis
f5de0101fe Implement Format80 RLE compression 2014-07-03 17:53:48 +03:00
Paul Chote
0ffe88753c Merge pull request #5789 from Mailaender/render-trait-documentation
Documented the various overlay and animation change traits
2014-07-03 23:54:13 +12:00
Paul Chote
a4083f4597 Merge pull request #5794 from Mailaender/lint-map-cordons
Added a new Lint check for invalid map cordons
2014-07-03 23:43:41 +12:00
Paul Chote
1a88769c12 Merge pull request #5795 from Mailaender/ts-harvester-tiberium-explosion
Added Tiberium explosions to destroyed harvesters in Tiberian Sun
2014-07-03 23:39:39 +12:00
Paul Chote
d92dc70a2f Merge pull request #5712 from RoosterDragon/sheet-release-buffer
Release sheet buffers
2014-07-03 22:57:56 +12:00
Matthias Mailänder
884fbc0ea9 add a new lint check for invalid map cordons 2014-07-03 10:56:59 +02:00
Matthias Mailänder
e666c75883 don't capture dead actors 2014-07-03 10:33:41 +02:00
Matthias Mailänder
6097b3eb19 document the various overlay and animation change traits 2014-07-03 09:50:10 +02:00
Matthias Mailänder
8a89accab6 Merge pull request #5805 from MustaphaTR/mount-idaho
Mount Idaho Map
2014-07-03 09:37:42 +02:00
Matthias Mailänder
04f1ebe969 abort change owner when the actor is destroyed
fixes #5638
2014-07-03 09:19:51 +02:00
Matthias Mailänder
3c3f85a272 add documentation 2014-07-03 09:05:22 +02:00
Matthias Mailänder
68a97b079b spurious tab 2014-07-03 09:05:22 +02:00
Mustapha
432638dcfa added mount idaho map 2014-07-03 09:59:07 +03:00
Mustapha
e13f8873c0 New Shellmap 2014-07-03 09:51:36 +03:00
RoosterDragon
3a30748f05 Reduce working set by releasing buffers for sheets.
Sheets carry a managed buffer of data that allows updates to be made without having to constantly fetch and set data to the texture memory of the video card. This is useful for things like SheetBuilder which make small progressive changes to sheets.

However these buffers are often large and are kept alive because sheets are referenced by the sprites that use them. If this buffer is explicitly null'ed when it is no longer needed then the GC can reclaim it. Sometimes a buffer need not even be created because the object using the sheet only works on the texture directly anyway.

In practise, this reduced memory consumed by such buffers from ~165 MiB to ~112 MiB (at the start of a new RA skirmish mission).
2014-07-02 17:25:56 +01:00
Matthias Mailänder
30edee01c2 check if palette.CurrentQueue is null to avoid a crash
fixes #5624
2014-07-02 12:18:47 +02:00
Matthias Mailänder
d011438ff3 let the harvester splatter Tiberium on destruction 2014-07-02 09:42:15 +02:00
Paul Chote
0d61a1d19a Merge pull request #5786 from Mailaender/shp-ts-offset-fix
Fixed Tiberian Sun construction yard flickering
2014-07-02 17:14:03 +12:00
Paul Chote
9a167317dd Merge pull request #5742 from tomlane/sniperChurches
Remove ability for Sniper to capture churches.
2014-07-02 17:05:06 +12:00
Matthias Mailänder
ea86aac089 replace EmitCargoOnSell with Cargo.EjectOnSell 2014-07-01 22:11:44 +02:00
Matthias Mailänder
6adf453ad1 finished EmitCargoOnSell
closes #2424
2014-07-01 22:07:15 +02:00
Matthias Mailänder
e8bccc33c6 StyleCop 2014-07-01 22:07:15 +02:00
Matthias Mailänder
392b77647d this does not make any sense
with 0 HP you also can not a single dude
2014-07-01 22:07:15 +02:00
Matthias Mailänder
40cd491bff Merge pull request #5778 from pchote/isometric
Add support for diamond cell grids
2014-07-01 16:59:22 +02:00
Tom Lane
eca4504006 Remove invalid sniper actor from Poseidon map. 2014-07-01 13:23:36 +01:00
Taryn Hill
249c522c00 Merge pull request #5785 from Mailaender/ts-high-fix
Fixed Tiberian Sun artillery not shooting over walls.
2014-07-01 07:02:56 -05:00
Matthias Mailänder
f5b749e9ce fix a rounding problem in SHP(TS) offset floating point math
closes #5765
2014-07-01 13:40:00 +02:00
Matthias Mailänder
de64b31aa4 allow the RPG tower to shoot over walls 2014-07-01 11:30:16 +02:00
Matthias Mailänder
78e4e7a440 allow artillery to shoot over walls 2014-07-01 11:30:12 +02:00
Paul Chote
cf7bd75dad Merge pull request #5759 from Mailaender/ra-tech-capture
Added capturable tech to Red Alert
2014-07-01 19:24:23 +12:00
Matthias Mailänder
38dd3bbdc9 remove pill boxes and hijacker from Allies02 2014-07-01 09:12:13 +02:00
Matthias Mailänder
7cd259d2b8 add a missing space for multi line property documentation 2014-07-01 09:12:13 +02:00
Matthias Mailänder
b05e4217cf document SelfHealing prerequisites 2014-07-01 09:12:11 +02:00
Matthias Mailänder
362c86764f document the buildable and country trait 2014-07-01 09:08:08 +02:00
Matthias Mailänder
a42ac640e4 remove unused copy pasta from TD 2014-07-01 09:03:33 +02:00
Matthias Mailänder
5602e49179 capturable production queues 2014-07-01 09:03:19 +02:00
Matthias Mailänder
6436088cdb Use Prerequisites: ~disabled for unbuildable actors. 2014-07-01 09:02:41 +02:00
reaperrr
5a7dbb6529 Fix TS refinery and repair pad using snow gfx
Until we support TS theater-specific graphics, we should stick to one of the theaters, temperate in this case.
2014-07-01 01:10:55 +02:00
Igor Popov
cefe26349f Merge pull request #5780 from Mailaender/master.openra.net
Changed master server URL to openra.net subdomain
2014-06-30 19:32:08 +04:00
Matthias Mailänder
5bd3a21d34 master server has been migrated to new machine and DNS
closes #5748
2014-06-30 16:09:00 +02:00
Paul Chote
0d625b6af6 Fix sprite overlap outside the map border. 2014-07-01 00:40:42 +12:00
Paul Chote
96c9de2b96 Enable isometric perspective in TS. 2014-06-30 23:44:23 +12:00
Paul Chote
0866903f20 remove blank-testmap. 2014-06-30 23:44:23 +12:00
Paul Chote
68969203bb Extract TS blank-conquest map. 2014-06-30 23:44:23 +12:00
Paul Chote
a30c8b53a7 Add support for diamond cell grids. 2014-06-30 23:44:23 +12:00
Matthias Mailänder
43dccee1b6 Merge pull request #5779 from MustaphaTR/bleed
Level Up from Crate at D2K
2014-06-30 13:41:50 +02:00
Mustafa Alperen Seki
68f8b5073a LevelUpCrate 2014-06-30 10:51:40 +03:00
Paul Chote
af0e948a67 Use map.Contains for the observer shroud check.
Checking against the bounds directly is no longer valid.
2014-06-30 11:24:41 +12:00
obrakmann
3682bc7069 Merge pull request #5772 from pchote/d2k-parachute-fix
Fix D2K paratroopers.
2014-06-29 13:32:57 +02:00
Paul Chote
52af0d2c81 Merge pull request #5771 from Mailaender/hackyai-mcv-cleanup
Cleaned up HackyAI MCV deployment
2014-06-29 13:00:21 +12:00
Matthias Mailänder
5130723fcd remove the overly complicated configurable MCV actor name hack 2014-06-28 15:17:06 +02:00
Matthias Mailänder
aae428be2b throw with a more helpful error than NullReferenceException
closes #5622
2014-06-28 15:17:05 +02:00
Paul Chote
e6a501bb66 Fix D2K paratroopers. 2014-06-28 22:57:12 +12:00
Paul Chote
1c511ea6eb Merge pull request #5769 from Mailaender/actor-lint
Added a new OpenRA.Lint check for invalid actor definitions
2014-06-28 22:00:40 +12:00
Paul Chote
281423c8f4 Merge pull request #5766 from RoosterDragon/read-only-frames
Make sprite frames read-only lists.
2014-06-28 21:54:30 +12:00
Matthias Mailänder
dcaef3b0e9 explain the strange console message 2014-06-28 10:38:51 +02:00
Matthias Mailänder
a5ac1aa581 tell us what you are doing 2014-06-28 10:38:33 +02:00
Matthias Mailänder
95c43132c7 only display lint check name when something goes wrong 2014-06-28 10:38:14 +02:00
Matthias Mailänder
492abc0853 don't spam passed checks 2014-06-28 10:37:38 +02:00
Matthias Mailänder
f9d5a439d8 and another hit for invalid players 2014-06-28 09:52:00 +02:00
Matthias Mailänder
59c12c2a31 now that we check actors and players we can't exclude them 2014-06-28 09:51:50 +02:00
Matthias Mailänder
a6ad359914 remove legacy actors as a test case 2014-06-28 09:51:12 +02:00
Matthias Mailänder
ba1fa7cd81 new check for undefined actors 2014-06-28 09:50:50 +02:00
Matthias Mailänder
7fa51712ec Merge pull request #5758 from pchote/cell-world-conversions
Generalize cell/world coordinate conversions.
2014-06-28 08:27:18 +02:00
Paul Chote
2431c34ca9 Merge pull request #5752 from Mailaender/tank-paradrop
Removed the tank paradrop icon
2014-06-28 16:17:15 +12:00
Paul Chote
d0c3fae1a2 Merge pull request #5406 from RoosterDragon/palette-efficiency
Changed HardwarePalette.ApplyModifiers to be more efficient.
2014-06-28 16:11:43 +12:00
Paul Chote
4216f66ca4 Add Exts.ISqrt to avoid fp sqrt calculations. 2014-06-28 15:48:53 +12:00
RoosterDragon
7030d8b2b6 Changed HardwarePalette.ApplyModifiers to be more efficient.
- Add separate ImmutablePalette and MutablePalette classes since the distinction is extremely important to HardwarePalette.
- Keep a cache of palettes in HardwarePalette to avoid reallocation them every time ApplyModifiers is called.
- Palettes that are not allowed to be modified are copied to the buffer once when added, rather than every time ApplyModifiers is called.
- The AdjustPalette method now takes a read-only dictionary to prevent the dictionary being messed with.
- Added a constant for the palette size to remove its usage as a magic number in several areas.
- The ColorPreviewManagerWidget is annoying in that it needs to actually permanently update a palette after it has been added. To allow this, HardwarePalette now allows a palette to be replaced after initialization. The WorldRenderer therefore now also updates the PaletteReference it created earlier with the new palette to prevent stale data being used elsewhere.
2014-06-28 01:11:48 +01:00
RoosterDragon
19072775d4 Changes ISpriteSource.Frames to be of type IReadOnlyList<ISpriteFrame>.
- Updated implementations to return a ReadOnlyList around an array (to reduce wasted memory from exposing lists or lazy enumerators around lists).
- Protect non-public ISpriteFrame classes by making them inner classes to prevent casting.
- Added an AsReadOnly extension method for lists.
2014-06-27 23:38:34 +01:00
Chris Forbes
5c82fff0ef Merge pull request #5751 from RoosterDragon/map-cache-tileset
Cache tileset lookup in Map
2014-06-28 09:27:27 +12:00
Matthias Mailänder
000768dd4f Merge pull request #5762 from obrakmann/fix-tech-capture-fallout
Fix fallout from tech-capture changes
2014-06-27 22:24:00 +02:00
Matthias Mailänder
7fa8cc10e9 Merge pull request #5763 from obrakmann/build-shift+keypress
Make Shift+<Hotkey> queue five units/buildings. Fixes #5544.
2014-06-27 22:18:50 +02:00
Oliver Brakmann
f7e32aac60 Fix fallout from tech-capture changes 2014-06-27 21:50:03 +02:00
RoosterDragon
bcbd1c2577 Cache tileset lookup in map so GetTerrainIndex and GetTerrainInfo need not repeat it every time.
The lookup accounts for ~50-60% of the time spent in GetTerrainIndex and GetTerrainInfo, and these methods themselves can account for up to 1.3% of total CPU used so this is a small but measurable win.
2014-06-27 19:52:57 +01:00
Matthias Mailänder
e9ee4a1e15 Update ShroudRenderer.cs
fix typo
2014-06-27 13:30:57 +02:00
Paul Chote
d7f1b1c9e2 Remove CVec -> WVec conversion. 2014-06-27 23:30:41 +12:00
Paul Chote
a256e722d5 Remove conversions between legacy and world types. 2014-06-27 23:30:41 +12:00
Paul Chote
9487f49cd5 Replace WPos.ToCPos -> Map.CellContaining. 2014-06-27 23:30:40 +12:00
Paul Chote
4bc09692e0 Remove WVec.ToCVec. 2014-06-27 23:30:40 +12:00
Paul Chote
7b52fa52b6 Replace CPos.CenterPosition -> Map.CenterOfCell. 2014-06-27 23:30:40 +12:00
Paul Chote
b6d1d26eeb Add World parameter to Util.BetweenCells. 2014-06-27 23:30:40 +12:00
Paul Chote
086ec07eb6 Add World parameter to Target.FromCell. 2014-06-27 23:30:40 +12:00
Paul Chote
e4ea012b9e Add World parameter to Target.FromOrder. 2014-06-27 23:30:40 +12:00
Paul Chote
b52cdd4b45 Remove redundant FindActorsInBox helpers. 2014-06-27 23:30:40 +12:00
Matthias Mailänder
0989a5ea08 Merge pull request #5757 from pchote/tsshroud
Use TS shroud sprites.
2014-06-27 13:29:10 +02:00
Paul Chote
8cd6f05b71 Use TS shroud artwork. 2014-06-27 22:28:33 +12:00
Paul Chote
8f046c7c5a Support split sprites for fog/shroud. 2014-06-27 22:28:33 +12:00
Paul Chote
8c4dcb7fe0 Configurable ShroudRenderer palettes and readonly state. 2014-06-27 22:28:33 +12:00
Matthias Mailänder
c60f19aee0 Merge pull request #5629 from pchote/celllayers
Introduce CellLayer and CellRegion abstractions.
2014-06-27 12:27:30 +02:00
Paul Chote
78f8c94df8 Make PathDistance struct immutable. 2014-06-27 22:07:03 +12:00
Paul Chote
5560f276ca Map: Rename IsInMap -> Contains. 2014-06-27 22:07:03 +12:00
Paul Chote
e0df669de9 Bridgelayer: Keys.Contains -> ContainsKey. 2014-06-27 22:07:03 +12:00
Paul Chote
fd4d3b40d0 Simplify shroud range checks. 2014-06-27 22:07:03 +12:00
Paul Chote
2a466d08c3 Remove the now-unused ExploredBounds optimization. 2014-06-27 22:07:03 +12:00
Paul Chote
441971f6d7 Use CellLayer for pathfinding. 2014-06-27 22:07:03 +12:00
Paul Chote
435f47158f Remove unused Map.IsInMap(x,y) overload. 2014-06-27 22:07:03 +12:00
Paul Chote
c5a13d4e65 Remove CellBounds from BuildableTerrainLayer and SmudgeLayer 2014-06-27 22:07:03 +12:00
Paul Chote
997216aef0 Use CellLayer for terrain. 2014-06-27 22:07:02 +12:00
Paul Chote
ad730a44c3 Use CellLayer for resources. 2014-06-27 22:07:02 +12:00
Paul Chote
ce331a28e8 Use CellLayer for custom terrain. 2014-06-27 22:07:02 +12:00
Paul Chote
c5b4d643af Use CellLayer for BridgeLayer. 2014-06-27 22:07:02 +12:00
Paul Chote
fb3477d630 Use CellLayer for BuildingInfluence. 2014-06-27 22:07:02 +12:00
Paul Chote
7c463c414c Use CellLayer for DomainIndex. 2014-06-27 22:07:02 +12:00
Paul Chote
8dc0967d2e Use CellLayer for ActorMap. 2014-06-27 22:07:02 +12:00
Paul Chote
baf27bc4cd Use CellLayers for shroud. 2014-06-27 22:07:02 +12:00
Paul Chote
295af5741f Use CellLayers for ResourceLayer. 2014-06-27 22:07:01 +12:00
Matthias Mailänder
e733ee0434 remove tank paradrop icon 2014-06-27 09:20:55 +02:00
Paul Chote
5a00757eab Use CellLayers for pathfinder debug. 2014-06-27 19:20:46 +12:00
Paul Chote
386b71de82 Integrate CellRegion with Map, Viewport. 2014-06-27 19:20:46 +12:00
Paul Chote
52ab8f3ca1 Add CellRegion and CellLayer classes to simplify map overlays. 2014-06-27 19:20:46 +12:00
Paul Chote
97a61273dd Bring PathSearch in line with the current code style. 2014-06-27 19:20:46 +12:00
Paul Chote
2026747f2a Use Map.IsInMap(CPos) for things that are checking CPos. 2014-06-27 19:20:46 +12:00
Paul Chote
e825205542 Stylecop BridgeLayer. 2014-06-27 19:20:46 +12:00
Paul Chote
bbd1331536 Clean up actor selection in WorldInteractionControllerWidget. 2014-06-27 19:20:44 +12:00
Matthias Mailänder
ea6f76e4f6 Merge pull request #5749 from MustaphaTR/bleed
Some fixes at TS
2014-06-27 08:33:30 +02:00
Matthias Mailänder
2ad6af6801 Merge pull request #5685 from pchote/race-restriction
Add capturable technology support. Fixes #2129
2014-06-27 08:23:59 +02:00
Mustafa Alperen Seki
9a4b4f5841 Infantry Hotkeys 2014-06-26 17:43:05 +03:00
Mustafa Alperen Seki
d70e4a9e32 Defence Hotkeys 2014-06-26 17:36:11 +03:00
Mustafa Alperen Seki
02c7d727d1 Hotkeys 2014-06-26 16:41:49 +03:00
Mustafa Alperen Seki
9ddc4ddc6b Hotkeys 2014-06-26 16:29:36 +03:00
Mustafa Alperen Seki
9ddc53e3fc Harv. Spawn point 2014-06-26 16:16:55 +03:00
Paul Chote
a9635e8c4a Refund the *old* player when a production structure is captured. 2014-06-26 23:14:14 +12:00
Paul Chote
4db2cf6b2b Propagate race to produced actors. 2014-06-26 23:14:14 +12:00
Paul Chote
4b2663015b Fix CanBuild not checking DeveloperMode.AllTech. 2014-06-26 23:14:14 +12:00
Paul Chote
749a947d3f Avoid repeated queries of DeveloperMode. 2014-06-26 23:14:14 +12:00
Paul Chote
2af123034d Use ExtraData for SetStance and SetUnitStance. 2014-06-26 23:14:13 +12:00
Paul Chote
7d24053f52 Introduce Order.SuppressVisualFeedback to cleanly disable flashes. 2014-06-26 23:14:13 +12:00
Paul Chote
32e0bf3edf Fix captured tech unlocking in TD. 2014-06-26 23:14:13 +12:00
Paul Chote
d318d7c5e3 Add HackyAI support for multiple structure queues. 2014-06-26 23:14:13 +12:00
Matthias Mailänder
74be133e40 Use Prerequisites: ~disabled for unbuildable actors. 2014-06-26 23:14:13 +12:00
Paul Chote
ca082e3cec Allow ProductionQueue to filter by race. 2014-06-26 23:14:13 +12:00
Paul Chote
d9e0559c7a Remove some long-dead code. 2014-06-26 23:14:13 +12:00
Paul Chote
66d9629520 Fix remaining tech tree issues. 2014-06-26 23:14:12 +12:00
Paul Chote
7b3a0ebeb5 Tidy production traits. 2014-06-26 23:14:10 +12:00
Paul Chote
f46f71217e Pass initial race to husks and transformed actors. 2014-06-26 23:12:23 +12:00
Paul Chote
7dfc822d76 Tidy transformation trait/activity. 2014-06-26 23:12:23 +12:00
Paul Chote
6536f92b12 Allow custom prerequisites to be restricted by race. 2014-06-26 23:12:23 +12:00
Paul Chote
d4227fa13e Fix production tooltip display. 2014-06-26 23:12:23 +12:00
Paul Chote
a5cc68efee Allow production ownership test to be disabled. 2014-06-26 23:12:23 +12:00
Paul Chote
c5089db19c Allow actors to exist in multiple building queues. 2014-06-26 23:12:22 +12:00
Paul Chote
d43acfe94b Merge pull request #5679 from RoosterDragon/main-loop-alloc
Reduce memory allocation in the main loop
2014-06-26 23:10:56 +12:00
Mustafa Alperen Seki
3c891f7c45 Hervaster collects tiberium 2014-06-26 12:29:42 +03:00
Tom Lane
8d6d06fc5f Remove ability for Sniper to capture churches. 2014-06-25 21:44:50 +01:00
Matthias Mailänder
48bd67b735 Merge pull request #5735 from pavlos256/always-save-replay
Properly save replay even when the game crashes (fixes #5610)
2014-06-25 20:17:39 +02:00
Matthias Mailänder
36c910fcae Merge pull request #5731 from RoosterDragon/sequence-initialize-fix
Fix #5452
2014-06-25 20:15:08 +02:00
Paul Chote
492513a89a Merge pull request #5706 from Mailaender/lint-players
Added a new OpenRA.Lint check for invalid player definitions
2014-06-25 11:30:34 +12:00
Pavlos Touboulidis
e19dae8eec Properly save replay even when the game crashes (fixes #5610) 2014-06-24 22:40:20 +03:00
Oliver Brakmann
0ff66949fb Make Shift+<Hotkey> queue five units/buildings. Fixes #5544. 2014-06-24 19:41:20 +02:00
Matthias Mailänder
66325f4941 Merge pull request #5733 from MustaphaTR/bleed
Heavy Support + Ordos Raider for light
2014-06-24 18:42:33 +02:00
RoosterDragon
3c9f589b5e Move try-catch during creation of sequences into the function rather than around the lazy initialization.
This fixes an issue with VS breaking on the exception because it thinks it will go unhandled, even though it will be handled.
2014-06-24 17:21:41 +01:00
Mustapha
50d12ee22e Update AUTHORS 2014-06-24 16:49:14 +03:00
Mustapha
b297bb7e75 Heavy Support + Ordos Raider for light 2014-06-24 16:43:09 +03:00
Matthias Mailänder
4018da3481 Merge pull request #5732 from MustaphaTR/bleed
Closes #5726
2014-06-24 09:39:40 +02:00
Mustapha
315fad8db7 Light Unit Support for D2K. 2014-06-24 09:30:39 +03:00
obrakmann
04dbe9fc2a Merge pull request #5687 from Mailaender/missile-out-of-map
Added a check for IsInMap(cell) to missiles.
2014-06-23 20:24:28 +02:00
Matthias Mailänder
378dd66622 Merge pull request #5701 from pavlos256/dev-crash
Add /crash dev command
2014-06-23 19:42:32 +02:00
obrakmann
07fc446520 Merge pull request #5697 from Mailaender/classic-minelay
Added a classic minelay order
2014-06-23 19:01:37 +02:00
Matthias Mailänder
7f8e84848d Merge pull request #5722 from MustaphaTR/bleed
Some description changes
2014-06-23 17:38:38 +02:00
Paul Chote
177dd02cd1 Merge pull request #5628 from pavlos256/smooth-scrolling
Add smooth scrolling to the ScrollPanelWidget
2014-06-23 21:46:50 +12:00
Paul Chote
0f115b0468 Merge pull request #5330 from Mailaender/jungle
Added the JUNGLE terrain
2014-06-23 21:42:26 +12:00
Chris Forbes
87ff787f26 Merge pull request #5721 from RoosterDragon/stylecop-small-projects
Run StyleCop on the smaller projects.
2014-06-23 19:09:04 +12:00
Mustapha
2d8f0ce96e Engineer's description changes. 2014-06-23 10:02:54 +03:00
Chris Forbes
3b99e79fd0 Merge pull request #5720 from pchote/revert-fail
Revert Utility changes
2014-06-23 19:01:35 +12:00
Mustapha
4159aa4bba Trike's weaknesses. 2014-06-23 09:56:15 +03:00
RoosterDragon
38617dc0a9 Run StyleCop on the smaller projects.
Also add a copy of the rules to the CrashDialog and Irc projects.
2014-06-23 00:03:37 +01:00
Paul Chote
7cf2a32a2a Revert "export health, cost and damage per section into a CSV file"
This reverts commit 8249012e4b.

Conflicts:
	OpenRA.Utility/Command.cs
2014-06-23 09:31:40 +12:00
obrakmann
e41791568d Merge pull request #5702 from Mailaender/reslayer-cell-full
Fixed exploding harvesters spawning resources on full cells
2014-06-22 18:57:57 +02:00
Matthias Mailänder
379686a64d Merge pull request #5711 from obrakmann/flyattack-fix
Fix FlyAttack discarding the activity queue upon completion
2014-06-22 18:49:00 +02:00
RoosterDragon
8a60880cf1 Tackle the last of the low hanging fruit for memory allocations in the main game loop.
- Avoid calling string.Split twice in SprintFont.Measure.
- Change ActorsInBox method of ActorMap and ScreenMap to avoid allocating and intermediate list. As a bonus this allows the sequence to be lazily consumed. Also avoid LINQ in these methods.
- In FrozenUnderFog.TickRender, the method exits early if no players are visible so the attempt at lazy generation was not needed.
- Unwrap a LINQ Any call in ClassicProductionQueue.Tick.
- Merge some successive Where calls in ProximityCapturable into single predicates.
2014-06-22 17:29:45 +01:00
Matthias Mailänder
a5d765e100 Merge pull request #5713 from RoosterDragon/game-project-config
Fix debug info regression from #5673
2014-06-22 17:55:03 +02:00
RoosterDragon
927b0499da Produce debug output for OpenRA.Game. 2014-06-22 16:38:05 +01:00
Oliver Brakmann
cf2fad673d Fix issue with capturing enemy buildings in 'Intervention' mission
The onDamaged event handler would still fire after an enemy building had
been captured. Fixed by checking the owner before starting repairs.

Thanks to Microbit for showing me that people actually did that.
2014-06-22 14:03:57 +02:00
Oliver Brakmann
c12527e866 Remove workaround for #4482 from 'Intervention' mission 2014-06-22 14:03:57 +02:00
Oliver Brakmann
aa91020790 Do not discard activity queue when FlyAttack completes. Fixes #4482. 2014-06-22 14:03:44 +02:00
Matthias Mailänder
4587ce6cd2 fix remaining errors spotted by new player lint check 2014-06-22 13:34:09 +02:00
Matthias Mailänder
6eabd080b8 StyleCop 2014-06-22 13:30:35 +02:00
Matthias Mailänder
b70c56927f add a new Lint check for map players 2014-06-22 13:30:35 +02:00
Matthias Mailänder
2e4749680c Merge pull request #5703 from abcdefg30/mapyamls-update
Fixed non-existing enemies in mini-games.
2014-06-22 13:02:29 +02:00
abcdefg30
3260590c59 updated training-camp mapyaml 2014-06-22 12:08:57 +02:00
abcdefg30
0daf8c173e updated drop-zone mapyaml 2014-06-22 12:07:48 +02:00
abcdefg30
fad98df605 updated bomber-john mapyaml 2014-06-22 12:07:02 +02:00
Matthias Mailänder
05609399eb don't try to spawn resources when the cell is already full
fixes #5699
2014-06-22 11:49:40 +02:00
Pavlos Touboulidis
98471092f6 Add /crash dev command
Throws an exception and crashes the game. Useful to test the
shutdown sequence.
2014-06-22 12:18:13 +03:00
Matthias Mailänder
48a5c69ab8 allow to lay single mines similiar to the original
closes #5467
2014-06-22 08:31:40 +02:00
Matthias Mailänder
d3d74c4e5f StyleCop 2014-06-22 08:31:36 +02:00
reaperrr
775f707e03 Made TD jungle terrain slightly less blueish. 2014-06-21 19:13:31 +02:00
Matthias Mailänder
52e2b83069 add the JUNGLE terrain to Tiberian Dawn
http://cnc-comm.com/community/index.php?topic=2880.0
2014-06-21 19:13:31 +02:00
Matthias Mailänder
69ddcf3fee Merge pull request #5692 from obrakmann/fix5681
Fix size of force-start lobby dialogs. Fixes #5681.
2014-06-21 18:04:10 +02:00
Pavlos Touboulidis
628c524494 Add smooth scrolling to the ScrollPanelWidget 2014-06-21 16:41:56 +03:00
Oliver Brakmann
235acea70a Fix size of force-start lobby dialogs. Fixes #5681. 2014-06-21 13:55:12 +02:00
Matthias Mailänder
8bff7baf4b destroy missiles leaving the map
fixes #5582
2014-06-21 13:28:09 +02:00
Matthias Mailänder
f48b53d5b1 Merge pull request #5690 from obrakmann/fix5686
Fix breakage of old Lua api. Fixes #5686.
2014-06-21 13:26:46 +02:00
Oliver Brakmann
f8e5217b11 Fix breakage of old Lua api. Fixes #5686. 2014-06-21 13:04:31 +02:00
Paul Chote
3ed0f75ecc Merge pull request #5689 from Mailaender/ts-domainindex
Added missing DomainIndex to Tiberian Sun
2014-06-21 22:57:23 +12:00
Paul Chote
2e605ba0f7 Merge pull request #5683 from Mailaender/autotarget-stance-documentation
Documented the AutoTarget stances system
2014-06-21 22:51:16 +12:00
Matthias Mailänder
ea4cde0da8 document DomainIndex 2014-06-21 12:37:04 +02:00
Matthias Mailänder
f13c5e20b4 add missing DomainIndex to Tiberian Sun 2014-06-21 12:31:38 +02:00
Matthias Mailänder
46b08273e0 Merge pull request #5680 from pchote/lobby-fixup
Clean up MapPreviewWidget.
2014-06-21 11:32:38 +02:00
Paul Chote
5760e665d3 Clean up map previews. Fixes #5665. 2014-06-21 21:15:11 +12:00
Matthias Mailänder
b85aaa7bfa document the stance system 2014-06-21 08:34:58 +02:00
Paul Chote
5cac1ed066 Merge pull request #5674 from abcdefg30/bleed
updated drop-zone-battle-of-tikiaki map.yaml
2014-06-21 13:39:51 +12:00
Paul Chote
444380b3cf Merge pull request #5676 from pavlos256/fix-rng-division-by-zero
Fix #5675
2014-06-21 12:57:49 +12:00
Pavlos Touboulidis
b9542e0f3f Fix #5675 2014-06-20 22:54:56 +03:00
abcdefg30
b592063a26 updated drop-zone-battle-of-tikiaki map.yaml
Replaced 7x "Multi17" (not existing) with "Multi7" and 1x "Multi11" (also not existing) with "Multi1"
2014-06-20 21:00:39 +02:00
Matthias Mailänder
53930fdc81 Merge pull request #5673 from RoosterDragon/solution-config
Clean up project settings
2014-06-20 20:58:05 +02:00
RoosterDragon
e0d8d8cf80 Clean up project settings.
- Create single platform config named x86 and have all projects target x86.
- Remove Release config (broken anyway).
- For the Debug config, ensure TRACE and DEBUG constants are set and unsafe code is allowed for all projects (same as the makefile).
- Warn level 4 and optimizations off were removed from the config automatically by VS (it assumes these values by default, and these match the makefile).
- The CrashDialog project can reuse the icon from the Game project as long as the path is set correctly.
- Fix TS project so it builds (I know it's going but its annoying that the project must be unloaded).
2014-06-20 19:29:54 +01:00
Paul Chote
bc92bc1774 Merge pull request #5649 from Mailaender/upnp-polish
Made the Mono.NAT integration more robust
2014-06-21 01:31:33 +12:00
Paul Chote
57280e3eab Merge pull request #5660 from Mailaender/document-traits
Documented some order related traits
2014-06-21 01:27:11 +12:00
Paul Chote
a6cb60e583 Merge pull request #5646 from Mailaender/replay-dropdown-polish
Polished the Replay Browser dropdowns
2014-06-21 01:23:33 +12:00
Paul Chote
fd78848de2 Merge pull request #5645 from Mailaender/travis-update-wiki
Added ./update-wiki.sh to Travis CI deployment
2014-06-21 01:20:29 +12:00
Paul Chote
c8c05ea19c Merge pull request #5451 from Mailaender/csv-dps
Added CSV rule export to OpenRA.Utility.exe
2014-06-21 01:18:12 +12:00
Paul Chote
f481c04ce6 Merge pull request #5305 from Mailaender/harvester-splatter-resoures
Added resource splattering to destroyed harvesters
2014-06-21 01:15:22 +12:00
Matthias Mailänder
e607c04cce let harvester splatter resources when exploding
closes #2346
2014-06-20 11:11:31 +02:00
Matthias Mailänder
3e627d2eba rename ore to the more generic name resources everywhere 2014-06-20 11:11:31 +02:00
Matthias Mailänder
30fa8f35d8 Update AttackGarrisoned.cs
closes #5264
2014-06-20 09:01:51 +02:00
Matthias Mailänder
0e1f98c2a9 Merge pull request #5600 from RoosterDragon/auto-restart
Offer user quick restart if settings change
2014-06-20 08:56:08 +02:00
Matthias Mailänder
6e97c51530 Merge pull request #5667 from noyanbaykal/bleed
Fixed #5664
2014-06-20 08:11:26 +02:00
Matthias Mailänder
ef2e02d008 document ScaredyCat 2014-06-19 21:21:16 +02:00
Matthias Mailänder
8ff5d9ef9b document Guard 2014-06-19 21:21:16 +02:00
Matthias Mailänder
d88fc7c3f2 document CanPowerDown 2014-06-19 21:21:16 +02:00
Matthias Mailänder
cf3f79bf29 document AttackWander 2014-06-19 21:21:16 +02:00
Matthias Mailänder
1c719cb34f document D2kResourceLayer 2014-06-19 21:21:16 +02:00
Matthias Mailänder
18805779a8 document RejectsOrders 2014-06-19 21:21:14 +02:00
noyanbaykal
54e53a1306 Changed spaces to tabs 2014-06-19 13:20:55 -04:00
noyanbaykal
0ad767a05e Fixed #5664
Mission description scrolls to the top whenever a new mission is
selected to avoid out-of-bounds scrollbar
2014-06-19 13:12:12 -04:00
Matthias Mailänder
e8473990ef Merge pull request #5658 from RoosterDragon/formatting-cleanup
Remove & sort usings
2014-06-19 08:36:57 +02:00
RoosterDragon
22abf9b4c4 Remove and sort usings. 2014-06-18 21:43:35 +01:00
RoosterDragon
e8111e8ac6 Restart the process rather than reloading a new AppDomain. 2014-06-18 21:36:59 +01:00
RoosterDragon
52b09bdfe8 If changed settings require a restart, offer the user to do it now.
Add a dialog when closing the settings screen asking the user if they would like to restart the game now in order to apply any settings that are only applied after restarting the game. The game is reloaded in-process by spinning up a new AppDomain in order to reset state.
2014-06-18 21:36:56 +01:00
Matthias Mailänder
6d2f180cd4 Merge pull request #5635 from RoosterDragon/traits
TraitDictionary cleanup
2014-06-18 11:09:50 +02:00
RoosterDragon
85734defec Improve trait enumeration speed for All and GetMultiple.
Use a hand-rolled enumerators to avoid the overhead from compiler generated enumerable blocks. This trades terseness for some minor performance gains.
2014-06-17 22:11:23 +01:00
RoosterDragon
909c5c7037 Some minor cleanup in TraitDictionary and affected callsites. 2014-06-17 22:10:41 +01:00
Paul Chote
50d3929862 Merge pull request #5616 from RoosterDragon/syncreport-simplify
Rewrite SyncReport for clarity and performance
2014-06-17 22:54:48 +12:00
Matthias Mailänder
3be26e4cda Merge pull request #5617 from pchote/attack-moveadjacent
Improve unit-attack movement
2014-06-17 10:03:49 +02:00
Matthias Mailänder
1f7b0ad5d4 time limit the port forwarding if possible 2014-06-16 16:42:06 +02:00
Matthias Mailänder
a8c029f130 check if we really found a UPnP compatible NAT device 2014-06-16 16:35:33 +02:00
Matthias Mailänder
4d2412f4b8 this can't throw 2014-06-16 16:34:44 +02:00
Matthias Mailänder
d25fd654bc NatUtility.DeviceLost is never fired 2014-06-16 16:33:57 +02:00
Matthias Mailänder
db319f8f0b this will never happen 2014-06-16 16:33:16 +02:00
Matthias Mailänder
521ca70254 set the git user and email to avoid problems 2014-06-16 10:30:14 +02:00
Matthias Mailänder
83e33b99e8 StyleCop 2014-06-16 10:22:10 +02:00
Matthias Mailänder
88480e0dc2 make it clear that this does not need to match content height 2014-06-16 10:17:30 +02:00
Matthias Mailänder
44ab94f03a limit replay browser dropdown box height to something sane
closes #5641
2014-06-16 10:16:54 +02:00
Matthias Mailänder
6928a828e8 pushd and popd is safer here to not confuse Travis 2014-06-16 09:34:17 +02:00
Matthias Mailänder
eb27c9ef9d run ./update-wiki.sh again after release deployment
closes #5643
2014-06-16 09:29:17 +02:00
Matthias Mailänder
1d276e4186 add a pure data export for non-spreadsheet applications 2014-06-15 20:13:14 +02:00
Matthias Mailänder
6d2dfabb41 factor in burst delay 2014-06-15 20:12:47 +02:00
Matthias Mailänder
e0ba2046b5 add weapon name 2014-06-15 20:12:24 +02:00
Matthias Mailänder
de005c284c add armor types and move calculation into spreadsheet 2014-06-15 20:11:41 +02:00
Matthias Mailänder
8249012e4b export health, cost and damage per section into a CSV file
closes #3855
2014-06-15 20:10:51 +02:00
Matthias Mailänder
60d973aab4 Merge pull request #5634 from pchote/supportpower-prereqs
Allow support powers to require tech prerequisites.
2014-06-15 13:10:39 +02:00
Paul Chote
a220182c9e Remove cruft from RA airfield rules. 2014-06-15 22:51:42 +12:00
Paul Chote
1db1a1b324 Fix a typo in ITechTreeElement. 2014-06-15 22:49:52 +12:00
Paul Chote
2180e1f3f1 Allow support powers to require tech prerequisites. 2014-06-15 22:49:52 +12:00
Paul Chote
afa3fc8143 Simplify MoveAdjacentTo pathfinding. 2014-06-15 22:48:44 +12:00
Paul Chote
2141656460 Only inset range for mobile targets. 2014-06-15 22:48:43 +12:00
Paul Chote
58c3f9ad0c Use MoveWithinRange for attack activities.
Fixes #2104. Fixes #2923. Fixes #4455.
2014-06-15 22:48:43 +12:00
Paul Chote
64ab0a77a9 Added MoveWithinRange activity for Mobile units. 2014-06-15 22:48:43 +12:00
Paul Chote
887a515e14 Add MinRange plumbing to attack activities. 2014-06-15 22:48:43 +12:00
Paul Chote
f5a44f3c41 Merge pull request #5633 from ScottNZ/refactor
Some R# refactoring
2014-06-15 22:33:30 +12:00
ScottNZ
90894aa03e Use var everywhere 2014-06-15 22:17:34 +12:00
ScottNZ
dbffce81a6 Remove unused usings 2014-06-15 22:16:40 +12:00
ScottNZ
23f0e00bcc Now that we're on .NET 4 again, reintroduce optional parameter for RegisterNewSquad 2014-06-15 22:14:40 +12:00
ScottNZ
5e641750aa Use Any() instead of Count() == 0 2014-06-15 22:14:39 +12:00
ScottNZ
831b9b3ca3 Remove some stray semicolons 2014-06-15 22:14:39 +12:00
ScottNZ
6b85660d7d Compact lambda expressions in some (not all) places 2014-06-15 22:14:38 +12:00
ScottNZ
375fc1c5f1 Remove redundant constructors 2014-06-15 22:14:38 +12:00
ScottNZ
91bc1acca3 Fixed selectedAuthor in ModBrowserLogic not being the correct value if mod.Author is null 2014-06-15 22:14:37 +12:00
Paul Chote
1169211893 Merge pull request #5579 from Mailaender/frozen-C4
Fixed C4 target inconsistencies with Fog of War and Husks
2014-06-15 22:01:04 +12:00
Paul Chote
cc3e9b55a8 Merge pull request #5596 from Mailaender/opengl-version
Fixed crash when OpenGL version parse fails
2014-06-15 21:45:32 +12:00
Paul Chote
91236b2ca0 Merge pull request #5639 from Mailaender/editor-stylecop
Fixed some minor StyleCop issues
2014-06-15 21:39:29 +12:00
Matthias Mailänder
8f64835898 StyleCop 2014-06-15 10:51:57 +02:00
Matthias Mailänder
0679940c77 Merge pull request #5637 from pchote/ready-blink
Restore the blinking ready text in TD.
2014-06-14 13:58:49 +02:00
Paul Chote
3ee54fd00a Restore the blinking ready text in TD. 2014-06-14 22:37:44 +12:00
Matthias Mailänder
88757eccfa Merge pull request #5517 from deniz1a/blink-ready
New alternating colors blink option for build palette widget
2014-06-14 12:00:26 +02:00
Matthias Mailänder
dac12839fd Merge pull request #5630 from pavlos256/map-helpers
Move map helpers from WorldUtils to Map
2014-06-14 11:49:19 +02:00
Matthias Mailänder
fe0d7ab00e Merge pull request #5627 from pchote/frozen-cloak-fix
Invalidate FrozenActors that don’t have any sprites.
2014-06-14 11:41:49 +02:00
Matthias Mailänder
b3a2f81706 Merge pull request #5470 from Kanar/AirfieldRP
Closes #5592
2014-06-14 11:03:17 +02:00
Matthias Mailänder
1ebfc6bb06 Merge pull request #5631 from pavlos256/dev-iddqd
Add "/all" dev command
2014-06-14 10:27:58 +02:00
Matthias Mailänder
ee0df9c1cb make C4 Demolition frozen actor aware 2014-06-14 09:35:38 +02:00
Matthias Mailänder
fa0e4c3d0d what if there is no vendor info to remove from version string 2014-06-14 08:25:46 +02:00
Matthias Mailänder
2cc1d34078 remove redundant OpenGL version check to avoid NREs 2014-06-14 08:25:46 +02:00
Matthias Mailänder
7b5476aca7 don't crash there yet when OpenGL version parsing fails
closes #5595
2014-06-14 08:25:26 +02:00
Paul Chote
479feadef3 Merge pull request #5469 from Mailaender/fort-lonestar-lua
Ported Fort Lonestar to Lua
2014-06-14 17:47:06 +12:00
Matthias Mailänder
525a0c4ff1 port Fort Lonestar to Lua 2014-06-14 07:40:52 +02:00
Matthias Mailänder
b7ca65fb7b update Lua project files 2014-06-14 07:32:47 +02:00
Matthias Mailänder
473ca13b17 dos2unix 2014-06-14 07:32:47 +02:00
Paul Chote
c58d737400 Merge pull request #5597 from Happy0/mouse_window_focus
Removing requirement to restart game after applying changes to mouse focus option
2014-06-14 17:30:02 +12:00
Paul Chote
f115dda5df Merge pull request #5550 from pavlos256/reload-chrome
Add developer shortcut to reload chrome files
2014-06-14 17:25:18 +12:00
Paul Chote
5e986b3079 Merge pull request #5615 from RoosterDragon/minor-alloc
Minor allocation tweaks
2014-06-14 12:26:39 +12:00
Pavlos Touboulidis
ee4f3e5642 Always allow cheats on single player games 2014-06-13 17:18:12 +03:00
Pavlos Touboulidis
d22658011b Add "/all" dev command 2014-06-13 16:26:48 +03:00
Pavlos Touboulidis
3f2425f1d6 StyleCop 2014-06-13 15:55:48 +03:00
Pavlos Touboulidis
86febed0ce Move ChooseRandomEdgeCell from WorldUtils to Map 2014-06-13 14:31:01 +03:00
Pavlos Touboulidis
060d5326ed Move FindTilesInCircle from WorldUtils to Map 2014-06-13 14:24:53 +03:00
Pavlos Touboulidis
03b8096807 Move DistanceToMapEdge from WorldUtils to Map 2014-06-13 14:04:36 +03:00
Pavlos Touboulidis
f0c672b70c Move ChooseRandomCell from WorldUtils to Map 2014-06-13 14:02:51 +03:00
Pavlos Touboulidis
77fb188585 Move ClampToWorld from WorldUtils to Map 2014-06-13 13:59:40 +03:00
Pavlos Touboulidis
c282fa1077 Move GetTerrainIndex/Info from WorldUtils to Map 2014-06-13 13:57:32 +03:00
Paul Chote
0cf2d608e4 Merge pull request #5463 from pavlos256/perf-terrain-movement
Change terrain type from string based dictionaries to arrays
2014-06-13 21:19:29 +12:00
Paul Chote
96477b7c1a Invalidate FrozenActors that don’t have any sprites. Fixes #4809. 2014-06-13 21:07:39 +12:00
Pavlos Touboulidis
db53f8e648 Add developer shortcut to reload chrome files
Hitting Ctrl+Shift+C will re-initialize the chrome provider,
reloading all chrome files instantly. Useful when changing the
UI.

Note: A new "RootWidget" was created to trap top-level (global)
shortcuts instead of putting everything in Widget.
2014-06-13 11:31:09 +03:00
Pavlos Touboulidis
092352729f Change terrain type from string based dictionaries to arrays 2014-06-13 11:20:54 +03:00
Paul Chote
ea276d466d Merge pull request #5621 from chrisforbes/travis-update-before-installing
Adjust travis config to update package lists before installing dependencies
2014-06-13 10:45:11 +12:00
Chris Forbes
83fc5085e3 Adjust travis config to update package lists before installing dependencies 2014-06-13 10:29:22 +12:00
Gordon Martin
89c9499909 Removing requirement to restart game after applying changes to mouse focus option. The setting now defaults to 'false' as it is likely to be disruptive to players who are used to the usual behaviour in windowed mode. 2014-06-12 22:57:25 +01:00
RoosterDragon
6f5fbeceb1 Use expressions to generate fast member access code rather than using the slower reflection based methods. 2014-06-12 08:32:26 +01:00
RoosterDragon
3e24e89477 Rewrite SyncReport for clarity and performance.
- Drop the impressive but inscrutable dynamically generated code in favour of some plain old code.
- Cache type information so costly reflection need not be performed each time.
- Only capture values from a sync object into an array rather than a dictionary lookup of both names and values for efficiency.
- Throw if the sync attribute is used on a property that cannot be read or that uses index parameters.
2014-06-12 08:30:27 +01:00
Paul Chote
b8cdb224d1 Merge pull request #5540 from RoosterDragon/begin-frame-cache-viewport
Avoid redundancy in BeginFrame.
2014-06-12 18:15:47 +12:00
Paul Chote
f6f366c4b3 Merge pull request #5401 from RoosterDragon/nodesdict
Changed MiniYaml.NodesDict property into a method.
2014-06-12 17:34:59 +12:00
RoosterDragon
b8b8b1e2df Minor changes to reduce allocation.
- Cache a predicate in ActorMap.
- Use short circuiting to skip a call to HasTrait in AttackBase.
- In AutoTarget.ScanForTarget, move the check for the scan time above the calculations since we can skip them if it's not time yet.
- In AutoTarget.ChooseTarget, merge four Where calls into one.
2014-06-12 05:32:44 +01:00
Paul Chote
e0c59511fb Merge pull request #5152 from Mailaender/auto-l10n
Automated translation string extraction
2014-06-12 10:31:07 +12:00
Chris Forbes
1c5c2b576c Merge pull request #5601 from RoosterDragon/sheet-perf
Speed up some loops with Marshal.Copy
2014-06-12 10:07:29 +12:00
Chris Forbes
ecb7b5056c Merge pull request #5602 from RoosterDragon/perfsample-streamline
Streamline PerfSample
2014-06-12 10:05:31 +12:00
RoosterDragon
4ce8a4a648 Use Marshal.Copy for faster array copying.
- Rewrite several methods to use Marshal.Copy to copy data faster and more succinctly compared to doing it manually.
- Rewrite Sheet.AsBitmap(TextureChannel, Palette) with a faster and more self descriptive loop.
2014-06-11 05:02:38 +01:00
RoosterDragon
783fd8eb32 Streamline PerfSample.
- Avoid memory allocations by making PerfSample a struct, and tracking ticks manually rather than creating a Stopwatch instance.
2014-06-11 03:52:16 +01:00
Paul Chote
e347cdfb32 Merge pull request #5410 from RoosterDragon/IDisposable
Disposable fixup
2014-06-11 10:55:44 +12:00
RoosterDragon
a2ed4fd5f9 Avoid redundantly setting viewport parameters in BeginFrame.
- Cache the old resolution, scroll and zoom in BeginFrame, and don't bother updating the viewport parameters again until they change.
- Pass around scroll as an int2 to reduce the number of back-and-forth casts.
2014-06-10 17:06:25 +01:00
Kanar
6fdb9e688a Adds RallyPoint to Airfield, queues TakeOff 2014-06-10 18:02:04 +02:00
Paul Chote
ccb34adb04 Merge pull request #5503 from RoosterDragon/map-preview-perf
Faster map preview generation.
2014-06-11 00:05:10 +12:00
RoosterDragon
9dbbc23967 Make map preview generation fast.
- Change Map.LoadMapTiles and Map.LoadResourceTiles to read the whole stream into memory before processing individual bytes. This removes the cost of significant overhead from repeated calls to ReadUInt8/16.
- Remove significant UI jank caused by the map chooser by not including the placeholder widget. The maps render fast enough that it is no longer worthwhile and it was causing a lot of flushes which were the source of the jank.
- Trigger async generation for all maps when the chooser is loaded. This means in practice all previews will be ready by the time the user begins to scroll the selection. Since generation is fast, there is no issue with scrolling straight to the bottom and having to wait for the backlog to clear.
2014-06-10 11:46:39 +01:00
RoosterDragon
a598a01108 Fixed IDisposable implementation and usage.
- Implement IDisposable interface correctly, with sealed classes where possible for simplicity.
- Add using statement around undisposed local variables.
2014-06-10 11:23:55 +01:00
deniz1a
1821c52db0 Make "Ready" text alternate between red and white
Make color of "Ready" text alternate between red and white.

Made the code cleaner.

Whitespace correction.

Whitespace correction again.

Change color from red to green and make it moddable

Use enum for ReadyTextStyle

Use enum for cnc

Made variables public and simplified if statements

fix enum

fix enum and )

ReadyText settings in ra yaml

ReadyText settings in cnc yaml

Move values from code to ra yaml

Move values from code to cnc yaml

revert code changes cnc

revert code changes ra

move around a bit in ra yaml

move around a bit in cnc yaml

Add values to d2k yaml
2014-06-10 12:00:57 +03:00
Matthias Mailänder
8093942913 fix bogus label descriptors 2014-06-10 09:24:35 +02:00
Matthias Mailänder
69d86cfcf2 add automated language string extraction to utility 2014-06-10 09:24:28 +02:00
Matthias Mailänder
c9a49538d6 translatable tooltips 2014-06-10 09:18:46 +02:00
Paul Chote
ee7573d01c Merge pull request #5484 from RoosterDragon/startup-efficiency
Improved efficiency of startup methods.
2014-06-10 18:28:25 +12:00
Paul Chote
373529e110 Merge pull request #5505 from pavlos256/map-preview-generation
Map preview generation
2014-06-10 17:56:21 +12:00
Chris Forbes
00b95f754f Merge pull request #5593 from RobotCaleb/misc_fixes
Expanded credits window a bit
2014-06-10 10:39:50 +12:00
Caleb Anderson
3b9f1ed43c expand credits window a bit to fit the text better. 2014-06-09 16:06:45 -06:00
Caleb Anderson
49def655c9 add sublime text project/workspace to ignore 2014-06-09 16:06:44 -06:00
Matthias Mailänder
9df00ad8f9 Merge pull request #5590 from Happy0/sd2windowgrab
Closes #4977
2014-06-09 20:29:29 +02:00
Gordon Martin
5eab479c34 Adding SDL2 window grab on loading the game. Made this behaviour configurable in the 'Input' tab of the Settings menu
Updated settings file for TD to expose the new 'Lock mouse to window' display configuration option

A text label notes that modifying the 'Lock mouse' check box requires a restart
2014-06-09 19:10:05 +01:00
RoosterDragon
e63f330717 Improved efficiency of startup methods.
- ShpReader will copy the input stream into memory just once rather than for every header.
- ShpReader.CopyImageData switched to use Array.Copy since that uses some unsafe magic for speed.
- In ActorInfo, cache a GetType call and prevent needless materialization in PrerequisitesOf.
- In ObjectCreator, cache type and ctor lookups since these are expensive and often repeated.
- Implement IReadOnlyDictionary<T, U> on Cache<T, U> to provide some supplementary functions.
- In TechTree.GatherOwnedPrerequisites, rearrange a Boolean 'and' expression to evaluate expensive functions later in the chain, and use ContainsKey to speed up name check.
2014-06-09 17:13:01 +01:00
RoosterDragon
2e992a7310 Changed MiniYaml.NodesDict property into a method.
Method is now called ToDictionary.
- Cached a few invocations into locals which should prevent some redundant evaluation.
- Added ToDictionary overloads that take projection functions for the keys and elements, since several callsites were doing a subsequent Linq.ToDictionary call to get this.
2014-06-09 17:06:42 +01:00
Matthias Mailänder
334a210231 Merge pull request #5564 from Kanar/MinibibsRework
Adds/reworks some minibibs
2014-06-09 16:54:35 +02:00
Matthias Mailänder
13fad65c19 Merge pull request #5539 from deniz1a/repair-pause
Closes #5322
2014-06-09 16:24:34 +02:00
Matthias Mailänder
7216688baf Merge pull request #5567 from ScottNZ/perf
Refactor AutoTarget scan and GPS interaction
2014-06-09 12:01:05 +02:00
Paul Chote
decdcf44d4 Merge pull request #5504 from RoosterDragon/frozen-fog-lookup-locals
Cache some dictionary lookups
2014-06-09 17:50:38 +12:00
Paul Chote
d8e5177a36 Merge pull request #5405 from RoosterDragon/min-max
Added MinBy, MaxBy, etc.
2014-06-09 17:42:01 +12:00
Chris Forbes
033f631f28 Merge pull request #5508 from pavlos256/read-only-list
Add IReadOnlyList
2014-06-09 17:36:40 +12:00
Paul Chote
1c8a8ca6ff Merge pull request #5400 from RoosterDragon/equatable
Implemented IEquatable<T>
2014-06-09 17:32:17 +12:00
Paul Chote
ea9601b128 Merge pull request #5509 from RoosterDragon/stream-exts-fixes
Fixes to StreamExts.
2014-06-09 17:25:25 +12:00
Chris Forbes
1051728790 Merge pull request #5541 from RoosterDragon/enumerate-armaments-once
Avoid repeated work in AttackBase.
2014-06-09 17:07:51 +12:00
Matthias Mailänder
799966d376 don't target or demolish oil derrick husks 2014-06-08 11:18:14 +02:00
Matthias Mailänder
a35d84bf5a don't remove and add a trait at the same time 2014-06-08 11:17:10 +02:00
Matthias Mailänder
80a4f33730 document MoveIntoWorld 2014-06-08 11:12:05 +02:00
Matthias Mailänder
bc103f8ffd Merge pull request #5577 from pchote/production-fix
Don’t queue rallypoint move if MoveIntoWorld:false.
2014-06-08 10:38:12 +02:00
Paul Chote
2c5f1de780 Don’t queue rallypoint move if MoveIntoWorld:false. Fixes #5576. 2014-06-08 11:52:39 +12:00
Paul Chote
9762ef8119 Merge pull request #5573 from Mailaender/replay-hotkeys
Fixed pixel doubling and health bar hotkeys unavailable in spectator mode
2014-06-07 23:24:02 +12:00
Matthias Mailänder
3a1c41c8ce move pixel doubling and health bar hotkeys to shared widget
closes #5572
2014-06-07 12:26:58 +02:00
Paul Chote
f06cbfa5fe Merge pull request #5571 from Mailaender/invisible-gems
Fixed single resources being spawned at 0 density
2014-06-07 22:08:46 +12:00
Matthias Mailänder
0dee8208a8 never spawn with density 0 because that is not rendered 2014-06-07 11:56:54 +02:00
Matthias Mailänder
1c92737798 Merge pull request #5570 from pchote/arch-packaging
Fix arch packaging (attempt two).
2014-06-07 11:02:13 +02:00
Paul Chote
a0723bfec3 Fix pacman installation. 2014-06-07 20:58:08 +12:00
Kanar
bf47543a0a Adds/reworks some minibibs 2014-06-07 09:24:08 +02:00
ScottNZ
7e6f7c51e1 Refactor AutoTarget scan and GPS interaction, and cache trait lookup for a slight performance boost 2014-06-07 12:01:50 +12:00
RoosterDragon
531e3b7861 Fixes to StreamExts.
- Almost all calls to Stream.Read were broken. These have been patched to all go through ReadBytes which itself has been fixed to function correctly. The key thing to note is that Stream.Read is very much allowed to return less than the requested number of bytes. If this happens and you're not checking the return result, you'll be working with partially initialized arrays and really bad stuff happens when you do that.
- Call CopyTo rather than copying between streams manually.
- Peek and ReadUInt8 have been changed to avoid a pointless array allocation which is significant overhead for such simple calls.
2014-06-07 00:49:25 +01:00
Deniz Ayıkol
5055764e04 Make repair animation pause if player has no money.
use anim.Paused

removed the using line
2014-06-04 22:15:18 +03:00
RoosterDragon
0027434fbd Avoid multiple enumerations of armaments in AttackBase.
- Avoid enumerating the collection more than once in a method as it is not trivial.
2014-06-04 02:17:44 +01:00
Pavlos Touboulidis
7d352fdad1 MapCache performance improvements 2014-05-31 23:49:04 +03:00
RoosterDragon
f180f44542 Cache some dictionary lookups in FrozenUnderFog.Tick.
Since FrozenUnderFog.Tick gets called a lot, these dictionary lookups were actually getting repeated a fair amount. Avoiding the repeated work is a minor performance improvement.
2014-05-31 18:29:31 +01:00
Pavlos Touboulidis
e083b392ba Add IReadOnlyList 2014-05-31 18:37:03 +03:00
Pavlos Touboulidis
441d602a6d Fix thread synchronization problem with Sheet.dirty 2014-05-31 17:26:24 +03:00
RoosterDragon
b1d5f4edd9 Also implemented on the Bits<T> struct. 2014-05-23 13:53:56 +01:00
RoosterDragon
0ea3509ee4 Added MinBy, MaxBy, MinByOrDefault and MaxByOrDefault methods and replaced calls of the style OrderBy[Descending]().First[OrDefault]() which is not as performant. 2014-05-23 08:23:42 +01:00
RoosterDragon
67594b844a Implemented IEquatable<T> to speed up equality comparisons.
Actor, CPos, CVec, WAngle, WPos, WRange, WRot and WVec structs now implement IEquatable<T> which means unboxing/casting costs can be eliminated.

Also simplified the ToString method by concatenating components directly rather than using a format string since the overhead is a bit high for simple cases like this.
2014-05-23 08:04:43 +01:00
993 changed files with 14494 additions and 9186 deletions

6
.gitignore vendored
View File

@@ -56,4 +56,8 @@ Lua-API.md
*.html
# StyleCop
*.Cache
*.Cache
# SublimeText
*.sublime-project
*.sublime-workspace

View File

@@ -6,7 +6,8 @@ language: c
# Make sure build dependencies are installed.
install:
- sudo apt-get install mono-gmcs cli-common-dev libgl1-mesa-glx libopenal1 libfreetype6
- sudo apt-get update -qq
- sudo apt-get install -qq mono-gmcs cli-common-dev libgl1-mesa-glx libopenal1 libfreetype6
cache: apt
# Run the build script
@@ -37,8 +38,10 @@ notifications:
before_deploy:
- sudo apt-get install nsis markdown dpkg rpm libarchive-dev m4 fakeroot bsdtar
- wget ftp://ftp.archlinux.org/other/pacman/pacman-4.0.3.tar.gz -O /tmp/pacman-4.0.3.tar.gz
- pushd /tmp
- tar -xzvf pacman-4.0.3.tar.gz
- cd pacman-4.0.3 && ./configure --disable-doc --prefix=/usr && make && sudo make install
- popd
- DOTVERSION=`echo ${TRAVIS_TAG} | sed "s/-/\\./g"`
- cd packaging
- mkdir build

View File

@@ -6,7 +6,6 @@ The OpenRA developers are:
* Curtis Shmyr (hamb)
* Matthias Mailänder (Mailaender)
* Paul Chote (pchote)
* ScottNZ
Previous developers included:
* Alli Witheford (alzeih)
@@ -15,9 +14,12 @@ Previous developers included:
* Megan Bowra-Dean (beedee)
* Mike Bundy (kehaar)
* Robert Pepperell (ytinasni)
* ScottNZ
Also thanks to:
* Adam Valy (Tschokky)
* Akseli Virtanen (RAGEQUIT)
* Allen262
* Andrew Aldridge (i80and)
* Andrew Perkins
* Andrew Riedi
@@ -35,6 +37,7 @@ Also thanks to:
* Fahrradkette
* Frank Razenberg (zzattack)
* Gareth Needham (Ripley`)
* Gordon Martin (Happy0)
* Igor Popov (ihptru)
* Iran
* James Dunne (jsd)
@@ -49,13 +52,16 @@ Also thanks to:
* Lesueur Benjamin (Valkirie)
* Maarten Meuris (Nyerguds)
* Mark Olson (markolson)
* Matija Hustic (matija-hustic)
* Matthew Gatland (mgatland)
* Matthew Uzzell (MUzzell)
* Max621
* Max Ugrumov (katzsmile)
* Mustafa Alperen Seki (MustaphaTR)
* Nukem
* Okunev Yu Dmitry (xaionaro)
* Olaf van der Spek
* Oliver Brakmann
* Paolo Chiodi (paolochiodi)
* Paul Dovydaitis (pdovy)
* Pavlos Touboulidis (pav)
@@ -73,6 +79,7 @@ Also thanks to:
* Teemu Nieminen (Temeez)
* Tim Mylemans (gecko)
* Tirili
* Tom Roostan (RoosterDragon)
* Tristan Keating (Kilkakon)
* Tristan Mühlbacher (MicroBit)
* Vladimir Komarov (VrKomarov)

View File

@@ -8,7 +8,7 @@
<RootNamespace>OpenRA</RootNamespace>
<AssemblyName>OpenRA.CrashDialog</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<OutputPath>..\</OutputPath>
@@ -16,18 +16,10 @@
<ErrorReport>prompt</ErrorReport>
<PlatformTarget>x86</PlatformTarget>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\</OutputPath>
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>OpenRA.ico</ApplicationIcon>
<ApplicationIcon>..\OpenRA.Game\OpenRA.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
@@ -43,8 +35,5 @@
<ItemGroup>
<Compile Include="Program.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="OpenRA.ico" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 264 KiB

View File

@@ -15,7 +15,6 @@ using System.IO;
using System.Media;
using System.Reflection;
using System.Windows.Forms;
using OpenRA;
namespace OpenRA.CrashDialog
{

View File

@@ -0,0 +1,344 @@
<StyleCopSettings Version="105">
<Analyzers>
<Analyzer AnalyzerId="StyleCop.CSharp.DocumentationRules">
<Rules>
<Rule Name="ElementsMustBeDocumented">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="PartialElementsMustBeDocumented">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="EnumerationItemsMustBeDocumented">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="DocumentationMustContainValidXml">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ElementDocumentationMustHaveSummary">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="PartialElementDocumentationMustHaveSummary">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ElementDocumentationMustHaveSummaryText">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="PartialElementDocumentationMustHaveSummaryText">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ElementDocumentationMustNotHaveDefaultSummary">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ElementParametersMustBeDocumented">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ElementParameterDocumentationMustMatchElementParameters">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ElementParameterDocumentationMustDeclareParameterName">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ElementParameterDocumentationMustHaveText">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ElementReturnValueMustBeDocumented">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ElementReturnValueDocumentationMustHaveText">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="VoidReturnValueMustNotBeDocumented">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="GenericTypeParametersMustBeDocumented">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="GenericTypeParametersMustBeDocumentedPartialClass">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="GenericTypeParameterDocumentationMustMatchTypeParameters">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="GenericTypeParameterDocumentationMustDeclareParameterName">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="GenericTypeParameterDocumentationMustHaveText">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="PropertySummaryDocumentationMustMatchAccessors">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="PropertySummaryDocumentationMustOmitSetAccessorWithRestrictedAccess">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ElementDocumentationMustNotBeCopiedAndPasted">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="SingleLineCommentsMustNotUseDocumentationStyleSlashes">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="DocumentationTextMustNotBeEmpty">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="DocumentationTextMustContainWhitespace">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="DocumentationMustMeetCharacterPercentage">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ConstructorSummaryDocumentationMustBeginWithStandardText">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="DestructorSummaryDocumentationMustBeginWithStandardText">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="DocumentationHeadersMustNotContainBlankLines">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="IncludedDocumentationXPathDoesNotExist">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="IncludeNodeDoesNotContainValidFileAndPath">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="InheritDocMustBeUsedWithInheritingClass">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ElementDocumentationMustBeSpelledCorrectly">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="FileMustHaveHeader">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="FileHeaderMustShowCopyright">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="FileHeaderMustHaveCopyrightText">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="FileHeaderMustContainFileName">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="FileHeaderFileNameDocumentationMustMatchFileName">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="FileHeaderMustHaveValidCompanyText">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="FileHeaderFileNameDocumentationMustMatchTypeName">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
</Rules>
<AnalyzerSettings />
</Analyzer>
<Analyzer AnalyzerId="StyleCop.CSharp.SpacingRules">
<Rules>
<Rule Name="TabsMustNotBeUsed">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
</Rules>
<AnalyzerSettings />
</Analyzer>
<Analyzer AnalyzerId="StyleCop.CSharp.LayoutRules">
<Rules>
<Rule Name="CurlyBracketsForMultiLineStatementsMustNotShareLine">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="StatementMustNotBeOnSingleLine">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ElementMustNotBeOnSingleLine">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="CurlyBracketsMustNotBeOmitted">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ElementsMustBeSeparatedByBlankLine">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
</Rules>
<AnalyzerSettings />
</Analyzer>
<Analyzer AnalyzerId="StyleCop.CSharp.OrderingRules">
<Rules>
<Rule Name="UsingDirectivesMustBePlacedWithinNamespace">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ElementsMustAppearInTheCorrectOrder">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ElementsMustBeOrderedByAccess">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
</Rules>
<AnalyzerSettings />
</Analyzer>
<Analyzer AnalyzerId="StyleCop.CSharp.ReadabilityRules">
<Rules>
<Rule Name="CodeMustNotContainMultipleStatementsOnOneLine">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="UseStringEmptyForEmptyStrings">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="PrefixLocalCallsWithThis">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="PrefixCallsCorrectly">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ParametersMustBeOnSameLineOrSeparateLines">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ParameterMustFollowComma">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="SplitParametersMustStartOnLineAfterDeclaration">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
</Rules>
<AnalyzerSettings />
</Analyzer>
<Analyzer AnalyzerId="StyleCop.CSharp.MaintainabilityRules">
<Rules>
<Rule Name="AccessModifierMustBeDeclared">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="FieldsMustBePrivate">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="FileMayOnlyContainASingleClass">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="ArithmeticExpressionsMustDeclarePrecedence">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
</Rules>
<AnalyzerSettings />
</Analyzer>
</Analyzers>
</StyleCopSettings>

View File

@@ -11,7 +11,6 @@
using System;
using System.Drawing;
using System.Windows.Forms;
using OpenRA.FileFormats;
namespace OpenRA.Editor
{

View File

@@ -9,8 +9,6 @@
#endregion
using System.Linq;
using OpenRA.FileFormats;
using SGraphics = System.Drawing.Graphics;
namespace OpenRA.Editor

View File

@@ -11,8 +11,6 @@
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using OpenRA.FileFormats;
using SGraphics = System.Drawing.Graphics;
namespace OpenRA.Editor
@@ -39,16 +37,15 @@ namespace OpenRA.Editor
for (var u = 0; u < template.Size.X; u++)
for (var v = 0; v < template.Size.Y; v++)
{
if (surface.Map.IsInMap(new CVec(u, v) + pos))
var cell = pos + new CVec(u, v);
if (surface.Map.Contains(cell))
{
var z = u + v * template.Size.X;
if (tile[z].Length > 0)
surface.Map.MapTiles.Value[u + pos.X, v + pos.Y] =
new TileReference<ushort, byte>
{
Type = brushTemplate.N,
Index = template.PickAny ? (byte)((u + pos.X) % 4 + ((v + pos.Y) % 4) * 4) : (byte)z,
};
{
var index = template.PickAny ? (byte)((u + pos.X) % 4 + ((v + pos.Y) % 4) * 4) : (byte)z;
surface.Map.MapTiles.Value[cell] = new TerrainTile(brushTemplate.N, index);
}
var ch = new int2((pos.X + u) / Surface.ChunkSize, (pos.Y + v) / Surface.ChunkSize);
if (surface.Chunks.ContainsKey(ch))
@@ -64,7 +61,7 @@ namespace OpenRA.Editor
{
g.DrawImage(brushTemplate.Bitmap,
surface.TileSetRenderer.TileSize * surface.GetBrushLocation().X * surface.Zoom + surface.GetOffset().X,
surface.TileSetRenderer.TileSize * surface.GetBrushLocation().Y * surface.Zoom + surface.GetOffset().Y,
surface.TileSetRenderer.TileSize * surface.GetBrushLocation().Y * surface.Zoom + surface.GetOffset().Y,
brushTemplate.Bitmap.Width * surface.Zoom,
brushTemplate.Bitmap.Height * surface.Zoom);
}
@@ -72,14 +69,15 @@ namespace OpenRA.Editor
void FloodFillWithBrush(Surface s, CPos pos)
{
var queue = new Queue<CPos>();
var replace = s.Map.MapTiles.Value[pos.X, pos.Y];
var replace = s.Map.MapTiles.Value[pos];
var touched = new bool[s.Map.MapSize.X, s.Map.MapSize.Y];
Action<int, int> maybeEnqueue = (x, y) =>
{
if (s.Map.IsInMap(x, y) && !touched[x, y])
var c = new CPos(x, y);
if (s.Map.Contains(c) && !touched[x, y])
{
queue.Enqueue(new CPos(x, y));
queue.Enqueue(c);
touched[x, y] = true;
}
};
@@ -88,7 +86,7 @@ namespace OpenRA.Editor
while (queue.Count > 0)
{
var p = queue.Dequeue();
if (s.Map.MapTiles.Value[p.X, p.Y].Type != replace.Type)
if (s.Map.MapTiles.Value[p].Type != replace.Type)
continue;
var a = FindEdge(s, p, new CVec(-1, 0), replace);
@@ -96,10 +94,10 @@ namespace OpenRA.Editor
for (var x = a.X; x <= b.X; x++)
{
s.Map.MapTiles.Value[x, p.Y] = new TileReference<ushort, byte> { Type = brushTemplate.N, Index = (byte)0 };
if (s.Map.MapTiles.Value[x, p.Y - 1].Type == replace.Type)
s.Map.MapTiles.Value[new CPos(x, p.Y)] = new TerrainTile(brushTemplate.N, (byte)0);
if (s.Map.MapTiles.Value[new CPos(x, p.Y - 1)].Type == replace.Type)
maybeEnqueue(x, p.Y - 1);
if (s.Map.MapTiles.Value[x, p.Y + 1].Type == replace.Type)
if (s.Map.MapTiles.Value[new CPos(x, p.Y + 1)].Type == replace.Type)
maybeEnqueue(x, p.Y + 1);
}
}
@@ -109,13 +107,13 @@ namespace OpenRA.Editor
s.Chunks.Clear();
}
static CPos FindEdge(Surface s, CPos p, CVec d, TileReference<ushort, byte> replace)
static CPos FindEdge(Surface s, CPos p, CVec d, TerrainTile replace)
{
for (;;)
{
var q = p + d;
if (!s.Map.IsInMap(q)) return p;
if (s.Map.MapTiles.Value[q.X, q.Y].Type != replace.Type) return p;
if (!s.Map.Contains(q)) return p;
if (s.Map.MapTiles.Value[q].Type != replace.Type) return p;
p = q;
}
}

View File

@@ -88,7 +88,11 @@ namespace OpenRA.Editor
foreach (var init in Program.Rules.Actors[kv.Value.Type].GetInitKeys())
apd.AddRow(init.First,
apd.MakeEditorControl(init.Second,
() => objSaved.NodesDict.ContainsKey(init.First) ? objSaved.NodesDict[init.First].Value : null,
() =>
{
var nodesDict = objSaved.ToDictionary();
return nodesDict.ContainsKey(init.First) ? nodesDict[init.First].Value : null;
},
_ => { }));
apd.ShowDialog();
@@ -149,11 +153,11 @@ namespace OpenRA.Editor
tileset = Program.Rules.TileSets[map.Tileset];
tilesetRenderer = new TileSetRenderer(tileset, modData.Manifest.TileSize);
var shadowIndex = new int[] { 3, 4 };
var palette = new Palette(GlobalFileSystem.Open(tileset.Palette), shadowIndex);
var palette = new ImmutablePalette(GlobalFileSystem.Open(tileset.Palette), shadowIndex);
// required for desert terrain in RA
var playerPalette = tileset.PlayerPalette ?? tileset.Palette;
var shadowedPalette = new Palette(GlobalFileSystem.Open(playerPalette), shadowIndex);
var shadowedPalette = new ImmutablePalette(GlobalFileSystem.Open(playerPalette), shadowIndex);
surface1.Bind(map, tileset, tilesetRenderer, palette, shadowedPalette);
@@ -162,7 +166,7 @@ namespace OpenRA.Editor
foreach (var p in palettes) { p.Visible = false; p.SuspendLayout(); }
var templateOrder = tileset.EditorTemplateOrder ?? new string[] { };
foreach (var tc in tileset.Templates.GroupBy(t => t.Value.Category).OrderBy(t => templateOrder.ToList().IndexOf(t.Key)))
foreach (var tc in tileset.Templates.GroupBy(t => t.Value.Category).OrderBy(t => Array.IndexOf(templateOrder, t.Key)))
{
var category = tc.Key ?? "(Uncategorized)";
var categoryHeader = new Label
@@ -633,11 +637,12 @@ namespace OpenRA.Editor
public int CalculateTotalResource()
{
int totalResource = 0;
for (int i = 0; i < surface1.Map.MapSize.X; i++)
for (int j = 0; j < surface1.Map.MapSize.Y; j++)
var totalResource = 0;
for (var i = 0; i < surface1.Map.MapSize.X; i++)
for (var j = 0; j < surface1.Map.MapSize.Y; j++)
{
if (surface1.Map.MapResources.Value[i, j].Type != 0)
var cell = new CPos(i, j);
if (surface1.Map.MapResources.Value[cell].Type != 0)
totalResource += GetResourceValue(i, j);
}
@@ -646,13 +651,16 @@ namespace OpenRA.Editor
int GetAdjecentCellsWith(int resourceType, int x, int y)
{
int sum = 0;
var sum = 0;
for (var u = -1; u < 2; u++)
for (var v = -1; v < 2; v++)
{
if (!surface1.Map.IsInMap(new CPos(x + u, y + v)))
var cell = new CPos(x + u, y + v);
if (!surface1.Map.Contains(cell))
continue;
if (surface1.Map.MapResources.Value[x + u, y + v].Type == resourceType)
if (surface1.Map.MapResources.Value[cell].Type == resourceType)
++sum;
}
@@ -661,15 +669,15 @@ namespace OpenRA.Editor
int GetResourceValue(int x, int y)
{
int imageLength = 0;
int type = surface1.Map.MapResources.Value[x, y].Type;
var imageLength = 0;
var type = surface1.Map.MapResources.Value[new CPos(x, y)].Type;
var template = surface1.ResourceTemplates.FirstOrDefault(a => a.Value.Info.ResourceType == type).Value;
if (type == 1)
imageLength = 12;
else if (type == 2)
imageLength = 3;
int density = (GetAdjecentCellsWith(type, x, y) * imageLength - 1) / 9;
int value = template.Info.ValuePerUnit;
var density = (GetAdjecentCellsWith(type, x, y) * imageLength - 1) / 9;
var value = template.Info.ValuePerUnit;
return density * value;
}

View File

@@ -47,7 +47,7 @@ namespace OpenRA.Editor
foreach (var map in MapCache.FindMapsIn(MapFolderPath))
{
ListViewItem map1 = new ListViewItem();
var map1 = new ListViewItem();
map1.Tag = map;
map1.Text = Path.GetFileNameWithoutExtension(map);
map1.ImageIndex = 0;

View File

@@ -32,30 +32,17 @@
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<UseVSHostingProcess>false</UseVSHostingProcess>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core">

View File

@@ -10,10 +10,7 @@
using System;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using OpenRA.FileFormats;
namespace OpenRA.Editor
{

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -8,21 +8,19 @@
*/
#endregion
using System.Collections;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.FileSystem;
using OpenRA.Graphics;
using OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA.Editor
{
static class RenderUtils
{
static Bitmap RenderShp(ISpriteSource shp, Palette p)
static Bitmap RenderShp(ISpriteSource shp, IPalette p)
{
var frame = shp.Frames.First();
@@ -35,7 +33,7 @@ namespace OpenRA.Editor
unsafe
{
byte* q = (byte*)data.Scan0.ToPointer();
var q = (byte*)data.Scan0.ToPointer();
var stride2 = data.Stride;
for (var i = 0; i < frame.Size.Width; i++)
@@ -47,7 +45,7 @@ namespace OpenRA.Editor
return bitmap;
}
public static ActorTemplate RenderActor(ActorInfo info, TileSet tileset, Palette p)
public static ActorTemplate RenderActor(ActorInfo info, TileSet tileset, IPalette p)
{
var image = RenderSprites.GetImage(info);
@@ -78,7 +76,7 @@ namespace OpenRA.Editor
}
}
public static ResourceTemplate RenderResourceType(ResourceTypeInfo info, string[] exts, Palette p)
public static ResourceTemplate RenderResourceType(ResourceTypeInfo info, string[] exts, IPalette p)
{
var image = info.EditorSprite;
using (var s = GlobalFileSystem.OpenWithExts(image, exts))
@@ -94,7 +92,7 @@ namespace OpenRA.Editor
unsafe
{
byte* q = (byte*)data.Scan0.ToPointer();
var q = (byte*)data.Scan0.ToPointer();
var stride = data.Stride;
for (var i = 0; i < frame.Size.Width; i++)
@@ -103,7 +101,7 @@ namespace OpenRA.Editor
}
bitmap.UnlockBits(data);
return new ResourceTemplate { Bitmap = bitmap, Info = info, Value = shp.Frames.Count() - 1 };
return new ResourceTemplate { Bitmap = bitmap, Info = info, Value = shp.Frames.Count - 1 };
}
}
}

View File

@@ -9,8 +9,6 @@
#endregion
using System;
using OpenRA.FileFormats;
using SGraphics = System.Drawing.Graphics;
namespace OpenRA.Editor
@@ -23,12 +21,9 @@ namespace OpenRA.Editor
public void Apply(Surface surface)
{
surface.Map.MapResources.Value[surface.GetBrushLocation().X, surface.GetBrushLocation().Y]
= new TileReference<byte, byte>
{
Type = (byte)resourceTemplate.Info.ResourceType,
Index = (byte)random.Next(resourceTemplate.Info.MaxDensity)
};
var type = (byte)resourceTemplate.Info.ResourceType;
var index = (byte)random.Next(resourceTemplate.Info.MaxDensity);
surface.Map.MapResources.Value[surface.GetBrushLocation()] = new ResourceTile(type, index);
var ch = new int2(surface.GetBrushLocation().X / Surface.ChunkSize,
surface.GetBrushLocation().Y / Surface.ChunkSize);

View File

@@ -14,7 +14,6 @@ using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Windows.Forms;
using OpenRA.FileSystem;
using OpenRA.Graphics;
using OpenRA.Primitives;
using OpenRA.Traits;
@@ -46,8 +45,8 @@ namespace OpenRA.Editor
public Map Map { get; private set; }
public TileSet TileSet { get; private set; }
public TileSetRenderer TileSetRenderer { get; private set; }
public Palette Palette { get; private set; }
public Palette PlayerPalette { get; private set; }
public IPalette Palette { get; private set; }
public IPalette PlayerPalette { get; private set; }
public int2 Offset;
public int2 GetOffset() { return Offset; }
@@ -63,8 +62,8 @@ namespace OpenRA.Editor
public bool ShowRuler;
public bool IsPaste { get { return TileSelection != null && ResourceSelection != null; } }
public TileReference<ushort, byte>[,] TileSelection;
public TileReference<byte, byte>[,] ResourceSelection;
public TerrainTile[,] TileSelection;
public ResourceTile[,] ResourceSelection;
public CPos SelectionStart;
public CPos SelectionEnd;
@@ -82,7 +81,7 @@ namespace OpenRA.Editor
public Keys GetModifiers() { return ModifierKeys; }
public void Bind(Map m, TileSet ts, TileSetRenderer tsr, Palette p, Palette pp)
public void Bind(Map m, TileSet ts, TileSetRenderer tsr, IPalette p, IPalette pp)
{
Map = m;
TileSet = ts;
@@ -207,9 +206,9 @@ namespace OpenRA.Editor
var key = Map.Actors.Value.FirstOrDefault(a => a.Value.Location() == brushLocation);
if (key.Key != null) Map.Actors.Value.Remove(key.Key);
if (Map.MapResources.Value[brushLocation.X, brushLocation.Y].Type != 0)
if (Map.MapResources.Value[brushLocation].Type != 0)
{
Map.MapResources.Value[brushLocation.X, brushLocation.Y] = new TileReference<byte, byte>();
Map.MapResources.Value[brushLocation] = new ResourceTile(0, 0);
var ch = new int2(brushLocation.X / ChunkSize, brushLocation.Y / ChunkSize);
if (Chunks.ContainsKey(ch))
{
@@ -266,13 +265,14 @@ namespace OpenRA.Editor
unsafe
{
int* p = (int*)data.Scan0.ToPointer();
var p = (int*)data.Scan0.ToPointer();
var stride = data.Stride >> 2;
for (var i = 0; i < ChunkSize; i++)
for (var j = 0; j < ChunkSize; j++)
{
var tr = Map.MapTiles.Value[u * ChunkSize + i, v * ChunkSize + j];
var cell = new CPos(u * ChunkSize + i, v * ChunkSize + j);
var tr = Map.MapTiles.Value[cell];
var tile = TileSetRenderer.Data(tr.Type);
var index = (tr.Index < tile.Count) ? tr.Index : (byte)0;
var rawImage = tile[index];
@@ -280,13 +280,13 @@ namespace OpenRA.Editor
for (var y = 0; y < TileSetRenderer.TileSize; y++)
p[(j * TileSetRenderer.TileSize + y) * stride + i * TileSetRenderer.TileSize + x] = Palette.GetColor(rawImage[x + TileSetRenderer.TileSize * y]).ToArgb();
if (Map.MapResources.Value[u * ChunkSize + i, v * ChunkSize + j].Type != 0)
if (Map.MapResources.Value[cell].Type != 0)
{
var resourceImage = ResourceTemplates[Map.MapResources.Value[u * ChunkSize + i, v * ChunkSize + j].Type].Bitmap;
var resourceImage = ResourceTemplates[Map.MapResources.Value[cell].Type].Bitmap;
var srcdata = resourceImage.LockBits(resourceImage.Bounds(),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
int* q = (int*)srcdata.Scan0.ToPointer();
var q = (int*)srcdata.Scan0.ToPointer();
var srcstride = srcdata.Stride >> 2;
for (var x = 0; x < TileSetRenderer.TileSize; x++)
@@ -345,10 +345,10 @@ namespace OpenRA.Editor
float2 GetDrawPosition(CPos location, Bitmap bmp, bool centered)
{
float offsetX = centered ? bmp.Width / 2 - TileSetRenderer.TileSize / 2 : 0;
float drawX = TileSetRenderer.TileSize * location.X * Zoom + Offset.X - offsetX;
var drawX = TileSetRenderer.TileSize * location.X * Zoom + Offset.X - offsetX;
float offsetY = centered ? bmp.Height / 2 - TileSetRenderer.TileSize / 2 : 0;
float drawY = TileSetRenderer.TileSize * location.Y * Zoom + Offset.Y - offsetY;
var drawY = TileSetRenderer.TileSize * location.Y * Zoom + Offset.Y - offsetY;
return new float2(drawX, drawY);
}
@@ -381,7 +381,7 @@ namespace OpenRA.Editor
var pr = Map.Players[name];
var pcpi = Program.Rules.Actors["player"].Traits.Get<PlayerColorPaletteInfo>();
var remap = new PlayerColorRemap(pcpi.RemapIndex, pr.Color, pcpi.Ramp);
return new Palette(PlayerPalette, remap).AsSystemPalette();
return new ImmutablePalette(PlayerPalette, remap).AsSystemPalette();
}
Cache<string, ColorPalette> playerPalettes;
@@ -418,8 +418,8 @@ namespace OpenRA.Editor
var drawX = TileSetRenderer.TileSize * (float)ChunkSize * (float)x.X * Zoom + Offset.X;
var drawY = TileSetRenderer.TileSize * (float)ChunkSize * (float)x.Y * Zoom + Offset.Y;
RectangleF sourceRect = new RectangleF(0, 0, bmp.Width, bmp.Height);
RectangleF destRect = new RectangleF(drawX, drawY, bmp.Width * Zoom, bmp.Height * Zoom);
var sourceRect = new RectangleF(0, 0, bmp.Width, bmp.Height);
var destRect = new RectangleF(drawX, drawY, bmp.Width * Zoom, bmp.Height * Zoom);
e.Graphics.DrawImage(bmp, destRect, sourceRect, GraphicsUnit.Pixel);
}
@@ -468,20 +468,20 @@ namespace OpenRA.Editor
if (ShowRuler && Zoom > 0.2)
{
for (int i = Map.Bounds.Left; i <= Map.Bounds.Right; i += 8)
for (var i = Map.Bounds.Left; i <= Map.Bounds.Right; i += 8)
{
if (i % 8 == 0)
{
PointF point = new PointF(i * TileSetRenderer.TileSize * Zoom + Offset.X, (Map.Bounds.Top - 8) * TileSetRenderer.TileSize * Zoom + Offset.Y);
var point = new PointF(i * TileSetRenderer.TileSize * Zoom + Offset.X, (Map.Bounds.Top - 8) * TileSetRenderer.TileSize * Zoom + Offset.Y);
e.Graphics.DrawString((i - Map.Bounds.Left).ToString(), MarkerFont, TextBrush, point);
}
}
for (int i = Map.Bounds.Top; i <= Map.Bounds.Bottom; i += 8)
for (var i = Map.Bounds.Top; i <= Map.Bounds.Bottom; i += 8)
{
if (i % 8 == 0)
{
PointF point = new PointF((Map.Bounds.Left - 8) * TileSetRenderer.TileSize * Zoom + Offset.X, i * TileSetRenderer.TileSize * Zoom + Offset.Y);
var point = new PointF((Map.Bounds.Left - 8) * TileSetRenderer.TileSize * Zoom + Offset.X, i * TileSetRenderer.TileSize * Zoom + Offset.Y);
e.Graphics.DrawString((i - Map.Bounds.Left).ToString(), MarkerFont, TextBrush, point);
}
}
@@ -506,19 +506,20 @@ namespace OpenRA.Editor
if (start == end) return;
int width = Math.Abs((start - end).X);
int height = Math.Abs((start - end).Y);
var width = Math.Abs((start - end).X);
var height = Math.Abs((start - end).Y);
TileSelection = new TileReference<ushort, byte>[width, height];
ResourceSelection = new TileReference<byte, byte>[width, height];
TileSelection = new TerrainTile[width, height];
ResourceSelection = new ResourceTile[width, height];
for (int x = 0; x < width; x++)
for (var x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
for (var y = 0; y < height; y++)
{
// TODO: crash prevention
TileSelection[x, y] = Map.MapTiles.Value[start.X + x, start.Y + y];
ResourceSelection[x, y] = Map.MapResources.Value[start.X + x, start.Y + y];
var cell = new CPos(start.X + x, start.Y + y);
TileSelection[x, y] = Map.MapTiles.Value[cell];
ResourceSelection[x, y] = Map.MapResources.Value[cell];
}
}
}
@@ -529,16 +530,17 @@ namespace OpenRA.Editor
var width = Math.Abs((SelectionStart - SelectionEnd).X);
var height = Math.Abs((SelectionStart - SelectionEnd).Y);
for (int x = 0; x < width; x++)
for (var x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
for (var y = 0; y < height; y++)
{
var mapX = loc.X + x;
var mapY = loc.Y + y;
var cell = new CPos(mapX, mapY);
// TODO: crash prevention for outside of bounds
Map.MapTiles.Value[mapX, mapY] = TileSelection[x, y];
Map.MapResources.Value[mapX, mapY] = ResourceSelection[x, y];
Map.MapTiles.Value[cell] = TileSelection[x, y];
Map.MapResources.Value[cell] = ResourceSelection[x, y];
var ch = new int2(mapX / ChunkSize, mapY / ChunkSize);
if (Chunks.ContainsKey(ch))

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -12,7 +12,6 @@ using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using OpenRA.FileSystem;
using OpenRA.Graphics;
@@ -21,9 +20,9 @@ namespace OpenRA.Editor
{
public class TileSetRenderer
{
public readonly int TileSize;
public TileSet TileSet;
Dictionary<ushort, List<byte[]>> templates;
public readonly int TileSize;
// Extract a square tile that the editor can render
byte[] ExtractSquareTile(ISpriteFrame frame)
@@ -62,7 +61,7 @@ namespace OpenRA.Editor
if (frames != null)
{
var ret = new List<byte[]>();
var srcFrames = source.Frames.ToArray();
var srcFrames = source.Frames;
foreach (var i in frames)
ret.Add(ExtractSquareTile(srcFrames[i]));
@@ -83,7 +82,7 @@ namespace OpenRA.Editor
templates.Add(t.Key, LoadTemplate(t.Value.Image, tileset.Extensions, sourceCache, t.Value.Frames));
}
public Bitmap RenderTemplate(ushort id, Palette p)
public Bitmap RenderTemplate(ushort id, IPalette p)
{
var template = TileSet.Templates[id];
var templateData = templates[id];

View File

@@ -21,7 +21,7 @@ using OpenRA.Traits;
namespace OpenRA
{
public class Actor : IScriptBindable, IScriptNotifyBind, ILuaTableBinding, ILuaEqualityBinding, ILuaToStringBinding
public class Actor : IScriptBindable, IScriptNotifyBind, ILuaTableBinding, ILuaEqualityBinding, ILuaToStringBinding, IEquatable<Actor>
{
public readonly ActorInfo Info;
@@ -160,7 +160,12 @@ namespace OpenRA
public override bool Equals(object obj)
{
var o = obj as Actor;
return o != null && o.ActorID == ActorID;
return o != null && Equals(o);
}
public bool Equals(Actor other)
{
return ActorID == other.ActorID;
}
public override string ToString()
@@ -212,6 +217,9 @@ namespace OpenRA
{
World.AddFrameEndTask(w =>
{
if (this.Destroyed)
return;
var oldOwner = Owner;
// momentarily remove from world so the ownership queries don't get confused

View File

@@ -16,7 +16,7 @@ using OpenRA.Scripting;
namespace OpenRA
{
public struct CPos : IScriptBindable, ILuaAdditionBinding, ILuaSubtractionBinding, ILuaEqualityBinding, ILuaTableBinding
public struct CPos : IScriptBindable, ILuaAdditionBinding, ILuaSubtractionBinding, ILuaEqualityBinding, ILuaTableBinding, IEquatable<CPos>
{
public readonly int X, Y;
@@ -37,13 +37,6 @@ namespace OpenRA
public static CPos Max(CPos a, CPos b) { return new CPos(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); }
public static CPos Min(CPos a, CPos b) { return new CPos(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); }
public float2 ToFloat2() { return new float2(X, Y); }
public int2 ToInt2() { return new int2(X, Y); }
public WPos CenterPosition { get { return new WPos(1024 * X + 512, 1024 * Y + 512, 0); } }
public WPos TopLeft { get { return new WPos(1024 * X, 1024 * Y, 0); } }
public WPos BottomRight { get { return new WPos(1024 * X + 1023, 1024 * Y + 1023, 0); } }
public CPos Clamp(Rectangle r)
{
return new CPos(Math.Min(r.Right, Math.Max(X, r.Left)),
@@ -52,13 +45,10 @@ namespace OpenRA
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); }
public override bool Equals(object obj)
{
var o = obj as CPos?;
return o != null && o == this;
}
public bool Equals(CPos other) { return other == this; }
public override bool Equals(object obj) { return obj is CPos && Equals((CPos)obj); }
public override string ToString() { return "{0},{1}".F(X, Y); }
public override string ToString() { return X + "," + Y; }
#region Scripting interface
@@ -111,16 +101,4 @@ namespace OpenRA
#endregion
}
public static class RectangleExtensions
{
public static CPos TopLeftAsCPos(this Rectangle r) { return new CPos(r.Left, r.Top); }
public static CPos BottomRightAsCPos(this Rectangle r) { return new CPos(r.Right, r.Bottom); }
}
public static class WorldCoordinateExtensions
{
public static CPos ToCPos(this WPos a) { return new CPos(a.X / 1024, a.Y / 1024); }
public static CVec ToCVec(this WVec a) { return new CVec(a.X / 1024, a.Y / 1024); }
}
}

View File

@@ -16,18 +16,13 @@ using OpenRA.Scripting;
namespace OpenRA
{
public struct CVec : IScriptBindable, ILuaAdditionBinding, ILuaSubtractionBinding, ILuaUnaryMinusBinding, ILuaEqualityBinding, ILuaTableBinding
public struct CVec : IScriptBindable, ILuaAdditionBinding, ILuaSubtractionBinding, ILuaUnaryMinusBinding, ILuaEqualityBinding, ILuaTableBinding, IEquatable<CVec>
{
public readonly int X, Y;
public CVec(int x, int y) { X = x; Y = y; }
public CVec(Size p) { X = p.Width; Y = p.Height; }
public static readonly CVec Zero = new CVec(0, 0);
public static explicit operator CVec(int2 a) { return new CVec(a.X, a.Y); }
public static explicit operator CVec(float2 a) { return new CVec((int)a.X, (int)a.Y); }
public static CVec operator +(CVec a, CVec b) { return new CVec(a.X + b.X, a.Y + b.Y); }
public static CVec operator -(CVec a, CVec b) { return new CVec(a.X - b.X, a.Y - b.Y); }
public static CVec operator *(int a, CVec b) { return new CVec(a * b.X, a * b.Y); }
@@ -47,11 +42,7 @@ namespace OpenRA
public CVec Sign() { return new CVec(Math.Sign(X), Math.Sign(Y)); }
public CVec Abs() { return new CVec(Math.Abs(X), Math.Abs(Y)); }
public int LengthSquared { get { return X * X + Y * Y; } }
public int Length { get { return (int)Math.Sqrt(LengthSquared); } }
public float2 ToFloat2() { return new float2(X, Y); }
public int2 ToInt2() { return new int2(X, Y); }
public WVec ToWVec() { return new WVec(X*1024, Y*1024, 0); }
public int Length { get { return Exts.ISqrt(LengthSquared); } }
public CVec Clamp(Rectangle r)
{
@@ -63,13 +54,10 @@ namespace OpenRA
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); }
public override bool Equals(object obj)
{
var o = obj as CVec?;
return o != null && o == this;
}
public bool Equals(CVec other) { return other == this; }
public override bool Equals(object obj) { return obj is CVec && Equals((CVec)obj); }
public override string ToString() { return "{0},{1}".F(X, Y); }
public override string ToString() { return X + "," + Y; }
public static readonly CVec[] directions =
{
@@ -125,7 +113,6 @@ namespace OpenRA
{
case "X": return X;
case "Y": return Y;
case "Facing": return Traits.Util.GetFacing(this, 0);
default: throw new LuaException("CVec does not define a member '{0}'".F(key));
}
}

View File

@@ -70,6 +70,7 @@ namespace OpenRA
{
Game.OnQuit -= Cancel;
wc.CancelAsync();
wc.Dispose();
cancelled = true;
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
#region Copyright & License Information
/*
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -13,15 +13,17 @@ using OpenRA.Graphics;
namespace OpenRA.Effects
{
public class MoveFlash : IEffect
public class SpriteEffect : IEffect
{
string palette;
Animation anim;
WPos pos;
public MoveFlash(WPos pos, World world)
public SpriteEffect(WPos pos, World world, string sprite, string palette)
{
this.pos = pos;
anim = new Animation(world, "moveflsh");
this.palette = palette;
anim = new Animation(world, sprite);
anim.PlayThen("idle", () => world.AddFrameEndTask(w => w.Remove(this)));
}
@@ -32,7 +34,7 @@ namespace OpenRA.Effects
public IEnumerable<IRenderable> Render(WorldRenderer wr)
{
return anim.Render(pos, WVec.Zero, 0, wr.Palette("moveflash"), 1f / wr.Viewport.Zoom);
return anim.Render(pos, WVec.Zero, 0, wr.Palette(palette), 1f / wr.Viewport.Zoom);
}
}
}

View File

@@ -20,6 +20,11 @@ namespace OpenRA
{
public static class Exts
{
public static bool IsUppercase(this string str)
{
return string.Compare(str.ToUpperInvariant(), str, false) == 0;
}
public static string F(this string fmt, params object[] args)
{
return string.Format(fmt, args);
@@ -131,6 +136,54 @@ namespace OpenRA
for (;;) { yield return t; t = f(t); }
}
public static T MinBy<T, U>(this IEnumerable<T> ts, Func<T, U> selector)
{
return ts.CompareBy(selector, 1, true);
}
public static T MaxBy<T, U>(this IEnumerable<T> ts, Func<T, U> selector)
{
return ts.CompareBy(selector, -1, true);
}
public static T MinByOrDefault<T, U>(this IEnumerable<T> ts, Func<T, U> selector)
{
return ts.CompareBy(selector, 1, false);
}
public static T MaxByOrDefault<T, U>(this IEnumerable<T> ts, Func<T, U> selector)
{
return ts.CompareBy(selector, -1, false);
}
static T CompareBy<T, U>(this IEnumerable<T> ts, Func<T, U> selector, int modifier, bool throws)
{
var comparer = Comparer<U>.Default;
T t;
U u;
using (var e = ts.GetEnumerator())
{
if (!e.MoveNext())
if (throws)
throw new ArgumentException("Collection must not be empty.", "ts");
else
return default(T);
t = e.Current;
u = selector(t);
while (e.MoveNext())
{
var nextT = e.Current;
var nextU = selector(nextT);
if (comparer.Compare(nextU, u) * modifier < 0)
{
t = nextT;
u = nextU;
}
}
return t;
}
}
public static int NextPowerOf2(int v)
{
--v;
@@ -149,6 +202,91 @@ namespace OpenRA
public static Size NextPowerOf2(this Size s) { return new Size(NextPowerOf2(s.Width), NextPowerOf2(s.Height)); }
public enum ISqrtRoundMode { Floor, Nearest, Ceiling }
public static int ISqrt(int number, ISqrtRoundMode round = ISqrtRoundMode.Floor)
{
if (number < 0)
throw new InvalidOperationException("Attempted to calculate the square root of a negative integer: {0}".F(number));
return (int)ISqrt((uint)number, round);
}
public static uint ISqrt(uint number, ISqrtRoundMode round = ISqrtRoundMode.Floor)
{
var divisor = 1U << 30;
var root = 0U;
var remainder = number;
// Find the highest term in the divisor
while (divisor > number)
divisor >>= 2;
// Evaluate the root, two bits at a time
while (divisor != 0)
{
if (root + divisor <= remainder)
{
remainder -= root + divisor;
root += 2 * divisor;
}
root >>= 1;
divisor >>= 2;
}
// Adjust for other rounding modes
if (round == ISqrtRoundMode.Nearest && remainder > root)
root += 1;
else if (round == ISqrtRoundMode.Ceiling && root * root < number)
root += 1;
return root;
}
public static long ISqrt(long number, ISqrtRoundMode round = ISqrtRoundMode.Floor)
{
if (number < 0)
throw new InvalidOperationException("Attempted to calculate the square root of a negative integer: {0}".F(number));
return (long)ISqrt((ulong)number, round);
}
public static ulong ISqrt(ulong number, ISqrtRoundMode round = ISqrtRoundMode.Floor)
{
var divisor = 1UL << 62;
var root = 0UL;
var remainder = number;
// Find the highest term in the divisor
while (divisor > number)
divisor >>= 2;
// Evaluate the root, two bits at a time
while (divisor != 0)
{
if (root + divisor <= remainder)
{
remainder -= root + divisor;
root += 2 * divisor;
}
root >>= 1;
divisor >>= 2;
}
// Adjust for other rounding modes
if (round == ISqrtRoundMode.Nearest && remainder > root)
root += 1;
else if (round == ISqrtRoundMode.Ceiling && root * root < number)
root += 1;
return root;
}
public static string JoinWith<T>(this IEnumerable<T> ts, string j)
{
return string.Join(j, ts);
@@ -175,8 +313,8 @@ namespace OpenRA
var d = new Dictionary<TKey, TElement>();
foreach (var item in source)
{
TKey key = keySelector(item);
TElement element = elementSelector(item);
var key = keySelector(item);
var element = elementSelector(item);
// Check for a key conflict:
if (d.ContainsKey(key))
@@ -221,8 +359,8 @@ namespace OpenRA
public static T[] MakeArray<T>(int count, Func<int, T> f)
{
T[] result = new T[count];
for (int i = 0; i < count; i++)
var result = new T[count];
for (var i = 0; i < count; i++)
result[i] = f(i);
return result;

View File

@@ -297,7 +297,7 @@ namespace OpenRA
var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
var ret = Array.CreateInstance(fieldType.GetElementType(), parts.Length);
for (int i = 0; i < parts.Length; i++)
for (var i = 0; i < parts.Length; i++)
ret.SetValue(GetValue(fieldName, fieldType.GetElementType(), parts[i].Trim(), field), i);
return ret;
}

View File

@@ -131,7 +131,7 @@ namespace OpenRA.FileFormats
while (dataSize > 0)
{
var chunk = Chunk.Read(s);
for (int n = 0; n < chunk.CompressedSize; n++)
for (var n = 0; n < chunk.CompressedSize; n++)
{
var b = s.ReadUInt8();

View File

@@ -92,7 +92,7 @@ namespace OpenRA.FileFormats
// Magic number for "done"
if (len == 519)
{
for (int i = 0; i < next; i++)
for (var i = 0; i < next; i++)
ms.WriteByte(outBuffer[i]);
break;
}
@@ -135,7 +135,7 @@ namespace OpenRA.FileFormats
// Flush window to outstream
if (next == MAXWIN)
{
for (int i = 0; i < next; i++)
for (var i = 0; i < next; i++)
ms.WriteByte(outBuffer[i]);
next = 0;
first = false;
@@ -149,7 +149,7 @@ namespace OpenRA.FileFormats
outBuffer[next++] = (byte)symbol;
if (next == MAXWIN)
{
for (int i = 0; i < next; i++)
for (var i = 0; i < next; i++)
ms.WriteByte(outBuffer[i]);
next = 0;
first = false;
@@ -236,7 +236,7 @@ namespace OpenRA.FileFormats
var s = 0; // current symbol
// convert compact repeat counts into symbol bit length list
foreach (byte code in rep)
foreach (var code in rep)
{
var num = (code >> 4) + 1; // Number of codes (top four bits plus 1)
var len = (byte)(code & 15); // Code length (low four bits)
@@ -250,7 +250,7 @@ namespace OpenRA.FileFormats
// count number of codes of each length
Count = new short[Blast.MAXBITS + 1];
for (int i = 0; i < n; i++)
for (var i = 0; i < n; i++)
Count[length[i]]++;
// no codes!
@@ -259,7 +259,7 @@ namespace OpenRA.FileFormats
// check for an over-subscribed or incomplete set of lengths
var left = 1; // one possible code of zero length
for (int len = 1; len <= Blast.MAXBITS; len++)
for (var len = 1; len <= Blast.MAXBITS; len++)
{
left <<= 1; // one more bit, double codes left
left -= Count[len]; // deduct count from possible codes
@@ -269,7 +269,7 @@ namespace OpenRA.FileFormats
// generate offsets into symbol table for each length for sorting
var offs = new short[Blast.MAXBITS + 1];
for (int len = 1; len < Blast.MAXBITS; len++)
for (var len = 1; len < Blast.MAXBITS; len++)
offs[len + 1] = (short)(offs[len] + Count[len]);
// put symbols in table sorted by length, by symbol order within each length

View File

@@ -26,15 +26,15 @@ namespace OpenRA.FileFormats
uint l = 0, r = 0;
for (int i = 0; i < 18; )
for (var i = 0; i < 18; )
{
Encrypt(ref l, ref r);
m_p[i++] = l;
m_p[i++] = r;
}
for (int i = 0; i < 4; ++i)
for (int j = 0; j < 256; )
for (var i = 0; i < 4; ++i)
for (var j = 0; j < 256; )
{
Encrypt(ref l, ref r);
m_s[i, j++] = l;
@@ -49,14 +49,14 @@ namespace OpenRA.FileFormats
static uint[] RunCipher(uint[] data, CipherFunc f)
{
uint[] result = new uint[data.Length];
var result = new uint[data.Length];
int size = data.Length / 2;
int i = 0;
var size = data.Length / 2;
var i = 0;
while (size-- > 0)
{
uint a = SwapBytes(data[i]);
uint b = SwapBytes(data[i+1]);
var a = SwapBytes(data[i]);
var b = SwapBytes(data[i+1]);
f(ref a, ref b);
@@ -72,8 +72,8 @@ namespace OpenRA.FileFormats
uint _a = a, _b = b;
_a ^= m_p[0];
bool x = false;
for( int i = 1; i <= 16; i++, x ^= true)
var x = false;
for( var i = 1; i <= 16; i++, x ^= true)
{
if (x)
Round(ref _a, _b, i);
@@ -91,8 +91,8 @@ namespace OpenRA.FileFormats
uint _a = a, _b = b;
_a ^= m_p[17];
bool x = false;
for (int i = 16; i >= 1; i--, x ^= true)
var x = false;
for (var i = 16; i >= 1; i--, x ^= true)
{
if (x)
Round(ref _a, _b, i);

View File

@@ -37,7 +37,7 @@ namespace OpenRA.FileFormats
static void init_bignum(uint[] n, uint val, uint len)
{
for (int i = 0; i < len; i++) n[i] = 0;
for (var i = 0; i < len; i++) n[i] = 0;
n[0] = val;
}
@@ -52,8 +52,8 @@ namespace OpenRA.FileFormats
{
fixed (uint* _pn = &n[0])
{
byte* pn = (byte*)_pn;
uint i = blen * 4;
var pn = (byte*)_pn;
var i = blen * 4;
for (; i > klen; i--) pn[i - 1] = (byte)sign;
for (; i > 0; i--) pn[i - 1] = key[klen - i];
}
@@ -65,7 +65,7 @@ namespace OpenRA.FileFormats
uint keylen;
int i;
int j = 0;
var j = 0;
if (key[j] != 2) return;
j++;
@@ -118,7 +118,7 @@ namespace OpenRA.FileFormats
uint len_predata()
{
uint a = (pubkey.len - 1) / 8;
var a = (pubkey.len - 1) / 8;
return (55 / a + 1) * (a + 1);
}
@@ -141,7 +141,7 @@ namespace OpenRA.FileFormats
static void shr_bignum(uint[] n, int bits, int len)
{
int i; int i2 = bits / 32;
int i; var i2 = bits / 32;
if (i2 > 0)
{
@@ -183,9 +183,9 @@ namespace OpenRA.FileFormats
fixed (uint* _ps2 = &src2[0])
fixed (uint* _pd = &dest[0])
{
ushort* ps1 = (ushort*)_ps1;
ushort* ps2 = (ushort*)_ps2;
ushort* pd = (ushort*)_pd;
var ps1 = (ushort*)_ps1;
var ps2 = (ushort*)_ps2;
var pd = (ushort*)_pd;
while (--len != -1)
{
@@ -205,9 +205,9 @@ namespace OpenRA.FileFormats
len += len;
ushort* ps1 = (ushort*)src1;
ushort* ps2 = (ushort*)src2;
ushort* pd = (ushort*)dest;
var ps1 = (ushort*)src1;
var ps2 = (ushort*)src2;
var pd = (ushort*)dest;
while (--len != -1)
{
@@ -222,11 +222,11 @@ namespace OpenRA.FileFormats
static void inv_bignum(uint[] n1, uint[] n2, uint len)
{
uint[] n_tmp = new uint[64];
var n_tmp = new uint[64];
uint n2_bytelen, bit;
int n2_bitlen;
int j = 0;
var j = 0;
init_bignum(n_tmp, 0, len);
init_bignum(n1, 0, len);
@@ -257,7 +257,7 @@ namespace OpenRA.FileFormats
static void inc_bignum(uint[] n, uint len)
{
int i = 0;
var i = 0;
while ((++n[i] == 0) && (--len > 0)) i++;
}
@@ -289,7 +289,7 @@ namespace OpenRA.FileFormats
{
fixed (uint* _pn2 = &n2[0])
{
ushort* pn2 = (ushort*)_pn2;
var pn2 = (ushort*)_pn2;
tmp = 0;
for (i = 0; i < len; i++)
@@ -314,8 +314,8 @@ namespace OpenRA.FileFormats
fixed( uint * _psrc2 = &src2[0] )
fixed(uint* _pdest = &dest[0])
{
ushort* psrc2 = (ushort*)_psrc2;
ushort* pdest = (ushort*)_pdest;
var psrc2 = (ushort*)_psrc2;
var pdest = (ushort*)_pdest;
init_bignum(dest, 0, len * 2);
for (i = 0; i < len * 2; i++)
@@ -338,8 +338,8 @@ namespace OpenRA.FileFormats
unsafe uint get_mulword(uint* n)
{
ushort* wn = (ushort*)n;
uint i = (uint)((((((((((*(wn - 1) ^ 0xffff) & 0xffff) * glob1_hi_inv_lo + 0x10000) >> 1)
var wn = (ushort*)n;
var i = (uint)((((((((((*(wn - 1) ^ 0xffff) & 0xffff) * glob1_hi_inv_lo + 0x10000) >> 1)
+ (((*(wn - 2) ^ 0xffff) * glob1_hi_inv_hi + glob1_hi_inv_hi) >> 1) + 1)
>> 16) + ((((*(wn - 1) ^ 0xffff) & 0xffff) * glob1_hi_inv_hi) >> 1) +
(((*wn ^ 0xffff) * glob1_hi_inv_lo) >> 1) + 1) >> 14) + glob1_hi_inv_hi
@@ -350,7 +350,7 @@ namespace OpenRA.FileFormats
static void dec_bignum(uint[] n, uint len)
{
int i = 0;
var i = 0;
while ((--n[i] == 0xffffffff) && (--len > 0))
i++;
}
@@ -371,12 +371,12 @@ namespace OpenRA.FileFormats
inc_bignum(glob2, len * 2 + 1);
neg_bignum(glob2, len * 2 + 1);
len_diff = g2_len_x2 + 1 - glob1_len_x2;
ushort* esi = ((ushort*)g2) + (1 + g2_len_x2 - glob1_len_x2);
ushort* edi = ((ushort*)g2) + (g2_len_x2 + 1);
var esi = ((ushort*)g2) + (1 + g2_len_x2 - glob1_len_x2);
var edi = ((ushort*)g2) + (g2_len_x2 + 1);
for (; len_diff != 0; len_diff--)
{
edi--;
uint tmp = get_mulword((uint*)edi);
var tmp = get_mulword((uint*)edi);
esi--;
if (tmp > 0)
{
@@ -410,7 +410,7 @@ namespace OpenRA.FileFormats
void calc_a_key(uint[] n1, uint[] n2, uint[] n3, uint[] n4, uint len)
{
uint[] n_tmp = new uint[64];
var n_tmp = new uint[64];
uint n3_len, n4_len;
int n3_bitlen;
uint bit_mask;
@@ -419,7 +419,7 @@ namespace OpenRA.FileFormats
{
fixed (uint* _pn3 = &n3[0])
{
uint* pn3 = _pn3;
var pn3 = _pn3;
init_bignum(n1, 1, len);
n4_len = len_bignum(n4, len);
@@ -457,10 +457,10 @@ namespace OpenRA.FileFormats
unsafe void process_predata(byte* pre, uint pre_len, byte *buf)
{
uint[] n2 = new uint[64];
uint[] n3 = new uint[64];
var n2 = new uint[64];
var n3 = new uint[64];
uint a = (pubkey.len - 1) / 8;
var a = (pubkey.len - 1) / 8;
while (a + 1 <= pre_len)
{
init_bignum(n2, 0, 64);
@@ -480,7 +480,7 @@ namespace OpenRA.FileFormats
public byte[] DecryptKey(byte[] src)
{
init_pubkey();
byte[] dest = new byte[256];
var dest = new byte[256];
unsafe
{

View File

@@ -98,8 +98,8 @@ namespace OpenRA.FileFormats
/// </returns>
public static uint Calculate(byte[] data, uint polynomial)
{
uint crc = polynomial;
for (int i = 0; i < data.Length; i++)
var crc = polynomial;
for (var i = 0; i < data.Length; i++)
crc = (crc >> 8) ^ lookUp[(crc & 0xFF) ^ data[i]];
crc ^= polynomial;
return crc;
@@ -119,8 +119,8 @@ namespace OpenRA.FileFormats
/// <returns>The calculated checksum.</returns>
public static unsafe uint Calculate(byte* data, uint len, uint polynomial)
{
uint crc = polynomial;
for (int i = 0; i < len; i++)
var crc = polynomial;
for (var i = 0; i < len; i++)
crc = (crc >> 8) ^ lookUp[(crc & 0xFF) ^ *data++];
crc ^= polynomial;
return crc;

View File

@@ -12,58 +12,58 @@ namespace OpenRA.FileFormats
{
public static class Format40
{
public static int DecodeInto( byte[] src, byte[] dest )
public static int DecodeInto(byte[] src, byte[] dest, int srcOffset)
{
var ctx = new FastByteReader(src);
int destIndex = 0;
var ctx = new FastByteReader(src, srcOffset);
var destIndex = 0;
while( true )
while (true)
{
byte i = ctx.ReadByte();
if( ( i & 0x80 ) == 0 )
var i = ctx.ReadByte();
if ((i & 0x80) == 0)
{
int count = i & 0x7F;
if( count == 0 )
var count = i & 0x7F;
if (count == 0)
{
// case 6
count = ctx.ReadByte();
byte value = ctx.ReadByte();
for( int end = destIndex + count ; destIndex < end ; destIndex++ )
dest[ destIndex ] ^= value;
var value = ctx.ReadByte();
for (var end = destIndex + count; destIndex < end; destIndex++)
dest[destIndex] ^= value;
}
else
{
// case 5
for( int end = destIndex + count ; destIndex < end ; destIndex++ )
for (var end = destIndex + count; destIndex < end; destIndex++)
dest[destIndex] ^= ctx.ReadByte();
}
}
else
{
int count = i & 0x7F;
if( count == 0 )
var count = i & 0x7F;
if (count == 0)
{
count = ctx.ReadWord();
if( count == 0 )
if (count == 0)
return destIndex;
if( ( count & 0x8000 ) == 0 )
if ((count & 0x8000) == 0)
{
// case 2
destIndex += ( count & 0x7FFF );
destIndex += (count & 0x7FFF);
}
else if( ( count & 0x4000 ) == 0 )
else if ((count & 0x4000) == 0)
{
// case 3
for( int end = destIndex + ( count & 0x3FFF ) ; destIndex < end ; destIndex++ )
for (var end = destIndex + (count & 0x3FFF); destIndex < end; destIndex++)
dest[destIndex] ^= ctx.ReadByte();
}
else
{
// case 4
byte value = ctx.ReadByte();
for( int end = destIndex + ( count & 0x3FFF ) ; destIndex < end ; destIndex++ )
dest[ destIndex ] ^= value;
var value = ctx.ReadByte();
for (var end = destIndex + (count & 0x3FFF); destIndex < end; destIndex++)
dest[destIndex] ^= value;
}
}
else

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -16,11 +16,12 @@ namespace OpenRA.FileFormats
class FastByteReader
{
readonly byte[] src;
int offset = 0;
int offset;
public FastByteReader(byte[] src)
public FastByteReader(byte[] src, int offset = 0)
{
this.src = src;
this.offset = offset;
}
public bool Done() { return offset >= src.Length; }
@@ -59,9 +60,9 @@ namespace OpenRA.FileFormats
}
}
public static int DecodeInto(byte[] src, byte[] dest)
public static int DecodeInto(byte[] src, byte[] dest, int srcOffset = 0)
{
var ctx = new FastByteReader(src);
var ctx = new FastByteReader(src, srcOffset);
var destIndex = 0;
while (true)
@@ -125,26 +126,78 @@ namespace OpenRA.FileFormats
}
}
static int CountSame(byte[] src, int offset, int maxCount)
{
maxCount = Math.Min(src.Length - offset, maxCount);
if (maxCount <= 0)
return 0;
var first = src[offset++];
var count = 1;
while (count < maxCount && src[offset++] == first)
count++;
return count;
}
static void WriteCopyBlocks(byte[] src, int offset, int count, MemoryStream output)
{
while (count > 0)
{
var writeNow = Math.Min(count, 0x3F);
output.WriteByte((byte)(0x80 | writeNow));
output.Write(src, offset, writeNow);
count -= writeNow;
offset += writeNow;
}
}
// Quick and dirty Format80 encoder version 2
// Uses raw copy and RLE compression
public static byte[] Encode(byte[] src)
{
/* quick & dirty format80 encoder -- only uses raw copy operator, terminated with a zero-run. */
/* this does not produce good compression, but it's valid format80 */
var ctx = new FastByteReader(src);
var ms = new MemoryStream();
do
using (var ms = new MemoryStream())
{
var len = Math.Min(ctx.Remaining(), 0x3F);
ms.WriteByte((byte)(0x80 | len));
while (len-- > 0)
ms.WriteByte(ctx.ReadByte());
var offset = 0;
var left = src.Length;
var blockStart = 0;
while (offset < left)
{
var repeatCount = CountSame(src, offset, 0xFFFF);
if (repeatCount >= 4)
{
// Write what we haven't written up to now
WriteCopyBlocks(src, blockStart, offset - blockStart, ms);
// Command 4: Repeat byte n times
ms.WriteByte(0xFE);
// Low byte
ms.WriteByte((byte)(repeatCount & 0xFF));
// High byte
ms.WriteByte((byte)(repeatCount >> 8));
// Value to repeat
ms.WriteByte(src[offset]);
offset += repeatCount;
blockStart = offset;
}
else
{
offset++;
}
}
// Write what we haven't written up to now
WriteCopyBlocks(src, blockStart, offset - blockStart, ms);
// Write terminator
ms.WriteByte(0x80);
return ms.ToArray();
}
while (!ctx.Done());
ms.WriteByte(0x80); // terminator -- 0-length run.
return ms.ToArray();
}
}
}

View File

@@ -33,7 +33,7 @@ namespace OpenRA.FileFormats
public void Load(Stream s)
{
StreamReader reader = new StreamReader(s);
var reader = new StreamReader(s);
IniSection currentSection = null;
while (!reader.EndOfStream)
@@ -55,10 +55,10 @@ namespace OpenRA.FileFormats
IniSection ProcessSection(string line)
{
Match m = sectionPattern.Match(line);
var m = sectionPattern.Match(line);
if (!m.Success)
return null;
string sectionName = m.Groups[1].Value.ToLowerInvariant();
var sectionName = m.Groups[1].Value.ToLowerInvariant();
IniSection ret;
if (!sections.TryGetValue(sectionName, out ret))
@@ -78,7 +78,7 @@ namespace OpenRA.FileFormats
var key = line;
var value = "";
int eq = line.IndexOf('=');
var eq = line.IndexOf('=');
if (eq >= 0)
{
key = line.Substring(0, eq);

View File

@@ -39,7 +39,7 @@ namespace OpenRA.FileFormats
Bitmap bitmap = null;
Color[] palette = null;
List<byte> data = new List<byte>();
var data = new List<byte>();
for (; ; )
{

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -8,72 +8,73 @@
*/
#endregion
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using OpenRA.Graphics;
namespace OpenRA.FileFormats
{
class R8Image : ISpriteFrame
{
public Size Size { get; private set; }
public Size FrameSize { get; private set; }
public float2 Offset { get; private set; }
public byte[] Data { get; set; }
public R8Image(Stream s)
{
// Scan forward until we find some data
var type = s.ReadUInt8();
while (type == 0)
type = s.ReadUInt8();
var width = s.ReadInt32();
var height = s.ReadInt32();
var x = s.ReadInt32();
var y = s.ReadInt32();
Size = new Size(width, height);
Offset = new int2(width/2 - x, height/2 - y);
/*var imageOffset = */s.ReadInt32();
var paletteOffset = s.ReadInt32();
var bpp = s.ReadUInt8();
if (bpp != 8)
throw new InvalidDataException("Error: {0} bits per pixel are not supported.".F(bpp));
var frameHeight = s.ReadUInt8();
var frameWidth = s.ReadUInt8();
FrameSize = new Size(frameWidth, frameHeight);
// Skip alignment byte
s.ReadUInt8();
Data = s.ReadBytes(width*height);
// Ignore palette
if (type == 1 && paletteOffset != 0)
s.Seek(520, SeekOrigin.Current);
}
}
public class R8Reader : ISpriteSource
{
readonly List<ISpriteFrame> frames = new List<ISpriteFrame>();
public IEnumerable<ISpriteFrame> Frames { get { return frames; } }
class R8Image : ISpriteFrame
{
public Size Size { get; private set; }
public Size FrameSize { get; private set; }
public float2 Offset { get; private set; }
public byte[] Data { get; set; }
public R8Image(Stream s)
{
// Scan forward until we find some data
var type = s.ReadUInt8();
while (type == 0)
type = s.ReadUInt8();
var width = s.ReadInt32();
var height = s.ReadInt32();
var x = s.ReadInt32();
var y = s.ReadInt32();
Size = new Size(width, height);
Offset = new int2(width / 2 - x, height / 2 - y);
/*var imageOffset = */
s.ReadInt32();
var paletteOffset = s.ReadInt32();
var bpp = s.ReadUInt8();
if (bpp != 8)
throw new InvalidDataException("Error: {0} bits per pixel are not supported.".F(bpp));
var frameHeight = s.ReadUInt8();
var frameWidth = s.ReadUInt8();
FrameSize = new Size(frameWidth, frameHeight);
// Skip alignment byte
s.ReadUInt8();
Data = s.ReadBytes(width * height);
// Ignore palette
if (type == 1 && paletteOffset != 0)
s.Seek(520, SeekOrigin.Current);
}
}
public IReadOnlyList<ISpriteFrame> Frames { get; private set; }
public bool CacheWhenLoadingTileset { get { return true; } }
public readonly int ImageCount;
public R8Reader(Stream stream)
{
var frames = new List<R8Image>();
while (stream.Position < stream.Length)
{
frames.Add(new R8Image(stream));
ImageCount++;
}
Frames = frames.ToArray().AsReadOnly();
}
}
}

View File

@@ -11,7 +11,6 @@
using System;
using System.IO;
using System.Text;
using OpenRA.Network;
namespace OpenRA.FileFormats
{
@@ -47,7 +46,7 @@ namespace OpenRA.FileFormats
throw new NotSupportedException("Metadata version {0} is not supported".F(version));
// Read game info (max 100K limit as a safeguard against corrupted files)
string data = fs.ReadString(Encoding.UTF8, 1024 * 100);
var data = fs.ReadString(Encoding.UTF8, 1024 * 100);
GameInfo = GameInformation.Deserialize(data);
}
@@ -58,7 +57,7 @@ namespace OpenRA.FileFormats
writer.Write(MetaVersion);
// Write data
int dataLength = 0;
var dataLength = 0;
{
// Write lobby info data
writer.Flush();

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -9,85 +9,81 @@
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using OpenRA.Graphics;
namespace OpenRA.FileFormats
{
[Flags] enum FormatFlags : int
{
PaletteTable = 1,
SkipFormat80 = 2,
VariableLengthTable = 4
}
class Frame : ISpriteFrame
{
public Size Size { get; private set; }
public Size FrameSize { get { return Size; } }
public float2 Offset { get { return float2.Zero; } }
public byte[] Data { get; set; }
public Frame(Stream s)
{
var flags = (FormatFlags)s.ReadUInt16();
s.Position += 1;
var width = s.ReadUInt16();
var height = s.ReadUInt8();
Size = new Size(width, height);
// Subtract header size
var dataLeft = s.ReadUInt16() - 10;
var dataSize = s.ReadUInt16();
byte[] table;
if ((flags & FormatFlags.PaletteTable) != 0)
{
var n = (flags & FormatFlags.VariableLengthTable) != 0 ? s.ReadUInt8() : (byte)16;
table = new byte[n];
for (var i = 0; i < n; i++)
table[i] = s.ReadUInt8();
dataLeft -= n;
}
else
{
table = new byte[256];
for (var i = 0; i < 256; i++)
table[i] = (byte)i;
table[1] = 0x7f;
table[2] = 0x7e;
table[3] = 0x7d;
table[4] = 0x7c;
}
Data = new byte[width * height];
// Decode image data
var compressed = s.ReadBytes(dataLeft);
if ((flags & FormatFlags.SkipFormat80) == 0)
{
var temp = new byte[dataSize];
Format80.DecodeInto(compressed, temp);
compressed = temp;
}
Format2.DecodeInto(compressed, Data, 0);
// Lookup values in lookup table
for (var j = 0; j < Data.Length; j++)
Data[j] = table[Data[j]];
}
}
public class ShpD2Reader : ISpriteSource
{
readonly List<ISpriteFrame> frames = new List<ISpriteFrame>();
public IEnumerable<ISpriteFrame> Frames { get { return frames; } }
[Flags] enum FormatFlags : int
{
PaletteTable = 1,
SkipFormat80 = 2,
VariableLengthTable = 4
}
class Frame : ISpriteFrame
{
public Size Size { get; private set; }
public Size FrameSize { get { return Size; } }
public float2 Offset { get { return float2.Zero; } }
public byte[] Data { get; set; }
public Frame(Stream s)
{
var flags = (FormatFlags)s.ReadUInt16();
s.Position += 1;
var width = s.ReadUInt16();
var height = s.ReadUInt8();
Size = new Size(width, height);
// Subtract header size
var dataLeft = s.ReadUInt16() - 10;
var dataSize = s.ReadUInt16();
byte[] table;
if ((flags & FormatFlags.PaletteTable) != 0)
{
var n = (flags & FormatFlags.VariableLengthTable) != 0 ? s.ReadUInt8() : (byte)16;
table = new byte[n];
for (var i = 0; i < n; i++)
table[i] = s.ReadUInt8();
dataLeft -= n;
}
else
{
table = new byte[256];
for (var i = 0; i < 256; i++)
table[i] = (byte)i;
table[1] = 0x7f;
table[2] = 0x7e;
table[3] = 0x7d;
table[4] = 0x7c;
}
Data = new byte[width * height];
// Decode image data
var compressed = s.ReadBytes(dataLeft);
if ((flags & FormatFlags.SkipFormat80) == 0)
{
var temp = new byte[dataSize];
Format80.DecodeInto(compressed, temp);
compressed = temp;
}
Format2.DecodeInto(compressed, Data, 0);
// Lookup values in lookup table
for (var j = 0; j < Data.Length; j++)
Data[j] = table[Data[j]];
}
}
public IReadOnlyList<ISpriteFrame> Frames { get; private set; }
public bool CacheWhenLoadingTileset { get { return false; } }
public ShpD2Reader(Stream s)
@@ -105,10 +101,12 @@ namespace OpenRA.FileFormats
for (var i = 0; i < imageCount + 1; i++)
offsets[i] = (twoByteOffset ? s.ReadUInt16() : s.ReadUInt32()) + 2;
for (var i = 0; i < imageCount; i++)
var frames = new Frame[imageCount];
Frames = frames.AsReadOnly();
for (var i = 0; i < frames.Length; i++)
{
s.Position = offsets[i];
frames.Add(new Frame(s));
frames[i] = new Frame(s);
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -17,56 +17,58 @@ using OpenRA.Graphics;
namespace OpenRA.FileFormats
{
enum Format { Format20 = 0x20, Format40 = 0x40, Format80 = 0x80 }
class ImageHeader : ISpriteFrame
{
public Size Size { get { return reader.Size; } }
public Size FrameSize { get { return reader.Size; } }
public float2 Offset { get { return float2.Zero; } }
public byte[] Data { get; set; }
public uint FileOffset;
public Format Format;
public uint RefOffset;
public Format RefFormat;
public ImageHeader RefImage;
ShpReader reader;
// Used by ShpWriter
public ImageHeader() { }
public ImageHeader(Stream stream, ShpReader reader)
{
this.reader = reader;
var data = stream.ReadUInt32();
FileOffset = data & 0xffffff;
Format = (Format)(data >> 24);
RefOffset = stream.ReadUInt16();
RefFormat = (Format)stream.ReadUInt16();
}
public void WriteTo(BinaryWriter writer)
{
writer.Write(FileOffset | ((uint)Format << 24));
writer.Write((ushort)RefOffset);
writer.Write((ushort)RefFormat);
}
}
public class ShpReader : ISpriteSource
{
readonly List<ImageHeader> headers = new List<ImageHeader>();
Lazy<IEnumerable<ISpriteFrame>> spriteFrames;
public IEnumerable<ISpriteFrame> Frames { get { return spriteFrames.Value; } }
enum Format { Format20 = 0x20, Format40 = 0x40, Format80 = 0x80 }
class ImageHeader : ISpriteFrame
{
public Size Size { get { return reader.Size; } }
public Size FrameSize { get { return reader.Size; } }
public float2 Offset { get { return float2.Zero; } }
public byte[] Data { get; set; }
public uint FileOffset;
public Format Format;
public uint RefOffset;
public Format RefFormat;
public ImageHeader RefImage;
ShpReader reader;
// Used by ShpWriter
public ImageHeader() { }
public ImageHeader(Stream stream, ShpReader reader)
{
this.reader = reader;
var data = stream.ReadUInt32();
FileOffset = data & 0xffffff;
Format = (Format)(data >> 24);
RefOffset = stream.ReadUInt16();
RefFormat = (Format)stream.ReadUInt16();
}
public void WriteTo(BinaryWriter writer)
{
writer.Write(FileOffset | ((uint)Format << 24));
writer.Write((ushort)RefOffset);
writer.Write((ushort)RefFormat);
}
}
public IReadOnlyList<ISpriteFrame> Frames { get; private set; }
public bool CacheWhenLoadingTileset { get { return false; } }
public readonly Size Size;
int recurseDepth = 0;
readonly int imageCount;
readonly long shpBytesFileOffset;
readonly byte[] shpBytes;
public ShpReader(Stream stream)
{
imageCount = stream.ReadUInt16();
@@ -76,8 +78,10 @@ namespace OpenRA.FileFormats
Size = new Size(width, height);
stream.Position += 4;
for (var i = 0; i < imageCount; i++)
headers.Add(new ImageHeader(stream, this));
var headers = new ImageHeader[imageCount];
Frames = headers.AsReadOnly();
for (var i = 0; i < headers.Length; i++)
headers[i] = new ImageHeader(stream, this);
// Skip eof and zero headers
stream.Position += 16;
@@ -88,30 +92,18 @@ namespace OpenRA.FileFormats
var h = headers[i];
if (h.Format == Format.Format20)
h.RefImage = headers[i - 1];
else if (h.Format == Format.Format40 && !offsets.TryGetValue(h.RefOffset, out h.RefImage))
throw new InvalidDataException("Reference doesnt point to image data {0}->{1}".F(h.FileOffset, h.RefOffset));
}
shpBytesFileOffset = stream.Position;
shpBytes = stream.ReadBytes((int)(stream.Length - stream.Position));
foreach (var h in headers)
Decompress(stream, h);
spriteFrames = Exts.Lazy(() => headers.Cast<ISpriteFrame>());
Decompress(h);
}
static byte[] ReadCompressedData(Stream stream, ImageHeader h)
{
stream.Position = h.FileOffset;
// Actually, far too big. There's no length field with the correct length though :(
var compressedLength = (int)(stream.Length - stream.Position);
var compressedBytes = new byte[compressedLength];
stream.Read(compressedBytes, 0, compressedLength);
return compressedBytes;
}
void Decompress(Stream stream, ImageHeader h)
void Decompress(ImageHeader h)
{
// No extra work is required for empty frames
if (h.Size.Width == 0 || h.Size.Height == 0)
@@ -128,19 +120,19 @@ namespace OpenRA.FileFormats
if (h.RefImage.Data == null)
{
++recurseDepth;
Decompress(stream, h.RefImage);
Decompress(h.RefImage);
--recurseDepth;
}
h.Data = CopyImageData(h.RefImage.Data);
Format40.DecodeInto(ReadCompressedData(stream, h), h.Data);
Format40.DecodeInto(shpBytes, h.Data, (int)(h.FileOffset - shpBytesFileOffset));
break;
}
case Format.Format80:
{
var imageBytes = new byte[Size.Width * Size.Height];
Format80.DecodeInto(ReadCompressedData(stream, h), imageBytes);
Format80.DecodeInto(shpBytes, imageBytes, (int)(h.FileOffset - shpBytesFileOffset));
h.Data = imageBytes;
break;
}
@@ -153,9 +145,7 @@ namespace OpenRA.FileFormats
byte[] CopyImageData(byte[] baseImage)
{
var imageData = new byte[Size.Width * Size.Height];
for (var i = 0; i < Size.Width * Size.Height; i++)
imageData[i] = baseImage[i];
Array.Copy(baseImage, imageData, imageData.Length);
return imageData;
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -8,47 +8,43 @@
*/
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using OpenRA.Graphics;
namespace OpenRA.FileFormats
{
class FrameHeader : ISpriteFrame
{
public Size Size { get; private set; }
public Size FrameSize { get; private set; }
public float2 Offset { get; private set; }
public byte[] Data { get; set; }
public readonly uint FileOffset;
public readonly byte Format;
public FrameHeader(Stream stream, Size frameSize)
{
var x = stream.ReadUInt16();
var y = stream.ReadUInt16();
var width = stream.ReadUInt16();
var height = stream.ReadUInt16();
Offset = new float2(x + 0.5f * (width - frameSize.Width), y + 0.5f * (height - frameSize.Height));
Size = new Size(width, height);
FrameSize = frameSize;
Format = stream.ReadUInt8();
stream.Position += 11;
FileOffset = stream.ReadUInt32();
}
}
public class ShpTSReader : ISpriteSource
{
readonly List<FrameHeader> frames = new List<FrameHeader>();
Lazy<IEnumerable<ISpriteFrame>> spriteFrames;
public IEnumerable<ISpriteFrame> Frames { get { return spriteFrames.Value; } }
class FrameHeader : ISpriteFrame
{
public Size Size { get; private set; }
public Size FrameSize { get; private set; }
public float2 Offset { get; private set; }
public byte[] Data { get; set; }
public readonly uint FileOffset;
public readonly byte Format;
public FrameHeader(Stream stream, Size frameSize)
{
var x = stream.ReadUInt16();
var y = stream.ReadUInt16();
var width = stream.ReadUInt16();
var height = stream.ReadUInt16();
// Note: the mixed Integer / fp division is intentional, and required for calculating the correct offset.
Offset = new float2(x + width / 2 - 0.5f * frameSize.Width, y + height / 2 - 0.5f * frameSize.Height);
Size = new Size(width, height);
FrameSize = frameSize;
Format = stream.ReadUInt8();
stream.Position += 11;
FileOffset = stream.ReadUInt32();
}
}
public IReadOnlyList<ISpriteFrame> Frames { get; private set; }
public bool CacheWhenLoadingTileset { get { return false; } }
public ShpTSReader(Stream stream)
@@ -59,8 +55,10 @@ namespace OpenRA.FileFormats
var size = new Size(width, height);
var frameCount = stream.ReadUInt16();
for (var i = 0; i < frameCount; i++)
frames.Add(new FrameHeader(stream, size));
var frames = new FrameHeader[frameCount];
Frames = frames.AsReadOnly();
for (var i = 0; i < frames.Length; i++)
frames[i] = new FrameHeader(stream, size);
for (var i = 0; i < frameCount; i++)
{
@@ -70,35 +68,36 @@ namespace OpenRA.FileFormats
stream.Position = f.FileOffset;
var frameSize = f.Size.Width * f.Size.Height;
// Uncompressed
if (f.Format == 1 || f.Format == 0)
f.Data = stream.ReadBytes(f.Size.Width * f.Size.Height);
f.Data = stream.ReadBytes(frameSize);
// Uncompressed scanlines
else if (f.Format == 2)
{
f.Data = new byte[f.Size.Width * f.Size.Height];
f.Data = new byte[frameSize];
for (var j = 0; j < f.Size.Height; j++)
{
var length = stream.ReadUInt16() - 2;
stream.Read(f.Data, f.Size.Width * j, length);
var offset = f.Size.Width * j;
stream.ReadBytes(f.Data, offset, length);
}
}
// RLE-zero compressed scanlines
else if (f.Format == 3)
{
f.Data = new byte[f.Size.Width * f.Size.Height];
f.Data = new byte[frameSize];
for (var j = 0; j < f.Size.Height; j++)
{
var length = stream.ReadUInt16() - 2;
Format2.DecodeInto(stream.ReadBytes(length), f.Data, j * f.Size.Width);
var offset = f.Size.Width * j;
Format2.DecodeInto(stream.ReadBytes(length), f.Data, offset);
}
}
}
spriteFrames = Exts.Lazy(() => frames.Cast<ISpriteFrame>());
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -8,18 +8,15 @@
*/
#endregion
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using OpenRA.Graphics;
namespace OpenRA.FileFormats
{
public class TmpRAReader : ISpriteSource
{
readonly List<ISpriteFrame> tiles = new List<ISpriteFrame>();
public IEnumerable<ISpriteFrame> Frames { get { return tiles; } }
public IReadOnlyList<ISpriteFrame> Frames { get; private set; }
public bool CacheWhenLoadingTileset { get { return false; } }
public TmpRAReader(Stream s)
@@ -36,15 +33,19 @@ namespace OpenRA.FileFormats
var indexStart = s.ReadInt32();
s.Position = indexStart;
foreach (byte b in s.ReadBytes(indexEnd - indexStart))
var count = indexEnd - indexStart;
var tiles = new TmpTile[count];
Frames = tiles.AsReadOnly();
var tilesIndex = 0;
foreach (var b in s.ReadBytes(count))
{
if (b != 255)
{
s.Position = imgStart + b * width * height;
tiles.Add(new TmpTile(s.ReadBytes(width * height), size));
tiles[tilesIndex++] = new TmpTile(s.ReadBytes(width * height), size);
}
else
tiles.Add(new TmpTile(null, size));
tiles[tilesIndex++] = new TmpTile(null, size);
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -8,9 +8,7 @@
*/
#endregion
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.IO;
using OpenRA.Graphics;
@@ -37,8 +35,7 @@ namespace OpenRA.FileFormats
public class TmpTDReader : ISpriteSource
{
readonly List<ISpriteFrame> tiles = new List<ISpriteFrame>();
public IEnumerable<ISpriteFrame> Frames { get { return tiles; } }
public IReadOnlyList<ISpriteFrame> Frames { get; private set; }
public bool CacheWhenLoadingTileset { get { return false; } }
public TmpTDReader(Stream s)
@@ -54,15 +51,19 @@ namespace OpenRA.FileFormats
var indexStart = s.ReadInt32();
s.Position = indexStart;
foreach (byte b in s.ReadBytes(indexEnd - indexStart))
var count = indexEnd - indexStart;
var tiles = new TmpTile[count];
Frames = tiles.AsReadOnly();
var tilesIndex = 0;
foreach (var b in s.ReadBytes(count))
{
if (b != 255)
{
s.Position = imgStart + b * width * height;
tiles.Add(new TmpTile(s.ReadBytes(width * height), size));
tiles[tilesIndex++] = new TmpTile(s.ReadBytes(width * height), size);
}
else
tiles.Add(new TmpTile(null, size));
tiles[tilesIndex++] = new TmpTile(null, size);
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -8,11 +8,9 @@
*/
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using OpenRA.Graphics;
namespace OpenRA.FileFormats
@@ -41,7 +39,7 @@ namespace OpenRA.FileFormats
for (var j = 0; j < width; j++)
Data[start + j] = s.ReadUInt8();
width += (i < size.Height / 2 - 1? 1 : -1) * 4;
width += (i < size.Height / 2 - 1 ? 1 : -1) * 4;
}
// Ignore Z-data for now
@@ -51,8 +49,7 @@ namespace OpenRA.FileFormats
public class TmpTSReader : ISpriteSource
{
readonly List<ISpriteFrame> tiles = new List<ISpriteFrame>();
public IEnumerable<ISpriteFrame> Frames { get { return tiles; } }
public IReadOnlyList<ISpriteFrame> Frames { get; private set; }
public bool CacheWhenLoadingTileset { get { return false; } }
public TmpTSReader(Stream s)
@@ -66,11 +63,14 @@ namespace OpenRA.FileFormats
for (var i = 0; i < offsets.Length; i++)
offsets[i] = s.ReadUInt32();
var tiles = new List<TmpTSTile>();
for (var i = 0; i < offsets.Length; i++)
{
s.Position = offsets[i];
tiles.Add(new TmpTSTile(s, size));
}
Frames = tiles.ToArray().AsReadOnly();
}
}
}

View File

@@ -101,7 +101,7 @@ namespace OpenRA.FileFormats
// Frame offsets
offsets = new UInt32[Frames];
for (int i = 0; i < Frames; i++)
for (var i = 0; i < Frames; i++)
{
offsets[i] = stream.ReadUInt32();
if (offsets[i] > 0x40000000)
@@ -125,7 +125,7 @@ namespace OpenRA.FileFormats
var ms = new MemoryStream();
var adpcmIndex = 0;
bool compressed = false;
var compressed = false;
for (var i = 0; i < Frames; i++)
{
stream.Seek(offsets[i], SeekOrigin.Begin);
@@ -201,7 +201,7 @@ namespace OpenRA.FileFormats
// Chunks are aligned on even bytes; may be padded with a single null
if (s.Peek() == 0) s.ReadByte();
var type = s.ReadASCII(4);
int subchunkLength = (int)int2.Swap(s.ReadUInt32());
var subchunkLength = (int)int2.Swap(s.ReadUInt32());
switch(type)
{
@@ -235,11 +235,11 @@ namespace OpenRA.FileFormats
// Palette
case "CPL0":
for (int i = 0; i < numColors; i++)
for (var i = 0; i < numColors; i++)
{
byte r = (byte)(s.ReadUInt8() << 2);
byte g = (byte)(s.ReadUInt8() << 2);
byte b = (byte)(s.ReadUInt8() << 2);
var r = (byte)(s.ReadUInt8() << 2);
var g = (byte)(s.ReadUInt8() << 2);
var b = (byte)(s.ReadUInt8() << 2);
palette[i] = (uint)((255 << 24) | (r << 16) | (g << 8) | b);
}
break;
@@ -269,7 +269,7 @@ namespace OpenRA.FileFormats
for (var i = 0; i < blockWidth; i++)
{
var cbfi = (mod*256 + px)*8 + j*blockWidth + i;
byte color = (mod == 0x0f) ? px : cbf[cbfi];
var color = (mod == 0x0f) ? px : cbf[cbfi];
frameData[y*blockHeight + j, x*blockWidth + i] = palette[color];
}
}

View File

@@ -79,8 +79,8 @@ namespace OpenRA.FileFormats
s.Seek(dataStart + colStart[i], SeekOrigin.Begin);
byte x = (byte)(i % l.Size[0]);
byte y = (byte)(i / l.Size[0]);
var x = (byte)(i % l.Size[0]);
var y = (byte)(i / l.Size[0]);
byte z = 0;
l.VoxelMap[x,y] = new Dictionary<byte, VxlElement>();
do

View File

@@ -56,10 +56,7 @@ namespace OpenRA.FileSystem
return null;
s.Seek(e.Offset, SeekOrigin.Begin);
var data = new byte[e.Length];
s.Read(data, 0, (int)e.Length);
return new MemoryStream(data);
return new MemoryStream(s.ReadBytes((int)e.Length));
}
public Stream GetContent(string filename)

View File

@@ -156,8 +156,7 @@ namespace OpenRA.FileSystem
var index = type == PackageHashType.CRC32 ? crcHashIndex : classicHashIndex;
var folder = index[PackageEntry.HashFilename(filename, type)]
.Where(x => x.Exists(filename))
.OrderBy(x => x.Priority)
.FirstOrDefault();
.MinByOrDefault(x => x.Priority);
if (folder != null)
return folder.GetContent(filename);
@@ -196,8 +195,7 @@ namespace OpenRA.FileSystem
{
var folder = MountedFolders
.Where(x => x.Exists(filename + ext))
.OrderByDescending(x => x.Priority)
.FirstOrDefault();
.MaxByOrDefault(x => x.Priority);
if (folder != null)
{
@@ -230,8 +228,7 @@ namespace OpenRA.FileSystem
if (Exists(filename))
using (var s = Open(filename))
{
var buf = new byte[s.Length];
s.Read(buf, 0, buf.Length);
var buf = s.ReadBytes((int)s.Length);
a = Assembly.Load(buf);
assemblyCache.Add(filename, a);
return a;

View File

@@ -32,8 +32,8 @@ namespace OpenRA.FileSystem
s = GlobalFileSystem.Open(filename);
// Parse package header
BinaryReader reader = new BinaryReader(s);
uint signature = reader.ReadUInt32();
var reader = new BinaryReader(s);
var signature = reader.ReadUInt32();
if (signature != 0x8C655D13)
throw new InvalidDataException("Not an Installshield package");
@@ -48,7 +48,7 @@ namespace OpenRA.FileSystem
// Parse the directory list
s.Seek(TOCAddress, SeekOrigin.Begin);
BinaryReader TOCreader = new BinaryReader(s);
var TOCreader = new BinaryReader(s);
var fileCountInDirs = new List<uint>();
// Parse directories
@@ -103,8 +103,7 @@ namespace OpenRA.FileSystem
return null;
s.Seek(dataStart + e.Offset, SeekOrigin.Begin);
var data = new byte[e.Length];
s.Read(data, 0, (int)e.Length);
var data = s.ReadBytes((int)e.Length);
return new MemoryStream(Blast.Decompress(data));
}

View File

@@ -17,7 +17,7 @@ using OpenRA.FileFormats;
namespace OpenRA.FileSystem
{
public class MixFile : IFolder
public sealed class MixFile : IFolder, IDisposable
{
readonly Dictionary<uint, PackageEntry> index;
readonly long dataStart;
@@ -157,8 +157,7 @@ namespace OpenRA.FileSystem
return null;
s.Seek(dataStart + e.Offset, SeekOrigin.Begin);
var data = new byte[e.Length];
s.Read(data, 0, (int)e.Length);
var data = s.ReadBytes((int)e.Length);
return new MemoryStream(data);
}
@@ -259,5 +258,11 @@ namespace OpenRA.FileSystem
s.Write(file.Value);
}
}
public void Dispose()
{
if (s != null)
s.Dispose();
}
}
}

View File

@@ -64,10 +64,10 @@ namespace OpenRA.FileSystem
if (name.Length % 4 != 0)
name = name.PadRight(name.Length + (4 - name.Length % 4), '\0');
MemoryStream ms = new MemoryStream(Encoding.ASCII.GetBytes(name));
BinaryReader reader = new BinaryReader(ms);
var ms = new MemoryStream(Encoding.ASCII.GetBytes(name));
var reader = new BinaryReader(ms);
int len = name.Length >> 2;
var len = name.Length >> 2;
uint result = 0;
while (len-- != 0)
@@ -80,11 +80,11 @@ namespace OpenRA.FileSystem
{
name = name.ToUpperInvariant();
var l = name.Length;
int a = l >> 2;
var a = l >> 2;
if ((l & 3) != 0)
{
name += (char)(l - (a << 2));
int i = 3 - (l & 3);
var i = 3 - (l & 3);
while (i-- != 0)
name += name[a << 2];
}
@@ -99,9 +99,9 @@ namespace OpenRA.FileSystem
public static void AddStandardName(string s)
{
uint hash = HashFilename(s, PackageHashType.Classic); // RA1 and TD
var hash = HashFilename(s, PackageHashType.Classic); // RA1 and TD
Names.Add(hash, s);
uint crcHash = HashFilename(s, PackageHashType.CRC32); // TS
var crcHash = HashFilename(s, PackageHashType.CRC32); // TS
Names.Add(crcHash, s);
}

View File

@@ -59,8 +59,7 @@ namespace OpenRA.FileSystem
return null;
stream.Seek(entry.Offset, SeekOrigin.Begin);
var data = new byte[entry.Length];
stream.Read(data, 0, (int)entry.Length);
var data = stream.ReadBytes((int)entry.Length);
return new MemoryStream(data);
}

View File

@@ -8,6 +8,7 @@
*/
#endregion
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
@@ -16,7 +17,7 @@ using SZipFile = ICSharpCode.SharpZipLib.Zip.ZipFile;
namespace OpenRA.FileSystem
{
public class ZipFile : IFolder
public sealed class ZipFile : IFolder, IDisposable
{
string filename;
SZipFile pkg;
@@ -60,11 +61,7 @@ namespace OpenRA.FileSystem
using (var z = pkg.GetInputStream(pkg.GetEntry(filename)))
{
var ms = new MemoryStream();
int bufSize = 2048;
byte[] buf = new byte[bufSize];
while ((bufSize = z.Read(buf, 0, buf.Length)) > 0)
ms.Write(buf, 0, bufSize);
z.CopyTo(ms);
ms.Seek(0, SeekOrigin.Begin);
return ms;
}
@@ -109,6 +106,12 @@ namespace OpenRA.FileSystem
pkg.Close();
pkg = new SZipFile(new MemoryStream(File.ReadAllBytes(filename)));
}
public void Dispose()
{
if (pkg != null)
pkg.Close();
}
}
class StaticMemoryDataSource : IStaticDataSource

View File

@@ -9,15 +9,13 @@
#endregion
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using OpenRA.FileSystem;
using MaxMind.GeoIP2;
using OpenRA.GameRules;
using OpenRA.FileSystem;
using OpenRA.Graphics;
using OpenRA.Network;
using OpenRA.Primitives;
@@ -141,12 +139,12 @@ namespace OpenRA
// worldRenderer is null during the initial install/download screen
if (worldRenderer != null)
{
Renderer.BeginFrame(worldRenderer.Viewport.TopLeft.ToFloat2(), worldRenderer.Viewport.Zoom);
Renderer.BeginFrame(worldRenderer.Viewport.TopLeft, worldRenderer.Viewport.Zoom);
Sound.SetListenerPosition(worldRenderer.Position(worldRenderer.Viewport.CenterLocation));
worldRenderer.Draw();
}
else
Renderer.BeginFrame(float2.Zero, 1f);
Renderer.BeginFrame(int2.Zero, 1f);
using (new PerfSample("render_widgets"))
{
@@ -273,6 +271,8 @@ namespace OpenRA
orderManager.LastTickTime = Environment.TickCount;
orderManager.StartGame();
worldRenderer.RefreshPalette();
GC.Collect();
}
public static bool IsHost
@@ -361,13 +361,13 @@ namespace OpenRA
foreach (var mod in ModMetadata.AllMods)
Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Title, mod.Value.Version);
InitializeWithMod(Settings.Game.Mod, args.GetValue("Launch.Replay", null));
InitializeMod(Settings.Game.Mod, args);
if (Settings.Server.DiscoverNatDevices)
RunAfterDelay(Settings.Server.NatDiscoveryTimeout, UPnP.TryStoppingNatDiscovery);
RunAfterDelay(Settings.Server.NatDiscoveryTimeout, UPnP.StoppingNatDiscovery);
}
public static void InitializeWithMod(string mod, string replay)
public static void InitializeMod(string mod, Arguments args)
{
// Clear static state if we have switched mods
LobbyInfoChanged = () => { };
@@ -439,13 +439,46 @@ namespace OpenRA
}
else
{
modData.LoadScreen.StartGame();
Settings.Save();
if (!string.IsNullOrEmpty(replay))
Game.JoinReplay(replay);
var window = args != null ? args.GetValue("Launch.Window", null) : null;
if (!string.IsNullOrEmpty(window))
{
var installData = modData.Manifest.ContentInstaller;
if (installData.InstallerBackgroundWidget != null)
Ui.LoadWidget(installData.InstallerBackgroundWidget, Ui.Root, new WidgetArgs());
Widgets.Ui.OpenWindow(window, new WidgetArgs());
}
else
{
modData.LoadScreen.StartGame();
Settings.Save();
var replay = args != null ? args.GetValue("Launch.Replay", null) : null;
if (!string.IsNullOrEmpty(replay))
Game.JoinReplay(replay);
}
}
}
public static void TestAndContinue()
{
Ui.ResetAll();
var installData = modData.Manifest.ContentInstaller;
if (!installData.TestFiles.All(f => GlobalFileSystem.Exists(f)))
{
var args = new WidgetArgs()
{
{ "continueLoading", () => InitializeMod(Game.Settings.Game.Mod, null) },
};
if (installData.InstallerBackgroundWidget != null)
Ui.LoadWidget(installData.InstallerBackgroundWidget, Ui.Root, args);
Ui.OpenWindow(installData.InstallerMenuWidget, args);
}
else
LoadShellMap();
}
public static void LoadShellMap()
{
var shellmap = ChooseShellmap();
@@ -466,16 +499,16 @@ namespace OpenRA
return shellmaps.Random(CosmeticRandom);
}
static bool quit;
static RunStatus state = RunStatus.Running;
public static event Action OnQuit = () => { };
static double idealFrameTime;
public static void SetIdealFrameTime(int fps)
{
{
idealFrameTime = 1.0 / fps;
}
internal static void Run()
internal static RunStatus Run()
{
if (Settings.Graphics.MaxFramerate < 1)
{
@@ -485,30 +518,47 @@ namespace OpenRA
SetIdealFrameTime(Settings.Graphics.MaxFramerate);
while (!quit)
try
{
if (Settings.Graphics.CapFramerate)
while (state == RunStatus.Running)
{
var sw = Stopwatch.StartNew();
if (Settings.Graphics.CapFramerate)
{
var sw = Stopwatch.StartNew();
Tick(orderManager);
Tick(orderManager);
var waitTime = Math.Min(idealFrameTime - sw.Elapsed.TotalSeconds, 1);
if (waitTime > 0)
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(waitTime));
var waitTime = Math.Min(idealFrameTime - sw.Elapsed.TotalSeconds, 1);
if (waitTime > 0)
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(waitTime));
}
else
Tick(orderManager);
}
else
Tick(orderManager);
}
// Ensure that the active replay is properly saved
if (orderManager != null)
orderManager.Dispose();
finally
{
// Ensure that the active replay is properly saved
if (orderManager != null)
orderManager.Dispose();
}
Renderer.Device.Dispose();
OnQuit();
return state;
}
public static void Exit() { quit = true; }
public static void Exit()
{
state = RunStatus.Success;
}
public static void Restart()
{
state = RunStatus.Restart;
}
public static Action<Color, string, string> AddChatLine = (c, n, s) => { };

View File

@@ -11,7 +11,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Primitives;
using OpenRA.Traits;
@@ -33,7 +32,7 @@ namespace OpenRA
{
try
{
var mergedNode = MergeWithParent(node, allUnits).NodesDict;
var mergedNode = MergeWithParent(node, allUnits).ToDictionary();
Name = name;
foreach (var t in mergedNode)
@@ -49,7 +48,7 @@ namespace OpenRA
static MiniYaml GetParent( MiniYaml node, Dictionary<string, MiniYaml> allUnits )
{
MiniYaml inherits;
node.NodesDict.TryGetValue( "Inherits", out inherits );
node.ToDictionary().TryGetValue( "Inherits", out inherits );
if( inherits == null || string.IsNullOrEmpty( inherits.Value ) )
return null;
@@ -90,11 +89,15 @@ namespace OpenRA
{
var ret = new List<ITraitInfo>();
var t = Traits.WithInterface<ITraitInfo>().ToList();
int index = 0;
var index = 0;
while (t.Count != 0)
{
var prereqs = PrerequisitesOf(t[index]);
var unsatisfied = prereqs.Where(n => !ret.Any(x => x.GetType() == n || n.IsAssignableFrom(x.GetType())));
var unsatisfied = prereqs.Where(n => !ret.Any(x =>
{
var type = x.GetType();
return type == n || n.IsAssignableFrom(type);
}));
if (!unsatisfied.Any())
{
ret.Add(t[index]);
@@ -111,14 +114,13 @@ namespace OpenRA
return ret;
}
static List<Type> PrerequisitesOf(ITraitInfo info)
static IEnumerable<Type> PrerequisitesOf(ITraitInfo info)
{
return info
.GetType()
.GetInterfaces()
.Where( t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof( Requires<> ) )
.Select( t => t.GetGenericArguments()[ 0 ] )
.ToList();
.Where(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Requires<>))
.Select(t => t.GetGenericArguments()[0]);
}
public IEnumerable<Pair<string, Type>> GetInitKeys()

View File

@@ -24,14 +24,15 @@ namespace OpenRA.GameRules
{
Title = value.Value;
var nd = value.NodesDict;
var nd = value.ToDictionary();
var ext = nd.ContainsKey("Extension") ? nd["Extension"].Value : "aud";
Filename = (nd.ContainsKey("Filename") ? nd["Filename"].Value : key)+"."+ext;
if (!GlobalFileSystem.Exists(Filename))
return;
Exists = true;
Length = (int)AudLoader.SoundLength(GlobalFileSystem.Open(Filename));
using (var s = GlobalFileSystem.Open(Filename))
Length = (int)AudLoader.SoundLength(s);
}
public void Reload()
@@ -40,7 +41,8 @@ namespace OpenRA.GameRules
return;
Exists = true;
Length = (int)AudLoader.SoundLength(GlobalFileSystem.Open(Filename));
using (var s = GlobalFileSystem.Open(Filename))
Length = (int)AudLoader.SoundLength(s);
}
}
}

View File

@@ -8,7 +8,6 @@
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.GameRules;

View File

@@ -11,7 +11,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.GameRules;
using OpenRA.Graphics;
using OpenRA.Support;

View File

@@ -11,7 +11,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.FileFormats;
namespace OpenRA.GameRules
{
@@ -28,10 +27,9 @@ namespace OpenRA.GameRules
static Dictionary<string, string[]> Load(MiniYaml y, string name)
{
return y.NodesDict.ContainsKey(name)
? y.NodesDict[name].NodesDict.ToDictionary(
a => a.Key,
a => FieldLoader.GetValue<string[]>("(value)", a.Value.Value))
var nd = y.ToDictionary();
return nd.ContainsKey(name)
? nd[name].ToDictionary(my => FieldLoader.GetValue<string[]>("(value)", my.Value))
: new Dictionary<string, string[]>();
}

View File

@@ -11,7 +11,6 @@
using System.Collections.Generic;
using System.Linq;
using OpenRA.Effects;
using OpenRA.FileFormats;
using OpenRA.Traits;
namespace OpenRA.GameRules
@@ -23,8 +22,10 @@ namespace OpenRA.GameRules
[FieldLoader.LoadUsing("LoadVersus")]
[Desc("Damage vs each armortype. 0% = can't target.")]
public readonly Dictionary<string, float> Versus;
[Desc("Can this damage ore?")]
public readonly bool Ore = false;
[Desc("Can this damage resource patches?")]
public readonly bool DestroyResources = false;
[Desc("Will this splatter resources and which?")]
public readonly string AddsResourceType = null;
[Desc("Explosion effect to use.")]
public readonly string Explosion = null;
[Desc("Palette to use for explosion effect.")]
@@ -51,6 +52,8 @@ namespace OpenRA.GameRules
public readonly DamageModel DamageModel = DamageModel.Normal;
[Desc("Whether we should prevent prone response for infantry.")]
public readonly bool PreventProne = false;
[Desc("By what percentage should damage be modified against prone infantry.")]
public readonly int ProneModifier = 50;
public float EffectivenessAgainst(ActorInfo ai)
{
@@ -73,10 +76,9 @@ namespace OpenRA.GameRules
static object LoadVersus(MiniYaml y)
{
return y.NodesDict.ContainsKey("Versus")
? y.NodesDict["Versus"].NodesDict.ToDictionary(
a => a.Key,
a => FieldLoader.GetValue<float>("(value)", a.Value.Value))
var nd = y.ToDictionary();
return nd.ContainsKey("Versus")
? nd["Versus"].ToDictionary(my => FieldLoader.GetValue<float>("(value)", my.Value))
: new Dictionary<string, float>();
}
}
@@ -126,7 +128,7 @@ namespace OpenRA.GameRules
static object LoadProjectile(MiniYaml yaml)
{
MiniYaml proj;
if (!yaml.NodesDict.TryGetValue("Projectile", out proj))
if (!yaml.ToDictionary().TryGetValue("Projectile", out proj))
return null;
var ret = Game.CreateObject<IProjectileInfo>(proj.Value + "Info");
FieldLoader.Load(ret, proj);
@@ -179,11 +181,11 @@ namespace OpenRA.GameRules
if (target.Type == TargetType.Terrain)
{
var cell = target.CenterPosition.ToCPos();
if (!world.Map.IsInMap(cell))
var cell = world.Map.CellContaining(target.CenterPosition);
if (!world.Map.Contains(cell))
return false;
var cellInfo = world.GetTerrainInfo(cell);
var cellInfo = world.Map.GetTerrainInfo(cell);
if (!ValidTargets.Intersect(cellInfo.TargetTypes).Any()
|| InvalidTargets.Intersect(cellInfo.TargetTypes).Any())
return false;

View File

@@ -23,9 +23,12 @@ namespace OpenRA.Graphics
int frame = 0;
bool backwards = false;
bool tickAlways;
string name;
readonly int defaultTick = 40; // 25 fps == 40 ms
bool tickAlways;
public string Name { get { return name; } }
readonly SequenceProvider sequenceProvider;
@@ -149,7 +152,7 @@ namespace OpenRA.Graphics
while (timeUntilNextFrame <= 0)
{
tickFunc();
timeUntilNextFrame += CurrentSequence != null ? CurrentSequence.Tick : 40; // 25 fps == 40 ms
timeUntilNextFrame += CurrentSequence != null ? CurrentSequence.Tick : defaultTick;
}
}
}

View File

@@ -8,10 +8,8 @@
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.FileFormats;
namespace OpenRA.Graphics
{
@@ -27,6 +25,8 @@ namespace OpenRA.Graphics
static Dictionary<string, Sheet> cachedSheets;
static Dictionary<string, Dictionary<string, Sprite>> cachedSprites;
static string[] storedChromeFiles;
public static void Initialize(params string[] chromeFiles)
{
collections = new Dictionary<string, Collection>();
@@ -34,7 +34,13 @@ namespace OpenRA.Graphics
cachedSprites = new Dictionary<string, Dictionary<string, Sprite>>();
if (chromeFiles.Length == 0)
return;
{
chromeFiles = storedChromeFiles;
if (chromeFiles == null || chromeFiles.Length == 0)
return;
}
else
storedChromeFiles = chromeFiles;
var chrome = chromeFiles.Select(s => MiniYaml.FromFile(s)).Aggregate(MiniYaml.MergeLiberal);

View File

@@ -67,13 +67,13 @@ namespace OpenRA.Graphics
// Start of the first line segment is the tail of the list - don't smooth it.
var curPos = trail[idx(next - skip - 1)];
var curCell = curPos.ToCPos();
var curCell = wr.world.Map.CellContaining(curPos);
var curColor = color;
for (var i = 0; i < length - skip - 4; i++)
{
var j = next - skip - i - 2;
var nextPos = Average(trail[idx(j)], trail[idx(j-1)], trail[idx(j-2)], trail[idx(j-3)]);
var nextCell = nextPos.ToCPos();
var nextCell = wr.world.Map.CellContaining(nextPos);
var nextColor = Exts.ColorLerp(i * 1f / (length - 4), color, Color.Transparent);
if (!world.FogObscures(curCell) && !world.FogObscures(nextCell))

View File

@@ -31,21 +31,22 @@ namespace OpenRA.Graphics
var sequences = new MiniYaml(null, sequenceFiles.Select(s => MiniYaml.FromFile(s)).Aggregate(MiniYaml.MergeLiberal));
var shadowIndex = new int[] { };
if (sequences.NodesDict.ContainsKey("ShadowIndex"))
var nodesDict = sequences.ToDictionary();
if (nodesDict.ContainsKey("ShadowIndex"))
{
Array.Resize(ref shadowIndex, shadowIndex.Length + 1);
Exts.TryParseIntegerInvariant(sequences.NodesDict["ShadowIndex"].Value,
Exts.TryParseIntegerInvariant(nodesDict["ShadowIndex"].Value,
out shadowIndex[shadowIndex.Length - 1]);
}
palette = new HardwarePalette();
foreach (var p in sequences.NodesDict["Palettes"].Nodes)
palette.AddPalette(p.Key, new Palette(GlobalFileSystem.Open(p.Value.Value), shadowIndex), false);
foreach (var p in nodesDict["Palettes"].Nodes)
palette.AddPalette(p.Key, new ImmutablePalette(GlobalFileSystem.Open(p.Value.Value), shadowIndex), false);
var spriteLoader = new SpriteLoader(new string[0], new SheetBuilder(SheetType.Indexed));
foreach (var s in sequences.NodesDict["Cursors"].Nodes)
foreach (var s in nodesDict["Cursors"].Nodes)
LoadSequencesForCursor(spriteLoader, s.Key, s.Value);
spriteLoader.SheetBuilder.Current.ReleaseBuffer();
palette.Initialize();
}
@@ -53,9 +54,6 @@ namespace OpenRA.Graphics
PaletteReference CreatePaletteReference(string name)
{
var pal = palette.GetPalette(name);
if (pal == null)
throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
return new PaletteReference(name, palette.GetPaletteIndex(name), pal);
}

View File

@@ -8,8 +8,6 @@
*/
#endregion
using OpenRA.FileFormats;
namespace OpenRA.Graphics
{
public class CursorSequence
@@ -28,7 +26,7 @@ namespace OpenRA.Graphics
public CursorSequence(SpriteLoader loader, string cursorSrc, string palette, MiniYaml info)
{
sprites = loader.LoadAllSprites(cursorSrc);
var d = info.NodesDict;
var d = info.ToDictionary();
start = Exts.ParseIntegerInvariant(d["start"].Value);
this.palette = palette;

View File

@@ -44,13 +44,13 @@ namespace OpenRA.Graphics
float[] trgb = { h + 1 / 3.0f, h, h - 1 / 3.0f };
float[] rgb = { 0, 0, 0 };
for (int k = 0; k < 3; k++)
for (var k = 0; k < 3; k++)
{
while (trgb[k] < 0) trgb[k] += 1.0f;
while (trgb[k] > 1) trgb[k] -= 1.0f;
}
for (int k = 0; k < 3; k++)
for (var k = 0; k < 3; k++)
{
if (trgb[k] < 1 / 6.0f) { rgb[k] = p + ((q - p) * 6 * trgb[k]); }
else if (trgb[k] >= 1 / 6.0f && trgb[k] < 0.5) { rgb[k] = q; }

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -10,8 +10,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Traits;
namespace OpenRA.Graphics
@@ -19,70 +17,101 @@ namespace OpenRA.Graphics
public class HardwarePalette
{
public const int MaxPalettes = 256;
int allocated = 0;
public ITexture Texture { get; private set; }
Dictionary<string, Palette> palettes;
Dictionary<string, int> indices;
Dictionary<string, bool> allowsMods;
readonly Dictionary<string, ImmutablePalette> palettes = new Dictionary<string, ImmutablePalette>();
readonly Dictionary<string, MutablePalette> modifiablePalettes = new Dictionary<string, MutablePalette>();
readonly IReadOnlyDictionary<string, MutablePalette> readOnlyModifiablePalettes;
readonly Dictionary<string, int> indices = new Dictionary<string, int>();
readonly uint[,] buffer = new uint[Palette.Size, MaxPalettes];
public HardwarePalette()
{
palettes = new Dictionary<string, Palette>();
indices = new Dictionary<string, int>();
allowsMods = new Dictionary<string, bool>();
Texture = Game.Renderer.Device.CreateTexture();
readOnlyModifiablePalettes = modifiablePalettes.AsReadOnly();
}
public Palette GetPalette(string name)
public IPalette GetPalette(string name)
{
Palette ret;
if (!palettes.TryGetValue(name,out ret))
throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
return ret;
MutablePalette mutable;
if (modifiablePalettes.TryGetValue(name, out mutable))
return mutable.AsReadOnly();
ImmutablePalette immutable;
if (palettes.TryGetValue(name, out immutable))
return immutable;
throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
}
public int GetPaletteIndex(string name)
{
int ret;
if (!indices.TryGetValue(name,out ret))
if (!indices.TryGetValue(name, out ret))
throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
return ret;
}
public void AddPalette(string name, Palette p, bool allowModifiers)
public void AddPalette(string name, ImmutablePalette p, bool allowModifiers)
{
if (palettes.Count >= MaxPalettes)
throw new InvalidOperationException("Limit of {0} palettes reached. Cannot add {1}.".F(MaxPalettes, name));
if (palettes.ContainsKey(name))
throw new InvalidOperationException("Palette {0} has already been defined".F(name));
int index = palettes.Count;
indices.Add(name, index);
palettes.Add(name, p);
indices.Add(name, allocated++);
allowsMods.Add(name, allowModifiers);
if (allowModifiers)
modifiablePalettes.Add(name, new MutablePalette(p));
else
CopyPaletteToBuffer(index, p);
}
uint[,] data = new uint[MaxPalettes, 256];
public void ApplyModifiers(IEnumerable<IPaletteModifier> paletteMods)
public void ReplacePalette(string name, IPalette p)
{
var copy = palettes.ToDictionary(p => p.Key, p => new Palette(p.Value));
var modifiable = copy.Where(p => allowsMods[p.Key]).ToDictionary(p => p.Key, p => p.Value);
foreach (var mod in paletteMods)
mod.AdjustPalette(modifiable);
foreach (var pal in copy)
{
var j = indices[pal.Key];
var c = pal.Value.Values;
for (var i = 0; i < 256; i++)
data[j,i] = c[i];
}
Texture.SetData(data);
if (modifiablePalettes.ContainsKey(name))
CopyPaletteToBuffer(indices[name], modifiablePalettes[name] = new MutablePalette(p));
else if (palettes.ContainsKey(name))
CopyPaletteToBuffer(indices[name], palettes[name] = new ImmutablePalette(p));
else
throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
Texture.SetData(buffer);
}
public void Initialize()
{
ApplyModifiers(new IPaletteModifier[] {});
CopyModifiablePalettesToBuffer();
Texture.SetData(buffer);
}
void CopyPaletteToBuffer(int index, IPalette p)
{
for (var i = 0; i < Palette.Size; i++)
buffer[i, index] = p[i];
}
void CopyModifiablePalettesToBuffer()
{
foreach (var kvp in modifiablePalettes)
CopyPaletteToBuffer(indices[kvp.Key], kvp.Value);
}
public void ApplyModifiers(IEnumerable<IPaletteModifier> paletteMods)
{
foreach (var mod in paletteMods)
mod.AdjustPalette(readOnlyModifiablePalettes);
// Update our texture with the changes.
CopyModifiablePalettesToBuffer();
Texture.SetData(buffer);
// Reset modified palettes back to their original colors, ready for next time.
foreach (var kvp in modifiablePalettes)
{
var originalPalette = palettes[kvp.Key];
var modifiedPalette = kvp.Value;
for (var i = 0; i < Palette.Size; i++)
modifiedPalette[i] = originalPalette[i];
}
}
}
}

View File

@@ -34,7 +34,7 @@ namespace OpenRA
public enum BlendMode { None, Alpha, Additive, Subtractive, Multiply }
public interface IGraphicsDevice
public interface IGraphicsDevice : IDisposable
{
IVertexBuffer<Vertex> CreateVertexBuffer(int length);
ITexture CreateTexture(Bitmap bitmap);
@@ -59,7 +59,8 @@ namespace OpenRA
void SetBlendMode(BlendMode mode);
void Quit();
void GrabWindowMouseFocus();
void ReleaseWindowMouseFocus();
}
public interface IVertexBuffer<T>

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -8,6 +8,7 @@
*/
#endregion
using System;
using System.Drawing;
namespace OpenRA.Graphics
@@ -98,14 +99,14 @@ namespace OpenRA.Graphics
var yc = (r.Bottom + r.Top) / 2;
for (var y = r.Top; y <= r.Bottom; y++)
{
var dx = a * System.Convert.ToSingle(System.Math.Sqrt(1 - (y - yc) * (y - yc) / b / b));
var dx = a * (float)(Math.Sqrt(1 - (y - yc) * (y - yc) / b / b));
DrawLine(new float2(xc - dx, y), new float2(xc + dx, y), color, color);
}
}
public void SetViewportParams(Size screen, float zoom, float2 scroll)
public void SetViewportParams(Size screen, float zoom, int2 scroll)
{
shader.SetVec("Scroll", (int)scroll.X, (int)scroll.Y);
shader.SetVec("Scroll", scroll.X, scroll.Y);
shader.SetVec("r1", zoom*2f/screen.Width, -zoom*2f/screen.Height);
shader.SetVec("r2", -1, 1);
}

View File

@@ -8,8 +8,8 @@
*/
#endregion
using System.Drawing;
using System.Collections.Generic;
using System.Drawing;
namespace OpenRA.Graphics
{

View File

@@ -11,7 +11,6 @@
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using OpenRA.Traits;
@@ -21,32 +20,35 @@ namespace OpenRA.Graphics
{
public static Bitmap TerrainBitmap(TileSet tileset, Map map, bool actualSize = false)
{
var width = map.Bounds.Width;
var height = map.Bounds.Height;
var b = map.Bounds;
var width = b.Width;
var height = b.Height;
if (!actualSize)
width = height = Exts.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height));
width = height = Exts.NextPowerOf2(Math.Max(b.Width, b.Height));
var terrain = new Bitmap(width, height);
var bitmapData = terrain.LockBits(terrain.Bounds(),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
var mapTiles = map.MapTiles.Value;
unsafe
{
int* c = (int*)bitmapData.Scan0;
var c = (int*)bitmapData.Scan0;
for (var x = 0; x < map.Bounds.Width; x++)
for (var y = 0; y < map.Bounds.Height; y++)
for (var x = 0; x < b.Width; x++)
{
for (var y = 0; y < b.Height; y++)
{
var mapX = x + map.Bounds.Left;
var mapY = y + map.Bounds.Top;
var type = tileset.GetTerrainType(map.MapTiles.Value[mapX, mapY]);
if (!tileset.Terrain.ContainsKey(type))
throw new InvalidDataException("Tileset {0} lacks terraintype {1}".F(tileset.Id, type));
var mapX = x + b.Left;
var mapY = y + b.Top;
var type = tileset.GetTerrainInfo(mapTiles[mapX, mapY]);
*(c + (y * bitmapData.Stride >> 2) + x) = tileset.Terrain[type].Color.ToArgb();
*(c + (y * bitmapData.Stride >> 2) + x) = type.Color.ToArgb();
}
}
}
terrain.UnlockBits(bitmapData);
@@ -57,31 +59,35 @@ namespace OpenRA.Graphics
// in a world use AddCustomTerrain instead
static Bitmap AddStaticResources(TileSet tileset, Map map, Ruleset resourceRules, Bitmap terrainBitmap)
{
Bitmap terrain = new Bitmap(terrainBitmap);
var terrain = new Bitmap(terrainBitmap);
var b = map.Bounds;
var bitmapData = terrain.LockBits(terrain.Bounds(),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
unsafe
{
int* c = (int*)bitmapData.Scan0;
var c = (int*)bitmapData.Scan0;
for (var x = 0; x < map.Bounds.Width; x++)
for (var y = 0; y < map.Bounds.Height; y++)
for (var x = 0; x < b.Width; x++)
{
for (var y = 0; y < b.Height; y++)
{
var mapX = x + map.Bounds.Left;
var mapY = y + map.Bounds.Top;
var mapX = x + b.Left;
var mapY = y + b.Top;
if (map.MapResources.Value[mapX, mapY].Type == 0)
continue;
var res = resourceRules.Actors["world"].Traits.WithInterface<ResourceTypeInfo>()
.Where(t => t.ResourceType == map.MapResources.Value[mapX, mapY].Type)
.Where(t => t.ResourceType == map.MapResources.Value[mapX, mapY].Type)
.Select(t => t.TerrainType).FirstOrDefault();
if (res == null)
continue;
*(c + (y * bitmapData.Stride >> 2) + x) = tileset.Terrain[res].Color.ToArgb();
*(c + (y * bitmapData.Stride >> 2) + x) = tileset[tileset.GetTerrainIndex(res)].Color.ToArgb();
}
}
}
terrain.UnlockBits(bitmapData);
@@ -92,25 +98,30 @@ namespace OpenRA.Graphics
public static Bitmap CustomTerrainBitmap(World world)
{
var map = world.Map;
var size = Exts.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height));
var b = map.Bounds;
var size = Exts.NextPowerOf2(Math.Max(b.Width, b.Height));
var bitmap = new Bitmap(size, size);
var bitmapData = bitmap.LockBits(bitmap.Bounds(),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
unsafe
{
int* c = (int*)bitmapData.Scan0;
var c = (int*)bitmapData.Scan0;
for (var x = 0; x < map.Bounds.Width; x++)
for (var y = 0; y < map.Bounds.Height; y++)
for (var x = 0; x < b.Width; x++)
{
for (var y = 0; y < b.Height; y++)
{
var mapX = x + map.Bounds.Left;
var mapY = y + map.Bounds.Top;
var mapX = x + b.Left;
var mapY = y + b.Top;
var custom = map.CustomTerrain[mapX, mapY];
if (custom == null)
if (custom == -1)
continue;
*(c + (y * bitmapData.Stride >> 2) + x) = world.TileSet.Terrain[custom].Color.ToArgb();
*(c + (y * bitmapData.Stride >> 2) + x) = world.TileSet[custom].Color.ToArgb();
}
}
}
bitmap.UnlockBits(bitmapData);
@@ -120,14 +131,16 @@ namespace OpenRA.Graphics
public static Bitmap ActorsBitmap(World world)
{
var map = world.Map;
var size = Exts.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height));
var b = map.Bounds;
var size = Exts.NextPowerOf2(Math.Max(b.Width, b.Height));
var bitmap = new Bitmap(size, size);
var bitmapData = bitmap.LockBits(bitmap.Bounds(),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
unsafe
{
int* c = (int*)bitmapData.Scan0;
var c = (int*)bitmapData.Scan0;
foreach (var t in world.ActorsWithTrait<IRadarSignature>())
{
@@ -136,8 +149,11 @@ namespace OpenRA.Graphics
var color = t.Trait.RadarSignatureColor(t.Actor);
foreach (var cell in t.Trait.RadarSignatureCells(t.Actor))
if (world.Map.IsInMap(cell))
*(c + ((cell.Y - world.Map.Bounds.Top) * bitmapData.Stride >> 2) + cell.X - world.Map.Bounds.Left) = color.ToArgb();
{
var uv = Map.CellToMap(map.TileShape, cell);
if (b.Contains(uv.X, uv.Y))
*(c + ((uv.Y - b.Top) * bitmapData.Stride >> 2) + uv.X - b.Left) = color.ToArgb();
}
}
}
@@ -148,7 +164,9 @@ namespace OpenRA.Graphics
public static Bitmap ShroudBitmap(World world)
{
var map = world.Map;
var size = Exts.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height));
var b = map.Bounds;
var size = Exts.NextPowerOf2(Math.Max(b.Width, b.Height));
var bitmap = new Bitmap(size, size);
if (world.RenderPlayer == null)
return bitmap;
@@ -158,20 +176,20 @@ namespace OpenRA.Graphics
var shroud = Color.Black.ToArgb();
var fog = Color.FromArgb(128, Color.Black).ToArgb();
var offset = new CVec(b.Left, b.Top);
unsafe
{
int* c = (int*)bitmapData.Scan0;
var c = (int*)bitmapData.Scan0;
for (var x = 0; x < map.Bounds.Width; x++)
for (var y = 0; y < map.Bounds.Height; y++)
{
var p = new CPos(x + map.Bounds.Left, y + map.Bounds.Top);
if (world.ShroudObscures(p))
*(c + (y * bitmapData.Stride >> 2) + x) = shroud;
else if (world.FogObscures(p))
*(c + (y * bitmapData.Stride >> 2) + x) = fog;
}
foreach (var cell in map.Cells)
{
var uv = Map.CellToMap(map.TileShape, cell) - offset;
if (world.ShroudObscures(cell))
*(c + (uv.Y * bitmapData.Stride >> 2) + uv.X) = shroud;
else if (world.FogObscures(cell))
*(c + (uv.Y * bitmapData.Stride >> 2) + uv.X) = fog;
}
}
bitmap.UnlockBits(bitmapData);
@@ -185,7 +203,7 @@ namespace OpenRA.Graphics
public static Bitmap RenderMapPreview(TileSet tileset, Map map, Ruleset resourceRules, bool actualSize)
{
Bitmap terrain = TerrainBitmap(tileset, map, actualSize);
var terrain = TerrainBitmap(tileset, map, actualSize);
return AddStaticResources(tileset, map, resourceRules, terrain);
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2012 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -8,94 +8,35 @@
*/
#endregion
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
namespace OpenRA.Graphics
{
public class Palette
public interface IPalette { uint this[int index] { get; } }
public interface IPaletteRemap { Color GetRemappedColor(Color original, int index); }
public static class Palette
{
public static Palette Load(string filename, int[] remap)
public const int Size = 256;
public static Color GetColor(this IPalette palette, int index)
{
using (var s = File.OpenRead(filename))
return new Palette(s, remap);
return Color.FromArgb((int)palette[index]);
}
uint[] colors;
public Color GetColor(int index)
{
return Color.FromArgb((int)colors[index]);
}
public void SetColor(int index, Color color)
{
colors[index] = (uint)color.ToArgb();
}
public void SetColor(int index, uint color)
{
colors[index] = (uint)color;
}
public uint[] Values
{
get { return colors; }
}
public void ApplyRemap(IPaletteRemap r)
{
for (int i = 0; i < 256; i++)
colors[i] = (uint)r.GetRemappedColor(Color.FromArgb((int)colors[i]), i).ToArgb();
}
public Palette(Stream s, int[] remapShadow)
{
colors = new uint[256];
using (BinaryReader reader = new BinaryReader(s))
{
for (int i = 0; i < 256; i++)
{
byte r = (byte)(reader.ReadByte() << 2);
byte g = (byte)(reader.ReadByte() << 2);
byte b = (byte)(reader.ReadByte() << 2);
colors[i] = (uint)((255 << 24) | (r << 16) | (g << 8) | b);
}
}
colors[0] = 0; // convert black background to transparency
foreach (int i in remapShadow)
colors[i] = 140u << 24;
}
public Palette(Palette p, IPaletteRemap r)
{
colors = (uint[])p.colors.Clone();
ApplyRemap(r);
}
public Palette(Palette p)
{
colors = (uint[])p.colors.Clone();
}
public Palette(uint[] data)
{
if (data.Length != 256)
throw new InvalidDataException("Attempting to create palette with incorrect array size");
colors = (uint[])data.Clone();
}
public ColorPalette AsSystemPalette()
public static ColorPalette AsSystemPalette(this IPalette palette)
{
ColorPalette pal;
using (var b = new Bitmap(1, 1, PixelFormat.Format8bppIndexed))
pal = b.Palette;
for (var i = 0; i < 256; i++)
pal.Entries[i] = GetColor(i);
for (var i = 0; i < Size; i++)
pal.Entries[i] = palette.GetColor(i);
// hack around a mono bug -- the palette flags get set wrong.
if (Platform.CurrentPlatform != PlatformType.Windows)
@@ -105,22 +46,116 @@ namespace OpenRA.Graphics
return pal;
}
public Bitmap AsBitmap()
public static Bitmap AsBitmap(this IPalette palette)
{
var b = new Bitmap(256, 1, PixelFormat.Format32bppArgb);
var b = new Bitmap(Size, 1, PixelFormat.Format32bppArgb);
var data = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
unsafe
{
uint* c = (uint*)data.Scan0;
for (var x = 0; x < 256; x++)
*(c + x) = colors[x];
}
var temp = new uint[Palette.Size];
for (int i = 0; i < temp.Length; i++)
temp[i] = palette[i];
Marshal.Copy((int[])(object)temp, 0, data.Scan0, Size);
b.UnlockBits(data);
return b;
}
public static IPalette AsReadOnly(this IPalette palette)
{
if (palette is ImmutablePalette)
return palette;
return new ReadOnlyPalette(palette);
}
class ReadOnlyPalette : IPalette
{
IPalette palette;
public ReadOnlyPalette(IPalette palette) { this.palette = palette; }
public uint this[int index] { get { return palette[index]; } }
}
}
public interface IPaletteRemap { Color GetRemappedColor(Color original, int index); }
public class ImmutablePalette : IPalette
{
readonly uint[] colors = new uint[Palette.Size];
public uint this[int index]
{
get { return colors[index]; }
}
public ImmutablePalette(string filename, int[] remap)
{
using (var s = File.OpenRead(filename))
LoadFromStream(s, remap);
}
public ImmutablePalette(Stream s, int[] remapShadow)
{
LoadFromStream(s, remapShadow);
}
void LoadFromStream(Stream s, int[] remapShadow)
{
using (var reader = new BinaryReader(s))
for (var i = 0; i < Palette.Size; i++)
{
var r = (byte)(reader.ReadByte() << 2);
var g = (byte)(reader.ReadByte() << 2);
var b = (byte)(reader.ReadByte() << 2);
colors[i] = (uint)((255 << 24) | (r << 16) | (g << 8) | b);
}
colors[0] = 0; // Convert black background to transparency.
foreach (var i in remapShadow)
colors[i] = 140u << 24;
}
public ImmutablePalette(IPalette p, IPaletteRemap r)
: this(p)
{
for (var i = 0; i < Palette.Size; i++)
colors[i] = (uint)r.GetRemappedColor(this.GetColor(i), i).ToArgb();
}
public ImmutablePalette(IPalette p)
{
for (int i = 0; i < Palette.Size; i++)
colors[i] = p[i];
}
public ImmutablePalette(IEnumerable<uint> sourceColors)
{
var i = 0;
foreach (var sourceColor in sourceColors)
colors[i++] = sourceColor;
}
}
public class MutablePalette : IPalette
{
readonly uint[] colors = new uint[Palette.Size];
public uint this[int index]
{
get { return colors[index]; }
set { colors[index] = value; }
}
public MutablePalette(IPalette p)
{
for (int i = 0; i < Palette.Size; i++)
this[i] = p[i];
}
public void SetColor(int index, Color color)
{
colors[index] = (uint)color.ToArgb();
}
public void ApplyRemap(IPaletteRemap r)
{
for (var i = 0; i < Palette.Size; i++)
colors[i] = (uint)r.GetRemappedColor(this.GetColor(i), i).ToArgb();
}
}
}

View File

@@ -58,9 +58,9 @@ namespace OpenRA.Graphics
nv += 4;
}
public void SetViewportParams(Size screen, float zoom, float2 scroll)
public void SetViewportParams(Size screen, float zoom, int2 scroll)
{
shader.SetVec("Scroll", (int)scroll.X, (int)scroll.Y);
shader.SetVec("Scroll", scroll.X, scroll.Y);
shader.SetVec("r1", zoom*2f/screen.Width, -zoom*2f/screen.Height);
shader.SetVec("r2", -1, 1);
}

View File

@@ -54,7 +54,7 @@ namespace OpenRA.Graphics
RgbaSpriteRenderer = new SpriteRenderer(this, device.CreateShader("rgba"));
SpriteRenderer = new SpriteRenderer(this, device.CreateShader("shp"));
for (int i = 0; i < TempBufferCount; i++)
for (var i = 0; i < TempBufferCount; i++)
tempBuffers.Enqueue(device.CreateVertexBuffer(TempBufferSize));
}
@@ -65,17 +65,34 @@ namespace OpenRA.Graphics
internal IGraphicsDevice Device { get { return device; } }
public void BeginFrame(float2 scroll, float zoom)
Size? lastResolution;
int2? lastScroll;
float? lastZoom;
public void BeginFrame(int2 scroll, float zoom)
{
device.Clear();
WorldSpriteRenderer.SetViewportParams(Resolution, zoom, scroll);
WorldRgbaSpriteRenderer.SetViewportParams(Resolution, zoom, scroll);
SpriteRenderer.SetViewportParams(Resolution, 1f, float2.Zero);
RgbaSpriteRenderer.SetViewportParams(Resolution, 1f, float2.Zero);
WorldLineRenderer.SetViewportParams(Resolution, zoom, scroll);
WorldQuadRenderer.SetViewportParams(Resolution, zoom, scroll);
LineRenderer.SetViewportParams(Resolution, 1f, float2.Zero);
WorldVoxelRenderer.SetViewportParams(Resolution, zoom, scroll);
var resolutionChanged = lastResolution != Resolution;
if (resolutionChanged)
{
lastResolution = Resolution;
RgbaSpriteRenderer.SetViewportParams(Resolution, 1f, int2.Zero);
SpriteRenderer.SetViewportParams(Resolution, 1f, int2.Zero);
LineRenderer.SetViewportParams(Resolution, 1f, int2.Zero);
}
// If zoom evaluates as different due to floating point weirdness that's OK, setting the parameters again is harmless.
if (resolutionChanged || lastScroll != scroll || lastZoom != zoom)
{
lastScroll = scroll;
lastZoom = zoom;
WorldRgbaSpriteRenderer.SetViewportParams(Resolution, zoom, scroll);
WorldSpriteRenderer.SetViewportParams(Resolution, zoom, scroll);
WorldVoxelRenderer.SetViewportParams(Resolution, zoom, scroll);
WorldLineRenderer.SetViewportParams(Resolution, zoom, scroll);
WorldQuadRenderer.SetViewportParams(Resolution, zoom, scroll);
}
}
ITexture currentPaletteTexture;
@@ -212,5 +229,15 @@ namespace OpenRA.Graphics
Flush();
Device.DisableDepthBuffer();
}
public void GrabWindowMouseFocus()
{
device.GrabWindowMouseFocus();
}
public void ReleaseWindowMouseFocus()
{
device.ReleaseWindowMouseFocus();
}
}
}

View File

@@ -33,7 +33,7 @@ namespace OpenRA.Graphics
{
var srcOverride = info.Value;
Name = name;
var d = info.NodesDict;
var d = info.ToDictionary();
var offset = float2.Zero;
var blendMode = BlendMode.Alpha;

View File

@@ -12,14 +12,15 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Primitives;
namespace OpenRA.Graphics
{
using Sequences = IReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>;
using UnitSequences = Lazy<IReadOnlyDictionary<string, Sequence>>;
public class SequenceProvider
{
readonly Lazy<IReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>> sequences;
readonly Lazy<Sequences> sequences;
public readonly SpriteLoader SpriteLoader;
public SequenceProvider(SequenceCache cache, Map map)
@@ -30,7 +31,7 @@ namespace OpenRA.Graphics
public Sequence GetSequence(string unitName, string sequenceName)
{
Lazy<IReadOnlyDictionary<string, Sequence>> unitSeq;
UnitSequences unitSeq;
if (!sequences.Value.TryGetValue(unitName, out unitSeq))
throw new InvalidOperationException("Unit `{0}` does not have any sequences defined.".F(unitName));
@@ -43,7 +44,7 @@ namespace OpenRA.Graphics
public bool HasSequence(string unitName, string sequenceName)
{
Lazy<IReadOnlyDictionary<string, Sequence>> unitSeq;
UnitSequences unitSeq;
if (!sequences.Value.TryGetValue(unitName, out unitSeq))
throw new InvalidOperationException("Unit `{0}` does not have any sequences defined.".F(unitName));
@@ -52,7 +53,7 @@ namespace OpenRA.Graphics
public IEnumerable<string> Sequences(string unitName)
{
Lazy<IReadOnlyDictionary<string, Sequence>> unitSeq;
UnitSequences unitSeq;
if (!sequences.Value.TryGetValue(unitName, out unitSeq))
throw new InvalidOperationException("Unit `{0}` does not have any sequences defined.".F(unitName));
@@ -62,16 +63,7 @@ namespace OpenRA.Graphics
public void Preload()
{
foreach (var unitSeq in sequences.Value.Values)
{
try
{
foreach (var seq in unitSeq.Value.Values);
}
catch (FileNotFoundException ex)
{
Log.Write("debug", ex.Message);
}
}
foreach (var seq in unitSeq.Value.Values) { }
}
}
@@ -81,7 +73,7 @@ namespace OpenRA.Graphics
readonly Lazy<SpriteLoader> spriteLoader;
public SpriteLoader SpriteLoader { get { return spriteLoader.Value; } }
readonly Dictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>> sequenceCache = new Dictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>();
readonly Dictionary<string, UnitSequences> sequenceCache = new Dictionary<string, UnitSequences>();
public SequenceCache(ModData modData, TileSet tileSet)
{
@@ -90,13 +82,13 @@ namespace OpenRA.Graphics
spriteLoader = Exts.Lazy(() => new SpriteLoader(tileSet.Extensions, new SheetBuilder(SheetType.Indexed)));
}
public IReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>> LoadSequences(Map map)
public Sequences LoadSequences(Map map)
{
using (new Support.PerfTimer("LoadSequences"))
return Load(map.SequenceDefinitions);
}
IReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>> Load(List<MiniYamlNode> sequenceNodes)
Sequences Load(List<MiniYamlNode> sequenceNodes)
{
var sequenceFiles = modData.Manifest.Sequences;
@@ -104,7 +96,7 @@ namespace OpenRA.Graphics
.Select(s => MiniYaml.FromFile(s))
.Aggregate(sequenceNodes, MiniYaml.MergeLiberal);
var items = new Dictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>();
var items = new Dictionary<string, UnitSequences>();
foreach (var n in nodes)
{
// Work around the loop closure issue in older versions of C#
@@ -112,23 +104,40 @@ namespace OpenRA.Graphics
var key = node.Value.ToLines(node.Key).JoinWith("|");
Lazy<IReadOnlyDictionary<string, Sequence>> t;
UnitSequences t;
if (sequenceCache.TryGetValue(key, out t))
items.Add(node.Key, t);
else
{
t = Exts.Lazy(() => (IReadOnlyDictionary<string, Sequence>)new ReadOnlyDictionary<string, Sequence>(
node.Value.NodesDict.ToDictionary(x => x.Key, x =>
{
using (new Support.PerfTimer("new Sequence(\"{0}\")".F(node.Key), 20))
return new Sequence(spriteLoader.Value, node.Key, x.Key, x.Value);
})));
t = Exts.Lazy(() => CreateUnitSequences(node));
sequenceCache.Add(key, t);
items.Add(node.Key, t);
}
}
return new ReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>(items);
return new ReadOnlyDictionary<string, UnitSequences>(items);
}
IReadOnlyDictionary<string, Sequence> CreateUnitSequences(MiniYamlNode node)
{
var unitSequences = new Dictionary<string, Sequence>();
foreach (var kvp in node.Value.ToDictionary())
{
using (new Support.PerfTimer("new Sequence(\"{0}\")".F(node.Key), 20))
{
try
{
unitSequences.Add(kvp.Key, new Sequence(spriteLoader.Value, node.Key, kvp.Key, kvp.Value));
}
catch (FileNotFoundException ex)
{
Log.Write("debug", ex.Message);
}
}
}
return new ReadOnlyDictionary<string, Sequence>(unitSequences);
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -11,24 +11,28 @@
using System;
using System.Drawing;
using System.Drawing.Imaging;
using OpenRA.FileFormats;
using System.Runtime.InteropServices;
using OpenRA.FileSystem;
namespace OpenRA.Graphics
{
public class Sheet
{
ITexture texture;
readonly object textureLock = new object();
bool dirty;
bool releaseBufferOnCommit;
ITexture texture;
byte[] data;
public readonly Size Size;
public byte[] Data { get { return data ?? texture.GetData(); } }
public bool Buffered { get { return data != null; } }
public Sheet(Size size)
public Sheet(Size size, bool buffered)
{
Size = size;
data = new byte[4*Size.Width*Size.Height];
if (buffered)
data = new byte[4 * Size.Width * Size.Height];
}
public Sheet(ITexture texture)
@@ -39,108 +43,118 @@ namespace OpenRA.Graphics
public Sheet(string filename)
{
var bitmap = (Bitmap)Image.FromStream(GlobalFileSystem.Open(filename));
Size = bitmap.Size;
data = new byte[4*Size.Width*Size.Height];
var b = bitmap.LockBits(bitmap.Bounds(),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
unsafe
using (var stream = GlobalFileSystem.Open(filename))
using (var bitmap = (Bitmap)Image.FromStream(stream))
{
int* c = (int*)b.Scan0;
Size = bitmap.Size;
for (var x = 0; x < Size.Width; x++)
for (var y = 0; y < Size.Height; y++)
{
var i = 4*Size.Width*y + 4*x;
var dataStride = 4 * Size.Width;
data = new byte[dataStride * Size.Height];
// Convert argb to bgra
var argb = *(c + (y * b.Stride >> 2) + x);
data[i++] = (byte)(argb >> 0);
data[i++] = (byte)(argb >> 8);
data[i++] = (byte)(argb >> 16);
data[i++] = (byte)(argb >> 24);
}
var bd = bitmap.LockBits(bitmap.Bounds(),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
for (var y = 0; y < Size.Height; y++)
Marshal.Copy(IntPtr.Add(bd.Scan0, y * bd.Stride), data, y * dataStride, dataStride);
bitmap.UnlockBits(bd);
}
bitmap.UnlockBits(b);
ReleaseBuffer();
}
public ITexture Texture
{
// This is only called from the main thread but 'dirty'
// is set from other threads too via CommitData().
get
{
if (texture == null)
{
texture = Game.Renderer.Device.CreateTexture();
dirty = true;
}
if (dirty)
{
texture.SetData(data, Size.Width, Size.Height);
dirty = false;
}
GenerateTexture();
return texture;
}
}
void GenerateTexture()
{
if (texture == null)
{
texture = Game.Renderer.Device.CreateTexture();
dirty = true;
}
if (Buffered)
{
lock (textureLock)
{
if (dirty)
{
texture.SetData(data, Size.Width, Size.Height);
dirty = false;
if (releaseBufferOnCommit)
data = null;
}
}
}
}
public Bitmap AsBitmap()
{
var d = Data;
var b = new Bitmap(Size.Width, Size.Height);
var output = b.LockBits(new Rectangle(0, 0, Size.Width, Size.Height),
var dataStride = 4 * Size.Width;
var bitmap = new Bitmap(Size.Width, Size.Height);
var bd = bitmap.LockBits(bitmap.Bounds(),
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
for (var y = 0; y < Size.Height; y++)
Marshal.Copy(d, y * dataStride, IntPtr.Add(bd.Scan0, y * bd.Stride), dataStride);
bitmap.UnlockBits(bd);
unsafe
{
int* c = (int*)output.Scan0;
for (var x = 0; x < Size.Width; x++)
for (var y = 0; y < Size.Height; y++)
{
var i = 4*Size.Width*y + 4*x;
// Convert bgra to argb
var argb = (d[i+3] << 24) | (d[i+2] << 16) | (d[i+1] << 8) | d[i];
*(c + (y * output.Stride >> 2) + x) = argb;
}
}
b.UnlockBits(output);
return b;
return bitmap;
}
public Bitmap AsBitmap(TextureChannel channel, Palette pal)
public Bitmap AsBitmap(TextureChannel channel, IPalette pal)
{
var d = Data;
var b = new Bitmap(Size.Width, Size.Height);
var output = b.LockBits(new Rectangle(0, 0, Size.Width, Size.Height),
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
var dataStride = 4 * Size.Width;
var bitmap = new Bitmap(Size.Width, Size.Height);
var channelOffset = (int)channel;
var bd = bitmap.LockBits(bitmap.Bounds(),
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
unsafe
{
int* c = (int*)output.Scan0;
for (var x = 0; x < Size.Width; x++)
for (var y = 0; y < Size.Height; y++)
var colors = (uint*)bd.Scan0;
for (var y = 0; y < Size.Height; y++)
{
var index = d[4*Size.Width*y + 4*x + (int)channel];
*(c + (y * output.Stride >> 2) + x) = pal.GetColor(index).ToArgb();
var dataRowIndex = y * dataStride + channelOffset;
var bdRowIndex = y * bd.Stride / 4;
for (var x = 0; x < Size.Width; x++)
{
var paletteIndex = d[dataRowIndex + 4 * x];
colors[bdRowIndex + x] = pal[paletteIndex];
}
}
}
b.UnlockBits(output);
return b;
bitmap.UnlockBits(bd);
return bitmap;
}
public void CommitData()
{
if (data == null)
throw new InvalidOperationException("Texture-wrappers are read-only");
if (!Buffered)
throw new InvalidOperationException(
"This sheet is unbuffered. You cannot call CommitData on an unbuffered sheet. " +
"If you need to completely replace the texture data you should set data into the texture directly. " +
"If you need to make only small changes to the texture data consider creating a buffered sheet instead.");
dirty = true;
lock (textureLock)
dirty = true;
}
public void ReleaseBuffer()
{
lock (textureLock)
releaseBufferOnCommit = true;
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -10,7 +10,6 @@
using System;
using System.Drawing;
using OpenRA.FileFormats;
namespace OpenRA.Graphics
{
@@ -18,7 +17,7 @@ namespace OpenRA.Graphics
public class SheetOverflowException : Exception
{
public SheetOverflowException(string message)
: base(message) {}
: base(message) { }
}
public enum SheetType
@@ -39,11 +38,11 @@ namespace OpenRA.Graphics
public static Sheet AllocateSheet()
{
return new Sheet(new Size(Renderer.SheetSize, Renderer.SheetSize));
return new Sheet(new Size(Renderer.SheetSize, Renderer.SheetSize), true);
}
public SheetBuilder(SheetType t)
: this(t, AllocateSheet) {}
: this(t, AllocateSheet) { }
public SheetBuilder(SheetType t, Func<Sheet> allocateSheet)
{
@@ -110,6 +109,7 @@ namespace OpenRA.Graphics
var next = NextChannel(channel);
if (next == null)
{
current.ReleaseBuffer();
current = allocateSheet();
channel = TextureChannel.Red;
}
@@ -117,7 +117,7 @@ namespace OpenRA.Graphics
channel = next.Value;
rowHeight = imageSize.Height;
p = new Point(0,0);
p = new Point(0, 0);
}
var rect = new Sprite(current, new Rectangle(p, imageSize), spriteOffset, channel, BlendMode.Alpha);

View File

@@ -11,9 +11,8 @@
using System;
using System.Drawing;
using System.Linq;
using SharpFont;
using OpenRA.FileFormats;
using OpenRA.Primitives;
using SharpFont;
namespace OpenRA.Graphics
{
@@ -86,7 +85,8 @@ namespace OpenRA.Graphics
public int2 Measure(string text)
{
return new int2((int)text.Split('\n').Max(s => s.Sum(a => glyphs[Pair.New(a, Color.White)].Advance)), text.Split('\n').Count()*size);
var lines = text.Split('\n');
return new int2((int)Math.Ceiling(lines.Max(s => s.Sum(a => glyphs[Pair.New(a, Color.White)].Advance))), lines.Length * size);
}
Cache<Pair<char,Color>, GlyphInfo> glyphs;
@@ -94,7 +94,7 @@ namespace OpenRA.Graphics
GlyphInfo CreateGlyph(Pair<char, Color> c)
{
uint index = face.GetCharIndex(c.First);
var index = face.GetCharIndex(c.First);
face.LoadGlyph(index, LoadFlags.Default, LoadTarget.Normal);
face.Glyph.RenderGlyph(RenderMode.Normal);
@@ -108,27 +108,29 @@ namespace OpenRA.Graphics
Offset = { X = face.Glyph.BitmapLeft, Y = -face.Glyph.BitmapTop }
};
unsafe
{
var p = (byte*)face.Glyph.Bitmap.Buffer;
var dest = s.sheet.Data;
var destStride = s.sheet.Size.Width * 4;
for (var j = 0; j < s.size.Y; j++)
// A new bitmap is generated each time this property is accessed, so we do need to dispose it.
using (var bitmap = face.Glyph.Bitmap)
unsafe
{
for (var i = 0; i < s.size.X; i++)
if (p[i] != 0)
{
var q = destStride * (j + s.bounds.Top) + 4 * (i + s.bounds.Left);
dest[q] = c.Second.B;
dest[q + 1] = c.Second.G;
dest[q + 2] = c.Second.R;
dest[q + 3] = p[i];
}
var p = (byte*)bitmap.Buffer;
var dest = s.sheet.Data;
var destStride = s.sheet.Size.Width * 4;
p += face.Glyph.Bitmap.Pitch;
for (var j = 0; j < s.size.Y; j++)
{
for (var i = 0; i < s.size.X; i++)
if (p[i] != 0)
{
var q = destStride * (j + s.bounds.Top) + 4 * (i + s.bounds.Left);
dest[q] = c.Second.B;
dest[q + 1] = c.Second.G;
dest[q + 2] = c.Second.R;
dest[q + 3] = p[i];
}
p += bitmap.Pitch;
}
}
}
s.sheet.CommitData();
return g;

View File

@@ -8,9 +8,7 @@
*/
#endregion
using System.IO;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.FileSystem;
using OpenRA.Primitives;
@@ -33,10 +31,10 @@ namespace OpenRA.Graphics
Sprite[] CacheSpriteFrames(string filename)
{
var stream = GlobalFileSystem.OpenWithExts(filename, exts);
return SpriteSource.LoadSpriteSource(stream, filename).Frames
.Select(a => SheetBuilder.Add(a))
.ToArray();
using (var stream = GlobalFileSystem.OpenWithExts(filename, exts))
return SpriteSource.LoadSpriteSource(stream, filename).Frames
.Select(a => SheetBuilder.Add(a))
.ToArray();
}
public Sprite[] LoadAllSprites(string filename) { return sprites[filename]; }

View File

@@ -120,9 +120,9 @@ namespace OpenRA.Graphics
shader.SetTexture("Palette", palette);
}
public void SetViewportParams(Size screen, float zoom, float2 scroll)
public void SetViewportParams(Size screen, float zoom, int2 scroll)
{
shader.SetVec("Scroll", (int)scroll.X, (int)scroll.Y);
shader.SetVec("Scroll", scroll.X, scroll.Y);
shader.SetVec("r1", zoom*2f/screen.Width, -zoom*2f/screen.Height);
shader.SetVec("r2", -1, 1);
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -8,10 +8,8 @@
*/
#endregion
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using OpenRA.FileFormats;
namespace OpenRA.Graphics
@@ -26,8 +24,7 @@ namespace OpenRA.Graphics
public interface ISpriteSource
{
// TODO: Change this to IReadOnlyList so users don't need to call .ToArray()
IEnumerable<ISpriteFrame> Frames { get; }
IReadOnlyList<ISpriteFrame> Frames { get; }
bool CacheWhenLoadingTileset { get; }
}

View File

@@ -26,17 +26,14 @@ namespace OpenRA.Graphics
var terrainPalette = wr.Palette("terrain").Index;
var vertices = new Vertex[4 * map.Bounds.Height * map.Bounds.Width];
int nv = 0;
var nv = 0;
for (var j = map.Bounds.Top; j < map.Bounds.Bottom; j++)
foreach (var cell in map.Cells)
{
for (var i = map.Bounds.Left; i < map.Bounds.Right; i++)
{
var tile = wr.Theater.TileSprite(map.MapTiles.Value[i, j]);
var pos = wr.ScreenPosition(new CPos(i, j).CenterPosition) - 0.5f * tile.size;
Util.FastCreateQuad(vertices, pos, tile, terrainPalette, nv, tile.size);
nv += 4;
}
var tile = wr.Theater.TileSprite(map.MapTiles.Value[cell]);
var pos = wr.ScreenPosition(map.CenterOfCell(cell)) - 0.5f * tile.size;
Util.FastCreateQuad(vertices, pos, tile, terrainPalette, nv, tile.size);
nv += 4;
}
vertexBuffer = Game.Renderer.Device.CreateVertexBuffer(vertices.Length);
@@ -46,12 +43,13 @@ namespace OpenRA.Graphics
public void Draw(WorldRenderer wr, Viewport viewport)
{
var verticesPerRow = 4*map.Bounds.Width;
var bounds = viewport.CellBounds;
var firstRow = bounds.Top - map.Bounds.Top;
var lastRow = bounds.Bottom - map.Bounds.Top;
var cells = viewport.VisibleCells;
var shape = wr.world.Map.TileShape;
if (lastRow < 0 || firstRow > map.Bounds.Height)
return;
// Only draw the rows that are visible.
// VisibleCells is clamped to the map, so additional checks are unnecessary
var firstRow = Map.CellToMap(shape, cells.TopLeft).Y - map.Bounds.Top;
var lastRow = Map.CellToMap(shape, cells.BottomRight).Y - map.Bounds.Top + 1;
Game.Renderer.WorldSpriteRenderer.DrawVertexBuffer(
vertexBuffer, verticesPerRow * firstRow, verticesPerRow * (lastRow - firstRow),

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -11,7 +11,6 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using OpenRA.FileSystem;
@@ -59,7 +58,7 @@ namespace OpenRA.Graphics
throw new SheetOverflowException("Terrain sheet overflow. Try increasing the tileset SheetSize parameter.");
allocated = true;
return new Sheet(new Size(tileset.SheetSize, tileset.SheetSize));
return new Sheet(new Size(tileset.SheetSize, tileset.SheetSize), true);
};
var sourceCache = new Dictionary<string, ISpriteSource>();
@@ -70,9 +69,11 @@ namespace OpenRA.Graphics
// 1x1px transparent tile
missingTile = sheetBuilder.Add(new byte[1], new Size(1, 1));
Sheet.ReleaseBuffer();
}
public Sprite TileSprite(TileReference<ushort, byte> r)
public Sprite TileSprite(TerrainTile r)
{
Sprite[] template;
if (!templates.TryGetValue(r.Type, out template))

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -11,6 +11,7 @@
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
namespace OpenRA.Graphics
{
@@ -51,7 +52,7 @@ namespace OpenRA.Graphics
var srcOffset = 0;
for (var j = 0; j < height; j++)
{
for (int i = 0; i < srcStride; i++, srcOffset++)
for (var i = 0; i < srcStride; i++, srcOffset++)
{
data[destOffset] = src[srcOffset];
destOffset += 4;
@@ -62,32 +63,18 @@ namespace OpenRA.Graphics
public static void FastCopyIntoSprite(Sprite dest, Bitmap src)
{
var destStride = dest.sheet.Size.Width;
var width = dest.bounds.Width;
var data = dest.sheet.Data;
var dataStride = dest.sheet.Size.Width * 4;
var x = dest.bounds.Left * 4;
var width = dest.bounds.Width * 4;
var y = dest.bounds.Top;
var height = dest.bounds.Height;
var srcData = src.LockBits(src.Bounds(),
var bd = src.LockBits(src.Bounds(),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
unsafe
{
var c = (int*)srcData.Scan0;
// Cast the data to an int array so we can copy the src data directly
fixed (byte* bd = &dest.sheet.Data[0])
{
var data = (int*)bd;
var x = dest.bounds.Left;
var y = dest.bounds.Top;
for (var j = 0; j < height; j++)
for (var i = 0; i < width; i++)
data[(y + j) * destStride + x + i] = *(c + (j * srcData.Stride >> 2) + i);
}
}
src.UnlockBits(srcData);
for (var row = 0; row < height; row++)
Marshal.Copy(IntPtr.Add(bd.Scan0, row * bd.Stride), data, (y + row) * dataStride + x, width);
src.UnlockBits(bd);
}
public static float[] IdentityMatrix()

54
OpenRA.Game/Graphics/Viewport.cs Executable file → Normal file
View File

@@ -9,6 +9,7 @@
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
@@ -46,7 +47,8 @@ namespace OpenRA.Graphics
public int2 TopLeft { get { return CenterLocation - viewportSize / 2; } }
public int2 BottomRight { get { return CenterLocation + viewportSize / 2; } }
int2 viewportSize;
bool cellBoundsDirty = true;
CellRegion cells;
bool cellsDirty = true;
float zoom = 1f;
public float Zoom
@@ -60,7 +62,7 @@ namespace OpenRA.Graphics
{
zoom = value;
viewportSize = (1f / zoom * new float2(Game.Renderer.Resolution)).ToInt2();
cellBoundsDirty = true;
cellsDirty = true;
}
}
@@ -88,14 +90,21 @@ namespace OpenRA.Graphics
// Calculate map bounds in world-px
var b = map.Bounds;
var tl = wr.ScreenPxPosition(new CPos(b.Left, b.Top).TopLeft);
var br = wr.ScreenPxPosition(new CPos(b.Right, b.Bottom).BottomRight);
// Expand to corners of cells
var tl = wr.ScreenPxPosition(map.CenterOfCell(Map.MapToCell(map.TileShape, new CPos(b.Left, b.Top))) - new WVec(512, 512, 0));
var br = wr.ScreenPxPosition(map.CenterOfCell(Map.MapToCell(map.TileShape, new CPos(b.Right, b.Bottom))) + new WVec(511, 511, 0));
mapBounds = Rectangle.FromLTRB(tl.X, tl.Y, br.X, br.Y);
CenterLocation = (tl + br) / 2;
Zoom = Game.Settings.Graphics.PixelDouble ? 2 : 1;
}
public CPos ViewToWorld(int2 view)
{
return worldRenderer.world.Map.CellContaining(worldRenderer.Position(ViewToWorldPx(view)));
}
public int2 ViewToWorldPx(int2 view) { return (1f / Zoom * view.ToFloat2()).ToInt2() + TopLeft; }
public int2 WorldToViewPx(int2 world) { return (Zoom * (world - TopLeft).ToFloat2()).ToInt2(); }
@@ -110,14 +119,14 @@ namespace OpenRA.Graphics
public void Center(WPos pos)
{
CenterLocation = worldRenderer.ScreenPxPosition(pos).Clamp(mapBounds);
cellBoundsDirty = true;
cellsDirty = true;
}
public void Scroll(float2 delta, bool ignoreBorders)
{
// Convert scroll delta from world-px to viewport-px
CenterLocation += (1f / Zoom * delta).ToInt2();
cellBoundsDirty = true;
cellsDirty = true;
if (!ignoreBorders)
CenterLocation = CenterLocation.Clamp(mapBounds);
@@ -129,33 +138,38 @@ namespace OpenRA.Graphics
{
get
{
var r = CellBounds;
var ctl = new CPos(r.Left, r.Top).TopLeft;
var cbr = new CPos(r.Right, r.Bottom).TopLeft;
// Visible rectangle in world coordinates (expanded to the corners of the cells)
var map = worldRenderer.world.Map;
var ctl = map.CenterOfCell(VisibleCells.TopLeft) - new WVec(512, 512, 0);
var cbr = map.CenterOfCell(VisibleCells.BottomRight) + new WVec(512, 512, 0);
// Convert to screen coordinates
var tl = WorldToViewPx(worldRenderer.ScreenPxPosition(ctl)).Clamp(ScreenClip);
var br = WorldToViewPx(worldRenderer.ScreenPxPosition(cbr)).Clamp(ScreenClip);
return Rectangle.FromLTRB(tl.X, tl.Y, br.X, br.Y);
}
}
// Rectangle (in cell coords) of cells that are currently visible on the screen
Rectangle cachedRect;
public Rectangle CellBounds
public CellRegion VisibleCells
{
get
{
if (cellBoundsDirty)
if (cellsDirty)
{
var boundary = new CVec(1, 1);
var tl = worldRenderer.Position(TopLeft).ToCPos() - boundary;
var br = worldRenderer.Position(BottomRight).ToCPos() + boundary;
// Visible rectangle in map coordinates
var map = worldRenderer.world.Map;
var ctl = Map.CellToMap(map.TileShape, map.CellContaining(worldRenderer.Position(TopLeft)));
var cbr = Map.CellToMap(map.TileShape, map.CellContaining(worldRenderer.Position(BottomRight)));
cachedRect = Rectangle.Intersect(Rectangle.FromLTRB(tl.X, tl.Y, br.X, br.Y), worldRenderer.world.Map.Bounds);
cellBoundsDirty = false;
// Add a 2 cell cordon to prevent holes, then convert back to cell coordinates
var tl = map.Clamp(Map.MapToCell(map.TileShape, ctl - new CVec(2, 2)));
var br = map.Clamp(Map.MapToCell(map.TileShape, cbr + new CVec(2, 2)));
cells = new CellRegion(map.TileShape, tl, br);
cellsDirty = false;
}
var b = worldRenderer.world.VisibleBounds;
return b.HasValue ? Rectangle.Intersect(cachedRect, b.Value) : cachedRect;
return cells;
}
}
}

View File

@@ -82,7 +82,7 @@ namespace OpenRA.Graphics
c++;
}
Sprite s = sheetBuilder.Allocate(new Size(su, sv));
var s = sheetBuilder.Allocate(new Size(su, sv));
Util.FastCopyIntoChannel(s, 0, colors);
Util.FastCopyIntoChannel(s, 1, normals);
s.sheet.CommitData();
@@ -179,6 +179,7 @@ namespace OpenRA.Graphics
{
// Sheet overflow - allocate a new sheet and try once more
Log.Write("debug", "Voxel sheet overflow! Generating new sheet");
sheetBuilder.Current.ReleaseBuffer();
sheetBuilder = CreateSheetBuilder();
v = GenerateSlicePlanes(l).SelectMany(x => x).ToArray();
}
@@ -210,8 +211,12 @@ namespace OpenRA.Graphics
Voxel LoadFile(Pair<string,string> files)
{
var vxl = new VxlReader(GlobalFileSystem.OpenWithExts(files.First, ".vxl"));
var hva = new HvaReader(GlobalFileSystem.OpenWithExts(files.Second, ".hva"));
VxlReader vxl;
HvaReader hva;
using (var s = GlobalFileSystem.OpenWithExts(files.First, ".vxl"))
vxl = new VxlReader(s);
using (var s = GlobalFileSystem.OpenWithExts(files.Second, ".hva"))
hva = new HvaReader(s);
return new Voxel(this, vxl, hva);
}
@@ -219,5 +224,10 @@ namespace OpenRA.Graphics
{
return voxels[Pair.New(vxl, hva)];
}
public void Finish()
{
sheetBuilder.Current.ReleaseBuffer();
}
}
}

View File

@@ -33,7 +33,7 @@ namespace OpenRA.Graphics
Game.modData.VoxelLoader.RefreshBuffer();
}
static Voxel LoadVoxel(string unit, string name, MiniYaml info)
static Voxel LoadVoxel(string unit, MiniYaml info)
{
var vxl = unit;
var hva = unit;
@@ -55,7 +55,7 @@ namespace OpenRA.Graphics
Game.modData.LoadScreen.Display();
try
{
var seq = sequences.NodesDict.ToDictionary(x => x.Key, x => LoadVoxel(unit,x.Key,x.Value));
var seq = sequences.ToDictionary(my => LoadVoxel(unit, my));
units.Add(unit, seq);
}
catch (FileNotFoundException) {} // Do nothing; we can crash later if we actually wanted art

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -89,10 +89,12 @@ namespace OpenRA.Graphics
static readonly float[] groundNormal = new float[] {0,0,1,1};
public void BeforeRender(WorldRenderer wr)
{
var draw = voxels.Where(v => v.DisableFunc == null || !v.DisableFunc());
renderProxy = Game.Renderer.WorldVoxelRenderer.RenderAsync(
wr, voxels, camera, scale, groundNormal, lightSource,
wr, draw, camera, scale, groundNormal, lightSource,
lightAmbientColor, lightDiffuseColor,
palette, normalsPalette, shadowPalette);
palette, normalsPalette, shadowPalette);
}
public void Render(WorldRenderer wr)

View File

@@ -66,7 +66,7 @@ namespace OpenRA.Graphics
shader.SetTexture("Palette", palette);
}
public void SetViewportParams(Size screen, float zoom, float2 scroll)
public void SetViewportParams(Size screen, float zoom, int2 scroll)
{
var a = 2f / Renderer.SheetSize;
var view = new float[]

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -12,8 +12,6 @@ using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA.Graphics
@@ -22,8 +20,8 @@ namespace OpenRA.Graphics
{
public readonly string Name;
public readonly int Index;
public readonly Palette Palette;
public PaletteReference(string name, int index, Palette palette)
public IPalette Palette { get; internal set; }
public PaletteReference(string name, int index, IPalette palette)
{
Name = name;
Index = index;
@@ -37,10 +35,10 @@ namespace OpenRA.Graphics
public readonly Theater Theater;
public Viewport Viewport { get; private set; }
internal readonly TerrainRenderer terrainRenderer;
internal readonly HardwarePalette palette;
internal Cache<string, PaletteReference> palettes;
Lazy<DeveloperMode> devTrait;
readonly TerrainRenderer terrainRenderer;
readonly HardwarePalette palette;
readonly Dictionary<string, PaletteReference> palettes;
readonly Lazy<DeveloperMode> devTrait;
internal WorldRenderer(World world)
{
@@ -48,9 +46,9 @@ namespace OpenRA.Graphics
Viewport = new Viewport(this, world.Map);
palette = new HardwarePalette();
palettes = new Cache<string, PaletteReference>(CreatePaletteReference);
foreach (var pal in world.traitDict.ActorsWithTraitMultiple<IPalette>(world))
pal.Trait.InitPalette(this);
palettes = new Dictionary<string, PaletteReference>();
foreach (var pal in world.traitDict.ActorsWithTrait<ILoadsPalettes>())
pal.Trait.LoadPalettes(this);
palette.Initialize();
@@ -63,14 +61,13 @@ namespace OpenRA.Graphics
PaletteReference CreatePaletteReference(string name)
{
var pal = palette.GetPalette(name);
if (pal == null)
throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
return new PaletteReference(name, palette.GetPaletteIndex(name), pal);
}
public PaletteReference Palette(string name) { return palettes[name]; }
public void AddPalette(string name, Palette pal, bool allowModifiers) { palette.AddPalette(name, pal, allowModifiers); }
public PaletteReference Palette(string name) { return palettes.GetOrAdd(name, CreatePaletteReference); }
public void AddPalette(string name, ImmutablePalette pal) { palette.AddPalette(name, pal, false); }
public void AddPalette(string name, ImmutablePalette pal, bool allowModifiers) { palette.AddPalette(name, pal, allowModifiers); }
public void ReplacePalette(string name, IPalette pal) { palette.ReplacePalette(name, pal); palettes[name].Palette = pal; }
List<IRenderable> GenerateRenderables()
{

View File

@@ -18,6 +18,22 @@ using OpenRA.FileSystem;
namespace OpenRA
{
public class InstallData
{
public readonly string InstallerMenuWidget = null;
public readonly string InstallerBackgroundWidget = null;
public readonly string[] TestFiles = {};
public readonly string[] DiskTestFiles = {};
public readonly string PackageToExtractFromCD = null;
public readonly string[] ExtractFilesFromCD = {};
public readonly string[] CopyFilesFromCD = {};
public readonly string PackageMirrorList = null;
public readonly string MusicPackageMirrorList = null;
public readonly int ShippedSoundtracks = 0;
}
public static class InstallUtils
{
static IEnumerable<ZipEntry> GetEntries(this ZipInputStream z)
@@ -39,23 +55,26 @@ namespace OpenRA
}
// TODO: The package should be mounted into its own context to avoid name collisions with installed files
public static bool ExtractFromPackage(string srcPath, string package, string[] files, string destPath, Action<string> onProgress, Action<string> onError)
public static bool ExtractFromPackage(string srcPath, string package, string annotation, string[] files, string destPath, Action<string> onProgress, Action<string> onError)
{
if (!Directory.Exists(destPath))
Directory.CreateDirectory(destPath);
if (!GlobalFileSystem.Exists(srcPath)) { onError("Cannot find " + package); return false; }
Log.Write("debug", "Mounting {0}".F(srcPath));
GlobalFileSystem.Mount(srcPath);
if (!GlobalFileSystem.Exists(package)) { onError("Cannot find " + package); return false; }
GlobalFileSystem.Mount(package);
Log.Write("debug", "Mounting {0}".F(package));
GlobalFileSystem.Mount(package, annotation);
foreach (string s in files)
foreach (var file in files)
{
var destFile = Path.Combine(destPath, s);
using (var sourceStream = GlobalFileSystem.Open(s))
using (var destStream = File.Create(destFile))
var dest = Path.Combine(destPath, file);
if (File.Exists(dest))
File.Delete(dest);
using (var sourceStream = GlobalFileSystem.Open(file))
using (var destStream = File.Create(dest))
{
onProgress("Extracting " + s);
Log.Write("debug", "Extracting {0} to {1}".F(file, dest));
onProgress("Extracting " + file);
destStream.Write(sourceStream.ReadAllBytes());
}
}
@@ -75,8 +94,12 @@ namespace OpenRA
}
var destFile = Path.GetFileName(file).ToLowerInvariant();
onProgress("Extracting " + destFile);
File.Copy(fromPath, Path.Combine(destPath, destFile), true);
var dest = Path.Combine(destPath, destFile);
if (File.Exists(dest))
File.Delete(dest);
onProgress("Copying " + destFile);
Log.Write("debug", "Copy {0} to {1}".F(fromPath, dest));
File.Copy(fromPath, dest, true);
}
return true;
@@ -90,11 +113,12 @@ namespace OpenRA
return false;
}
List<string> extracted = new List<string>();
var extracted = new List<string>();
try
{
var z = new ZipInputStream(File.OpenRead(zipFile));
z.ExtractZip(dest, extracted, s => onProgress("Extracting " + s));
using (var stream = File.OpenRead(zipFile))
using (var z = new ZipInputStream(stream))
z.ExtractZip(dest, extracted, s => onProgress("Extracting " + s));
}
catch (SharpZipBaseException)
{
@@ -122,12 +146,7 @@ namespace OpenRA
extracted.Add(path);
using (var f = File.Create(path))
{
int bufSize = 2048;
byte[] buf = new byte[bufSize];
while ((bufSize = z.Read(buf, 0, buf.Length)) > 0)
f.Write(buf, 0, bufSize);
}
z.CopyTo(f);
}
z.Close();

View File

@@ -16,6 +16,8 @@ using OpenRA.Primitives;
namespace OpenRA
{
public enum TileShape { Rectangle, Diamond }
// Describes what is to be loaded in order to run a mod
public class Manifest
{
@@ -30,14 +32,15 @@ namespace OpenRA
public readonly IReadOnlyDictionary<string, string> MapFolders;
public readonly MiniYaml LoadScreen;
public readonly MiniYaml LobbyDefaults;
public readonly InstallData ContentInstaller;
public readonly Dictionary<string, Pair<string, int>> Fonts;
public readonly Size TileSize = new Size(24, 24);
public readonly string NewsUrl;
public readonly TileShape TileShape = TileShape.Rectangle;
public Manifest(string mod)
{
var path = new[] { "mods", mod, "mod.yaml" }.Aggregate(Path.Combine);
var yaml = new MiniYaml(null, MiniYaml.FromFile(path)).NodesDict;
var yaml = new MiniYaml(null, MiniYaml.FromFile(path)).ToDictionary();
Mod = FieldLoader.Load<ModMetadata>(yaml["Metadata"]);
Mod.Id = mod;
@@ -68,13 +71,22 @@ namespace OpenRA
LoadScreen = yaml["LoadScreen"];
LobbyDefaults = yaml["LobbyDefaults"];
Fonts = yaml["Fonts"].NodesDict.ToDictionary(x => x.Key,
x => Pair.New(x.Value.NodesDict["Font"].Value,
Exts.ParseIntegerInvariant(x.Value.NodesDict["Size"].Value)));
if (yaml.ContainsKey("ContentInstaller"))
ContentInstaller = FieldLoader.Load<InstallData>(yaml["ContentInstaller"]);
Fonts = yaml["Fonts"].ToDictionary(my =>
{
var nd = my.ToDictionary();
return Pair.New(nd["Font"].Value, Exts.ParseIntegerInvariant(nd["Size"].Value));
});
if (yaml.ContainsKey("TileSize"))
TileSize = FieldLoader.GetValue<Size>("TileSize", yaml["TileSize"].Value);
if (yaml.ContainsKey("TileShape"))
TileShape = FieldLoader.GetValue<TileShape>("TileShape", yaml["TileShape"].Value);
// Allow inherited mods to import parent maps.
var compat = new List<string>();
compat.Add(mod);
@@ -84,9 +96,6 @@ namespace OpenRA
compat.Add(c.Trim());
MapCompatibility = compat.ToArray();
if (yaml.ContainsKey("NewsUrl"))
NewsUrl = yaml["NewsUrl"].Value;
}
static string[] YamlList(Dictionary<string, MiniYaml> yaml, string key)
@@ -94,7 +103,7 @@ namespace OpenRA
if (!yaml.ContainsKey(key))
return new string[] { };
return yaml[key].NodesDict.Keys.ToArray();
return yaml[key].ToDictionary().Keys.ToArray();
}
static IReadOnlyDictionary<string, string> YamlDictionary(Dictionary<string, MiniYaml> yaml, string key)
@@ -102,7 +111,7 @@ namespace OpenRA
if (!yaml.ContainsKey(key))
return new ReadOnlyDictionary<string, string>();
var inner = yaml[key].NodesDict.ToDictionary(x => x.Key, x => x.Value.Value);
var inner = yaml[key].ToDictionary(my => my.Value);
return new ReadOnlyDictionary<string, string>(inner);
}
}

View File

@@ -57,10 +57,10 @@ namespace OpenRA
public class LocationInit : IActorInit<CPos>
{
[FieldFromYamlKey] public readonly int2 value = int2.Zero;
[FieldFromYamlKey] public readonly CPos value = CPos.Zero;
public LocationInit() { }
public LocationInit(CPos init) { value = init.ToInt2(); }
public CPos Value(World world) { return (CPos)value; }
public LocationInit(CPos init) { value = init; }
public CPos Value(World world) { return value; }
}
public class SubCellInit : IActorInit<SubCell>

View File

@@ -24,9 +24,9 @@ namespace OpenRA
}
Lazy<TypeDictionary> initDict;
public ActorReference( string type ) : this( type, new Dictionary<string, MiniYaml>() ) { }
public ActorReference( string type ) : this(type, new Dictionary<string, MiniYaml>()) { }
public ActorReference( string type, Dictionary<string, MiniYaml> inits )
public ActorReference(string type, Dictionary<string, MiniYaml> inits)
{
Type = type;
initDict = Exts.Lazy(() =>
@@ -47,17 +47,17 @@ namespace OpenRA
public MiniYaml Save()
{
var ret = new MiniYaml( Type );
foreach( var init in InitDict )
var ret = new MiniYaml(Type);
foreach (var init in InitDict)
{
var initName = init.GetType().Name;
ret.Nodes.Add( new MiniYamlNode( initName.Substring( 0, initName.Length - 4 ), FieldSaver.Save( init ) ) );
ret.Nodes.Add(new MiniYamlNode(initName.Substring(0, initName.Length - 4), FieldSaver.Save(init)));
}
return ret;
}
// for initialization syntax
public void Add( object o ) { InitDict.Add( o ); }
public void Add(object o) { InitDict.Add(o); }
public IEnumerator GetEnumerator() { return InitDict.GetEnumerator(); }
}
}

View File

@@ -0,0 +1,107 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using OpenRA.Graphics;
namespace OpenRA
{
// Represents a layer of "something" that covers the map
public class CellLayer<T> : IEnumerable<T>
{
public readonly Size Size;
public readonly TileShape Shape;
T[] entries;
public CellLayer(Map map)
: this(map.TileShape, new Size(map.MapSize.X, map.MapSize.Y)) { }
public CellLayer(TileShape shape, Size size)
{
Size = size;
Shape = shape;
entries = new T[size.Width * size.Height];
}
// Resolve an array index from cell coordinates
int Index(CPos cell)
{
var uv = Map.CellToMap(Shape, cell);
return uv.Y * Size.Width + uv.X;
}
/// <summary>Gets or sets the <see cref="OpenRA.CellLayer"/> using cell coordinates</summary>
public T this[CPos cell]
{
get
{
return entries[Index(cell)];
}
set
{
entries[Index(cell)] = value;
}
}
/// <summary>Gets or sets the layer contents using raw map coordinates (not CPos!)</summary>
public T this[int u, int v]
{
get
{
return entries[v * Size.Width + u];
}
set
{
entries[v * Size.Width + u] = value;
}
}
/// <summary>Clears the layer contents with a known value</summary>
public void Clear(T clearValue)
{
for (var i = 0; i < entries.Length; i++)
entries[i] = clearValue;
}
public IEnumerator<T> GetEnumerator()
{
return (IEnumerator<T>)entries.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
// Helper functions
public static class CellLayer
{
/// <summary>Create a new layer by resizing another layer. New cells are filled with defaultValue.</summary>
public static CellLayer<T> Resize<T>(CellLayer<T> layer, Size newSize, T defaultValue)
{
var result = new CellLayer<T>(layer.Shape, newSize);
var width = Math.Min(layer.Size.Width, newSize.Width);
var height = Math.Min(layer.Size.Height, newSize.Height);
result.Clear(defaultValue);
for (var j = 0; j < height; j++)
for (var i = 0; i < width; i++)
result[i, j] = layer[i, j];
return result;
}
}
}

View File

@@ -0,0 +1,112 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using OpenRA.Graphics;
namespace OpenRA
{
// Represents a (on-screen) rectangular collection of tiles.
// TopLeft and BottomRight are inclusive
public class CellRegion : IEnumerable<CPos>
{
// Corners of the region
public readonly CPos TopLeft;
public readonly CPos BottomRight;
readonly TileShape shape;
// Corners in map coordinates
// These will only equal TopLeft and BottomRight for TileShape.Rectangular
readonly CPos mapTopLeft;
readonly CPos mapBottomRight;
public CellRegion(TileShape shape, CPos topLeft, CPos bottomRight)
{
this.shape = shape;
TopLeft = topLeft;
BottomRight = bottomRight;
mapTopLeft = Map.CellToMap(shape, TopLeft);
mapBottomRight = Map.CellToMap(shape, BottomRight);
}
/// <summary>Expand the specified region with an additional cordon. This may expand the region outside the map borders.</summary>
public static CellRegion Expand(CellRegion region, int cordon)
{
var offset = new CVec(cordon, cordon);
var tl = Map.MapToCell(region.shape, Map.CellToMap(region.shape, region.TopLeft) - offset);
var br = Map.MapToCell(region.shape, Map.CellToMap(region.shape, region.BottomRight) + offset);
return new CellRegion(region.shape, tl, br);
}
public bool Contains(CPos cell)
{
var uv = Map.CellToMap(shape, cell);
return uv.X >= mapTopLeft.X && uv.X <= mapBottomRight.X && uv.Y >= mapTopLeft.Y && uv.Y <= mapBottomRight.Y;
}
public IEnumerator<CPos> GetEnumerator()
{
return new CellRegionEnumerator(this);
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
class CellRegionEnumerator : IEnumerator<CPos>
{
readonly CellRegion r;
// Current position, in map coordinates
int u, v;
public CellRegionEnumerator(CellRegion region)
{
r = region;
Reset();
}
public bool MoveNext()
{
u += 1;
// Check for column overflow
if (u > r.mapBottomRight.X)
{
v += 1;
u = r.mapTopLeft.X;
// Check for row overflow
if (v > r.mapBottomRight.Y)
return false;
}
return true;
}
public void Reset()
{
// Enumerator starts *before* the first element in the sequence.
u = r.mapTopLeft.X - 1;
v = r.mapTopLeft.Y;
}
public CPos Current { get { return Map.MapToCell(r.shape, new CPos(u, v)); } }
object IEnumerator.Current { get { return Current; } }
public void Dispose() { }
}
}
}

View File

@@ -9,6 +9,7 @@
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
@@ -16,9 +17,10 @@ using System.Linq;
using System.Security.Cryptography;
using System.Text;
using OpenRA.FileSystem;
using OpenRA.Network;
using OpenRA.Traits;
using OpenRA.Graphics;
using OpenRA.Network;
using OpenRA.Support;
using OpenRA.Traits;
namespace OpenRA
{
@@ -74,14 +76,17 @@ namespace OpenRA
public bool AllowStartUnitConfig = true;
public Bitmap CustomPreview;
public readonly TileShape TileShape;
[FieldLoader.LoadUsing("LoadOptions")]
public MapOptions Options;
static object LoadOptions(MiniYaml y)
{
var options = new MapOptions();
if (y.NodesDict.ContainsKey("Options"))
FieldLoader.Load(options, y.NodesDict["Options"]);
var nodesDict = y.ToDictionary();
if (nodesDict.ContainsKey("Options"))
FieldLoader.Load(options, nodesDict["Options"]);
return options;
}
@@ -108,29 +113,40 @@ namespace OpenRA
[FieldLoader.Ignore] public byte TileFormat = 1;
public int2 MapSize;
[FieldLoader.Ignore] public Lazy<TileReference<ushort, byte>[,]> MapTiles;
[FieldLoader.Ignore] public Lazy<TileReference<byte, byte>[,]> MapResources;
[FieldLoader.Ignore] public string[,] CustomTerrain;
[FieldLoader.Ignore] public Lazy<CellLayer<TerrainTile>> MapTiles;
[FieldLoader.Ignore] public Lazy<CellLayer<ResourceTile>> MapResources;
[FieldLoader.Ignore] public CellLayer<int> CustomTerrain;
[FieldLoader.Ignore] Lazy<TileSet> cachedTileSet;
[FieldLoader.Ignore] Lazy<Ruleset> rules;
public Ruleset Rules { get { return rules != null ? rules.Value : null; } }
public SequenceProvider SequenceProvider { get { return Rules.Sequences[Tileset]; } }
[FieldLoader.Ignore] public CellRegion Cells;
public static Map FromTileset(TileSet tileset)
{
var tile = tileset.Templates.First();
var tileRef = new TileReference<ushort, byte> { Type = tile.Key, Index = (byte)0 };
var size = new Size(1, 1);
var tileShape = Game.modData.Manifest.TileShape;
var tileRef = new TerrainTile(tileset.Templates.First().Key, (byte)0);
Map map = new Map()
var makeMapTiles = Exts.Lazy(() =>
{
var ret = new CellLayer<TerrainTile>(tileShape, size);
ret.Clear(tileRef);
return ret;
});
var map = new Map()
{
Title = "Name your map here",
Description = "Describe your map here",
Author = "Your name here",
MapSize = new int2(1, 1),
MapSize = new int2(size),
Tileset = tileset.Id,
Options = new MapOptions(),
MapResources = Exts.Lazy(() => new TileReference<byte, byte>[1, 1]),
MapTiles = Exts.Lazy(() => new TileReference<ushort, byte>[1, 1] { { tileRef } }),
MapResources = Exts.Lazy(() => new CellLayer<ResourceTile>(tileShape, size)),
MapTiles = makeMapTiles,
Actors = Exts.Lazy(() => new Dictionary<string, ActorReference>()),
Smudges = Exts.Lazy(() => new List<SmudgeReference>())
};
@@ -185,18 +201,20 @@ namespace OpenRA
RequiresMod = upgradeForMod;
}
var nd = yaml.ToDictionary();
// Load players
foreach (var kv in yaml.NodesDict["Players"].NodesDict)
foreach (var my in nd["Players"].ToDictionary().Values)
{
var player = new PlayerReference(kv.Value);
var player = new PlayerReference(my);
Players.Add(player.Name, player);
}
Actors = Exts.Lazy(() =>
{
var ret = new Dictionary<string, ActorReference>();
foreach (var kv in yaml.NodesDict["Actors"].NodesDict)
ret.Add(kv.Key, new ActorReference(kv.Value.Value, kv.Value.NodesDict));
foreach (var kv in nd["Actors"].ToDictionary())
ret.Add(kv.Key, new ActorReference(kv.Value.Value, kv.Value.ToDictionary()));
return ret;
});
@@ -204,9 +222,9 @@ namespace OpenRA
Smudges = Exts.Lazy(() =>
{
var ret = new List<SmudgeReference>();
foreach (var kv in yaml.NodesDict["Smudges"].NodesDict)
foreach (var name in nd["Smudges"].ToDictionary().Keys)
{
var vals = kv.Key.Split(' ');
var vals = name.Split(' ');
var loc = vals[1].Split(',');
ret.Add(new SmudgeReference(vals[0], new int2(
Exts.ParseIntegerInvariant(loc[0]),
@@ -225,10 +243,9 @@ namespace OpenRA
NotificationDefinitions = MiniYaml.NodesOrEmpty(yaml, "Notifications");
TranslationDefinitions = MiniYaml.NodesOrEmpty(yaml, "Translations");
CustomTerrain = new string[MapSize.X, MapSize.Y];
MapTiles = Exts.Lazy(() => LoadMapTiles());
MapResources = Exts.Lazy(() => LoadResourceTiles());
TileShape = Game.modData.Manifest.TileShape;
// The Uid is calculated from the data on-disk, so
// format changes must be flushed to disk.
@@ -247,6 +264,15 @@ namespace OpenRA
void PostInit()
{
rules = Exts.Lazy(() => Game.modData.RulesetCache.LoadMapRules(this));
cachedTileSet = Exts.Lazy(() => Rules.TileSets[Tileset]);
var tl = Map.MapToCell(TileShape, new CPos(Bounds.Left, Bounds.Top));
var br = Map.MapToCell(TileShape, new CPos(Bounds.Right - 1, Bounds.Bottom - 1));
Cells = new CellRegion(TileShape, tl, br);
CustomTerrain = new CellLayer<int>(this);
foreach (var cell in Cells)
CustomTerrain[cell] = -1;
}
public Ruleset PreloadRules()
@@ -339,9 +365,9 @@ namespace OpenRA
Container.Write(entries);
}
public TileReference<ushort, byte>[,] LoadMapTiles()
public CellLayer<TerrainTile> LoadMapTiles()
{
var tiles = new TileReference<ushort, byte>[MapSize.X, MapSize.Y];
var tiles = new CellLayer<TerrainTile>(this);
using (var dataStream = Container.GetContent("map.bin"))
{
if (dataStream.ReadUInt8() != 1)
@@ -355,24 +381,30 @@ namespace OpenRA
throw new InvalidDataException("Invalid tile data");
// Load tile data
for (int i = 0; i < MapSize.X; i++)
for (int j = 0; j < MapSize.Y; j++)
var data = dataStream.ReadBytes(MapSize.X * MapSize.Y * 3);
var d = 0;
for (var i = 0; i < MapSize.X; i++)
{
for (var j = 0; j < MapSize.Y; j++)
{
var tile = dataStream.ReadUInt16();
var index = dataStream.ReadUInt8();
var tile = BitConverter.ToUInt16(data, d);
d += 2;
var index = data[d++];
if (index == byte.MaxValue)
index = (byte)(i % 4 + (j % 4) * 4);
tiles[i, j] = new TileReference<ushort, byte>(tile, index);
tiles[i, j] = new TerrainTile(tile, index);
}
}
}
return tiles;
}
public TileReference<byte, byte>[,] LoadResourceTiles()
public CellLayer<ResourceTile> LoadResourceTiles()
{
var resources = new TileReference<byte, byte>[MapSize.X, MapSize.Y];
var resources = new CellLayer<ResourceTile>(this);
using (var dataStream = Container.GetContent("map.bin"))
{
@@ -389,14 +421,13 @@ namespace OpenRA
// Skip past tile data
dataStream.Seek(3 * MapSize.X * MapSize.Y, SeekOrigin.Current);
var data = dataStream.ReadBytes(MapSize.X * MapSize.Y * 2);
var d = 0;
// Load resource data
for (var i = 0; i < MapSize.X; i++)
for (var j = 0; j < MapSize.Y; j++)
{
var type = dataStream.ReadUInt8();
var index = dataStream.ReadUInt8();
resources[i, j] = new TileReference<byte, byte>(type, index);
}
resources[i, j] = new ResourceTile(data[d++], data[d++]);
}
return resources;
@@ -416,38 +447,126 @@ namespace OpenRA
for (var i = 0; i < MapSize.X; i++)
for (var j = 0; j < MapSize.Y; j++)
{
writer.Write(MapTiles.Value[i, j].Type);
writer.Write(MapTiles.Value[i, j].Index);
var tile = MapTiles.Value[new CPos(i, j)];
writer.Write(tile.Type);
writer.Write(tile.Index);
}
// Resource data
for (var i = 0; i < MapSize.X; i++)
{
for (var j = 0; j < MapSize.Y; j++)
{
writer.Write(MapResources.Value[i, j].Type);
writer.Write(MapResources.Value[i, j].Index);
var tile = MapResources.Value[new CPos(i, j)];
writer.Write(tile.Type);
writer.Write(tile.Index);
}
}
}
return dataStream.ToArray();
}
public bool IsInMap(CPos xy) { return IsInMap(xy.X, xy.Y); }
public bool IsInMap(int x, int y) { return Bounds.Contains(x, y); }
public bool Contains(CPos cell)
{
var uv = CellToMap(TileShape, cell);
return Bounds.Contains(uv.X, uv.Y);
}
public WPos CenterOfCell(CPos cell)
{
if (TileShape == TileShape.Rectangle)
return new WPos(1024 * cell.X + 512, 1024 * cell.Y + 512, 0);
// Convert from diamond cell position (x, y) to world position (u, v):
// (a) Consider the relationships:
// - Center of origin cell is (512, 512)
// - +x adds (512, 512) to world pos
// - +y adds (-512, 512) to world pos
// (b) Therefore:
// - ax + by adds (a - b) * 512 + 512 to u
// - ax + by adds (a + b) * 512 + 512 to v
return new WPos(512 * (cell.X - cell.Y + 1), 512 * (cell.X + cell.Y + 1), 0);
}
public CPos CellContaining(WPos pos)
{
if (TileShape == TileShape.Rectangle)
return new CPos(pos.X / 1024, pos.Y / 1024);
// Convert from world position to diamond cell position:
// (a) Subtract (512, 512) to move the rotation center to the middle of the corner cell
// (b) Rotate axes by -pi/4
// (c) Add 512 to x (but not y) to realign the cell
// (d) Divide by 1024 to find final cell coords
var u = (pos.Y + pos.X - 512) / 1024;
var v = (pos.Y - pos.X) / 1024;
return new CPos(u, v);
}
public static CPos MapToCell(TileShape shape, CPos map)
{
if (shape == TileShape.Rectangle)
return map;
// Convert from rectangular map position to diamond cell position
// - The staggered rows make this fiddly (hint: draw a diagram!)
// (a) Consider the relationships:
// - +1u (even -> odd) adds (1, -1) to (x, y)
// - +1v (even -> odd) adds (1, 0) to (x, y)
// - +1v (odd -> even) adds (0, 1) to (x, y)
// (b) Therefore:
// - au + 2bv adds (a + b) to (x, y)
// - a correction factor is added if v is odd
var offset = (map.Y & 1) == 1 ? 1 : 0;
var y = (map.Y - offset) / 2 - map.X;
var x = map.Y - y;
return new CPos(x, y);
}
public static CPos CellToMap(TileShape shape, CPos cell)
{
if (shape == TileShape.Rectangle)
return cell;
// Convert from diamond cell (x, y) position to rectangular map position (u, v)
// - The staggered rows make this fiddly (hint: draw a diagram!)
// (a) Consider the relationships:
// - +1x (even -> odd) adds (0, 1) to (u, v)
// - +1x (odd -> even) adds (1, 1) to (u, v)
// - +1y (even -> odd) adds (-1, 1) to (u, v)
// - +1y (odd -> even) adds (0, 1) to (u, v)
// (b) Therefore:
// - ax + by adds (a - b)/2 to u (only even increments count)
// - ax + by adds a + b to v
var u = (cell.X - cell.Y) / 2;
var v = cell.X + cell.Y;
return new CPos(u, v);
}
public int FacingBetween(CPos cell, CPos towards, int fallbackfacing)
{
return Traits.Util.GetFacing(CenterOfCell(towards) - CenterOfCell(cell), fallbackfacing);
}
public void Resize(int width, int height) // editor magic.
{
var oldMapTiles = MapTiles.Value;
var oldMapResources = MapResources.Value;
var newSize = new Size(width, height);
MapTiles = Exts.Lazy(() => Exts.ResizeArray(oldMapTiles, oldMapTiles[0, 0], width, height));
MapResources = Exts.Lazy(() => Exts.ResizeArray(oldMapResources, oldMapResources[0, 0], width, height));
MapSize = new int2(width, height);
MapTiles = Exts.Lazy(() => CellLayer.Resize(oldMapTiles, newSize, oldMapTiles[0, 0]));
MapResources = Exts.Lazy(() => CellLayer.Resize(oldMapResources, newSize, oldMapResources[0, 0]));
MapSize = new int2(newSize);
}
public void ResizeCordon(int left, int top, int right, int bottom)
{
Bounds = Rectangle.FromLTRB(left, top, right, bottom);
var tl = Map.MapToCell(TileShape, new CPos(Bounds.Left, Bounds.Top));
var br = Map.MapToCell(TileShape, new CPos(Bounds.Right - 1, Bounds.Bottom - 1));
Cells = new CellRegion(TileShape, tl, br);
}
string ComputeHash()
@@ -517,19 +636,138 @@ namespace OpenRA
{
for (var i = Bounds.Left; i < Bounds.Right; i++)
{
var tr = MapTiles.Value[i, j];
if (!tileset.Templates.ContainsKey(tr.Type))
var cell = new CPos(i, j);
var type = MapTiles.Value[cell].Type;
var index = MapTiles.Value[cell].Index;
if (!tileset.Templates.ContainsKey(type))
{
Console.WriteLine("Unknown Tile ID {0}".F(tr.Type));
Console.WriteLine("Unknown Tile ID {0}".F(type));
continue;
}
var template = tileset.Templates[tr.Type];
var template = tileset.Templates[type];
if (!template.PickAny)
continue;
tr.Index = (byte)r.Next(0, template.Tiles.Count);
MapTiles.Value[i, j] = tr;
index = (byte)r.Next(0, template.TilesCount);
MapTiles.Value[cell] = new TerrainTile(type, index);
}
}
}
public int GetTerrainIndex(CPos cell)
{
var custom = CustomTerrain[cell];
return custom != -1 ? custom : cachedTileSet.Value.GetTerrainIndex(MapTiles.Value[cell]);
}
public TerrainTypeInfo GetTerrainInfo(CPos cell)
{
return cachedTileSet.Value[GetTerrainIndex(cell)];
}
public CPos Clamp(CPos cell)
{
var bounds = new Rectangle(Bounds.X, Bounds.Y, Bounds.Width - 1, Bounds.Height - 1);
return MapToCell(TileShape, CellToMap(TileShape, cell).Clamp(bounds));
}
public CPos ChooseRandomCell(MersenneTwister rand)
{
var x = rand.Next(Bounds.Left, Bounds.Right);
var y = rand.Next(Bounds.Top, Bounds.Bottom);
return MapToCell(TileShape, new CPos(x, y));
}
public CPos ChooseRandomEdgeCell(MersenneTwister rand)
{
var isX = rand.Next(2) == 0;
var edge = rand.Next(2) == 0;
var x = isX ? rand.Next(Bounds.Left, Bounds.Right) : (edge ? Bounds.Left : Bounds.Right);
var y = !isX ? rand.Next(Bounds.Top, Bounds.Bottom) : (edge ? Bounds.Top : Bounds.Bottom);
return MapToCell(TileShape, new CPos(x, y));
}
public WRange DistanceToEdge(WPos pos, WVec dir)
{
var tl = CenterOfCell(Cells.TopLeft) - new WVec(512, 512, 0);
var br = CenterOfCell(Cells.BottomRight) + new WVec(511, 511, 0);
var x = dir.X == 0 ? int.MaxValue : ((dir.X < 0 ? tl.X : br.X) - pos.X) / dir.X;
var y = dir.Y == 0 ? int.MaxValue : ((dir.Y < 0 ? tl.Y : br.Y) - pos.Y) / dir.Y;
return new WRange(Math.Min(x, y) * dir.Length);
}
public const int MaxTilesInCircleRange = 50;
static CVec[][] TilesByDistance = InitTilesByDistance(MaxTilesInCircleRange);
static CVec[][] InitTilesByDistance(int max)
{
var ts = new List<CVec>[max + 1];
for (var i = 0; i < max + 1; i++)
ts [i] = new List<CVec>();
for (var j = -max; j <= max; j++)
for (var i = -max; i <= max; i++)
if (max * max >= i * i + j * j)
ts [Exts.ISqrt(i * i + j * j, Exts.ISqrtRoundMode.Ceiling)].Add(new CVec(i, j));
// Sort each integer-distance group by the actual distance
foreach (var list in ts)
{
list.Sort((a, b) =>
{
var result = a.LengthSquared.CompareTo(b.LengthSquared);
if (result != 0)
return result;
// If the lengths are equal, use other means to sort them.
// Try the hashcode first because it gives more
// random-appearing results than X or Y that would always
// prefer the leftmost/topmost position.
result = a.GetHashCode().CompareTo(b.GetHashCode());
if (result != 0)
return result;
result = a.X.CompareTo(b.X);
if (result != 0)
return result;
return a.Y.CompareTo(b.Y);
});
}
return ts.Select(list => list.ToArray()).ToArray();
}
// Both ranges are inclusive because everything that calls it is designed for maxRange being inclusive:
// it rounds the actual distance up to the next integer so that this call
// will return any cells that intersect with the requested range circle.
// The returned positions are sorted by distance from the center.
public IEnumerable<CPos> FindTilesInAnnulus(CPos center, int minRange, int maxRange)
{
if (maxRange < minRange)
throw new ArgumentOutOfRangeException("maxRange", "Maximum range is less than the minimum range.");
if (maxRange > TilesByDistance.Length)
throw new ArgumentOutOfRangeException("maxRange", "The requested range ({0}) exceeds the maximum allowed ({1})".F(maxRange, MaxTilesInCircleRange));
for (var i = minRange; i <= maxRange; i++)
{
foreach (var offset in TilesByDistance[i])
{
var t = offset + center;
if (Contains(t))
yield return t;
}
}
}
public IEnumerable<CPos> FindTilesInCircle(CPos center, int maxRange)
{
return FindTilesInAnnulus(center, 0, maxRange);
}
}
}

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