Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Map chooser polish & refactoring #2968

Merged
merged 15 commits into from
Apr 6, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion OpenRA.Game/Game.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,8 @@ static void Tick( OrderManager orderManager )
else
if (orderManager.NetFrameNumber == 0)
orderManager.LastTickTime = Environment.TickCount;


world.TickRender(worldRenderer);
viewport.Tick();
}
}
Expand Down
1 change: 1 addition & 0 deletions OpenRA.Game/OpenRA.Game.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@
<Compile Include="World.cs" />
<Compile Include="WorldUtils.cs" />
<Compile Include="Network\ReplayRecorderConnection.cs" />
<Compile Include="Widgets\TooltipContainerWidget.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">
Expand Down
1 change: 1 addition & 0 deletions OpenRA.Game/Traits/TraitsInterfaces.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public class AttackInfo
}

public interface ITick { void Tick(Actor self); }
public interface ITickRender { void TickRender(WorldRenderer wr, Actor self); }
public interface IRender { IEnumerable<Renderable> Render(Actor self, WorldRenderer wr); }
public interface IAutoSelectionSize { int2 SelectionSize(Actor self); }

Expand Down
138 changes: 117 additions & 21 deletions OpenRA.Game/Widgets/MapPreviewWidget.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,31 +12,42 @@
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading;
using OpenRA.FileFormats;
using OpenRA.Graphics;
using OpenRA.Network;

