From cad46e43c5f5191eefd3f625d8cb11f0176138f6 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Fri, 27 Sep 2013 15:20:49 +1200 Subject: [PATCH 1/7] Add WorldRenderer parameter to WorldLoaded. --- OpenRA.Game/Game.cs | 5 ++++- OpenRA.Game/Traits/TraitsInterfaces.cs | 2 +- OpenRA.Game/Traits/World/ResourceLayer.cs | 2 +- OpenRA.Game/World.cs | 6 +++++- OpenRA.Mods.Cnc/Missions/CncShellmapScript.cs | 3 ++- OpenRA.Mods.Cnc/Missions/Gdi01Script.cs | 3 ++- OpenRA.Mods.Cnc/Missions/Nod01Script.cs | 3 ++- OpenRA.Mods.RA/BridgeLayer.cs | 3 ++- OpenRA.Mods.RA/LoadWidgetAtGameStart.cs | 3 ++- OpenRA.Mods.RA/MPStartLocations.cs | 3 ++- OpenRA.Mods.RA/Missions/Allies01Script.cs | 3 ++- OpenRA.Mods.RA/Missions/Allies02Script.cs | 5 +++-- OpenRA.Mods.RA/Missions/Allies03Script.cs | 5 +++-- OpenRA.Mods.RA/Missions/Allies04Script.cs | 3 ++- OpenRA.Mods.RA/Missions/DefaultShellmapScript.cs | 3 ++- OpenRA.Mods.RA/Missions/DesertShellmapScript.cs | 13 +++++++------ OpenRA.Mods.RA/Missions/FortLonestarScript.cs | 3 ++- OpenRA.Mods.RA/Missions/MonsterTankMadnessScript.cs | 7 ++++--- OpenRA.Mods.RA/Missions/Soviet01ClassicScript.cs | 5 +++-- OpenRA.Mods.RA/Missions/Survival01Script.cs | 3 ++- OpenRA.Mods.RA/Missions/Survival02Script.cs | 3 ++- OpenRA.Mods.RA/SpawnMPUnits.cs | 3 ++- OpenRA.Mods.RA/SpawnMapActors.cs | 3 ++- OpenRA.Mods.RA/World/DebugOverlay.cs | 2 +- OpenRA.Mods.RA/World/DomainIndex.cs | 3 ++- OpenRA.Mods.RA/World/PlayMusicOnMapLoad.cs | 3 ++- OpenRA.Mods.RA/World/ResourceClaimLayer.cs | 3 ++- OpenRA.Mods.RA/World/SmudgeLayer.cs | 2 +- 28 files changed, 67 insertions(+), 38 deletions(-) diff --git a/OpenRA.Game/Game.cs b/OpenRA.Game/Game.cs index 5e76423425..825f73af25 100644 --- a/OpenRA.Game/Game.cs +++ b/OpenRA.Game/Game.cs @@ -213,8 +213,11 @@ namespace OpenRA viewport = new Viewport(new int2(Renderer.Resolution), map.Bounds, Renderer); orderManager.world = new World(modData.Manifest, map, orderManager, isShellmap); worldRenderer = new WorldRenderer(orderManager.world); + orderManager.world.LoadComplete(worldRenderer); + + if (orderManager.GameStarted) + return; - if (orderManager.GameStarted) return; Ui.MouseFocusWidget = null; Ui.KeyboardFocusWidget = null; diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index 62cb04cb45..63863d7847 100755 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -174,7 +174,7 @@ namespace OpenRA.Traits public interface UsesInit where T : IActorInit { } public interface INotifySelection { void SelectionChanged(); } - public interface IWorldLoaded { void WorldLoaded(World w); } + public interface IWorldLoaded { void WorldLoaded(World w, WorldRenderer wr); } public interface ICreatePlayers { void CreatePlayers(World w); } public interface IBotInfo { string Name { get; } } diff --git a/OpenRA.Game/Traits/World/ResourceLayer.cs b/OpenRA.Game/Traits/World/ResourceLayer.cs index 8994a17a62..7f44e87ab5 100644 --- a/OpenRA.Game/Traits/World/ResourceLayer.cs +++ b/OpenRA.Game/Traits/World/ResourceLayer.cs @@ -57,7 +57,7 @@ namespace OpenRA.Traits } } - public void WorldLoaded(World w) + public void WorldLoaded(World w, WorldRenderer wr) { this.world = w; content = new CellContents[w.Map.MapSize.X, w.Map.MapSize.Y]; diff --git a/OpenRA.Game/World.cs b/OpenRA.Game/World.cs index 8934ba0c3e..a2288f7a3f 100644 --- a/OpenRA.Game/World.cs +++ b/OpenRA.Game/World.cs @@ -135,8 +135,12 @@ namespace OpenRA p.Stances[q] = Stance.Neutral; Sound.SoundVolumeModifier = 1.0f; + } + + public void LoadComplete(WorldRenderer wr) + { foreach (var wlh in WorldActor.TraitsImplementing()) - wlh.WorldLoaded(this); + wlh.WorldLoaded(this, wr); } public Actor CreateActor( string name, TypeDictionary initDict ) diff --git a/OpenRA.Mods.Cnc/Missions/CncShellmapScript.cs b/OpenRA.Mods.Cnc/Missions/CncShellmapScript.cs index c56c0dd91f..5e2e1041c5 100755 --- a/OpenRA.Mods.Cnc/Missions/CncShellmapScript.cs +++ b/OpenRA.Mods.Cnc/Missions/CncShellmapScript.cs @@ -11,6 +11,7 @@ using System; using System.Collections.Generic; using OpenRA.FileFormats; +using OpenRA.Graphics; using OpenRA.Mods.RA.Activities; using OpenRA.Mods.RA.Move; using OpenRA.Traits; @@ -24,7 +25,7 @@ namespace OpenRA.Mods.RA static CPos viewportOrigin; Dictionary actors; - public void WorldLoaded(World w) + public void WorldLoaded(World w, WorldRenderer wr) { var b = w.Map.Bounds; viewportOrigin = new CPos(b.Left + b.Width / 2, b.Top + b.Height / 2); diff --git a/OpenRA.Mods.Cnc/Missions/Gdi01Script.cs b/OpenRA.Mods.Cnc/Missions/Gdi01Script.cs index 6261f6689a..627f4224eb 100644 --- a/OpenRA.Mods.Cnc/Missions/Gdi01Script.cs +++ b/OpenRA.Mods.Cnc/Missions/Gdi01Script.cs @@ -12,6 +12,7 @@ using System; using System.Collections.Generic; using System.Linq; using OpenRA.FileFormats; +using OpenRA.Graphics; using OpenRA.Mods.RA; using OpenRA.Mods.RA.Activities; using OpenRA.Mods.RA.Move; @@ -28,7 +29,7 @@ namespace OpenRA.Mods.Cnc.Missions Dictionary actors; Dictionary players; - public void WorldLoaded(World w) + public void WorldLoaded(World w, WorldRenderer wr) { players = w.Players.ToDictionary(p => p.InternalName); actors = w.WorldActor.Trait().Actors; diff --git a/OpenRA.Mods.Cnc/Missions/Nod01Script.cs b/OpenRA.Mods.Cnc/Missions/Nod01Script.cs index be8b23def6..607acb2a16 100644 --- a/OpenRA.Mods.Cnc/Missions/Nod01Script.cs +++ b/OpenRA.Mods.Cnc/Missions/Nod01Script.cs @@ -12,6 +12,7 @@ using System; using System.Collections.Generic; using System.Linq; using OpenRA.FileFormats; +using OpenRA.Graphics; using OpenRA.Mods.Cnc; using OpenRA.Mods.RA; using OpenRA.Mods.RA.Activities; @@ -162,7 +163,7 @@ namespace OpenRA.Mods.Cnc.Missions nr3.QueueActivity(nr3.Trait().ScriptedMove(nr3.Location - new CVec(0, -5))); } - public void WorldLoaded(World w) + public void WorldLoaded(World w, WorldRenderer wr) { world = w; nod = w.Players.Single(p => p.InternalName == "NOD"); diff --git a/OpenRA.Mods.RA/BridgeLayer.cs b/OpenRA.Mods.RA/BridgeLayer.cs index 5ef0ca2bdc..8711c9de9b 100644 --- a/OpenRA.Mods.RA/BridgeLayer.cs +++ b/OpenRA.Mods.RA/BridgeLayer.cs @@ -11,6 +11,7 @@ using System.Collections.Generic; using System.Linq; using OpenRA.FileFormats; +using OpenRA.Graphics; using OpenRA.Traits; namespace OpenRA.Mods.RA @@ -36,7 +37,7 @@ namespace OpenRA.Mods.RA this.world = self.World; } - public void WorldLoaded(World w) + public void WorldLoaded(World w, WorldRenderer wr) { Bridges = new Bridge[w.Map.MapSize.X, w.Map.MapSize.Y]; diff --git a/OpenRA.Mods.RA/LoadWidgetAtGameStart.cs b/OpenRA.Mods.RA/LoadWidgetAtGameStart.cs index d284e4532d..cb387d7e57 100644 --- a/OpenRA.Mods.RA/LoadWidgetAtGameStart.cs +++ b/OpenRA.Mods.RA/LoadWidgetAtGameStart.cs @@ -8,6 +8,7 @@ */ #endregion +using OpenRA.Graphics; using OpenRA.Traits; using OpenRA.Widgets; @@ -28,7 +29,7 @@ namespace OpenRA.Mods.RA this.Info = Info; } - public void WorldLoaded(World world) + public void WorldLoaded(World world, WorldRenderer wr) { // Clear any existing widget state if (Info.ClearRoot) diff --git a/OpenRA.Mods.RA/MPStartLocations.cs b/OpenRA.Mods.RA/MPStartLocations.cs index a64af630f4..2597fce1ad 100755 --- a/OpenRA.Mods.RA/MPStartLocations.cs +++ b/OpenRA.Mods.RA/MPStartLocations.cs @@ -12,6 +12,7 @@ using System; using System.Collections.Generic; using System.Linq; using OpenRA.FileFormats; +using OpenRA.Graphics; using OpenRA.Network; using OpenRA.Traits; @@ -26,7 +27,7 @@ namespace OpenRA.Mods.RA { public Dictionary Start = new Dictionary(); - public void WorldLoaded(World world) + public void WorldLoaded(World world, WorldRenderer wr) { var taken = world.LobbyInfo.Clients.Where(c => c.SpawnPoint != 0 && c.Slot != null) .Select(c => (CPos) world.Map.GetSpawnPoints()[c.SpawnPoint-1]).ToList(); diff --git a/OpenRA.Mods.RA/Missions/Allies01Script.cs b/OpenRA.Mods.RA/Missions/Allies01Script.cs index 789e7c40ed..4f80c447f6 100644 --- a/OpenRA.Mods.RA/Missions/Allies01Script.cs +++ b/OpenRA.Mods.RA/Missions/Allies01Script.cs @@ -12,6 +12,7 @@ using System; using System.Collections.Generic; using System.Linq; using OpenRA.FileFormats; +using OpenRA.Graphics; using OpenRA.Mods.RA.Activities; using OpenRA.Mods.RA.Air; using OpenRA.Mods.RA.Move; @@ -274,7 +275,7 @@ namespace OpenRA.Mods.RA.Missions actor.Trait().stance = UnitStance.Defend; } - public void WorldLoaded(World w) + public void WorldLoaded(World w, WorldRenderer wr) { world = w; diff --git a/OpenRA.Mods.RA/Missions/Allies02Script.cs b/OpenRA.Mods.RA/Missions/Allies02Script.cs index fcd455985f..5a281de234 100644 --- a/OpenRA.Mods.RA/Missions/Allies02Script.cs +++ b/OpenRA.Mods.RA/Missions/Allies02Script.cs @@ -12,6 +12,7 @@ using System; using System.Collections.Generic; using System.Linq; using OpenRA.FileFormats; +using OpenRA.Graphics; using OpenRA.Mods.RA.Activities; using OpenRA.Mods.RA.Air; using OpenRA.Mods.RA.Buildings; @@ -270,7 +271,7 @@ namespace OpenRA.Mods.RA.Missions { new LocationInit(yakEntryPoint.Location), new OwnerInit(soviets), - new FacingInit(Util.GetFacing(yakAttackPoint.Location - yakEntryPoint.Location, 0)), + new FacingInit(Traits.Util.GetFacing(yakAttackPoint.Location - yakEntryPoint.Location, 0)), new AltitudeInit(Rules.Info[YakName].Traits.Get().CruiseAltitude) }); } @@ -405,7 +406,7 @@ namespace OpenRA.Mods.RA.Missions unit.QueueActivity(new AttackMove.AttackMoveActivity(unit, new Move.Move(townPoint.Location, SovietTownMoveNearEnough))); } - public void WorldLoaded(World w) + public void WorldLoaded(World w, WorldRenderer wr) { world = w; diff --git a/OpenRA.Mods.RA/Missions/Allies03Script.cs b/OpenRA.Mods.RA/Missions/Allies03Script.cs index 9bebeabf7c..b471b023d3 100644 --- a/OpenRA.Mods.RA/Missions/Allies03Script.cs +++ b/OpenRA.Mods.RA/Missions/Allies03Script.cs @@ -13,6 +13,7 @@ using System.Collections.Generic; using System.Drawing; using System.Linq; using OpenRA.FileFormats; +using OpenRA.Graphics; using OpenRA.Mods.RA.Activities; using OpenRA.Mods.RA.Air; using OpenRA.Mods.RA.Buildings; @@ -335,7 +336,7 @@ namespace OpenRA.Mods.RA.Missions { new OwnerInit(owner), new LocationInit(entry), - new FacingInit(Util.GetFacing(to - entry, 0)) + new FacingInit(Traits.Util.GetFacing(to - entry, 0)) }); unit.QueueActivity(new Move.Move(to)); return unit; @@ -380,7 +381,7 @@ namespace OpenRA.Mods.RA.Missions } } - public void WorldLoaded(World w) + public void WorldLoaded(World w, WorldRenderer wr) { world = w; diff --git a/OpenRA.Mods.RA/Missions/Allies04Script.cs b/OpenRA.Mods.RA/Missions/Allies04Script.cs index 173d461f2a..b880170720 100644 --- a/OpenRA.Mods.RA/Missions/Allies04Script.cs +++ b/OpenRA.Mods.RA/Missions/Allies04Script.cs @@ -13,6 +13,7 @@ using System.Collections.Generic; using System.Drawing; using System.Linq; using OpenRA.FileFormats; +using OpenRA.Graphics; using OpenRA.Mods.RA.Activities; using OpenRA.Mods.RA.Buildings; using OpenRA.Mods.RA.Move; @@ -350,7 +351,7 @@ namespace OpenRA.Mods.RA.Missions actor.Trait().stance = UnitStance.Defend; } - public void WorldLoaded(World w) + public void WorldLoaded(World w, WorldRenderer wr) { world = w; diff --git a/OpenRA.Mods.RA/Missions/DefaultShellmapScript.cs b/OpenRA.Mods.RA/Missions/DefaultShellmapScript.cs index 6dfbbe6371..9114b90693 100644 --- a/OpenRA.Mods.RA/Missions/DefaultShellmapScript.cs +++ b/OpenRA.Mods.RA/Missions/DefaultShellmapScript.cs @@ -11,6 +11,7 @@ using System; using System.Collections.Generic; using OpenRA.FileFormats; +using OpenRA.Graphics; using OpenRA.Mods.RA.Air; using OpenRA.Traits; @@ -23,7 +24,7 @@ namespace OpenRA.Mods.RA Dictionary Actors; static CPos ViewportOrigin; - public void WorldLoaded(World w) + public void WorldLoaded(World w, WorldRenderer wr) { var b = w.Map.Bounds; ViewportOrigin = new CPos(b.Left + b.Width/2, b.Top + b.Height/2); diff --git a/OpenRA.Mods.RA/Missions/DesertShellmapScript.cs b/OpenRA.Mods.RA/Missions/DesertShellmapScript.cs index c0e8661733..05e9d85525 100644 --- a/OpenRA.Mods.RA/Missions/DesertShellmapScript.cs +++ b/OpenRA.Mods.RA/Missions/DesertShellmapScript.cs @@ -11,6 +11,7 @@ using System.Collections.Generic; using System.Linq; using OpenRA.FileFormats; +using OpenRA.Graphics; using OpenRA.Mods.RA.Activities; using OpenRA.Mods.RA.Air; using OpenRA.Mods.RA.Buildings; @@ -90,7 +91,7 @@ namespace OpenRA.Mods.RA.Missions { var actor = OffmapAttackers.Random(world.SharedRandom); var spawn = offmapAttackerSpawns.Random(world.SharedRandom); - var u = world.CreateActor(actor, soviets, spawn.Location, Util.GetFacing(attackLocation.Location - spawn.Location, 0)); + var u = world.CreateActor(actor, soviets, spawn.Location, Traits.Util.GetFacing(attackLocation.Location - spawn.Location, 0)); var cargo = u.TraitOrDefault(); if (cargo != null) { @@ -176,7 +177,7 @@ namespace OpenRA.Mods.RA.Missions { foreach (var tank in HeavyTanks) { - var u = world.CreateActor(tank, soviets, heavyTankSpawn.Location, Util.GetFacing(heavyTankWP.Location - heavyTankSpawn.Location, 0)); + var u = world.CreateActor(tank, soviets, heavyTankSpawn.Location, Traits.Util.GetFacing(heavyTankWP.Location - heavyTankSpawn.Location, 0)); u.QueueActivity(new AttackMove.AttackMoveActivity(u, new Move.Move(heavyTankWP.Location, 0))); } ironCurtain.Trait().Activate(ironCurtain, new Order { TargetLocation = heavyTankSpawn.Location }); @@ -187,7 +188,7 @@ namespace OpenRA.Mods.RA.Missions var chronoInfo = new List>(); foreach (var tank in MediumTanks.Select((x, i) => new { x, i })) { - var u = world.CreateActor(tank.x, allies, mediumTankChronoSpawn.Location, Util.GetFacing(heavyTankWP.Location - mediumTankChronoSpawn.Location, 0)); + var u = world.CreateActor(tank.x, allies, mediumTankChronoSpawn.Location, Traits.Util.GetFacing(heavyTankWP.Location - mediumTankChronoSpawn.Location, 0)); chronoInfo.Add(Pair.New(u, new CPos(mediumTankChronoSpawn.Location.X + tank.i, mediumTankChronoSpawn.Location.Y))); } RASpecialPowers.Chronoshift(world, chronoInfo, chronosphere, -1, false); @@ -201,7 +202,7 @@ namespace OpenRA.Mods.RA.Missions { new OwnerInit(soviets), new LocationInit(waypoints[0]), - new FacingInit(Util.GetFacing(waypoints[1] - waypoints[0], 0)) + new FacingInit(Traits.Util.GetFacing(waypoints[1] - waypoints[0], 0)) }); foreach (var waypoint in waypoints) m.QueueActivity(Fly.ToCell(waypoint)); @@ -210,7 +211,7 @@ namespace OpenRA.Mods.RA.Missions void SendChinookReinforcements(CPos entry, Actor lz) { - var chinook = world.CreateActor("tran", allies, entry, Util.GetFacing(lz.Location - entry, 0)); + var chinook = world.CreateActor("tran", allies, entry, Traits.Util.GetFacing(lz.Location - entry, 0)); var cargo = chinook.Trait(); while (cargo.HasSpace(1)) @@ -234,7 +235,7 @@ namespace OpenRA.Mods.RA.Missions alliedWarFactory.Trait().SetPrimaryProducer(alliedWarFactory, true); } - public void WorldLoaded(World w) + public void WorldLoaded(World w, WorldRenderer wr) { world = w; diff --git a/OpenRA.Mods.RA/Missions/FortLonestarScript.cs b/OpenRA.Mods.RA/Missions/FortLonestarScript.cs index bc4360879a..51604bdc88 100644 --- a/OpenRA.Mods.RA/Missions/FortLonestarScript.cs +++ b/OpenRA.Mods.RA/Missions/FortLonestarScript.cs @@ -12,6 +12,7 @@ using System; using System.Drawing; using System.Linq; using OpenRA.FileFormats; +using OpenRA.Graphics; using OpenRA.Mods.RA.Activities; using OpenRA.Mods.RA.Buildings; using OpenRA.Mods.RA.Move; @@ -342,7 +343,7 @@ namespace OpenRA.Mods.RA.Missions bool SpawnVehicles = true; - public void WorldLoaded(World w) + public void WorldLoaded(World w, WorldRenderer wr) { world = w; soviets = w.Players.Single(p => p.InternalName == "Soviets"); diff --git a/OpenRA.Mods.RA/Missions/MonsterTankMadnessScript.cs b/OpenRA.Mods.RA/Missions/MonsterTankMadnessScript.cs index 6b4da0cd2d..78793f84e8 100644 --- a/OpenRA.Mods.RA/Missions/MonsterTankMadnessScript.cs +++ b/OpenRA.Mods.RA/Missions/MonsterTankMadnessScript.cs @@ -11,6 +11,7 @@ using System; using System.Collections.Generic; using System.Linq; +using OpenRA.Graphics; using OpenRA.Mods.RA.Activities; using OpenRA.Mods.RA.Buildings; using OpenRA.Mods.RA.Move; @@ -258,7 +259,7 @@ namespace OpenRA.Mods.RA.Missions { Sound.Play("reinfor1.aud"); foreach (var unit in units) - world.CreateActor(unit, greece, startEntryPoint.Location, Util.GetFacing(startBridgeEndPoint.CenterPosition - startEntryPoint.CenterPosition, 0)) + world.CreateActor(unit, greece, startEntryPoint.Location, Traits.Util.GetFacing(startBridgeEndPoint.CenterPosition - startEntryPoint.CenterPosition, 0)) .QueueActivity(new Move.Move(startMovePoint.Location, 0)); } @@ -266,7 +267,7 @@ namespace OpenRA.Mods.RA.Missions { Sound.Play("reinfor1.aud"); foreach (var unit in units) - world.CreateActor(unit, greece, alliedBaseEntryPoint.Location, Util.GetFacing(alliedBaseMovePoint.CenterPosition - alliedBaseEntryPoint.CenterPosition, 0)) + world.CreateActor(unit, greece, alliedBaseEntryPoint.Location, Traits.Util.GetFacing(alliedBaseMovePoint.CenterPosition - alliedBaseEntryPoint.CenterPosition, 0)) .QueueActivity(new Move.Move(alliedBaseMovePoint.Location, 0)); } @@ -294,7 +295,7 @@ namespace OpenRA.Mods.RA.Missions OnObjectivesUpdated(true); } - public void WorldLoaded(World w) + public void WorldLoaded(World w, WorldRenderer wr) { world = w; diff --git a/OpenRA.Mods.RA/Missions/Soviet01ClassicScript.cs b/OpenRA.Mods.RA/Missions/Soviet01ClassicScript.cs index b910b948e9..257221e235 100644 --- a/OpenRA.Mods.RA/Missions/Soviet01ClassicScript.cs +++ b/OpenRA.Mods.RA/Missions/Soviet01ClassicScript.cs @@ -12,6 +12,7 @@ using System; using System.Collections.Generic; using System.Linq; using OpenRA.FileFormats; +using OpenRA.Graphics; using OpenRA.Mods.RA.Activities; using OpenRA.Mods.RA.Air; using OpenRA.Mods.RA.Buildings; @@ -107,7 +108,7 @@ namespace OpenRA.Mods.RA.Missions { new OwnerInit(ussr), new LocationInit(entry), - new FacingInit(Util.GetFacing(airfield.Location - entry, 0)), + new FacingInit(Traits.Util.GetFacing(airfield.Location - entry, 0)), new AltitudeInit(Rules.Info["yak"].Traits.Get().CruiseAltitude) }); @@ -133,7 +134,7 @@ namespace OpenRA.Mods.RA.Missions })); } - public void WorldLoaded(World w) + public void WorldLoaded(World w, WorldRenderer wr) { world = w; diff --git a/OpenRA.Mods.RA/Missions/Survival01Script.cs b/OpenRA.Mods.RA/Missions/Survival01Script.cs index 4a77635de2..f4365ead65 100644 --- a/OpenRA.Mods.RA/Missions/Survival01Script.cs +++ b/OpenRA.Mods.RA/Missions/Survival01Script.cs @@ -12,6 +12,7 @@ using System; using System.Collections.Generic; using System.Linq; using OpenRA.FileFormats; +using OpenRA.Graphics; using OpenRA.Mods.RA.Activities; using OpenRA.Mods.RA.Buildings; using OpenRA.Mods.RA.Move; @@ -271,7 +272,7 @@ namespace OpenRA.Mods.RA.Missions OnObjectivesUpdated(true); } - public void WorldLoaded(World w) + public void WorldLoaded(World w, WorldRenderer wr) { world = w; diff --git a/OpenRA.Mods.RA/Missions/Survival02Script.cs b/OpenRA.Mods.RA/Missions/Survival02Script.cs index 47b54ab47b..d8180c21ab 100644 --- a/OpenRA.Mods.RA/Missions/Survival02Script.cs +++ b/OpenRA.Mods.RA/Missions/Survival02Script.cs @@ -13,6 +13,7 @@ using System.Linq; using System; using System.Drawing; using OpenRA.FileFormats; +using OpenRA.Graphics; using OpenRA.Mods.RA.Activities; using OpenRA.Mods.RA.Move; using OpenRA.Traits; @@ -351,7 +352,7 @@ namespace OpenRA.Mods.RA.Missions bool producing = true; - public void WorldLoaded(World w) + public void WorldLoaded(World w, WorldRenderer wr) { world = w; allies = w.Players.SingleOrDefault(p => p.InternalName == "Allies"); diff --git a/OpenRA.Mods.RA/SpawnMPUnits.cs b/OpenRA.Mods.RA/SpawnMPUnits.cs index e7c093b591..e824df78a6 100644 --- a/OpenRA.Mods.RA/SpawnMPUnits.cs +++ b/OpenRA.Mods.RA/SpawnMPUnits.cs @@ -12,6 +12,7 @@ using System; using System.Linq; using OpenRA.FileFormats; +using OpenRA.Graphics; using OpenRA.Mods.RA.Move; using OpenRA.Traits; @@ -21,7 +22,7 @@ namespace OpenRA.Mods.RA public class SpawnMPUnits : IWorldLoaded { - public void WorldLoaded(World world) + public void WorldLoaded(World world, WorldRenderer wr) { foreach (var s in world.WorldActor.Trait().Start) SpawnUnitsForPlayer(world, s.Key, s.Value); diff --git a/OpenRA.Mods.RA/SpawnMapActors.cs b/OpenRA.Mods.RA/SpawnMapActors.cs index 2d116499f4..5999564846 100644 --- a/OpenRA.Mods.RA/SpawnMapActors.cs +++ b/OpenRA.Mods.RA/SpawnMapActors.cs @@ -10,6 +10,7 @@ using System.Collections.Generic; using System.Linq; +using OpenRA.Graphics; using OpenRA.Traits; namespace OpenRA.Mods.RA @@ -20,7 +21,7 @@ namespace OpenRA.Mods.RA { public Dictionary Actors = new Dictionary(); - public void WorldLoaded(World world) + public void WorldLoaded(World world, WorldRenderer wr) { foreach (var actorReference in world.Map.Actors.Value) { diff --git a/OpenRA.Mods.RA/World/DebugOverlay.cs b/OpenRA.Mods.RA/World/DebugOverlay.cs index 9afb185bc9..729a953f6a 100644 --- a/OpenRA.Mods.RA/World/DebugOverlay.cs +++ b/OpenRA.Mods.RA/World/DebugOverlay.cs @@ -20,7 +20,7 @@ namespace OpenRA.Mods.RA World world; public bool Visible; - public void WorldLoaded(World w) + public void WorldLoaded(World w, WorldRenderer wr) { this.world = w; this.refreshTick = 0; diff --git a/OpenRA.Mods.RA/World/DomainIndex.cs b/OpenRA.Mods.RA/World/DomainIndex.cs index 72551e1374..d5490afd15 100644 --- a/OpenRA.Mods.RA/World/DomainIndex.cs +++ b/OpenRA.Mods.RA/World/DomainIndex.cs @@ -14,6 +14,7 @@ using System.Drawing; using System.Linq; using OpenRA.FileFormats; +using OpenRA.Graphics; using OpenRA.Mods.RA.Move; using OpenRA.Support; using OpenRA.Traits; @@ -27,7 +28,7 @@ namespace OpenRA.Mods.RA { Dictionary domainIndexes; - public void WorldLoaded(World world) + public void WorldLoaded(World world, WorldRenderer wr) { domainIndexes = new Dictionary(); var movementClasses = new HashSet( diff --git a/OpenRA.Mods.RA/World/PlayMusicOnMapLoad.cs b/OpenRA.Mods.RA/World/PlayMusicOnMapLoad.cs index b9c0669ad3..fe60262301 100644 --- a/OpenRA.Mods.RA/World/PlayMusicOnMapLoad.cs +++ b/OpenRA.Mods.RA/World/PlayMusicOnMapLoad.cs @@ -11,6 +11,7 @@ using System; using System.Collections.Generic; using OpenRA.FileFormats; +using OpenRA.Graphics; using OpenRA.Traits; using OpenRA.Widgets; @@ -30,7 +31,7 @@ namespace OpenRA.Mods.RA public PlayMusicOnMapLoad(PlayMusicOnMapLoadInfo info) { Info = info; } - public void WorldLoaded(World w) { PlayMusic(); } + public void WorldLoaded(World w, WorldRenderer wr) { PlayMusic(); } void PlayMusic() { diff --git a/OpenRA.Mods.RA/World/ResourceClaimLayer.cs b/OpenRA.Mods.RA/World/ResourceClaimLayer.cs index 1228f7b67d..80e1aaf7dd 100644 --- a/OpenRA.Mods.RA/World/ResourceClaimLayer.cs +++ b/OpenRA.Mods.RA/World/ResourceClaimLayer.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using OpenRA.Graphics; using OpenRA.Traits; namespace OpenRA.Mods.RA @@ -34,7 +35,7 @@ namespace OpenRA.Mods.RA } } - public void WorldLoaded(OpenRA.World w) + public void WorldLoaded(OpenRA.World w, WorldRenderer wr) { // NOTE(jsd): 32 seems a sane default initial capacity for the total # of harvesters in a game. Purely a guesstimate. claimByCell = new Dictionary(32); diff --git a/OpenRA.Mods.RA/World/SmudgeLayer.cs b/OpenRA.Mods.RA/World/SmudgeLayer.cs index dda25e7a34..f70e3313eb 100644 --- a/OpenRA.Mods.RA/World/SmudgeLayer.cs +++ b/OpenRA.Mods.RA/World/SmudgeLayer.cs @@ -43,7 +43,7 @@ namespace OpenRA.Mods.RA smudgeSprites = Info.Types.Select(x => Game.modData.SpriteLoader.LoadAllSprites(x)).ToArray(); } - public void WorldLoaded(World w) + public void WorldLoaded(World w, WorldRenderer wr) { world = w; tiles = new Dictionary>(); From dfd51c0caae05c525f71d7515ce83b3e6309d606 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 21 Sep 2013 13:39:39 +1200 Subject: [PATCH 2/7] Introduce ScreenMap trait for caching screen-coord queries. --- OpenRA.Game/Graphics/WorldRenderer.cs | 9 +- OpenRA.Game/OpenRA.Game.csproj | 1 + OpenRA.Game/Orders/UnitOrderGenerator.cs | 11 +- OpenRA.Game/Traits/Player/FrozenActorLayer.cs | 40 +---- OpenRA.Game/Traits/Waypoint.cs | 12 +- OpenRA.Game/Traits/World/ScreenMap.cs | 137 ++++++++++++++++++ .../Widgets/ViewportControllerWidget.cs | 4 +- .../WorldInteractionControllerWidget.cs | 4 +- OpenRA.Game/World.cs | 4 +- OpenRA.Game/WorldUtils.cs | 22 +-- OpenRA.Mods.RA/Air/Aircraft.cs | 23 ++- OpenRA.Mods.RA/Buildings/Building.cs | 12 +- OpenRA.Mods.RA/Crate.cs | 15 +- OpenRA.Mods.RA/Guard.cs | 22 +-- OpenRA.Mods.RA/Husk.cs | 19 ++- OpenRA.Mods.RA/Mine.cs | 12 +- OpenRA.Mods.RA/Minelayer.cs | 3 +- OpenRA.Mods.RA/Move/Mobile.cs | 14 +- .../Orders/PowerDownOrderGenerator.cs | 5 +- OpenRA.Mods.RA/Orders/RepairOrderGenerator.cs | 4 +- mods/cnc/rules/system.yaml | 1 + mods/d2k/rules/system.yaml | 1 + mods/ra/rules/system.yaml | 1 + mods/ts/rules/system.yaml | 1 + 24 files changed, 281 insertions(+), 96 deletions(-) create mode 100755 OpenRA.Game/Traits/World/ScreenMap.cs diff --git a/OpenRA.Game/Graphics/WorldRenderer.cs b/OpenRA.Game/Graphics/WorldRenderer.cs index ea6b61a1d0..65c989d36a 100644 --- a/OpenRA.Game/Graphics/WorldRenderer.cs +++ b/OpenRA.Game/Graphics/WorldRenderer.cs @@ -73,12 +73,11 @@ namespace OpenRA.Graphics List GenerateRenderables() { - var bounds = Game.viewport.WorldBounds(world); var comparer = new RenderableComparer(this); - - var tl = bounds.TopLeftAsCPos(); - var br = bounds.BottomRightAsCPos(); - var actors = world.FindActorsInBox(tl, br) + var vb = Game.viewport.ViewBounds(world); + var tl = Game.viewport.ViewToWorldPx(new int2(vb.Left, vb.Top)).ToInt2(); + var br = Game.viewport.ViewToWorldPx(new int2(vb.Right, vb.Bottom)).ToInt2(); + var actors = world.ScreenMap.ActorsInBox(tl, br) .Append(world.WorldActor) .ToList(); diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj index f4846fecb7..5e339a3f97 100644 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -238,6 +238,7 @@ + diff --git a/OpenRA.Game/Orders/UnitOrderGenerator.cs b/OpenRA.Game/Orders/UnitOrderGenerator.cs index af8e2c5bad..f405c6a7f3 100644 --- a/OpenRA.Game/Orders/UnitOrderGenerator.cs +++ b/OpenRA.Game/Orders/UnitOrderGenerator.cs @@ -19,8 +19,8 @@ namespace OpenRA.Orders { public IEnumerable Order(World world, CPos xy, MouseInput mi) { - var underCursor = world.FindUnitsAtMouse(mi.Location) - .Where(a => a.HasTrait()) + var underCursor = world.ScreenMap.ActorsAt(Game.viewport.ViewToWorldPx(mi.Location)) + .Where(a => !world.FogObscures(a) && a.HasTrait()) .OrderByDescending(a => a.Info.SelectionPriority()) .FirstOrDefault(); @@ -59,10 +59,9 @@ namespace OpenRA.Orders public string GetCursor(World world, CPos xy, MouseInput mi) { - bool useSelect = false; - - var underCursor = world.FindUnitsAtMouse(mi.Location) - .Where(a => a.HasTrait()) + var useSelect = false; + var underCursor = world.ScreenMap.ActorsAt(Game.viewport.ViewToWorldPx(mi.Location)) + .Where(a => !world.FogObscures(a) && a.HasTrait()) .OrderByDescending(a => a.Info.SelectionPriority()) .FirstOrDefault(); diff --git a/OpenRA.Game/Traits/Player/FrozenActorLayer.cs b/OpenRA.Game/Traits/Player/FrozenActorLayer.cs index 20521cd096..9cb594ca35 100755 --- a/OpenRA.Game/Traits/Player/FrozenActorLayer.cs +++ b/OpenRA.Game/Traits/Player/FrozenActorLayer.cs @@ -20,10 +20,7 @@ namespace OpenRA.Traits { public class FrozenActorLayerInfo : ITraitInfo { - [Desc("Size of partition bins (screen pixels)")] - public readonly int BinSize = 250; - - public object Create(ActorInitializer init) { return new FrozenActorLayer(init.world, this); } + public object Create(ActorInitializer init) { return new FrozenActorLayer(init.self); } } public class FrozenActor @@ -98,34 +95,21 @@ namespace OpenRA.Traits [Sync] public int VisibilityHash; [Sync] public int FrozenHash; - readonly FrozenActorLayerInfo info; + readonly World world; + readonly Player owner; Dictionary frozen; - List[,] bins; - public FrozenActorLayer(World world, FrozenActorLayerInfo info) + public FrozenActorLayer(Actor self) { - this.info = info; + world = self.World; + owner = self.Owner; frozen = new Dictionary(); - bins = new List[ - world.Map.MapSize.X * Game.CellSize / info.BinSize, - world.Map.MapSize.Y * Game.CellSize / info.BinSize]; - - for (var j = 0; j <= bins.GetUpperBound(1); j++) - for (var i = 0; i <= bins.GetUpperBound(0); i++) - bins[i, j] = new List(); } public void Add(FrozenActor fa) { frozen.Add(fa.ID, fa); - - var top = (int)Math.Max(0, fa.Bounds.Top / info.BinSize); - var left = (int)Math.Max(0, fa.Bounds.Left / info.BinSize); - var bottom = (int)Math.Min(bins.GetUpperBound(1), fa.Bounds.Bottom / info.BinSize); - var right = (int)Math.Min(bins.GetUpperBound(0), fa.Bounds.Right / info.BinSize); - for (var j = top; j <= bottom; j++) - for (var i = left; i <= right; i++) - bins[i, j].Add(fa); + world.ScreenMap.Add(owner, fa); } public void Tick(Actor self) @@ -148,8 +132,7 @@ namespace OpenRA.Traits foreach (var r in remove) { - foreach (var bin in bins) - bin.Remove(frozen[r]); + world.ScreenMap.Remove(owner, frozen[r]); frozen.Remove(r); } } @@ -161,13 +144,6 @@ namespace OpenRA.Traits .SelectMany(ff => ff.Render(wr)); } - public IEnumerable FrozenActorsAt(int2 pxPos) - { - var x = (pxPos.X / info.BinSize).Clamp(0, bins.GetUpperBound(0)); - var y = (pxPos.Y / info.BinSize).Clamp(0, bins.GetUpperBound(1)); - return bins[x, y].Where(p => p.Bounds.Contains(pxPos) && p.IsValid); - } - public FrozenActor FromID(uint id) { FrozenActor ret; diff --git a/OpenRA.Game/Traits/Waypoint.cs b/OpenRA.Game/Traits/Waypoint.cs index 2ea8e2a381..2e129bbf06 100644 --- a/OpenRA.Game/Traits/Waypoint.cs +++ b/OpenRA.Game/Traits/Waypoint.cs @@ -18,7 +18,7 @@ namespace OpenRA.Traits public object Create( ActorInitializer init ) { return new Waypoint( init ); } } - class Waypoint : IOccupySpace, ISync + class Waypoint : IOccupySpace, ISync, INotifyAddedToWorld, INotifyRemovedFromWorld { [Sync] CPos location; @@ -30,5 +30,15 @@ namespace OpenRA.Traits public CPos TopLeft { get { return location; } } public IEnumerable> OccupiedCells() { yield break; } public WPos CenterPosition { get { return location.CenterPosition; } } + + public void AddedToWorld(Actor self) + { + self.World.ScreenMap.Add(self); + } + + public void RemovedFromWorld(Actor self) + { + self.World.ScreenMap.Remove(self); + } } } diff --git a/OpenRA.Game/Traits/World/ScreenMap.cs b/OpenRA.Game/Traits/World/ScreenMap.cs new file mode 100755 index 0000000000..bfbde690ff --- /dev/null +++ b/OpenRA.Game/Traits/World/ScreenMap.cs @@ -0,0 +1,137 @@ +#region Copyright & License Information +/* + * Copyright 2007-2013 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.Generic; +using System.Drawing; +using System.Linq; +using OpenRA.FileFormats; +using OpenRA.Graphics; +using OpenRA.Traits; + +namespace OpenRA.Traits +{ + public class ScreenMapInfo : ITraitInfo + { + [Desc("Size of partition bins (world pixels)")] + public readonly int BinSize = 250; + + public object Create(ActorInitializer init) { return new ScreenMap(init.world, this); } + } + + public class ScreenMap + { + ScreenMapInfo info; + Cache[]> frozen; + List[] actors; + int rows, cols; + + public ScreenMap(World world, ScreenMapInfo info) + { + this.info = info; + cols = world.Map.MapSize.X * Game.CellSize / info.BinSize + 1; + rows = world.Map.MapSize.Y * Game.CellSize / info.BinSize + 1; + + frozen = new Cache[]>(InitializeFrozenActors); + actors = new List[rows * cols]; + for (var j = 0; j < rows; j++) + for (var i = 0; i < cols; i++) + actors[j * cols + i] = new List(); + } + + List[] InitializeFrozenActors(Player p) + { + var f = new List[rows * cols]; + for (var j = 0; j < rows; j++) + for (var i = 0; i < cols; i++) + f[j * cols + i] = new List(); + + return f; + } + + public void Add(Player viewer, FrozenActor fa) + { + var top = Math.Max(0, fa.Bounds.Top / info.BinSize); + var left = Math.Max(0, fa.Bounds.Left / info.BinSize); + var bottom = Math.Min(rows - 1, fa.Bounds.Bottom / info.BinSize); + var right = Math.Min(cols - 1, fa.Bounds.Right / info.BinSize); + + for (var j = top; j <= bottom; j++) + for (var i = left; i <= right; i++) + frozen[viewer][j*cols + i].Add(fa); + } + + public void Remove(Player viewer, FrozenActor fa) + { + foreach (var bin in frozen[viewer]) + bin.Remove(fa); + } + + public void Add(Actor a) + { + var b = a.Bounds.Value; + var top = Math.Max(0, b.Top / info.BinSize); + var left = Math.Max(0, b.Left / info.BinSize); + var bottom = Math.Min(rows - 1, b.Bottom / info.BinSize); + var right = Math.Min(cols - 1, b.Right / info.BinSize); + + for (var j = top; j <= bottom; j++) + for (var i = left; i <= right; i++) + actors[j * cols + i].Add(a); + } + + public void Remove(Actor a) + { + foreach (var bin in actors) + bin.Remove(a); + } + + public void Update(Actor a) + { + Remove(a); + Add(a); + } + + public IEnumerable FrozenActorsAt(Player viewer, int2 pxPos) + { + var i = (pxPos.X / info.BinSize).Clamp(0, cols - 1); + var j = (pxPos.Y / info.BinSize).Clamp(0, rows - 1); + return frozen[viewer][j*cols + i].Where(fa => fa.Bounds.Contains(pxPos) && fa.IsValid); + } + + public IEnumerable ActorsAt(int2 pxPos) + { + var i = (pxPos.X / info.BinSize).Clamp(0, cols - 1); + var j = (pxPos.Y / info.BinSize).Clamp(0, rows - 1); + return actors[j*cols + i].Where(a => a.Bounds.Value.Contains(pxPos) && a.IsInWorld); + } + + // Legacy fallback + public IEnumerable ActorsAt(PPos pxPos) { return ActorsAt(pxPos.ToInt2()); } + + public IEnumerable ActorsInBox(int2 a, int2 b) + { + return ActorsInBox(Rectangle.FromLTRB(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y), Math.Max(a.X, b.X), Math.Max(a.Y, b.Y))); + } + + public IEnumerable ActorsInBox(Rectangle r) + { + var left = (r.Left / info.BinSize).Clamp(0, cols - 1); + var right = (r.Right / info.BinSize).Clamp(0, cols - 1); + var top = (r.Top / info.BinSize).Clamp(0, rows - 1); + var bottom = (r.Bottom / info.BinSize).Clamp(0, rows - 1); + + for (var j = top; j <= bottom; j++) + for (var i = left; i <= right; i++) + foreach (var a in actors[j*cols + i].Where(b => b.Bounds.Value.IntersectsWith(r) && b.IsInWorld)) + yield return a; + } + } +} diff --git a/OpenRA.Game/Widgets/ViewportControllerWidget.cs b/OpenRA.Game/Widgets/ViewportControllerWidget.cs index 25b4970904..10324995b0 100755 --- a/OpenRA.Game/Widgets/ViewportControllerWidget.cs +++ b/OpenRA.Game/Widgets/ViewportControllerWidget.cs @@ -103,8 +103,8 @@ namespace OpenRA.Widgets return; } - var underCursor = world.FindUnitsAtMouse(Viewport.LastMousePos) - .Where(a => a.HasTrait()) + var underCursor = world.ScreenMap.ActorsAt(Game.viewport.ViewToWorldPx(Viewport.LastMousePos)) + .Where(a => !world.FogObscures(a) && a.HasTrait()) .OrderByDescending(a => a.Info.SelectionPriority()) .FirstOrDefault(); diff --git a/OpenRA.Game/Widgets/WorldInteractionControllerWidget.cs b/OpenRA.Game/Widgets/WorldInteractionControllerWidget.cs index 80d981b50a..d58e682a35 100644 --- a/OpenRA.Game/Widgets/WorldInteractionControllerWidget.cs +++ b/OpenRA.Game/Widgets/WorldInteractionControllerWidget.cs @@ -90,7 +90,7 @@ namespace OpenRA.Widgets { if (MultiClick) { - var unit = SelectActorsInBox(world, xy, xy, _ => true).FirstOrDefault(); + var unit = world.ScreenMap.ActorsAt(xy).FirstOrDefault(); var visibleWorld = Game.viewport.ViewBounds(world); var topLeft = Game.viewport.ViewToWorldPx(new int2(visibleWorld.Left, visibleWorld.Top)); @@ -185,7 +185,7 @@ namespace OpenRA.Widgets static readonly Actor[] NoActors = {}; IEnumerable SelectActorsInBox(World world, PPos a, PPos b, Func cond) { - return world.FindActorsInBox(a.ToWPos(0), b.ToWPos(0)) + return world.ScreenMap.ActorsInBox(a.ToInt2(), b.ToInt2()) .Where(x => x.HasTrait() && x.Trait().Info.Selectable && !world.FogObscures(x) && cond(x)) .GroupBy(x => x.GetSelectionPriority()) .OrderByDescending(g => g.Key) diff --git a/OpenRA.Game/World.cs b/OpenRA.Game/World.cs index a2288f7a3f..0d22448ebf 100644 --- a/OpenRA.Game/World.cs +++ b/OpenRA.Game/World.cs @@ -79,6 +79,7 @@ namespace OpenRA public readonly Map Map; public readonly TileSet TileSet; public readonly ActorMap ActorMap; + public readonly ScreenMap ScreenMap; public void IssueOrder( Order o ) { orderManager.IssueOrder( o ); } /* avoid exposing the OM to mod code */ @@ -121,8 +122,9 @@ namespace OpenRA TileSet = Rules.TileSets[Map.Tileset]; SharedRandom = new XRandom(orderManager.LobbyInfo.GlobalSettings.RandomSeed); - WorldActor = CreateActor( "World", new TypeDictionary() ); + WorldActor = CreateActor("World", new TypeDictionary()); ActorMap = new ActorMap(this); + ScreenMap = WorldActor.Trait(); // Add players foreach (var cmp in WorldActor.TraitsImplementing()) diff --git a/OpenRA.Game/WorldUtils.cs b/OpenRA.Game/WorldUtils.cs index 94f635ba1d..b9c0d2a4b5 100755 --- a/OpenRA.Game/WorldUtils.cs +++ b/OpenRA.Game/WorldUtils.cs @@ -21,24 +21,13 @@ namespace OpenRA { public static class WorldUtils { - public static IEnumerable FindUnitsAtMouse(this World world, int2 mouseLocation) - { - var loc = Game.viewport.ViewToWorldPx(mouseLocation).ToWPos(0); - return FindActorsInBox(world, loc, loc).Where(a => !world.FogObscures(a)); - } - public static readonly IEnumerable NoFrozenActors = new FrozenActor[0].AsEnumerable(); public static IEnumerable FindFrozenActorsAtMouse(this World world, int2 mouseLocation) { if (world.RenderPlayer == null) return NoFrozenActors; - var frozenLayer = world.RenderPlayer.PlayerActor.TraitOrDefault(); - if (frozenLayer == null) - return NoFrozenActors; - - var loc = Game.viewport.ViewToWorldPx(mouseLocation).ToInt2(); - return frozenLayer.FrozenActorsAt(loc); + return world.ScreenMap.FrozenActorsAt(world.RenderPlayer, Game.viewport.ViewToWorldPx(mouseLocation).ToInt2()); } public static IEnumerable FindActorsInBox(this World world, CPos tl, CPos br) @@ -73,13 +62,8 @@ namespace OpenRA // Target ranges are calculated in 2D, so ignore height differences var vec = new WVec(r, r, WRange.Zero); var rSq = r.Range*r.Range; - return world.FindActorsInBox(origin - vec, origin + vec).Where(a => - { - var pos = a.CenterPosition; - var dx = (long)(pos.X - origin.X); - var dy = (long)(pos.Y - origin.Y); - return dx*dx + dy*dy <= rSq; - }); + return world.FindActorsInBox(origin - vec, origin + vec).Where( + a => (a.CenterPosition - origin).HorizontalLengthSquared <= rSq); } } diff --git a/OpenRA.Mods.RA/Air/Aircraft.cs b/OpenRA.Mods.RA/Air/Aircraft.cs index 90e4285b56..ff450b021e 100755 --- a/OpenRA.Mods.RA/Air/Aircraft.cs +++ b/OpenRA.Mods.RA/Air/Aircraft.cs @@ -36,7 +36,7 @@ namespace OpenRA.Mods.RA.Air public int GetInitialFacing() { return InitialFacing; } } - public class Aircraft : IFacing, IPositionable, ISync, INotifyKilled, IIssueOrder, IOrderVoice + public class Aircraft : IFacing, IPositionable, ISync, INotifyKilled, IIssueOrder, IOrderVoice, INotifyAddedToWorld, INotifyRemovedFromWorld { static readonly Pair[] NoCells = new Pair[] { }; @@ -101,15 +101,28 @@ namespace OpenRA.Mods.RA.Air UnReserve(); } - public void SetPosition(Actor self, CPos cell) + public void SetPosition(Actor self, WPos pos) { - // Changes position, but not altitude - CenterPosition = cell.CenterPosition + new WVec(0, 0, CenterPosition.Z); + CenterPosition = pos; + + if (self.IsInWorld) + self.World.ScreenMap.Update(self); } - public void SetPosition(Actor self, WPos pos) { CenterPosition = pos; } + // Changes position, but not altitude + public void SetPosition(Actor self, CPos cell) { SetPosition(self, cell.CenterPosition + new WVec(0, 0, CenterPosition.Z)); } public void SetVisualPosition(Actor self, WPos pos) { SetPosition(self, pos); } + public void AddedToWorld(Actor self) + { + self.World.ScreenMap.Add(self); + } + + public void RemovedFromWorld(Actor self) + { + self.World.ScreenMap.Remove(self); + } + public bool AircraftCanEnter(Actor a) { if (self.AppearsHostileTo(a)) diff --git a/OpenRA.Mods.RA/Buildings/Building.cs b/OpenRA.Mods.RA/Buildings/Building.cs index be027171d7..62c64e2c72 100755 --- a/OpenRA.Mods.RA/Buildings/Building.cs +++ b/OpenRA.Mods.RA/Buildings/Building.cs @@ -97,7 +97,7 @@ namespace OpenRA.Mods.RA.Buildings } } - public class Building : INotifyDamage, IOccupySpace, INotifyCapture, ISync, ITechTreePrerequisite + public class Building : INotifyDamage, IOccupySpace, INotifyCapture, ISync, ITechTreePrerequisite, INotifyAddedToWorld, INotifyRemovedFromWorld { readonly Actor self; public readonly BuildingInfo Info; @@ -157,5 +157,15 @@ namespace OpenRA.Mods.RA.Buildings { PlayerPower = newOwner.PlayerActor.Trait(); } + + public void AddedToWorld(Actor self) + { + self.World.ScreenMap.Add(self); + } + + public void RemovedFromWorld(Actor self) + { + self.World.ScreenMap.Remove(self); + } } } diff --git a/OpenRA.Mods.RA/Crate.cs b/OpenRA.Mods.RA/Crate.cs index b1ab283250..8193cefec3 100644 --- a/OpenRA.Mods.RA/Crate.cs +++ b/OpenRA.Mods.RA/Crate.cs @@ -24,7 +24,7 @@ namespace OpenRA.Mods.RA } // ITeleportable is required for paradrop - class Crate : ITick, IPositionable, ICrushable, ISync, INotifyParachuteLanded + class Crate : ITick, IPositionable, ICrushable, ISync, INotifyParachuteLanded, INotifyAddedToWorld, INotifyRemovedFromWorld { readonly Actor self; readonly CrateInfo info; @@ -115,12 +115,25 @@ namespace OpenRA.Mods.RA rs.anim.PlayRepeating(seq); if (self.IsInWorld) + { self.World.ActorMap.Add(self, this); + self.World.ScreenMap.Update(self); + } } public bool CrushableBy(string[] crushClasses, Player owner) { return crushClasses.Contains("crate"); } + + public void AddedToWorld(Actor self) + { + self.World.ScreenMap.Add(self); + } + + public void RemovedFromWorld(Actor self) + { + self.World.ScreenMap.Remove(self); + } } } diff --git a/OpenRA.Mods.RA/Guard.cs b/OpenRA.Mods.RA/Guard.cs index 94cf1cba70..ef60634cc8 100644 --- a/OpenRA.Mods.RA/Guard.cs +++ b/OpenRA.Mods.RA/Guard.cs @@ -58,7 +58,7 @@ namespace OpenRA.Mods.RA yield break; } - var target = FriendlyGuardableUnitsAtMouse(world, mi).FirstOrDefault(); + var target = FriendlyGuardableUnits(world, mi).FirstOrDefault(); if (target == null || subjects.All(s => s.IsDead())) yield break; @@ -79,19 +79,19 @@ namespace OpenRA.Mods.RA public string GetCursor(World world, CPos xy, MouseInput mi) { - if (world.Map.IsInMap(xy)) - { - var targets = FriendlyGuardableUnitsAtMouse(world, mi); - if (targets.Any() && (subjects.Count() > 1 || (subjects.Count() == 1 && subjects.First() != targets.First()))) - return "guard"; - } - return "move-blocked"; + var multiple = subjects.Count() > 1; + var canGuard = FriendlyGuardableUnits(world, mi) + .Any(a => multiple || a != subjects.First()); + + return canGuard ? "guard" : "move-blocked"; } - static IEnumerable FriendlyGuardableUnitsAtMouse(World world, MouseInput mi) + static IEnumerable FriendlyGuardableUnits(World world, MouseInput mi) { - return world.FindUnitsAtMouse(mi.Location) - .Where(a => !a.IsDead() && a.AppearsFriendlyTo(world.LocalPlayer.PlayerActor) && a.HasTrait()); + return world.ScreenMap.ActorsAt(Game.viewport.ViewToWorldPx(mi.Location)) + .Where(a => !world.FogObscures(a) && !a.IsDead() && + a.AppearsFriendlyTo(world.LocalPlayer.PlayerActor) && + a.HasTrait()); } } diff --git a/OpenRA.Mods.RA/Husk.cs b/OpenRA.Mods.RA/Husk.cs index 8c5a4cd27e..1879b01017 100644 --- a/OpenRA.Mods.RA/Husk.cs +++ b/OpenRA.Mods.RA/Husk.cs @@ -25,7 +25,7 @@ namespace OpenRA.Mods.RA public int GetInitialFacing() { return 128; } } - class Husk : IPositionable, IFacing, ISync + class Husk : IPositionable, IFacing, ISync, INotifyAddedToWorld, INotifyRemovedFromWorld { readonly HuskInfo info; readonly Actor self; @@ -64,7 +64,11 @@ namespace OpenRA.Mods.RA } public void SetPosition(Actor self, CPos cell) { SetPosition(self, cell.CenterPosition); } - public void SetVisualPosition(Actor self, WPos pos) { CenterPosition = pos; } + public void SetVisualPosition(Actor self, WPos pos) + { + CenterPosition = pos; + self.World.ScreenMap.Update(self); + } public void SetPosition(Actor self, WPos pos) { @@ -72,6 +76,17 @@ namespace OpenRA.Mods.RA CenterPosition = pos; TopLeft = pos.ToCPos(); self.World.ActorMap.Add(self, this); + self.World.ScreenMap.Update(self); + } + + public void AddedToWorld(Actor self) + { + self.World.ScreenMap.Add(self); + } + + public void RemovedFromWorld(Actor self) + { + self.World.ScreenMap.Remove(self); } } diff --git a/OpenRA.Mods.RA/Mine.cs b/OpenRA.Mods.RA/Mine.cs index 3c3ad8df31..cab1ed9280 100644 --- a/OpenRA.Mods.RA/Mine.cs +++ b/OpenRA.Mods.RA/Mine.cs @@ -26,7 +26,7 @@ namespace OpenRA.Mods.RA public object Create(ActorInitializer init) { return new Mine(init, this); } } - class Mine : ICrushable, IOccupySpace, ISync + class Mine : ICrushable, IOccupySpace, ISync, INotifyAddedToWorld, INotifyRemovedFromWorld { readonly Actor self; readonly MineInfo info; @@ -62,6 +62,16 @@ namespace OpenRA.Mods.RA public IEnumerable> OccupiedCells() { yield return Pair.New(TopLeft, SubCell.FullCell); } public WPos CenterPosition { get { return location.CenterPosition; } } + + public void AddedToWorld(Actor self) + { + self.World.ScreenMap.Add(self); + } + + public void RemovedFromWorld(Actor self) + { + self.World.ScreenMap.Remove(self); + } } /* tag trait for stuff that shouldnt trigger mines */ diff --git a/OpenRA.Mods.RA/Minelayer.cs b/OpenRA.Mods.RA/Minelayer.cs index a8f56b9913..d52144080c 100644 --- a/OpenRA.Mods.RA/Minelayer.cs +++ b/OpenRA.Mods.RA/Minelayer.cs @@ -106,7 +106,8 @@ namespace OpenRA.Mods.RA yield break; } - var underCursor = world.FindUnitsAtMouse(mi.Location) + var underCursor = world.ScreenMap.ActorsAt(Game.viewport.ViewToWorldPx(mi.Location)) + .Where(a => !world.FogObscures(a)) .OrderByDescending(a => a.Info.Traits.Contains() ? a.Info.Traits.Get().Priority : int.MinValue) .FirstOrDefault(); diff --git a/OpenRA.Mods.RA/Move/Mobile.cs b/OpenRA.Mods.RA/Move/Mobile.cs index 5f5345e0b5..bb72477cdc 100755 --- a/OpenRA.Mods.RA/Move/Mobile.cs +++ b/OpenRA.Mods.RA/Move/Mobile.cs @@ -144,7 +144,7 @@ namespace OpenRA.Mods.RA.Move public int GetInitialFacing() { return InitialFacing; } } - public class Mobile : IIssueOrder, IResolveOrder, IOrderVoice, IPositionable, IMove, IFacing, ISync + public class Mobile : IIssueOrder, IResolveOrder, IOrderVoice, IPositionable, IMove, IFacing, ISync, INotifyAddedToWorld, INotifyRemovedFromWorld { public readonly Actor self; public readonly MobileInfo Info; @@ -231,6 +231,18 @@ namespace OpenRA.Mods.RA.Move public void SetVisualPosition(Actor self, WPos pos) { CenterPosition = pos; + if (self.IsInWorld) + self.World.ScreenMap.Update(self); + } + + public void AddedToWorld(Actor self) + { + self.World.ScreenMap.Add(self); + } + + public void RemovedFromWorld(Actor self) + { + self.World.ScreenMap.Remove(self); } public IEnumerable Orders { get { yield return new MoveOrderTargeter(Info); } } diff --git a/OpenRA.Mods.RA/Orders/PowerDownOrderGenerator.cs b/OpenRA.Mods.RA/Orders/PowerDownOrderGenerator.cs index 2a0eecc226..dc600a5407 100755 --- a/OpenRA.Mods.RA/Orders/PowerDownOrderGenerator.cs +++ b/OpenRA.Mods.RA/Orders/PowerDownOrderGenerator.cs @@ -39,9 +39,8 @@ namespace OpenRA.Mods.RA.Orders { if (mi.Button == MouseButton.Left) { - var underCursor = world.FindUnitsAtMouse(mi.Location) - .Where(a => a.Owner == world.LocalPlayer - && a.HasTrait()).FirstOrDefault(); + var underCursor = world.ScreenMap.ActorsAt(Game.viewport.ViewToWorldPx(mi.Location)) + .Where(a => a.Owner == world.LocalPlayer && a.HasTrait()).FirstOrDefault(); if (underCursor != null) yield return new Order(order, underCursor, false); diff --git a/OpenRA.Mods.RA/Orders/RepairOrderGenerator.cs b/OpenRA.Mods.RA/Orders/RepairOrderGenerator.cs index d57d624c36..c2d931ba4a 100644 --- a/OpenRA.Mods.RA/Orders/RepairOrderGenerator.cs +++ b/OpenRA.Mods.RA/Orders/RepairOrderGenerator.cs @@ -30,8 +30,8 @@ namespace OpenRA.Mods.RA.Orders { if (mi.Button == MouseButton.Left) { - var underCursor = world.FindUnitsAtMouse(mi.Location) - .Where(a => a.AppearsFriendlyTo(world.LocalPlayer.PlayerActor) && a.HasTrait()).FirstOrDefault(); + var underCursor = world.ScreenMap.ActorsAt(Game.viewport.ViewToWorldPx(mi.Location)) + .Where(a => !world.FogObscures(a) && a.AppearsFriendlyTo(world.LocalPlayer.PlayerActor) && a.HasTrait()).FirstOrDefault(); if (underCursor == null) yield break; diff --git a/mods/cnc/rules/system.yaml b/mods/cnc/rules/system.yaml index 4d1ce3e2da..2f45b021a7 100644 --- a/mods/cnc/rules/system.yaml +++ b/mods/cnc/rules/system.yaml @@ -206,6 +206,7 @@ Player: FrozenActorLayer: World: + ScreenMap: LoadWidgetAtGameStart: Widget: INGAME_ROOT CncMenuPaletteEffect: diff --git a/mods/d2k/rules/system.yaml b/mods/d2k/rules/system.yaml index 94d209e1dc..401d19e266 100644 --- a/mods/d2k/rules/system.yaml +++ b/mods/d2k/rules/system.yaml @@ -357,6 +357,7 @@ Player: PlayerStatistics: World: + ScreenMap: LoadWidgetAtGameStart: Widget: INGAME_ROOT ScreenShaker: diff --git a/mods/ra/rules/system.yaml b/mods/ra/rules/system.yaml index 14f64b79c1..49a0920f8a 100644 --- a/mods/ra/rules/system.yaml +++ b/mods/ra/rules/system.yaml @@ -529,6 +529,7 @@ Player: PlayerStatistics: World: + ScreenMap: LoadWidgetAtGameStart: Widget: INGAME_ROOT ScreenShaker: diff --git a/mods/ts/rules/system.yaml b/mods/ts/rules/system.yaml index 5a5bfdb1dd..cc885b62ed 100644 --- a/mods/ts/rules/system.yaml +++ b/mods/ts/rules/system.yaml @@ -42,6 +42,7 @@ Player: PlayerStatistics: World: + ScreenMap: LoadWidgetAtGameStart: Widget: INGAME_ROOT BuildingInfluence: From 4a2a747556409bed71ab6aea654035b793ade963 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 21 Sep 2013 15:38:30 +1200 Subject: [PATCH 3/7] Pull ActorMap back out into a trait. --- OpenRA.Game/ActorInitializer.cs | 1 + OpenRA.Game/OpenRA.Game.csproj | 2 +- OpenRA.Game/{ => Traits/World}/ActorMap.cs | 60 ++++++++++++---------- OpenRA.Game/World.cs | 2 +- mods/cnc/rules/system.yaml | 1 + mods/d2k/rules/system.yaml | 1 + mods/ra/rules/system.yaml | 1 + mods/ts/rules/system.yaml | 1 + 8 files changed, 41 insertions(+), 28 deletions(-) rename OpenRA.Game/{ => Traits/World}/ActorMap.cs (59%) diff --git a/OpenRA.Game/ActorInitializer.cs b/OpenRA.Game/ActorInitializer.cs index 71ee1eb43f..f342c21d24 100755 --- a/OpenRA.Game/ActorInitializer.cs +++ b/OpenRA.Game/ActorInitializer.cs @@ -10,6 +10,7 @@ using System.Linq; using OpenRA.FileFormats; +using OpenRA.Traits; namespace OpenRA { diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj index 5e339a3f97..96e9c36fa4 100644 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -83,7 +83,6 @@ - @@ -239,6 +238,7 @@ + diff --git a/OpenRA.Game/ActorMap.cs b/OpenRA.Game/Traits/World/ActorMap.cs similarity index 59% rename from OpenRA.Game/ActorMap.cs rename to OpenRA.Game/Traits/World/ActorMap.cs index 5fc8ac1f8f..06afa295f0 100644 --- a/OpenRA.Game/ActorMap.cs +++ b/OpenRA.Game/Traits/World/ActorMap.cs @@ -12,10 +12,15 @@ using System.Collections.Generic; using System.Linq; using OpenRA.Traits; -namespace OpenRA +namespace OpenRA.Traits { public enum SubCell { FullCell, TopLeft, TopRight, Center, BottomLeft, BottomRight } + class ActorMapInfo : ITraitInfo + { + public object Create(ActorInitializer init) { return new ActorMap(init.world); } + } + public class ActorMap { class InfluenceNode @@ -28,29 +33,31 @@ namespace OpenRA InfluenceNode[,] influence; Map map; - public ActorMap( World world ) + public ActorMap(World world) { map = world.Map; influence = new InfluenceNode[world.Map.MapSize.X, world.Map.MapSize.Y]; - world.ActorAdded += a => Add( a, a.OccupiesSpace ); - world.ActorRemoved += a => Remove( a, a.OccupiesSpace ); + world.ActorAdded += a => Add(a, a.OccupiesSpace); + world.ActorRemoved += a => Remove(a, a.OccupiesSpace); } public IEnumerable GetUnitsAt(CPos a) { - if (!map.IsInMap(a)) yield break; + if (!map.IsInMap(a)) + yield break; - for( var i = influence[ a.X, a.Y ] ; i != null ; i = i.next ) + for (var i = influence[a.X, a.Y]; i != null; i = i.next) if (!i.actor.Destroyed) yield return i.actor; } public IEnumerable GetUnitsAt(CPos a, SubCell sub) { - if (!map.IsInMap(a)) yield break; + if (!map.IsInMap(a)) + yield break; - for( var i = influence[ a.X, a.Y ] ; i != null ; i = i.next ) + for (var i = influence[a.X, a.Y]; i != null; i = i.next) if (!i.actor.Destroyed && (i.subCell == sub || i.subCell == SubCell.FullCell)) yield return i.actor; } @@ -60,7 +67,7 @@ namespace OpenRA if (!AnyUnitsAt(a)) return true; - return new[]{ SubCell.TopLeft, SubCell.TopRight, SubCell.Center, + return new[] { SubCell.TopLeft, SubCell.TopRight, SubCell.Center, SubCell.BottomLeft, SubCell.BottomRight }.Any(b => !AnyUnitsAt(a,b)); } @@ -69,54 +76,55 @@ namespace OpenRA if (!HasFreeSubCell(a)) return null; - return new[]{ SubCell.TopLeft, SubCell.TopRight, SubCell.Center, + return new[] { SubCell.TopLeft, SubCell.TopRight, SubCell.Center, SubCell.BottomLeft, SubCell.BottomRight }.First(b => !AnyUnitsAt(a,b)); } public bool AnyUnitsAt(CPos a) { - return influence[ a.X, a.Y ] != null; + return influence[a.X, a.Y] != null; } public bool AnyUnitsAt(CPos a, SubCell sub) { - for( var i = influence[ a.X, a.Y ] ; i != null ; i = i.next ) + for (var i = influence[a.X, a.Y]; i != null; i = i.next) if (i.subCell == sub || i.subCell == SubCell.FullCell) return true; return false; } - public void Add( Actor self, IOccupySpace unit ) - { - if (unit != null) - foreach( var c in unit.OccupiedCells() ) - influence[ c.First.X, c.First.Y ] = new InfluenceNode { next = influence[ c.First.X, c.First.Y ], subCell = c.Second, actor = self }; - } - - public void Remove( Actor self, IOccupySpace unit ) + public void Add(Actor self, IOccupySpace unit) { if (unit != null) foreach (var c in unit.OccupiedCells()) - RemoveInner( ref influence[ c.First.X, c.First.Y ], self ); + influence[c.First.X, c.First.Y] = new InfluenceNode { next = influence[c.First.X, c.First.Y], subCell = c.Second, actor = self }; } - void RemoveInner( ref InfluenceNode influenceNode, Actor toRemove ) + public void Remove(Actor self, IOccupySpace unit) { - if( influenceNode == null ) + if (unit != null) + foreach (var c in unit.OccupiedCells()) + RemoveInner(ref influence[c.First.X, c.First.Y], self); + } + + void RemoveInner(ref InfluenceNode influenceNode, Actor toRemove) + { + if (influenceNode == null) return; - else if( influenceNode.actor == toRemove ) + else if (influenceNode.actor == toRemove) influenceNode = influenceNode.next; if (influenceNode != null) - RemoveInner( ref influenceNode.next, toRemove ); + RemoveInner(ref influenceNode.next, toRemove); } public void Update(Actor self, IOccupySpace unit) { Remove(self, unit); - if (!self.IsDead()) Add(self, unit); + if (!self.IsDead()) + Add(self, unit); } } } diff --git a/OpenRA.Game/World.cs b/OpenRA.Game/World.cs index 0d22448ebf..01e27d1649 100644 --- a/OpenRA.Game/World.cs +++ b/OpenRA.Game/World.cs @@ -123,7 +123,7 @@ namespace OpenRA SharedRandom = new XRandom(orderManager.LobbyInfo.GlobalSettings.RandomSeed); WorldActor = CreateActor("World", new TypeDictionary()); - ActorMap = new ActorMap(this); + ActorMap = WorldActor.Trait(); ScreenMap = WorldActor.Trait(); // Add players diff --git a/mods/cnc/rules/system.yaml b/mods/cnc/rules/system.yaml index 2f45b021a7..4909e4f53d 100644 --- a/mods/cnc/rules/system.yaml +++ b/mods/cnc/rules/system.yaml @@ -207,6 +207,7 @@ Player: World: ScreenMap: + ActorMap: LoadWidgetAtGameStart: Widget: INGAME_ROOT CncMenuPaletteEffect: diff --git a/mods/d2k/rules/system.yaml b/mods/d2k/rules/system.yaml index 401d19e266..e9bc422318 100644 --- a/mods/d2k/rules/system.yaml +++ b/mods/d2k/rules/system.yaml @@ -358,6 +358,7 @@ Player: World: ScreenMap: + ActorMap: LoadWidgetAtGameStart: Widget: INGAME_ROOT ScreenShaker: diff --git a/mods/ra/rules/system.yaml b/mods/ra/rules/system.yaml index 49a0920f8a..384c8e8d58 100644 --- a/mods/ra/rules/system.yaml +++ b/mods/ra/rules/system.yaml @@ -530,6 +530,7 @@ Player: World: ScreenMap: + ActorMap: LoadWidgetAtGameStart: Widget: INGAME_ROOT ScreenShaker: diff --git a/mods/ts/rules/system.yaml b/mods/ts/rules/system.yaml index cc885b62ed..52cc6ddb03 100644 --- a/mods/ts/rules/system.yaml +++ b/mods/ts/rules/system.yaml @@ -43,6 +43,7 @@ Player: World: ScreenMap: + ActorMap: LoadWidgetAtGameStart: Widget: INGAME_ROOT BuildingInfluence: From b00cc6108d789acdb2b0dfe1a22eccb983dfc4a9 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 21 Sep 2013 15:46:42 +1200 Subject: [PATCH 4/7] Make ActorMap addition explicit. --- OpenRA.Game/Traits/Waypoint.cs | 2 ++ OpenRA.Game/Traits/World/ActorMap.cs | 28 ++++++++-------------------- OpenRA.Mods.RA/Air/Aircraft.cs | 2 ++ OpenRA.Mods.RA/Buildings/Building.cs | 2 ++ OpenRA.Mods.RA/Crate.cs | 6 ++++-- OpenRA.Mods.RA/Husk.cs | 6 ++++-- OpenRA.Mods.RA/Mine.cs | 2 ++ OpenRA.Mods.RA/Move/Mobile.cs | 6 ++++-- 8 files changed, 28 insertions(+), 26 deletions(-) diff --git a/OpenRA.Game/Traits/Waypoint.cs b/OpenRA.Game/Traits/Waypoint.cs index 2e129bbf06..c7afeae949 100644 --- a/OpenRA.Game/Traits/Waypoint.cs +++ b/OpenRA.Game/Traits/Waypoint.cs @@ -33,11 +33,13 @@ namespace OpenRA.Traits public void AddedToWorld(Actor self) { + self.World.ActorMap.AddInfluence(self, this); self.World.ScreenMap.Add(self); } public void RemovedFromWorld(Actor self) { + self.World.ActorMap.RemoveInfluence(self, this); self.World.ScreenMap.Remove(self); } } diff --git a/OpenRA.Game/Traits/World/ActorMap.cs b/OpenRA.Game/Traits/World/ActorMap.cs index 06afa295f0..af50470346 100644 --- a/OpenRA.Game/Traits/World/ActorMap.cs +++ b/OpenRA.Game/Traits/World/ActorMap.cs @@ -37,9 +37,6 @@ namespace OpenRA.Traits { map = world.Map; influence = new InfluenceNode[world.Map.MapSize.X, world.Map.MapSize.Y]; - - world.ActorAdded += a => Add(a, a.OccupiesSpace); - world.ActorRemoved += a => Remove(a, a.OccupiesSpace); } public IEnumerable GetUnitsAt(CPos a) @@ -95,21 +92,19 @@ namespace OpenRA.Traits return false; } - public void Add(Actor self, IOccupySpace unit) + public void AddInfluence(Actor self, IOccupySpace ios) { - if (unit != null) - foreach (var c in unit.OccupiedCells()) - influence[c.First.X, c.First.Y] = new InfluenceNode { next = influence[c.First.X, c.First.Y], subCell = c.Second, actor = self }; + foreach (var c in ios.OccupiedCells()) + influence[c.First.X, c.First.Y] = new InfluenceNode { next = influence[c.First.X, c.First.Y], subCell = c.Second, actor = self }; } - public void Remove(Actor self, IOccupySpace unit) + public void RemoveInfluence(Actor self, IOccupySpace ios) { - if (unit != null) - foreach (var c in unit.OccupiedCells()) - RemoveInner(ref influence[c.First.X, c.First.Y], self); + foreach (var c in ios.OccupiedCells()) + RemoveInfluenceInner(ref influence[c.First.X, c.First.Y], self); } - void RemoveInner(ref InfluenceNode influenceNode, Actor toRemove) + void RemoveInfluenceInner(ref InfluenceNode influenceNode, Actor toRemove) { if (influenceNode == null) return; @@ -117,14 +112,7 @@ namespace OpenRA.Traits influenceNode = influenceNode.next; if (influenceNode != null) - RemoveInner(ref influenceNode.next, toRemove); - } - - public void Update(Actor self, IOccupySpace unit) - { - Remove(self, unit); - if (!self.IsDead()) - Add(self, unit); + RemoveInfluenceInner(ref influenceNode.next, toRemove); } } } diff --git a/OpenRA.Mods.RA/Air/Aircraft.cs b/OpenRA.Mods.RA/Air/Aircraft.cs index ff450b021e..c1baf48b51 100755 --- a/OpenRA.Mods.RA/Air/Aircraft.cs +++ b/OpenRA.Mods.RA/Air/Aircraft.cs @@ -115,11 +115,13 @@ namespace OpenRA.Mods.RA.Air public void AddedToWorld(Actor self) { + self.World.ActorMap.AddInfluence(self, this); self.World.ScreenMap.Add(self); } public void RemovedFromWorld(Actor self) { + self.World.ActorMap.RemoveInfluence(self, this); self.World.ScreenMap.Remove(self); } diff --git a/OpenRA.Mods.RA/Buildings/Building.cs b/OpenRA.Mods.RA/Buildings/Building.cs index 62c64e2c72..0ec7af8b7a 100755 --- a/OpenRA.Mods.RA/Buildings/Building.cs +++ b/OpenRA.Mods.RA/Buildings/Building.cs @@ -160,11 +160,13 @@ namespace OpenRA.Mods.RA.Buildings public void AddedToWorld(Actor self) { + self.World.ActorMap.AddInfluence(self, this); self.World.ScreenMap.Add(self); } public void RemovedFromWorld(Actor self) { + self.World.ActorMap.RemoveInfluence(self, this); self.World.ScreenMap.Remove(self); } } diff --git a/OpenRA.Mods.RA/Crate.cs b/OpenRA.Mods.RA/Crate.cs index 8193cefec3..68ba35bb26 100644 --- a/OpenRA.Mods.RA/Crate.cs +++ b/OpenRA.Mods.RA/Crate.cs @@ -104,7 +104,7 @@ namespace OpenRA.Mods.RA public void SetPosition(Actor self, CPos cell) { if (self.IsInWorld) - self.World.ActorMap.Remove(self, this); + self.World.ActorMap.RemoveInfluence(self, this); Location = cell; CenterPosition = cell.CenterPosition; @@ -116,7 +116,7 @@ namespace OpenRA.Mods.RA if (self.IsInWorld) { - self.World.ActorMap.Add(self, this); + self.World.ActorMap.AddInfluence(self, this); self.World.ScreenMap.Update(self); } } @@ -128,11 +128,13 @@ namespace OpenRA.Mods.RA public void AddedToWorld(Actor self) { + self.World.ActorMap.AddInfluence(self, this); self.World.ScreenMap.Add(self); } public void RemovedFromWorld(Actor self) { + self.World.ActorMap.RemoveInfluence(self, this); self.World.ScreenMap.Remove(self); } } diff --git a/OpenRA.Mods.RA/Husk.cs b/OpenRA.Mods.RA/Husk.cs index 1879b01017..9e41fb64ca 100644 --- a/OpenRA.Mods.RA/Husk.cs +++ b/OpenRA.Mods.RA/Husk.cs @@ -72,20 +72,22 @@ namespace OpenRA.Mods.RA public void SetPosition(Actor self, WPos pos) { - self.World.ActorMap.Remove(self, this); + self.World.ActorMap.RemoveInfluence(self, this); CenterPosition = pos; TopLeft = pos.ToCPos(); - self.World.ActorMap.Add(self, this); + self.World.ActorMap.AddInfluence(self, this); self.World.ScreenMap.Update(self); } public void AddedToWorld(Actor self) { + self.World.ActorMap.AddInfluence(self, this); self.World.ScreenMap.Add(self); } public void RemovedFromWorld(Actor self) { + self.World.ActorMap.RemoveInfluence(self, this); self.World.ScreenMap.Remove(self); } } diff --git a/OpenRA.Mods.RA/Mine.cs b/OpenRA.Mods.RA/Mine.cs index cab1ed9280..f42264d4a8 100644 --- a/OpenRA.Mods.RA/Mine.cs +++ b/OpenRA.Mods.RA/Mine.cs @@ -65,11 +65,13 @@ namespace OpenRA.Mods.RA public void AddedToWorld(Actor self) { + self.World.ActorMap.AddInfluence(self, this); self.World.ScreenMap.Add(self); } public void RemovedFromWorld(Actor self) { + self.World.ActorMap.RemoveInfluence(self, this); self.World.ScreenMap.Remove(self); } } diff --git a/OpenRA.Mods.RA/Move/Mobile.cs b/OpenRA.Mods.RA/Move/Mobile.cs index bb72477cdc..1679654e42 100755 --- a/OpenRA.Mods.RA/Move/Mobile.cs +++ b/OpenRA.Mods.RA/Move/Mobile.cs @@ -237,11 +237,13 @@ namespace OpenRA.Mods.RA.Move public void AddedToWorld(Actor self) { + self.World.ActorMap.AddInfluence(self, this); self.World.ScreenMap.Add(self); } public void RemovedFromWorld(Actor self) { + self.World.ActorMap.RemoveInfluence(self, this); self.World.ScreenMap.Remove(self); } @@ -442,13 +444,13 @@ namespace OpenRA.Mods.RA.Move public void AddInfluence() { if (self.IsInWorld) - self.World.ActorMap.Add(self, this); + self.World.ActorMap.AddInfluence(self, this); } public void RemoveInfluence() { if (self.IsInWorld) - self.World.ActorMap.Remove(self, this); + self.World.ActorMap.RemoveInfluence(self, this); } public void Nudge(Actor self, Actor nudger, bool force) From e03ec690ff20dce3ea914a2f0e68189f4aa29ad2 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 21 Sep 2013 16:06:39 +1200 Subject: [PATCH 5/7] Track actor positions in ActorMap. --- OpenRA.Game/Traits/Waypoint.cs | 4 ++- OpenRA.Game/Traits/World/ActorMap.cs | 44 +++++++++++++++++++++++++--- OpenRA.Mods.RA/Air/Aircraft.cs | 5 ++++ OpenRA.Mods.RA/Buildings/Building.cs | 2 ++ OpenRA.Mods.RA/Crate.cs | 7 +++-- OpenRA.Mods.RA/Husk.cs | 3 ++ OpenRA.Mods.RA/Mine.cs | 2 ++ OpenRA.Mods.RA/Move/Mobile.cs | 5 ++++ 8 files changed, 64 insertions(+), 8 deletions(-) diff --git a/OpenRA.Game/Traits/Waypoint.cs b/OpenRA.Game/Traits/Waypoint.cs index c7afeae949..a0cf83becd 100644 --- a/OpenRA.Game/Traits/Waypoint.cs +++ b/OpenRA.Game/Traits/Waypoint.cs @@ -20,7 +20,7 @@ namespace OpenRA.Traits class Waypoint : IOccupySpace, ISync, INotifyAddedToWorld, INotifyRemovedFromWorld { - [Sync] CPos location; + [Sync] readonly CPos location; public Waypoint(ActorInitializer init) { @@ -34,12 +34,14 @@ namespace OpenRA.Traits public void AddedToWorld(Actor self) { self.World.ActorMap.AddInfluence(self, this); + self.World.ActorMap.AddPosition(self, this); self.World.ScreenMap.Add(self); } public void RemovedFromWorld(Actor self) { self.World.ActorMap.RemoveInfluence(self, this); + self.World.ActorMap.RemovePosition(self, this); self.World.ScreenMap.Remove(self); } } diff --git a/OpenRA.Game/Traits/World/ActorMap.cs b/OpenRA.Game/Traits/World/ActorMap.cs index af50470346..7a74294f40 100644 --- a/OpenRA.Game/Traits/World/ActorMap.cs +++ b/OpenRA.Game/Traits/World/ActorMap.cs @@ -10,15 +10,19 @@ using System.Collections.Generic; using System.Linq; +using OpenRA.FileFormats; using OpenRA.Traits; namespace OpenRA.Traits { public enum SubCell { FullCell, TopLeft, TopRight, Center, BottomLeft, BottomRight } - class ActorMapInfo : ITraitInfo + public class ActorMapInfo : ITraitInfo { - public object Create(ActorInitializer init) { return new ActorMap(init.world); } + [Desc("Size of partition bins (cells)")] + public readonly int BinSize = 10; + + public object Create(ActorInitializer init) { return new ActorMap(init.world, this); } } public class ActorMap @@ -30,13 +34,25 @@ namespace OpenRA.Traits public Actor actor; } + readonly ActorMapInfo info; + readonly Map map; InfluenceNode[,] influence; - Map map; - public ActorMap(World world) + List[] actors; + int rows, cols; + + public ActorMap(World world, ActorMapInfo info) { + this.info = info; map = world.Map; influence = new InfluenceNode[world.Map.MapSize.X, world.Map.MapSize.Y]; + + cols = world.Map.MapSize.X / info.BinSize + 1; + rows = world.Map.MapSize.Y / info.BinSize + 1; + actors = new List[rows * cols]; + for (var j = 0; j < rows; j++) + for (var i = 0; i < cols; i++) + actors[j * cols + i] = new List(); } public IEnumerable GetUnitsAt(CPos a) @@ -114,5 +130,25 @@ namespace OpenRA.Traits if (influenceNode != null) RemoveInfluenceInner(ref influenceNode.next, toRemove); } + + public void AddPosition(Actor a, IOccupySpace ios) + { + var pos = ios.CenterPosition; + var i = (pos.X / info.BinSize).Clamp(0, cols - 1); + var j = (pos.Y / info.BinSize).Clamp(0, rows - 1); + actors[j*cols + i].Add(a); + } + + public void RemovePosition(Actor a, IOccupySpace ios) + { + foreach (var bin in actors) + bin.Remove(a); + } + + public void UpdatePosition(Actor a, IOccupySpace ios) + { + RemovePosition(a, ios); + AddPosition(a, ios); + } } } diff --git a/OpenRA.Mods.RA/Air/Aircraft.cs b/OpenRA.Mods.RA/Air/Aircraft.cs index c1baf48b51..ab88485cc6 100755 --- a/OpenRA.Mods.RA/Air/Aircraft.cs +++ b/OpenRA.Mods.RA/Air/Aircraft.cs @@ -106,7 +106,10 @@ namespace OpenRA.Mods.RA.Air CenterPosition = pos; if (self.IsInWorld) + { self.World.ScreenMap.Update(self); + self.World.ActorMap.UpdatePosition(self, this); + } } // Changes position, but not altitude @@ -116,12 +119,14 @@ namespace OpenRA.Mods.RA.Air public void AddedToWorld(Actor self) { self.World.ActorMap.AddInfluence(self, this); + self.World.ActorMap.AddPosition(self, this); self.World.ScreenMap.Add(self); } public void RemovedFromWorld(Actor self) { self.World.ActorMap.RemoveInfluence(self, this); + self.World.ActorMap.RemovePosition(self, this); self.World.ScreenMap.Remove(self); } diff --git a/OpenRA.Mods.RA/Buildings/Building.cs b/OpenRA.Mods.RA/Buildings/Building.cs index 0ec7af8b7a..60a3490dd5 100755 --- a/OpenRA.Mods.RA/Buildings/Building.cs +++ b/OpenRA.Mods.RA/Buildings/Building.cs @@ -161,12 +161,14 @@ namespace OpenRA.Mods.RA.Buildings public void AddedToWorld(Actor self) { self.World.ActorMap.AddInfluence(self, this); + self.World.ActorMap.AddPosition(self, this); self.World.ScreenMap.Add(self); } public void RemovedFromWorld(Actor self) { self.World.ActorMap.RemoveInfluence(self, this); + self.World.ActorMap.RemovePosition(self, this); self.World.ScreenMap.Remove(self); } } diff --git a/OpenRA.Mods.RA/Crate.cs b/OpenRA.Mods.RA/Crate.cs index 68ba35bb26..2fdeb44bce 100644 --- a/OpenRA.Mods.RA/Crate.cs +++ b/OpenRA.Mods.RA/Crate.cs @@ -103,9 +103,7 @@ namespace OpenRA.Mods.RA public void SetPosition(Actor self, CPos cell) { - if (self.IsInWorld) - self.World.ActorMap.RemoveInfluence(self, this); - + self.World.ActorMap.RemoveInfluence(self, this); Location = cell; CenterPosition = cell.CenterPosition; @@ -117,6 +115,7 @@ namespace OpenRA.Mods.RA if (self.IsInWorld) { self.World.ActorMap.AddInfluence(self, this); + self.World.ActorMap.UpdatePosition(self, this); self.World.ScreenMap.Update(self); } } @@ -129,12 +128,14 @@ namespace OpenRA.Mods.RA public void AddedToWorld(Actor self) { self.World.ActorMap.AddInfluence(self, this); + self.World.ActorMap.AddPosition(self, this); self.World.ScreenMap.Add(self); } public void RemovedFromWorld(Actor self) { self.World.ActorMap.RemoveInfluence(self, this); + self.World.ActorMap.RemovePosition(self, this); self.World.ScreenMap.Remove(self); } } diff --git a/OpenRA.Mods.RA/Husk.cs b/OpenRA.Mods.RA/Husk.cs index 9e41fb64ca..2e9c0b0383 100644 --- a/OpenRA.Mods.RA/Husk.cs +++ b/OpenRA.Mods.RA/Husk.cs @@ -76,18 +76,21 @@ namespace OpenRA.Mods.RA CenterPosition = pos; TopLeft = pos.ToCPos(); self.World.ActorMap.AddInfluence(self, this); + self.World.ActorMap.UpdatePosition(self, this); self.World.ScreenMap.Update(self); } public void AddedToWorld(Actor self) { self.World.ActorMap.AddInfluence(self, this); + self.World.ActorMap.AddPosition(self, this); self.World.ScreenMap.Add(self); } public void RemovedFromWorld(Actor self) { self.World.ActorMap.RemoveInfluence(self, this); + self.World.ActorMap.RemovePosition(self, this); self.World.ScreenMap.Remove(self); } } diff --git a/OpenRA.Mods.RA/Mine.cs b/OpenRA.Mods.RA/Mine.cs index f42264d4a8..aa45da5d14 100644 --- a/OpenRA.Mods.RA/Mine.cs +++ b/OpenRA.Mods.RA/Mine.cs @@ -66,12 +66,14 @@ namespace OpenRA.Mods.RA public void AddedToWorld(Actor self) { self.World.ActorMap.AddInfluence(self, this); + self.World.ActorMap.AddPosition(self, this); self.World.ScreenMap.Add(self); } public void RemovedFromWorld(Actor self) { self.World.ActorMap.RemoveInfluence(self, this); + self.World.ActorMap.RemovePosition(self, this); self.World.ScreenMap.Remove(self); } } diff --git a/OpenRA.Mods.RA/Move/Mobile.cs b/OpenRA.Mods.RA/Move/Mobile.cs index 1679654e42..fb315d6267 100755 --- a/OpenRA.Mods.RA/Move/Mobile.cs +++ b/OpenRA.Mods.RA/Move/Mobile.cs @@ -232,18 +232,23 @@ namespace OpenRA.Mods.RA.Move { CenterPosition = pos; if (self.IsInWorld) + { self.World.ScreenMap.Update(self); + self.World.ActorMap.UpdatePosition(self, this); + } } public void AddedToWorld(Actor self) { self.World.ActorMap.AddInfluence(self, this); + self.World.ActorMap.AddPosition(self, this); self.World.ScreenMap.Add(self); } public void RemovedFromWorld(Actor self) { self.World.ActorMap.RemoveInfluence(self, this); + self.World.ActorMap.RemovePosition(self, this); self.World.ScreenMap.Remove(self); } From 3f8d75a1ac5e347cb45faa9b2407566e808b08a4 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 21 Sep 2013 16:31:07 +1200 Subject: [PATCH 6/7] Remove SpatialBins. --- OpenRA.Game/OpenRA.Game.csproj | 1 - OpenRA.Game/Traits/World/ActorMap.cs | 26 ++++++++ OpenRA.Game/Traits/World/SpatialBins.cs | 87 ------------------------- OpenRA.Game/WorldUtils.cs | 7 +- mods/cnc/rules/system.yaml | 2 - mods/d2k/rules/system.yaml | 2 - mods/ra/rules/system.yaml | 2 - mods/ts/rules/system.yaml | 2 - 8 files changed, 28 insertions(+), 101 deletions(-) delete mode 100644 OpenRA.Game/Traits/World/SpatialBins.cs diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj index 96e9c36fa4..410110aeee 100644 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -184,7 +184,6 @@ - diff --git a/OpenRA.Game/Traits/World/ActorMap.cs b/OpenRA.Game/Traits/World/ActorMap.cs index 7a74294f40..26a845fb51 100644 --- a/OpenRA.Game/Traits/World/ActorMap.cs +++ b/OpenRA.Game/Traits/World/ActorMap.cs @@ -8,6 +8,7 @@ */ #endregion +using System; using System.Collections.Generic; using System.Linq; using OpenRA.FileFormats; @@ -150,5 +151,30 @@ namespace OpenRA.Traits RemovePosition(a, ios); AddPosition(a, ios); } + + public IEnumerable ActorsInBox(WPos a, WPos b) + { + var left = Math.Min(a.X, b.X); + var top = Math.Min(a.Y, b.Y); + var right = Math.Max(a.X, b.X); + var bottom = Math.Max(a.Y, b.Y); + var i1 = (left / info.BinSize).Clamp(0, cols - 1); + var i2 = (right / info.BinSize).Clamp(0, cols - 1); + var j1 = (top / info.BinSize).Clamp(0, rows - 1); + var j2 = (bottom / info.BinSize).Clamp(0, rows - 1); + + for (var j = j1; j <= j2; j++) + { + for (var i = i1; i <= i2; i++) + { + foreach (var actor in actors[j*cols + i]) + { + var c = actor.CenterPosition; + if (left <= c.X && c.X <= right && top <= c.Y && c.Y <= bottom) + yield return actor; + } + } + } + } } } diff --git a/OpenRA.Game/Traits/World/SpatialBins.cs b/OpenRA.Game/Traits/World/SpatialBins.cs deleted file mode 100644 index a6b17a508c..0000000000 --- a/OpenRA.Game/Traits/World/SpatialBins.cs +++ /dev/null @@ -1,87 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2011 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.Generic; -using System.Drawing; -using System.Linq; - -namespace OpenRA.Traits -{ - class SpatialBinsInfo : ITraitInfo - { - public readonly int BinSize = 8; - public object Create(ActorInitializer init) { return new SpatialBins( init.self, this ); } - } - - class SpatialBins : ITick - { - List[,] bins; - int scale; - - public SpatialBins(Actor self, SpatialBinsInfo info) - { - bins = new List[ - self.World.Map.MapSize.X / info.BinSize, - self.World.Map.MapSize.Y / info.BinSize]; - - scale = Game.CellSize * info.BinSize; - - for (var j = 0; j <= bins.GetUpperBound(1); j++) - for (var i = 0; i <= bins.GetUpperBound(0); i++) - bins[i, j] = new List(); - } - - public void Tick(Actor self) - { - for (var j = 0; j <= bins.GetUpperBound(1); j++) - for (var i = 0; i <= bins.GetUpperBound(0); i++) - bins[i, j].Clear(); - - foreach (var a in self.World.ActorsWithTrait()) - { - var bounds = a.Actor.ExtendedBounds.Value; - - if (bounds.Right <= Game.CellSize * self.World.Map.Bounds.Left) continue; - if (bounds.Bottom <= Game.CellSize * self.World.Map.Bounds.Top) continue; - if (bounds.Left >= Game.CellSize * self.World.Map.Bounds.Right) continue; - if (bounds.Top >= Game.CellSize * self.World.Map.Bounds.Bottom) continue; - - var i1 = Math.Max(0, bounds.Left / scale); - var i2 = Math.Min(bins.GetUpperBound(0), bounds.Right / scale); - var j1 = Math.Max(0, bounds.Top / scale); - var j2 = Math.Min(bins.GetUpperBound(1), bounds.Bottom / scale); - - for (var j = j1; j <= j2; j++) - for (var i = i1; i <= i2; i++) - bins[i, j].Add(a.Actor); - } - } - - IEnumerable ActorsInBins(int i1, int i2, int j1, int j2) - { - j1 = Math.Max(0, j1); j2 = Math.Min(j2, bins.GetUpperBound(1)); - i1 = Math.Max(0, i1); i2 = Math.Min(i2, bins.GetUpperBound(0)); - for (var j = j1; j <= j2; j++) - for (var i = i1; i <= i2; i++) - foreach (var a in bins[i, j]) - yield return a; - } - - public IEnumerable ActorsInBox(PPos a, PPos b) - { - var r = Rectangle.FromLTRB(a.X, a.Y, b.X, b.Y); - - return ActorsInBins(a.X / scale, b.X / scale, a.Y / scale, b.Y / scale) - .Distinct() - .Where(u => u.IsInWorld && u.ExtendedBounds.Value.IntersectsWith(r)); - } - } -} diff --git a/OpenRA.Game/WorldUtils.cs b/OpenRA.Game/WorldUtils.cs index b9c0d2a4b5..df54b6d96b 100755 --- a/OpenRA.Game/WorldUtils.cs +++ b/OpenRA.Game/WorldUtils.cs @@ -32,16 +32,13 @@ namespace OpenRA public static IEnumerable FindActorsInBox(this World world, CPos tl, CPos br) { + // TODO: Support diamond boxes for isometric maps? return world.FindActorsInBox(tl.TopLeft, br.BottomRight); } public static IEnumerable FindActorsInBox(this World world, WPos tl, WPos br) { - var a = PPos.FromWPos(tl); - var b = PPos.FromWPos(br); - var u = PPos.Min(a, b); - var v = PPos.Max(a, b); - return world.WorldActor.Trait().ActorsInBox(u,v); + return world.ActorMap.ActorsInBox(tl, br); } public static Actor ClosestTo(this IEnumerable actors, Actor a) diff --git a/mods/cnc/rules/system.yaml b/mods/cnc/rules/system.yaml index 4909e4f53d..748199d14b 100644 --- a/mods/cnc/rules/system.yaml +++ b/mods/cnc/rules/system.yaml @@ -365,8 +365,6 @@ World: BaseActor: mcv SupportActors: e1,e1,e1,e1,e1,e2,e2,e2,e3,e3,apc,mtnk SpawnMPUnits: - SpatialBins: - BinSize: 4 CrateSpawner: Minimum: 1 Maximum: 6 diff --git a/mods/d2k/rules/system.yaml b/mods/d2k/rules/system.yaml index e9bc422318..f719298a56 100644 --- a/mods/d2k/rules/system.yaml +++ b/mods/d2k/rules/system.yaml @@ -476,8 +476,6 @@ World: Races: ordos BaseActor: mcvo SpawnMPUnits: - SpatialBins: - BinSize: 4 PathFinder: ValidateOrder: DebugPauseState: diff --git a/mods/ra/rules/system.yaml b/mods/ra/rules/system.yaml index 384c8e8d58..4881555cd3 100644 --- a/mods/ra/rules/system.yaml +++ b/mods/ra/rules/system.yaml @@ -682,8 +682,6 @@ World: OuterSupportRadius: 5 MPStartLocations: SpawnMPUnits: - SpatialBins: - BinSize: 4 PathFinder: ValidateOrder: DebugPauseState: diff --git a/mods/ts/rules/system.yaml b/mods/ts/rules/system.yaml index 52cc6ddb03..d0567f83e1 100644 --- a/mods/ts/rules/system.yaml +++ b/mods/ts/rules/system.yaml @@ -124,8 +124,6 @@ World: BaseActor: mcv MPStartLocations: SpawnMPUnits: - SpatialBins: - BinSize: 4 PathFinder: ValidateOrder: DebugPauseState: From ad44610e5aec51746dc975efc5912fff091412a4 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 21 Sep 2013 17:15:46 +1200 Subject: [PATCH 7/7] Replace dynamic Actor.Bounds with the (unchanging) relative rect. --- OpenRA.Game/Actor.cs | 60 +++++-------------- OpenRA.Game/Graphics/WorldRenderer.cs | 13 +++-- OpenRA.Game/Traits/Selectable.cs | 4 ++ OpenRA.Game/Traits/SelectionDecorations.cs | 3 + OpenRA.Game/Traits/World/ScreenMap.cs | 68 ++++++++++++++-------- OpenRA.Mods.RA/GainsExperience.cs | 7 ++- 6 files changed, 77 insertions(+), 78 deletions(-) diff --git a/OpenRA.Game/Actor.cs b/OpenRA.Game/Actor.cs index e9adebf8dd..4fcd7f5f5e 100755 --- a/OpenRA.Game/Actor.cs +++ b/OpenRA.Game/Actor.cs @@ -24,13 +24,11 @@ namespace OpenRA public readonly World World; public readonly uint ActorID; + public Lazy Bounds; Lazy occupySpace; Lazy facing; - public Cached Bounds; - public Cached ExtendedBounds; - public IOccupySpace OccupiesSpace { get { return occupySpace.Value; } } public CPos Location { get { return occupySpace.Value.TopLeft; } } @@ -76,27 +74,25 @@ namespace OpenRA facing = Lazy.New(() => TraitOrDefault()); - size = Lazy.New(() => - { - var si = Info.Traits.GetOrDefault(); - if (si != null && si.Bounds != null) - return new int2(si.Bounds[0], si.Bounds[1]); - - return TraitsImplementing().Select(x => x.SelectionSize(this)).FirstOrDefault(); - }); - applyIRender = (x, wr) => x.Render(this, wr); applyRenderModifier = (m, p, wr) => p.ModifyRender(this, wr, m); - Bounds = Cached.New(() => CalculateBounds(false)); - ExtendedBounds = Cached.New(() => CalculateBounds(true)); + Bounds = Lazy.New(() => + { + var si = Info.Traits.GetOrDefault(); + var size = (si != null && si.Bounds != null) ? new int2(si.Bounds[0], si.Bounds[1]) : + TraitsImplementing().Select(x => x.SelectionSize(this)).FirstOrDefault(); + + var offset = -size / 2; + if (si != null && si.Bounds != null && si.Bounds.Length > 2) + offset += new int2(si.Bounds[2], si.Bounds[3]); + + return new Rectangle(offset.X, offset.Y, size.X, size.Y); + }); } public void Tick() { - Bounds.Invalidate(); - ExtendedBounds.Invalidate(); - currentActivity = Traits.Util.RunActivity(this, currentActivity); } @@ -105,8 +101,6 @@ namespace OpenRA get { return currentActivity == null; } } - OpenRA.FileFormats.Lazy size; - // note: these delegates are cached to avoid massive allocation. Func> applyIRender; Func, IRenderModifier, WorldRenderer, IEnumerable> applyRenderModifier; @@ -117,34 +111,6 @@ namespace OpenRA return mods.Aggregate(sprites, (m, p) => applyRenderModifier(m, p, wr)); } - // When useAltitude = true, the bounding box is extended - // vertically to altitude = 0 to support FindUnitsInCircle queries - // When false, the bounding box is given for the actor - // at its current altitude - Rectangle CalculateBounds(bool useAltitude) - { - var sizeVector = (PVecInt)size.Value; - var loc = CenterLocation - sizeVector / 2; - - var si = Info.Traits.GetOrDefault(); - if (si != null && si.Bounds != null && si.Bounds.Length > 2) - { - loc += new PVecInt(si.Bounds[2], si.Bounds[3]); - } - - var ios = occupySpace.Value; - if (ios != null) - { - var altitude = ios.CenterPosition.Z * Game.CellSize / 1024; - loc -= new PVecInt(0, altitude); - - if (useAltitude) - sizeVector = new PVecInt(sizeVector.X, sizeVector.Y + altitude); - } - - return new Rectangle(loc.X, loc.Y, sizeVector.X, sizeVector.Y); - } - public bool IsInWorld { get; internal set; } public void QueueActivity(bool queued, Activity nextActivity) diff --git a/OpenRA.Game/Graphics/WorldRenderer.cs b/OpenRA.Game/Graphics/WorldRenderer.cs index 65c989d36a..56c2f10c9b 100644 --- a/OpenRA.Game/Graphics/WorldRenderer.cs +++ b/OpenRA.Game/Graphics/WorldRenderer.cs @@ -150,14 +150,15 @@ namespace OpenRA.Graphics Game.Renderer.Flush(); } - public void DrawSelectionBox(Actor selectedUnit, Color c) + public void DrawSelectionBox(Actor a, Color c) { - var bounds = selectedUnit.Bounds.Value; + var pos = ScreenPxPosition(a.CenterPosition); + var bounds = a.Bounds.Value; - var xy = new float2(bounds.Left, bounds.Top); - var Xy = new float2(bounds.Right, bounds.Top); - var xY = new float2(bounds.Left, bounds.Bottom); - var XY = new float2(bounds.Right, bounds.Bottom); + var xy = pos + new float2(bounds.Left, bounds.Top); + var Xy = pos + new float2(bounds.Right, bounds.Top); + var xY = pos + new float2(bounds.Left, bounds.Bottom); + var XY = pos + new float2(bounds.Right, bounds.Bottom); var wlr = Game.Renderer.WorldLineRenderer; wlr.DrawLine(xy, xy + new float2(4, 0), c, c); diff --git a/OpenRA.Game/Traits/Selectable.cs b/OpenRA.Game/Traits/Selectable.cs index 0a5d6d9609..b01cc222c8 100644 --- a/OpenRA.Game/Traits/Selectable.cs +++ b/OpenRA.Game/Traits/Selectable.cs @@ -40,7 +40,9 @@ namespace OpenRA.Traits if (!Info.Selectable) return; + var pos = wr.ScreenPxPosition(self.CenterPosition); var bounds = self.Bounds.Value; + bounds.Offset(pos.X, pos.Y); var xy = new float2(bounds.Left, bounds.Top); var Xy = new float2(bounds.Right, bounds.Top); @@ -56,7 +58,9 @@ namespace OpenRA.Traits if (!Info.Selectable) return; + var pos = wr.ScreenPxPosition(self.CenterPosition); var bounds = self.Bounds.Value; + bounds.Offset(pos.X, pos.Y); var xy = new float2(bounds.Left, bounds.Top); var Xy = new float2(bounds.Right, bounds.Top); diff --git a/OpenRA.Game/Traits/SelectionDecorations.cs b/OpenRA.Game/Traits/SelectionDecorations.cs index d9981c52b5..be999bd9b9 100644 --- a/OpenRA.Game/Traits/SelectionDecorations.cs +++ b/OpenRA.Game/Traits/SelectionDecorations.cs @@ -34,7 +34,10 @@ namespace OpenRA.Traits if (self.World.FogObscures(self)) return; + var pos = wr.ScreenPxPosition(self.CenterPosition); var bounds = self.Bounds.Value; + bounds.Offset(pos.X, pos.Y); + var xy = new float2(bounds.Left, bounds.Top); var xY = new float2(bounds.Left, bounds.Bottom); diff --git a/OpenRA.Game/Traits/World/ScreenMap.cs b/OpenRA.Game/Traits/World/ScreenMap.cs index bfbde690ff..684a60c365 100755 --- a/OpenRA.Game/Traits/World/ScreenMap.cs +++ b/OpenRA.Game/Traits/World/ScreenMap.cs @@ -26,11 +26,12 @@ namespace OpenRA.Traits public object Create(ActorInitializer init) { return new ScreenMap(init.world, this); } } - public class ScreenMap + public class ScreenMap : IWorldLoaded { ScreenMapInfo info; - Cache[]> frozen; - List[] actors; + WorldRenderer worldRenderer; + Cache[]> frozen; + Dictionary[] actors; int rows, cols; public ScreenMap(World world, ScreenMapInfo info) @@ -39,33 +40,39 @@ namespace OpenRA.Traits cols = world.Map.MapSize.X * Game.CellSize / info.BinSize + 1; rows = world.Map.MapSize.Y * Game.CellSize / info.BinSize + 1; - frozen = new Cache[]>(InitializeFrozenActors); - actors = new List[rows * cols]; + frozen = new Cache[]>(InitializeFrozenActors); + actors = new Dictionary[rows * cols]; for (var j = 0; j < rows; j++) for (var i = 0; i < cols; i++) - actors[j * cols + i] = new List(); + actors[j * cols + i] = new Dictionary(); } - List[] InitializeFrozenActors(Player p) + public void WorldLoaded(World w, WorldRenderer wr) { worldRenderer = wr; } + + Dictionary[] InitializeFrozenActors(Player p) { - var f = new List[rows * cols]; + var f = new Dictionary[rows * cols]; for (var j = 0; j < rows; j++) for (var i = 0; i < cols; i++) - f[j * cols + i] = new List(); + f[j * cols + i] = new Dictionary(); return f; } public void Add(Player viewer, FrozenActor fa) { - var top = Math.Max(0, fa.Bounds.Top / info.BinSize); - var left = Math.Max(0, fa.Bounds.Left / info.BinSize); - var bottom = Math.Min(rows - 1, fa.Bounds.Bottom / info.BinSize); - var right = Math.Min(cols - 1, fa.Bounds.Right / info.BinSize); + var pos = worldRenderer.ScreenPxPosition(fa.CenterPosition); + var bounds = fa.Bounds; + bounds.Offset(pos.X, pos.Y); + + var top = Math.Max(0, bounds.Top / info.BinSize); + var left = Math.Max(0, bounds.Left / info.BinSize); + var bottom = Math.Min(rows - 1, bounds.Bottom / info.BinSize); + var right = Math.Min(cols - 1, bounds.Right / info.BinSize); for (var j = top; j <= bottom; j++) for (var i = left; i <= right; i++) - frozen[viewer][j*cols + i].Add(fa); + frozen[viewer][j*cols + i].Add(fa, bounds); } public void Remove(Player viewer, FrozenActor fa) @@ -76,15 +83,18 @@ namespace OpenRA.Traits public void Add(Actor a) { - var b = a.Bounds.Value; - var top = Math.Max(0, b.Top / info.BinSize); - var left = Math.Max(0, b.Left / info.BinSize); - var bottom = Math.Min(rows - 1, b.Bottom / info.BinSize); - var right = Math.Min(cols - 1, b.Right / info.BinSize); + var pos = worldRenderer.ScreenPxPosition(a.CenterPosition); + var bounds = a.Bounds.Value; + bounds.Offset(pos.X, pos.Y); + + var top = Math.Max(0, bounds.Top / info.BinSize); + var left = Math.Max(0, bounds.Left / info.BinSize); + var bottom = Math.Min(rows - 1, bounds.Bottom / info.BinSize); + var right = Math.Min(cols - 1, bounds.Right / info.BinSize); for (var j = top; j <= bottom; j++) for (var i = left; i <= right; i++) - actors[j * cols + i].Add(a); + actors[j * cols + i].Add(a, bounds); } public void Remove(Actor a) @@ -103,14 +113,18 @@ namespace OpenRA.Traits { var i = (pxPos.X / info.BinSize).Clamp(0, cols - 1); var j = (pxPos.Y / info.BinSize).Clamp(0, rows - 1); - return frozen[viewer][j*cols + i].Where(fa => fa.Bounds.Contains(pxPos) && fa.IsValid); + return frozen[viewer][j*cols + i] + .Where(kv => kv.Key.IsValid && kv.Value.Contains(pxPos)) + .Select(kv => kv.Key); } public IEnumerable ActorsAt(int2 pxPos) { var i = (pxPos.X / info.BinSize).Clamp(0, cols - 1); var j = (pxPos.Y / info.BinSize).Clamp(0, rows - 1); - return actors[j*cols + i].Where(a => a.Bounds.Value.Contains(pxPos) && a.IsInWorld); + return actors[j * cols + i] + .Where(kv => kv.Key.IsInWorld && kv.Value.Contains(pxPos)) + .Select(kv => kv.Key); } // Legacy fallback @@ -129,9 +143,17 @@ namespace OpenRA.Traits var bottom = (r.Bottom / info.BinSize).Clamp(0, rows - 1); for (var j = top; j <= bottom; j++) + { for (var i = left; i <= right; i++) - foreach (var a in actors[j*cols + i].Where(b => b.Bounds.Value.IntersectsWith(r) && b.IsInWorld)) + { + var ret = actors[j * cols + i] + .Where(kv => kv.Key.IsInWorld && kv.Value.IntersectsWith(r)) + .Select(kv => kv.Key); + + foreach (var a in ret) yield return a; + } + } } } } diff --git a/OpenRA.Mods.RA/GainsExperience.cs b/OpenRA.Mods.RA/GainsExperience.cs index 135e4ba4b1..5c9edd51e0 100644 --- a/OpenRA.Mods.RA/GainsExperience.cs +++ b/OpenRA.Mods.RA/GainsExperience.cs @@ -117,9 +117,12 @@ namespace OpenRA.Mods.RA if (self.World.FogObscures(self)) yield break; + var pos = wr.ScreenPxPosition(self.CenterPosition); var bounds = self.Bounds.Value; - var pos = new PPos(bounds.Right, bounds.Bottom - 2).ToWPos(0); - yield return new SpriteRenderable(RankAnim.Image, pos, WVec.Zero, 0, wr.Palette("effect"), 1f, true); + bounds.Offset(pos.X, pos.Y); + + var effectPos = new PPos(bounds.Right, bounds.Bottom - 2).ToWPos(0); + yield return new SpriteRenderable(RankAnim.Image, effectPos, WVec.Zero, 0, wr.Palette("effect"), 1f, true); } }