Add a mission objectives GUI panel

This commit is contained in:
Oliver Brakmann
2014-07-27 13:25:58 +02:00
parent 2c22e5099f
commit 8cec848a0f
46 changed files with 1252 additions and 886 deletions

View File

@@ -18,7 +18,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
public class DebugMenuLogic
{
[ObjectCreator.UseCtor]
public DebugMenuLogic(Widget widget, Action onExit, World world, bool transient)
public DebugMenuLogic(Widget widget, World world)
{
var devTrait = world.LocalPlayer.PlayerActor.Trait<DeveloperMode>();
@@ -112,21 +112,6 @@ namespace OpenRA.Mods.RA.Widgets.Logic
showAstarCostCheckbox.IsChecked = () => dbgOverlay != null ? dbgOverlay.Visible : false;
showAstarCostCheckbox.OnClick = () => { if (dbgOverlay != null) dbgOverlay.Visible ^= true; };
}
var close = widget.GetOrNull<ButtonWidget>("CLOSE");
if (close != null)
{
close.OnClick = () =>
{
if (transient)
{
Ui.CloseWindow();
Ui.Root.RemoveChild(widget);
}
onExit();
};
}
}
public void Order(World world, string order)

View File

@@ -23,7 +23,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
ScrollPanelWidget diplomacyPanel;
[ObjectCreator.UseCtor]
public DiplomacyLogic(Widget widget, Action onExit, World world, bool transient)
public DiplomacyLogic(Widget widget, Action onExit, World world)
{
this.world = world;
@@ -33,18 +33,12 @@ namespace OpenRA.Mods.RA.Widgets.Logic
var close = widget.GetOrNull<ButtonWidget>("CLOSE");
if (close != null)
{
close.OnClick = () =>
{
if (transient)
{
Ui.CloseWindow();
Ui.Root.RemoveChild(widget);
}
Ui.CloseWindow();
Ui.Root.RemoveChild(widget);
onExit();
};
}
}
void LayoutPlayers()

View File

@@ -0,0 +1,38 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Linq;
using OpenRA.Widgets;
using OpenRA.Traits;
using OpenRA.Mods.RA;
namespace OpenRA.Mods.RA.Widgets.Logic
{
class GameInfoBriefingLogic
{
[ObjectCreator.UseCtor]
public GameInfoBriefingLogic(Widget widget, World world)
{
var previewWidget = widget.Get<MapPreviewWidget>("MAP_PREVIEW");
previewWidget.Preview = () => Game.modData.MapCache[world.Map.Uid];
var mapDescriptionPanel = widget.Get<ScrollPanelWidget>("MAP_DESCRIPTION_PANEL");
var mapDescription = widget.Get<LabelWidget>("MAP_DESCRIPTION");
var mapFont = Game.Renderer.Fonts[mapDescription.Font];
var text = world.Map.Description != null ? world.Map.Description.Replace("\\n", "\n") : "";
text = WidgetUtils.WrapText(text, mapDescription.Bounds.Width, mapFont);
mapDescription.Text = text;
mapDescription.Bounds.Height = mapFont.Measure(text).Y;
mapDescriptionPanel.ScrollToTop();
mapDescriptionPanel.Layout.AdjustChildren();
}
}
}

View File

