diff --git a/OpenRa.Game/Chrome.cs b/OpenRa.Game/Chrome.cs index 2da6386970..20350c86c6 100644 --- a/OpenRa.Game/Chrome.cs +++ b/OpenRa.Game/Chrome.cs @@ -74,6 +74,11 @@ namespace OpenRa static float2 powerOrigin = new float2(42, 205); // Relative to radarOrigin static Size powerSize = new Size(138,5); + // mapchooser + Sheet mapChooserSheet; + Sprite mapChooserSprite; + Sprite colorBlock; + public Chrome(Renderer r) { this.renderer = r; @@ -137,6 +142,9 @@ namespace OpenRa ready = new Animation("pips"); ready.PlayRepeating("ready"); clock = new Animation("clock"); + + mapChooserSheet = new Sheet(r, new Size(128, 128)); + colorBlock = SheetBuilder.Add(new Size(65 - 8, 22 - 8), 0x54); } public void Tick() @@ -223,16 +231,29 @@ namespace OpenRa AddButton(r, _ => { }); } - Lazy> mapList = Lazy.New( + class MapInfo + { + public readonly string Filename; + public readonly Map Map; + + public MapInfo(string filename) + { + Filename = filename.ToLowerInvariant(); + Map = new Map(new IniFile(FileSystem.Open(Filename))); + } + }; + + Lazy> mapList = Lazy.New( () => { var builtinMaps = new IniFile(FileSystem.Open("missions.pkt")).GetSection("Missions").Select(a => a.Key); var mapsFolderMaps = Directory.GetFiles("maps/"); - return builtinMaps.Concat(mapsFolderMaps).ToList(); + return builtinMaps.Concat(mapsFolderMaps).Select(a => new MapInfo(a)).ToList(); }); bool showMapChooser = false; - string currentMap; + MapInfo currentMap; + bool mapPreviewDirty = true; void AddUiButton(int2 pos, string text, Action a) { @@ -244,7 +265,7 @@ namespace OpenRa public void DrawMapChooser() { - var w = 600; + var w = 800; var h = 600; var r = new Rectangle( (Game.viewport.Width - w) / 2, (Game.viewport.Height - h) / 2, w, h ); DrawDialogBackground(r, optionsSprites, true); @@ -256,8 +277,7 @@ namespace OpenRa AddUiButton(new int2(r.Left + 200, r.Bottom - 40), "OK", _ => { - Game.orderManager.IssueOrder( - Order.Chat("/map " + currentMap)); + Game.orderManager.IssueOrder(Order.Chat("/map " + currentMap.Filename)); showMapChooser = false; }); @@ -267,23 +287,78 @@ namespace OpenRa showMapChooser = false; }); + if (mapPreviewDirty) + { + var b = Minimap.RenderTerrainBitmap(currentMap.Map, Game.world.TileSet); // tileset -> hack + mapChooserSheet.Texture.SetData(b); + mapChooserSprite = new Sprite(mapChooserSheet, + Minimap.MakeMinimapBounds(currentMap.Map), TextureChannel.Alpha); + mapPreviewDirty = false; + } + + var mapRect = new Rectangle(r.Right - 280, r.Top + 30, 256, 256); + DrawDialogBackground(mapRect, panelSprites, false); + rgbaRenderer.DrawSprite(mapChooserSprite, + new float2(mapRect.Location) + new float2(4, 4), + PaletteType.Chrome, + new float2(mapRect.Size) - new float2(8, 8)); + rgbaRenderer.Flush(); + var y = r.Top + 50; foreach (var map in mapList.Value) { - var itemRect = new Rectangle(r.Left + 50, y - 2, r.Width - 100, 20); - if (map.ToLowerInvariant() == currentMap) + var itemRect = new Rectangle(r.Left + 50, y - 2, r.Width - 340, 20); + if (map == currentMap) DrawDialogBackground(itemRect, panelSprites, false); - renderer.DrawText(map, new int2(r.Left + 60, y), Color.White); - var closureMap = map.ToLowerInvariant(); - AddButton(itemRect, _ => currentMap = closureMap); + renderer.DrawText(map.Map.Title, new int2(r.Left + 60, y), Color.White); + var closureMap = map; + AddButton(itemRect, _ => { currentMap = closureMap; mapPreviewDirty = true; }); y += 20; } + y = mapRect.Bottom + 20; + DrawCentered("Title: {0}".F(currentMap.Map.Title, currentMap.Map.Height), + new int2(mapRect.Left + mapRect.Width / 2, y), Color.White); + y += 20; + DrawCentered("Size: {0}x{1}".F(currentMap.Map.Width, currentMap.Map.Height), + new int2(mapRect.Left + mapRect.Width / 2, y), Color.White); + y += 20; + DrawCentered("Theater: {0}".F(currentMap.Map.Theater, currentMap.Map.Height), + new int2(mapRect.Left + mapRect.Width / 2, y), Color.White); + y += 20; + DrawCentered("Spawnpoints: {0}".F(currentMap.Map.SpawnPoints.Count()), + new int2(mapRect.Left + mapRect.Width / 2, y), Color.White); + AddButton(r, _ => { }); } + bool PaletteAvailable(int palette) { return Game.LobbyInfo.Clients.All(c => c.Palette != palette); } + + void CyclePalette(bool left) + { + var d = left ? 1 : 7; + var newpalette = ((int)Game.world.LocalPlayer.Palette + d) % 8; + while (!PaletteAvailable(newpalette) && newpalette != (int)Game.world.LocalPlayer.Palette) + newpalette = (newpalette + d) % 8; + + Game.orderManager.IssueOrder( + Order.Chat("/pal " + newpalette)); + } + + void CycleRace(bool left) + { + Game.orderManager.IssueOrder( + Order.Chat("/race " + (((int)Game.world.LocalPlayer.Race - 1) ^ 1))); + } + + void CycleReady(bool left) + { + Game.orderManager.IssueOrder( + new Order("ToggleReady", Game.world.LocalPlayer.PlayerActor, "") { IsImmediate = true }); + } + public void DrawLobby( World world ) { buttons.Clear(); @@ -327,12 +402,14 @@ namespace OpenRa if (isLmb) { showMapChooser = true; - currentMap = Game.LobbyInfo.GlobalSettings.Map.ToLowerInvariant(); + currentMap = mapList.Value.Single( + m => m.Filename == Game.LobbyInfo.GlobalSettings.Map.ToLowerInvariant()); + mapPreviewDirty = true; } }); } - renderer.DrawText2("Name", new int2(r.Left + 30, r.Top + 50), Color.White); + renderer.DrawText2("Name", new int2(r.Left + 40, r.Top + 50), Color.White); renderer.DrawText2("Color", new int2(r.Left + 230, r.Top + 50), Color.White); renderer.DrawText2("Faction", new int2(r.Left + 300, r.Top + 50), Color.White); renderer.DrawText2("Status", new int2(r.Left + 370, r.Top + 50), Color.White); @@ -340,8 +417,38 @@ namespace OpenRa var y = r.Top + 80; foreach (var client in Game.LobbyInfo.Clients) { - renderer.DrawText(client.Name, new int2(r.Left + 30, y), Color.White); - renderer.DrawText(((PaletteType)client.Palette).ToString(), new int2(r.Left + 230, y), Color.White); + var isLocalPlayer = client.Index == Game.orderManager.Connection.LocalClientId; + var paletteRect = new Rectangle(r.Left + 220, y - 2, 65, 22); + + if (isLocalPlayer) + { + // todo: name editing + var nameRect = new Rectangle(r.Left + 30, y - 2, 185, 22); + DrawDialogBackground(nameRect, panelSprites, false); + + DrawDialogBackground(paletteRect, panelSprites, false); + AddButton(paletteRect, CyclePalette); + + shpRenderer.DrawSprite(colorBlock, new float2(paletteRect.Left + 4, paletteRect.Top + 4), + (PaletteType)client.Palette); + + var raceRect = new Rectangle(r.Left + 290, y - 2, 65, 22); + DrawDialogBackground(raceRect, panelSprites, false); + AddButton(raceRect, CycleRace); + + var readyRect = new Rectangle(r.Left + 360, y - 2, 95, 22); + DrawDialogBackground(readyRect, panelSprites, false); + AddButton(readyRect, CycleReady); + } + + shpRenderer.Flush(); + + renderer.DrawText(client.Name, new int2(r.Left + 40, y), Color.White); + + + shpRenderer.DrawSprite(colorBlock, new float2(paletteRect.Left + 4, paletteRect.Top + 4), + (PaletteType)client.Palette); + renderer.DrawText(((Race)client.Race).ToString(), new int2(r.Left + 300, y), Color.White); renderer.DrawText(client.State.ToString(), new int2(r.Left + 370, y), Color.White); y += 30; diff --git a/OpenRa.Game/Game.cs b/OpenRa.Game/Game.cs index f1a55533ec..e9e2f4db2e 100644 --- a/OpenRa.Game/Game.cs +++ b/OpenRa.Game/Game.cs @@ -271,13 +271,6 @@ namespace OpenRa { int sync = Game.world.SyncHash(); - /* hack hack hack */ - if( e.KeyCode == Keys.F8 && !Game.orderManager.GameStarted ) - { - Game.orderManager.IssueOrder( - new Order( "ToggleReady", Game.world.LocalPlayer.PlayerActor, "" ) { IsImmediate = true } ); - } - if( !Game.chat.isChatting ) if( e.KeyCode >= Keys.D0 && e.KeyCode <= Keys.D9 ) Game.controller.DoControlGroup( world, (int)e.KeyCode - (int)Keys.D0, (Modifiers)(int)e.Modifiers ); diff --git a/OpenRa.Game/Graphics/Minimap.cs b/OpenRa.Game/Graphics/Minimap.cs index a0a1d9f1b0..73a1495591 100644 --- a/OpenRa.Game/Graphics/Minimap.cs +++ b/OpenRa.Game/Graphics/Minimap.cs @@ -4,6 +4,7 @@ using System.Linq; using OpenRa.Traits; using OpenRa.FileFormats; using System.Drawing.Imaging; +using IjwFramework.Collections; namespace OpenRa.Graphics { @@ -35,50 +36,63 @@ namespace OpenRa.Graphics mapOnlySprite = new Sprite(mapOnlySheet, rect, TextureChannel.Alpha); } - Color[] terrainTypeColors; + public static Rectangle MakeMinimapBounds(Map m) + { + var size = Math.Max(m.Width, m.Height); + var dw = (size - m.Width) / 2; + var dh = (size - m.Height) / 2; + + return new Rectangle(m.Offset.X - dw, m.Offset.Y - dh, size, size); + } + + static Cache terrainTypeColors = new Cache( + theater => + { + var pal = new Palette(FileSystem.Open(theater + ".pal")); + return new[] { + theater == "snow" ? 0xe3 :0x1a, + 0x63, 0x2f, 0x1f, 0x14, 0x64, 0x1f, 0x68, 0x6b, 0x6d, 0x88 } + .Select(a => Color.FromArgb(alpha, pal.GetColor(a))).ToArray(); + }); + Color[] playerColors; - Color shroudColor; + static Color shroudColor; string theater; public void InvalidateOre() { oreLayer = null; } + public static Bitmap RenderTerrainBitmap(Map map, TileSet tileset) + { + var colors = terrainTypeColors[map.Theater.ToLowerInvariant()]; + var terrain = new Bitmap(128, 128); + for (var y = 0; y < 128; y++) + for (var x = 0; x < 128; x++) + terrain.SetPixel(x, y, map.IsInMap(x, y) + ? colors[tileset.GetWalkability(map.MapTiles[x, y])] + : shroudColor); + + return terrain; + } + public void Update() { - if (world.Map.Theater != theater) - { - terrainTypeColors = null; - theater = world.Map.Theater; - } - if (terrainTypeColors == null) { - var pal = new Palette(FileSystem.Open(world.Map.Theater + ".pal")); - terrainTypeColors = new[] { - theater.ToLowerInvariant() == "snow" ? 0xe3 :0x1a, - 0x63, 0x2f, 0x1f, 0x14, 0x64, 0x1f, 0x68, 0x6b, 0x6d, 0x88 } - .Select( a => Color.FromArgb(alpha, pal.GetColor(a) )).ToArray(); - playerColors = Util.MakeArray( 8, b => Color.FromArgb(alpha, Chat.paletteColors[b]) ); shroudColor = Color.FromArgb(alpha, Color.Black); } - + if (terrain == null) - { - terrain = new Bitmap(128, 128); - for (var y = 0; y < 128; y++) - for (var x = 0; x < 128; x++) - terrain.SetPixel(x, y, world.Map.IsInMap(x, y) - ? terrainTypeColors[world.TileSet.GetWalkability(world.Map.MapTiles[x, y])] - : shroudColor); - } + terrain = RenderTerrainBitmap(world.Map, world.TileSet); if (oreLayer == null) { + var colors = terrainTypeColors[world.Map.Theater.ToLowerInvariant()]; oreLayer = new Bitmap(terrain); for (var y = 0; y < 128; y++) for (var x = 0; x < 128; x++) if (world.Map.ContainsResource(new int2(x, y))) - oreLayer.SetPixel(x, y, terrainTypeColors[(int)TerrainMovementType.Ore]); + oreLayer.SetPixel(x, y, colors[(int)TerrainMovementType.Ore]); } mapOnlySheet.Texture.SetData(oreLayer); @@ -92,6 +106,7 @@ namespace OpenRa.Graphics unsafe { + var colors = terrainTypeColors[world.Map.Theater.ToLowerInvariant()]; int* c = (int*)bitmapData.Scan0; for (var y = 0; y < 128; y++) @@ -100,7 +115,7 @@ namespace OpenRa.Graphics var b = world.BuildingInfluence.GetBuildingAt(new int2(x, y)); if (b != null) *(c + (y * bitmapData.Stride >> 2) + x) = - (b.Owner != null ? playerColors[(int)b.Owner.Palette] : terrainTypeColors[4]).ToArgb(); + (b.Owner != null ? playerColors[(int)b.Owner.Palette] : colors[4]).ToArgb(); } foreach (var a in world.Actors.Where(a => a.traits.Contains()))