namespace OpenRA.Widgets
{
public class MapPreviewWidget : Widget
{
public Func<Map> Map = () => null;
public Func<Dictionary<int2, Color>> SpawnColors = () => new Dictionary<int2, Color>();
public Func<Dictionary<int2, Session.Client>> SpawnClients = () => new Dictionary<int2, Session.Client>();
public Action<MouseInput> OnMouseDown = _ => {};
public Action<int, int2> OnTooltip = (_, __) => { };
public bool IgnoreMouseInput = false;
public bool ShowSpawnPoints = true;

static readonly Cache<Map,Bitmap> PreviewCache = new Cache<Map, Bitmap>(stub => Minimap.RenderMapPreview( new Map( stub.Path )));
public readonly string TooltipContainer;
public readonly string TooltipTemplate = "SPAWN_TOOLTIP";
Lazy<TooltipContainerWidget> tooltipContainer;
public int TooltipSpawnIndex = -1;

public MapPreviewWidget() : base() { }
public MapPreviewWidget() : base()
{
tooltipContainer = Lazy.New(() => Ui.Root.Get<TooltipContainerWidget>(TooltipContainer));
}

protected MapPreviewWidget(MapPreviewWidget other)
: base(other)
{
lastMap = other.lastMap;
Map = other.Map;
SpawnColors = other.SpawnColors;
SpawnClients = other.SpawnClients;
ShowSpawnPoints = other.ShowSpawnPoints;
TooltipTemplate = other.TooltipTemplate;
TooltipContainer = other.TooltipContainer;
tooltipContainer = Lazy.New(() => Ui.Root.Get<TooltipContainerWidget>(TooltipContainer));
}

public override Widget Clone() { return new MapPreviewWidget(this); }
Expand All @@ -53,6 +64,18 @@ public override bool HandleMouseInput(MouseInput mi)
return true;
}

public override void MouseEntered()
{
if (TooltipContainer == null) return;
tooltipContainer.Value.SetTooltip(TooltipTemplate, new WidgetArgs() {{ "preview", this }});
}

public override void MouseExited()
{
if (TooltipContainer == null) return;
tooltipContainer.Value.RemoveTooltip();
}

public int2 ConvertToPreview(int2 point)
{
var map = Map();
Expand All @@ -68,19 +91,30 @@ public int2 ConvertToPreview(int2 point)
public override void Draw()
{
var map = Map();
if( map == null ) return;
if (map == null)
return;

// Preview unavailable
if (!Loaded)
{
GeneratePreview();
return;
}

if (lastMap != map)
{
lastMap = map;

// Update image data
var preview = PreviewCache[map];
if( mapChooserSheet == null || mapChooserSheet.Size.Width != preview.Width || mapChooserSheet.Size.Height != preview.Height )
mapChooserSheet = new Sheet(new Size( preview.Width, preview.Height ) );
Bitmap preview;
lock (syncRoot)
preview = Previews[map.Uid];

if (mapChooserSheet == null || mapChooserSheet.Size.Width != preview.Width || mapChooserSheet.Size.Height != preview.Height)
mapChooserSheet = new Sheet(new Size(preview.Width, preview.Height));

mapChooserSheet.Texture.SetData( preview );
mapChooserSprite = new Sprite( mapChooserSheet, new Rectangle( 0, 0, map.Bounds.Width, map.Bounds.Height ), TextureChannel.Alpha );
mapChooserSheet.Texture.SetData(preview);
mapChooserSprite = new Sprite(mapChooserSheet, new Rectangle(0, 0, map.Bounds.Width, map.Bounds.Height), TextureChannel.Alpha);
}

// Update map rect
Expand All @@ -90,13 +124,14 @@ public override void Draw()
var dh = (int)(PreviewScale * (size - map.Bounds.Height)) / 2;
MapRect = new Rectangle(RenderBounds.X + dw, RenderBounds.Y + dh, (int)(map.Bounds.Width * PreviewScale), (int)(map.Bounds.Height * PreviewScale));

Game.Renderer.RgbaSpriteRenderer.DrawSprite( mapChooserSprite,
Game.Renderer.RgbaSpriteRenderer.DrawSprite(mapChooserSprite,
new float2(MapRect.Location),
new float2( MapRect.Size ) );
new float2(MapRect.Size));

TooltipSpawnIndex = -1;
if (ShowSpawnPoints)
{
var colors = SpawnColors();
var colors = SpawnClients().ToDictionary(c => c.Key, c => c.Value.ColorRamp.GetColor(0));

var spawnPoints = map.GetSpawnPoints().ToList();
foreach (var p in spawnPoints)
Expand All @@ -113,21 +148,82 @@ public override void Draw()

if ((pos - Viewport.LastMousePos).LengthSquared < 64)
{
OnTooltip(spawnPoints.IndexOf(p) + 1, pos);
TooltipSpawnIndex = spawnPoints.IndexOf(p) + 1;

// Legacy tooltip behavior
if (TooltipContainer == null)
OnTooltip(TooltipSpawnIndex, pos);
}
}
}
}

/// <summary>
/// Forces loading the preview into the map cache.
/// </summary>
public Bitmap LoadMapPreview()
// Async map preview generation bits
enum PreviewStatus { Invalid, Uncached, Generating, Cached }
static Thread previewLoaderThread;
static object syncRoot = new object();
static Queue<string> cacheUids = new Queue<string>();
static readonly Dictionary<string, Bitmap> Previews = new Dictionary<string, Bitmap>();

void LoadAsyncInternal()
{
var map = Map();
if( map == null ) return null;
for (;;)
{
string uid;
lock (syncRoot)
{
if (cacheUids.Count == 0)
break;
uid = cacheUids.Peek();
}

return PreviewCache[map];
var bitmap = Minimap.RenderMapPreview(Game.modData.AvailableMaps[uid]);
lock (syncRoot)
{
// TODO: We should add previews to a sheet here (with multiple previews per sheet)
Previews.Add(uid, bitmap);
cacheUids.Dequeue();
}

// Yuck... But this helps the UI Jank when opening the map selector significantly.
Thread.Sleep(50);
}
}

void GeneratePreview()
{
var m = Map();
if (m == null)
return;

var status = Status(m);
if (status == PreviewStatus.Uncached)
lock (syncRoot)
cacheUids.Enqueue(m.Uid);

if (previewLoaderThread == null || !previewLoaderThread.IsAlive)
{
previewLoaderThread = new Thread(LoadAsyncInternal);
previewLoaderThread.Start();
}
}

static PreviewStatus Status(Map m)
{
if (m == null)
return PreviewStatus.Invalid;

lock (syncRoot)
{
if (Previews.ContainsKey(m.Uid))
return PreviewStatus.Cached;

if (cacheUids.Contains(m.Uid))
return PreviewStatus.Generating;
}
return PreviewStatus.Uncached;
}

public bool Loaded { get { return Status(Map()) == PreviewStatus.Cached; } }
}
}
10 changes: 10 additions & 0 deletions OpenRA.Game/Widgets/ScrollItemWidget.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ namespace OpenRA.Widgets
{
public class ScrollItemWidget : ButtonWidget
{
public string ItemKey;

public ScrollItemWidget()
: base()
{
Expand All @@ -28,6 +30,7 @@ protected ScrollItemWidget(ScrollItemWidget other)
IsVisible = () => false;
VisualHeight = 0;
IgnoreChildMouseOver = true;
Key = other.Key;
}

public Func<bool> IsSelected = () => false;
Expand Down Expand Up @@ -59,5 +62,12 @@ public static ScrollItemWidget Setup(ScrollItemWidget template, Func<bool> isSel
w.OnDoubleClick = onDoubleClick;
return w;
}

public static ScrollItemWidget Setup(string key, ScrollItemWidget template, Func<bool> isSelected, Action onClick)
{
var w = Setup(template, isSelected, onClick);
w.ItemKey = key;
return w;
}
}
}
20 changes: 20 additions & 0 deletions OpenRA.Game/Widgets/ScrollPanelWidget.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