@@ -0,0 +1,109 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Linq;
using OpenRA.Widgets;
using OpenRA.Traits;
using OpenRA.Mods.RA;
namespace OpenRA.Mods.RA.Widgets.Logic
{
public enum IngameInfoPanel { AutoSelect, Map, Objectives, Debug };
class GameInfoLogic
{
[ObjectCreator.UseCtor]
public GameInfoLogic(Widget widget, World world, IngameInfoPanel activePanel)
{
var lp = world.LocalPlayer;
var numTabs = 0;
widget.IsVisible = () => activePanel != IngameInfoPanel.AutoSelect;
// Objectives/Stats tab
var iop = world.WorldActor.TraitsImplementing<IObjectivesPanel>().FirstOrDefault();
if (lp != null && iop != null && iop.PanelName != null)
{
numTabs++;
var objectivesTabButton = widget.Get<ButtonWidget>(string.Concat("BUTTON", numTabs.ToString()));
objectivesTabButton.GetText = () => "Objectives";
objectivesTabButton.IsVisible = () => lp != null && numTabs > 1;
objectivesTabButton.OnClick = () => activePanel = IngameInfoPanel.Objectives;
objectivesTabButton.IsHighlighted = () => activePanel == IngameInfoPanel.Objectives;
var objectivesPanel = widget.Get<ContainerWidget>("OBJECTIVES_PANEL");
objectivesPanel.IsVisible = () => activePanel == IngameInfoPanel.Objectives;
Game.LoadWidget(world, iop.PanelName, objectivesPanel, new WidgetArgs());
if (activePanel == IngameInfoPanel.AutoSelect)
activePanel = IngameInfoPanel.Objectives;
}
// Briefing tab
if (world.Map.CustomPreview != null)
{
numTabs++;
var mapTabButton = widget.Get<ButtonWidget>(string.Concat("BUTTON", numTabs.ToString()));
mapTabButton.Text = "Briefing";
mapTabButton.IsVisible = () => numTabs > 1;
mapTabButton.OnClick = () => activePanel = IngameInfoPanel.Map;
mapTabButton.IsHighlighted = () => activePanel == IngameInfoPanel.Map;
var mapPanel = widget.Get<ContainerWidget>("MAP_PANEL");
mapPanel.IsVisible = () => activePanel == IngameInfoPanel.Map;
Game.LoadWidget(world, "MAP_PANEL", mapPanel, new WidgetArgs());
if (activePanel == IngameInfoPanel.AutoSelect)
activePanel = IngameInfoPanel.Map;
}
// Debug/Cheats tab
if (lp != null && world.LobbyInfo.GlobalSettings.AllowCheats)
{
numTabs++;
var debugTabButton = widget.Get<ButtonWidget>(string.Concat("BUTTON", numTabs.ToString()));
debugTabButton.Text = "Debug";
debugTabButton.IsVisible = () => lp != null && world.LobbyInfo.GlobalSettings.AllowCheats && numTabs > 1;
debugTabButton.OnClick = () => activePanel = IngameInfoPanel.Debug;
debugTabButton.IsHighlighted = () => activePanel == IngameInfoPanel.Debug;
var debugPanelContainer = widget.Get<ContainerWidget>("DEBUG_PANEL");
debugPanelContainer.IsVisible = () => activePanel == IngameInfoPanel.Debug;
Game.LoadWidget(world, "DEBUG_PANEL", debugPanelContainer, new WidgetArgs());
if (activePanel == IngameInfoPanel.AutoSelect)
activePanel = IngameInfoPanel.Debug;
}
// Handle empty space when tabs aren't displayed
var titleText = widget.Get<LabelWidget>("TITLE");
var titleTextNoTabs = widget.GetOrNull<LabelWidget>("TITLE_NO_TABS");
titleText.IsVisible = () => numTabs > 1 || (numTabs == 1 && titleTextNoTabs == null);
titleText.GetText = () => string.Concat(world.Map.Type, ": ", world.Map.Title);
if (titleTextNoTabs != null)
{
titleTextNoTabs.IsVisible = () => numTabs == 1;
titleTextNoTabs.GetText = () => string.Concat(world.Map.Type, ": ", world.Map.Title);
}
var bg = widget.Get<BackgroundWidget>("BACKGROUND");
var bgNoTabs = widget.GetOrNull<BackgroundWidget>("BACKGROUND_NO_TABS");
bg.IsVisible = () => numTabs > 1 || (numTabs == 1 && bgNoTabs == null);
if (bgNoTabs != null)
bgNoTabs.IsVisible = () => numTabs == 1;
}
}
}

View File

@@ -0,0 +1,72 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Linq;
using System.Drawing;
using OpenRA.Widgets;
using OpenRA.Traits;
using OpenRA.Mods.RA;
namespace OpenRA.Mods.RA.Widgets.Logic
{
class GameInfoObjectivesLogic
{
ContainerWidget template;
[ObjectCreator.UseCtor]
public GameInfoObjectivesLogic(Widget widget, World world)
{
var lp = world.LocalPlayer;
var missionStatus = widget.Get<LabelWidget>("MISSION_STATUS");
missionStatus.GetText = () => lp.WinState == WinState.Undefined ? "In progress" :
lp.WinState == WinState.Won ? "Accomplished" : "Failed";
missionStatus.GetColor = () => lp.WinState == WinState.Undefined ? Color.White :
lp.WinState == WinState.Won ? Color.LimeGreen : Color.Red;
var mo = lp.PlayerActor.TraitOrDefault<MissionObjectives>();
if (mo == null)
return;
var objectivesPanel = widget.Get<ScrollPanelWidget>("OBJECTIVES_PANEL");
template = objectivesPanel.Get<ContainerWidget>("OBJECTIVE_TEMPLATE");
PopulateObjectivesList(mo, objectivesPanel, template);
Action<Player> RedrawObjectives = player =>
{
if (player == lp)
PopulateObjectivesList(mo, objectivesPanel, template);
};
mo.ObjectiveAdded += RedrawObjectives;
}
void PopulateObjectivesList(MissionObjectives mo, ScrollPanelWidget parent, ContainerWidget template)
{
parent.RemoveChildren();
foreach (var objective in mo.Objectives.OrderBy(o => o.Type))
{
var widget = template.Clone();
var label = widget.Get<LabelWidget>("OBJECTIVE_TYPE");
label.GetText = () => objective.Type == ObjectiveType.Primary ? "Primary" : "Secondary";
var checkbox = widget.Get<CheckboxWidget>("OBJECTIVE_STATUS");
checkbox.IsChecked = () => objective.State != ObjectiveState.Incomplete;
checkbox.GetCheckType = () => objective.State == ObjectiveState.Completed ? "checked" : "crossed";
checkbox.GetText = () => objective.Description;
parent.AddChild(widget);
}
}
}
}

View File

@@ -0,0 +1,72 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Drawing;
using System.Linq;
using OpenRA.Widgets;
using OpenRA.Traits;
using OpenRA.Mods.RA;
namespace OpenRA.Mods.RA.Widgets.Logic
{
class GameInfoStatsLogic
{
[ObjectCreator.UseCtor]
public GameInfoStatsLogic(Widget widget, World world)
{
var lp = world.LocalPlayer;
var checkbox = widget.Get<CheckboxWidget>("STATS_CHECKBOX");
checkbox.IsChecked = () => lp.WinState != WinState.Undefined;
checkbox.GetCheckType = () => lp.WinState == WinState.Won ?
"checked" : "crossed";
var statusLabel = widget.Get<LabelWidget>("STATS_STATUS");
statusLabel.GetText = () => lp.WinState == WinState.Won ? "Accomplished" :
lp.WinState == WinState.Lost ? "Failed" : "In progress";
statusLabel.GetColor = () => lp.WinState == WinState.Won ? Color.LimeGreen :
lp.WinState == WinState.Lost ? Color.Red : Color.White;
var playerPanel = widget.Get<ScrollPanelWidget>("PLAYER_LIST");
var playerTemplate = playerPanel.Get("PLAYER_TEMPLATE");
playerPanel.RemoveChildren();
foreach (var p in world.Players.Where(a => !a.NonCombatant))
{
var pp = p;
var item = playerTemplate.Clone();
var nameLabel = item.Get<LabelWidget>("NAME");
nameLabel.GetText = () => pp.WinState == WinState.Lost ? pp.PlayerName + " (Dead)" : pp.PlayerName;
nameLabel.GetColor = () => pp.Color.RGB;
var flag = item.Get<ImageWidget>("FACTIONFLAG");
flag.GetImageName = () => pp.Country.Race;
flag.GetImageCollection = () => "flags";
item.Get<LabelWidget>("FACTION").GetText = () => pp.Country.Name;
var team = item.Get<LabelWidget>("TEAM");
var client = world.LobbyInfo.ClientWithIndex(pp.ClientIndex);
var teamNumber = (client == null) ? 0 : client.Team;
team.GetText = () => (teamNumber == 0) ? "-" : teamNumber.ToString();
playerPanel.AddChild(item);
var stats = pp.PlayerActor.TraitOrDefault<PlayerStatistics>();
if (stats == null)
break;
var totalKills = stats.UnitsKilled + stats.BuildingsKilled;
var totalDeaths = stats.UnitsDead + stats.BuildingsDead;
item.Get<LabelWidget>("KILLS").GetText = () => totalKills.ToString();
item.Get<LabelWidget>("DEATHS").GetText = () => totalDeaths.ToString();
}
}
}
}

View File