using System;
using System.Drawing;
using System.Linq;
using OpenRA.Graphics;

namespace OpenRA.Widgets
Expand Down Expand Up @@ -143,6 +144,25 @@ public void ScrollToTop()
ListOffset = 0;
}

public void ScrollToItem(string itemKey)
{
var item = Children.FirstOrDefault(c =>
{
var si = c as ScrollItemWidget;
return si != null && si.ItemKey == itemKey;
});

if (item == null)
return;

// Scroll the item to be visible
if (item.Bounds.Top + ListOffset < 0)
ListOffset = ItemSpacing - item.Bounds.Top;

if (item.Bounds.Bottom + ListOffset > RenderBounds.Height)
ListOffset = RenderBounds.Height - item.Bounds.Bottom - ItemSpacing;
}

public override void Tick ()
{
if (UpPressed) Scroll(1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,10 @@
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Graphics;
using OpenRA.Mods.RA;
using OpenRA.Widgets;
using System;

namespace OpenRA.Mods.Cnc.Widgets
namespace OpenRA.Widgets
{
public class TooltipContainerWidget : Widget
{
Expand Down
8 changes: 7 additions & 1 deletion OpenRA.Game/World.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using System.Linq;
using OpenRA.Effects;
using OpenRA.FileFormats;
using OpenRA.Graphics;
using OpenRA.Network;
using OpenRA.Orders;
using OpenRA.Support;
Expand Down Expand Up @@ -192,7 +193,12 @@ public void Tick()

while (frameEndActions.Count != 0)
frameEndActions.Dequeue()(this);

}

// For things that want to update their render state once per tick, ignoring pause state
public void TickRender(WorldRenderer wr)
{
ActorsWithTrait<ITickRender>().Do(x => x.Trait.TickRender(wr, x.Actor));
}

public IEnumerable<Actor> Actors { get { return actors; } }
Expand Down
5 changes: 3 additions & 2 deletions OpenRA.Mods.Cnc/CncMenuPaletteEffect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using System.Collections.Generic;
using System.Drawing;
using OpenRA.FileFormats;
using OpenRA.Graphics;
using OpenRA.Traits;

namespace OpenRA.Mods.Cnc
Expand All @@ -22,7 +23,7 @@ public class CncMenuPaletteEffectInfo : ITraitInfo
public object Create(ActorInitializer init) { return new CncMenuPaletteEffect(this); }
}

public class CncMenuPaletteEffect : IPaletteModifier, ITick
public class CncMenuPaletteEffect : IPaletteModifier, ITickRender
{
public enum EffectType { None, Black, Desaturated }
public readonly CncMenuPaletteEffectInfo Info;
Expand All @@ -40,7 +41,7 @@ public void Fade(EffectType type)
to = type;
}

public void Tick(Actor self)
public void TickRender(WorldRenderer wr, Actor self)
{
if (remainingFrames > 0)
remainingFrames--;
Expand Down
2 changes: 1 addition & 1 deletion OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,10 @@
<Compile Include="Widgets\ProductionTabsWidget.cs" />
<Compile Include="Widgets\SupportPowersWidget.cs" />
<Compile Include="Widgets\ToggleButtonWidget.cs" />
<Compile Include="Widgets\TooltipContainerWidget.cs" />
<Compile Include="WithFire.cs" />
<Compile Include="WithRoof.cs" />
<Compile Include="Widgets\ResourceBarWidget.cs" />
<Compile Include="Widgets\Logic\SpawnSelectorTooltipLogic.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">
Expand Down
Loading