@@ -1,4 +1,4 @@
#region Copyright & License Information
#region Copyright & License Information
/*
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
@@ -9,19 +9,34 @@
#endregion
using System;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Mods.RA;
using OpenRA.Mods.RA.Widgets;
using OpenRA.Traits;
using OpenRA.Widgets;
namespace OpenRA.Mods.RA.Widgets.Logic
{
class IngameMenuLogic
public class IngameMenuLogic
{
Widget menu;
[ObjectCreator.UseCtor]
public IngameMenuLogic(Widget widget, World world, Action onExit, WorldRenderer worldRenderer, bool transient)
public IngameMenuLogic(Widget widget, World world, Action onExit, WorldRenderer worldRenderer, IngameInfoPanel activePanel)
{
var resumeDisabled = false;
menu = widget.Get("INGAME_MENU");
var mpe = world.WorldActor.TraitOrDefault<MenuPaletteEffect>();
if (mpe != null)
mpe.Fade(mpe.Info.MenuEffect);
menu.Get<LabelWidget>("VERSION_LABEL").Text = Game.modData.Manifest.Mod.Version;
var hideMenu = false;
menu.Get("MENU_BUTTONS").IsVisible = () => !hideMenu;
// TODO: Create a mechanism to do things like this cleaner. Also needed for scripted missions
Action onQuit = () =>
{
Sound.PlayNotification(world.Map.Rules, null, "Speech", "Leave", world.LocalPlayer == null ? null : world.LocalPlayer.Country.Race);
@@ -33,7 +48,6 @@ namespace OpenRA.Mods.RA.Widgets.Logic
Game.RunAfterDelay(exitDelay, () => mpe.Fade(MenuPaletteEffect.EffectType.Black));
exitDelay += 40 * mpe.Info.FadeLength;
}
Game.RunAfterDelay(exitDelay, () =>
{
Game.Disconnect();
@@ -42,62 +56,68 @@ namespace OpenRA.Mods.RA.Widgets.Logic
});
};
Action onSurrender = () =>
Action closeMenu = () =>
{
world.IssueOrder(new Order("Surrender", world.LocalPlayer.PlayerActor, false));
Ui.CloseWindow();
Ui.Root.RemoveChild(menu);
if (mpe != null)
mpe.Fade(MenuPaletteEffect.EffectType.None);
onExit();
};
widget.Get<ButtonWidget>("DISCONNECT").OnClick = () =>
Action showMenu = () => hideMenu = false;
menu.Get<ButtonWidget>("ABORT_MISSION").OnClick = () =>
{
widget.Visible = false;
ConfirmationDialogs.PromptConfirmAction("Abort Mission", "Leave this game and return to the menu?", onQuit, () => widget.Visible = true);
hideMenu = true;
ConfirmationDialogs.PromptConfirmAction("Abort Mission", "Leave this game and return to the menu?", onQuit, showMenu);
};
widget.Get<ButtonWidget>("SETTINGS").OnClick = () =>
Action onSurrender = () =>
{
widget.Visible = false;
Ui.OpenWindow("SETTINGS_PANEL", new WidgetArgs()
{
{ "onExit", () => widget.Visible = true },
{ "worldRenderer", worldRenderer },
});
world.IssueOrder(new Order("Surrender", world.LocalPlayer.PlayerActor, false));
closeMenu();
};
widget.Get<ButtonWidget>("MUSIC").OnClick = () =>
var surrenderButton = menu.Get<ButtonWidget>("SURRENDER");
surrenderButton.IsDisabled = () => (world.LocalPlayer == null || world.LocalPlayer.WinState != WinState.Undefined);
surrenderButton.OnClick = () =>
{
widget.Visible = false;
Ui.OpenWindow("MUSIC_PANEL", new WidgetArgs
hideMenu = true;
ConfirmationDialogs.PromptConfirmAction("Surrender", "Are you sure you want to surrender?", onSurrender, showMenu);
};
widget.Get("SURRENDER").IsVisible = () => world.LocalPlayer != null && world.LocalPlayer.WinState == WinState.Undefined;
menu.Get<ButtonWidget>("MUSIC").OnClick = () =>
{
hideMenu = true;
Ui.OpenWindow("MUSIC_PANEL", new WidgetArgs()
{
{ "onExit", () => { widget.Visible = true; } },
{ "onExit", () => hideMenu = false },
{ "world", world }
});
};
var resumeButton = widget.Get<ButtonWidget>("RESUME");
resumeButton.IsDisabled = () => resumeDisabled;
resumeButton.OnClick = () =>
menu.Get<ButtonWidget>("SETTINGS").OnClick = () =>
{
if (transient)
hideMenu = true;
Ui.OpenWindow("SETTINGS_PANEL", new WidgetArgs()
{
Ui.CloseWindow();
Ui.Root.RemoveChild(widget);
}
onExit();
{ "world", world },
{ "worldRenderer", worldRenderer },
{ "onExit", () => hideMenu = false },
});
};
widget.Get<ButtonWidget>("SURRENDER").OnClick = () =>
var resumeButton = menu.Get<ButtonWidget>("RESUME");
resumeButton.IsDisabled = () => resumeDisabled;
resumeButton.OnClick = closeMenu;
// Game info panel
var gameInfoPanel = Game.LoadWidget(world, "GAME_INFO_PANEL", menu, new WidgetArgs()
{
widget.Visible = false;
ConfirmationDialogs.PromptConfirmAction(
"Surrender",
"Are you sure you want to surrender?",
onSurrender,
() => widget.Visible = true,
"Surrender");
};
widget.Get("SURRENDER").IsVisible = () => world.LocalPlayer != null && world.LocalPlayer.WinState == WinState.Undefined;
{ "activePanel", activePanel }
});
gameInfoPanel.IsVisible = () => !hideMenu;
}
}
}

View File

@@ -40,7 +40,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
WorldRenderer worldRenderer;
[ObjectCreator.UseCtor]
public ObserverStatsLogic(World world, WorldRenderer worldRenderer, Widget widget, Action onExit, bool transient)
public ObserverStatsLogic(World world, WorldRenderer worldRenderer, Widget widget, Action onExit)
{
this.world = world;
this.worldRenderer = worldRenderer;
@@ -139,18 +139,12 @@ namespace OpenRA.Mods.RA.Widgets.Logic
var close = widget.GetOrNull<ButtonWidget>("CLOSE");
if (close != null)
{
close.OnClick = () =>
{
if (transient)
{
Ui.CloseWindow();
Ui.Root.RemoveChild(widget);
}
Ui.CloseWindow();
Ui.Root.RemoveChild(widget);
onExit();
};
}
}
void ClearStats()

View File

@@ -8,9 +8,11 @@
*/
#endregion
using System;
using System.Linq;
using OpenRA.Mods.RA.Orders;
using OpenRA.Widgets;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Widgets.Logic
{
@@ -59,8 +61,32 @@ namespace OpenRA.Mods.RA.Widgets.Logic
var options = widget.GetOrNull<MenuButtonWidget>("OPTIONS_BUTTON");
if (options != null)
{
var blinking = false;
var lp = world.LocalPlayer;
options.IsDisabled = () => disableSystemButtons;
options.OnClick = () => OpenMenuPanel(options);
options.OnClick = () =>
{
blinking = false;
OpenMenuPanel(options, new WidgetArgs()
{
{ "activePanel", IngameInfoPanel.AutoSelect }
});
};
options.IsHighlighted = () => blinking && Game.LocalTick % 50 < 25;
if (lp != null)
{
Action<Player> StartBlinking = player =>
{
if (player == world.LocalPlayer)
blinking = true;
};
var mo = lp.PlayerActor.TraitOrDefault<MissionObjectives>();
if (mo != null)
mo.ObjectiveAdded += StartBlinking;
}
}
var diplomacy = widget.GetOrNull<MenuButtonWidget>("DIPLOMACY_BUTTON");
@@ -76,7 +102,10 @@ namespace OpenRA.Mods.RA.Widgets.Logic
{
debug.IsVisible = () => world.LobbyInfo.GlobalSettings.AllowCheats;
debug.IsDisabled = () => disableSystemButtons;
debug.OnClick = () => OpenMenuPanel(debug);
debug.OnClick = () => OpenMenuPanel(debug, new WidgetArgs()
{
{ "activePanel", IngameInfoPanel.Debug }
});
}
var stats = widget.GetOrNull<MenuButtonWidget>("OBSERVER_STATS_BUTTON");
@@ -87,7 +116,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
}
}
void OpenMenuPanel(MenuButtonWidget button)
void OpenMenuPanel(MenuButtonWidget button, WidgetArgs widgetArgs = null)
{
disableSystemButtons = true;
var cachedPause = world.PredictedPaused;
@@ -98,21 +127,19 @@ namespace OpenRA.Mods.RA.Widgets.Logic
if (button.Pause && world.LobbyInfo.IsSinglePlayer)
world.SetPauseState(true);
Game.LoadWidget(world, button.MenuContainer, Ui.Root, new WidgetArgs()
widgetArgs = widgetArgs ?? new WidgetArgs();
widgetArgs.Add("onExit", () =>
{
{ "transient", true },
{ "onExit", () =>
{
if (button.HideIngameUI)
ingameRoot.IsVisible = () => true;
if (button.HideIngameUI)
ingameRoot.IsVisible = () => true;
if (button.Pause && world.LobbyInfo.IsSinglePlayer)
world.SetPauseState(cachedPause);
if (button.Pause && world.LobbyInfo.IsSinglePlayer)
world.SetPauseState(cachedPause);
disableSystemButtons = false;
}
}
disableSystemButtons = false;
});
Game.LoadWidget(world, button.MenuContainer, Ui.Root, widgetArgs);
}
static void BindOrderButton<T>(World world, ButtonWidget w, string icon)