Merge pull request #2879 from bidifx/chat
closes #2874: improved ingame chat
This commit is contained in:
@@ -210,7 +210,7 @@ namespace OpenRA
|
||||
|
||||
var map = modData.PrepareMap(mapUID);
|
||||
viewport = new Viewport(new int2(Renderer.Resolution), map.Bounds, Renderer);
|
||||
orderManager.world = new World(modData.Manifest, map, orderManager) { IsShellmap = isShellmap };
|
||||
orderManager.world = new World(modData.Manifest, map, orderManager, isShellmap);
|
||||
worldRenderer = new WorldRenderer(orderManager.world);
|
||||
|
||||
if (orderManager.GameStarted) return;
|
||||
|
||||
@@ -59,6 +59,7 @@ namespace OpenRA.Network
|
||||
public string Bot; // Bot type, null for real clients
|
||||
public bool IsAdmin;
|
||||
public bool IsReady { get { return State == ClientState.Ready; } }
|
||||
public bool IsObserver { get { return Slot == null; } }
|
||||
}
|
||||
|
||||
public class Slot
|
||||
|
||||
@@ -44,6 +44,7 @@ namespace OpenRA.Network
|
||||
{
|
||||
var player = world != null ? world.FindPlayerByClient(client) : null;
|
||||
var suffix = (player != null && player.WinState == WinState.Lost) ? " (Dead)" : "";
|
||||
suffix = client.IsObserver ? " (Spectator)" : suffix;
|
||||
Game.AddChatLine(client.ColorRamp.GetColor(0), client.Name + suffix, order.TargetString);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace OpenRA.Widgets
|
||||
|
||||
public Func<bool> OnEnterKey = () => false;
|
||||
public Func<bool> OnTabKey = () => false;
|
||||
public Func<bool> OnEscKey = () => false;
|
||||
public Action OnLoseFocus = () => { };
|
||||
public int CursorPosition { get; protected set; }
|
||||
|
||||
@@ -121,6 +122,9 @@ namespace OpenRA.Widgets
|
||||
if (e.KeyName == "tab" && OnTabKey())
|
||||
return true;
|
||||
|
||||
if (e.KeyName == "escape" && OnEscKey())
|
||||
return true;
|
||||
|
||||
if (e.KeyName == "left")
|
||||
{
|
||||
if (CursorPosition > 0)
|
||||
|
||||
@@ -403,6 +403,8 @@ namespace OpenRA.Widgets
|
||||
|
||||
public override string GetCursor(int2 pos) { return null; }
|
||||
public override Widget Clone() { return new ContainerWidget(this); }
|
||||
public Func<KeyInput, bool> OnKeyPress = _ => false;
|
||||
public override bool HandleKeyPress(KeyInput e) { return OnKeyPress(e); }
|
||||
}
|
||||
|
||||
public class WidgetArgs : Dictionary<string, object>
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace OpenRA
|
||||
public void AddPlayer(Player p) { Players.Add(p); }
|
||||
public Player LocalPlayer { get; private set; }
|
||||
public readonly Shroud LocalShroud;
|
||||
|
||||
public bool Observer { get { return LocalPlayer == null; } }
|
||||
public Player RenderedPlayer;
|
||||
public Shroud RenderedShroud { get { return RenderedPlayer != null ? RenderedPlayer.Shroud : LocalShroud; } }
|
||||
|
||||
@@ -90,8 +90,9 @@ namespace OpenRA
|
||||
}
|
||||
}
|
||||
|
||||
internal World(Manifest manifest, Map map, OrderManager orderManager)
|
||||
internal World(Manifest manifest, Map map, OrderManager orderManager, bool isShellmap)
|
||||
{
|
||||
IsShellmap = isShellmap;
|
||||
this.orderManager = orderManager;
|
||||
orderGenerator_ = new UnitOrderGenerator();
|
||||
Map = map;
|
||||
|
||||
@@ -375,6 +375,7 @@
|
||||
<Compile Include="Widgets\Logic\DiplomacyLogic.cs" />
|
||||
<Compile Include="Widgets\Logic\DirectConnectLogic.cs" />
|
||||
<Compile Include="Widgets\Logic\DownloadPackagesLogic.cs" />
|
||||
<Compile Include="Widgets\Logic\IngameChatLogic.cs" />
|
||||
<Compile Include="Widgets\Logic\IngameChromeLogic.cs" />
|
||||
<Compile Include="Widgets\Logic\IngameObserverChromeLogic.cs" />
|
||||
<Compile Include="Widgets\Logic\LobbyLogic.cs" />
|
||||
|
||||
156
OpenRA.Mods.RA/Widgets/Logic/IngameChatLogic.cs
Normal file
156
OpenRA.Mods.RA/Widgets/Logic/IngameChatLogic.cs
Normal file
@@ -0,0 +1,156 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 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.Drawing;
|
||||
using OpenRA.Widgets;
|
||||
using OpenRA.Network;
|
||||
|
||||
namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
{
|
||||
public class IngameChatLogic
|
||||
{
|
||||
internal World World;
|
||||
internal readonly ContainerWidget ChatOverlay;
|
||||
internal readonly ChatDisplayWidget ChatOverlayDisplay;
|
||||
|
||||
|
||||
internal readonly ContainerWidget ChatChrome;
|
||||
internal readonly ScrollPanelWidget ChatScrollPanel;
|
||||
internal readonly ContainerWidget ChatTemplate;
|
||||
internal readonly TextFieldWidget ChatText;
|
||||
|
||||
private bool teamChat = false;
|
||||
internal bool TeamChat
|
||||
{
|
||||
get { return World.Observer ? false : teamChat; }
|
||||
set { teamChat = value; }
|
||||
}
|
||||
|
||||
[ObjectCreator.UseCtor]
|
||||
public IngameChatLogic(Widget widget, OrderManager orderManager, World world)
|
||||
{
|
||||
World = world;
|
||||
var chatPanel = (ContainerWidget) widget;
|
||||
|
||||
|
||||
ChatOverlay = chatPanel.Get<ContainerWidget>("CHAT_OVERLAY");
|
||||
ChatOverlayDisplay = ChatOverlay.Get<ChatDisplayWidget>("CHAT_DISPLAY");
|
||||
ChatOverlay.Visible = false;
|
||||
|
||||
ChatChrome = chatPanel.Get<ContainerWidget>("CHAT_CHROME");
|
||||
ChatChrome.Visible = true;
|
||||
|
||||
var chatMode = ChatChrome.Get<ButtonWidget>("CHAT_MODE");
|
||||
chatMode.GetText = () => TeamChat ? "Team" : "All";
|
||||
chatMode.OnClick = () => TeamChat = !TeamChat;
|
||||
|
||||
ChatText = ChatChrome.Get<TextFieldWidget>("CHAT_TEXTFIELD");
|
||||
ChatText.OnTabKey = () => { TeamChat = !TeamChat; return true; };
|
||||
ChatText.OnEnterKey = () =>
|
||||
{
|
||||
ChatText.Text = ChatText.Text.Trim();
|
||||
if (ChatText.Text != "")
|
||||
orderManager.IssueOrder(Order.Chat(TeamChat, ChatText.Text));
|
||||
CloseChat();
|
||||
return true;
|
||||
};
|
||||
ChatText.OnEscKey = () => {CloseChat(); return true; };
|
||||
|
||||
var chatClose = ChatChrome.Get<ButtonWidget>("CHAT_CLOSE");
|
||||
chatClose.OnClick += () => CloseChat();
|
||||
|
||||
chatPanel.OnKeyPress = (e) =>
|
||||
{
|
||||
if (e.Event == KeyInputEvent.Up) return false;
|
||||
if (!IsOpen && (e.KeyName == "enter" || e.KeyName == "return") )
|
||||
{
|
||||
|
||||
var shift = e.Modifiers.HasModifier(Modifiers.Shift);
|
||||
var toggle = Game.Settings.Game.TeamChatToggle ;
|
||||
TeamChat = (!toggle && shift) || ( toggle && (TeamChat ^ shift) );
|
||||
OpenChat();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
ChatScrollPanel = ChatChrome.Get<ScrollPanelWidget>("CHAT_SCROLLPANEL");
|
||||
ChatTemplate = ChatScrollPanel.Get<ContainerWidget>("CHAT_TEMPLATE");
|
||||
|
||||
Game.AddChatLine += AddChatLine;
|
||||
Game.BeforeGameStart += UnregisterEvents;
|
||||
|
||||
CloseChat();
|
||||
ChatOverlayDisplay.AddLine(Color.White, null, "Use RETURN key to open chat window...");
|
||||
}
|
||||
|
||||
void UnregisterEvents()
|
||||
{
|
||||
Game.AddChatLine -= AddChatLine;
|
||||
Game.BeforeGameStart -= UnregisterEvents;
|
||||
}
|
||||
|
||||
public void OpenChat()
|
||||
{
|
||||
ChatText.Text = "";
|
||||
ChatOverlay.Visible = false;
|
||||
ChatChrome.Visible = true;
|
||||
ChatText.TakeFocus(new MouseInput());
|
||||
}
|
||||
|
||||
public void CloseChat()
|
||||
{
|
||||
ChatOverlay.Visible = true;
|
||||
ChatChrome.Visible = false;
|
||||
ChatText.LoseFocus();
|
||||
}
|
||||
|
||||
public bool IsOpen { get { return ChatChrome.IsVisible(); } }
|
||||
|
||||
public void AddChatLine(Color c, string from, string text)
|
||||
{
|
||||
|
||||
ChatOverlayDisplay.AddLine(c, from, text);
|
||||
|
||||
var template = ChatTemplate.Clone();
|
||||
var nameLabel = template.Get<LabelWidget>("NAME");
|
||||
var textLabel = template.Get<LabelWidget>("TEXT");
|
||||
|
||||
var name = "";
|
||||
if (!string.IsNullOrEmpty(from))
|
||||
name = from + ":";
|
||||
var font = Game.Renderer.Fonts[nameLabel.Font];
|
||||
var nameSize = font.Measure(from);
|
||||
|
||||
nameLabel.GetColor = () => c;
|
||||
nameLabel.GetText = () => name;
|
||||
nameLabel.Bounds.Width = nameSize.X;
|
||||
textLabel.Bounds.X += nameSize.X;
|
||||
textLabel.Bounds.Width -= nameSize.X;
|
||||
|
||||
// Hack around our hacky wordwrap behavior: need to resize the widget to fit the text
|
||||
text = WidgetUtils.WrapText(text, textLabel.Bounds.Width, font);
|
||||
textLabel.GetText = () => text;
|
||||
var dh = font.Measure(text).Y - textLabel.Bounds.Height;
|
||||
if (dh > 0)
|
||||
{
|
||||
textLabel.Bounds.Height += dh;
|
||||
template.Bounds.Height += dh;
|
||||
}
|
||||
|
||||
ChatScrollPanel.AddChild(template);
|
||||
ChatScrollPanel.ScrollToBottom();
|
||||
Sound.PlayNotification(null, "Sounds", "ChatLine", null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,9 +22,6 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
[ObjectCreator.UseCtor]
|
||||
public IngameChromeLogic(World world)
|
||||
{
|
||||
Game.AddChatLine += AddChatLine;
|
||||
Game.BeforeGameStart += UnregisterEvents;
|
||||
|
||||
var r = Ui.Root;
|
||||
gameRoot = r.Get("INGAME_ROOT");
|
||||
var optionsBG = gameRoot.Get("INGAME_OPTIONS_BG");
|
||||
@@ -58,8 +55,10 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
moneybin.Get<OrderButtonWidget>("POWER_DOWN").GetKey = _ => Game.Settings.Keys.PowerDownKey;
|
||||
moneybin.Get<OrderButtonWidget>("REPAIR").GetKey = _ => Game.Settings.Keys.RepairKey;
|
||||
|
||||
optionsBG.Get<ButtonWidget>("DISCONNECT").OnClick = () => LeaveGame(optionsBG, world);
|
||||
var chatPanel = Game.LoadWidget(world, "CHAT_PANEL", Ui.Root, new WidgetArgs());
|
||||
gameRoot.AddChild(chatPanel);
|
||||
|
||||
optionsBG.Get<ButtonWidget>("DISCONNECT").OnClick = () => LeaveGame(optionsBG, world);
|
||||
optionsBG.Get<ButtonWidget>("SETTINGS").OnClick = () => Ui.OpenWindow("SETTINGS_MENU");
|
||||
optionsBG.Get<ButtonWidget>("MUSIC").OnClick = () => Ui.OpenWindow("MUSIC_MENU");
|
||||
optionsBG.Get<ButtonWidget>("RESUME").OnClick = () =>
|
||||
@@ -110,16 +109,5 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
Ui.CloseWindow();
|
||||
Ui.OpenWindow("MAINMENU_BG");
|
||||
}
|
||||
|
||||
void UnregisterEvents()
|
||||
{
|
||||
Game.AddChatLine -= AddChatLine;
|
||||
Game.BeforeGameStart -= UnregisterEvents;
|
||||
}
|
||||
|
||||
void AddChatLine(Color c, string from, string text)
|
||||
{
|
||||
gameRoot.Get<ChatDisplayWidget>("CHAT_DISPLAY").AddLine(c, from, text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Widgets;
|
||||
using OpenRA.Network;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
@@ -24,9 +25,6 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
[ObjectCreator.UseCtor]
|
||||
public IngameObserverChromeLogic(World world)
|
||||
{
|
||||
Game.AddChatLine += AddChatLine;
|
||||
Game.BeforeGameStart += UnregisterEvents;
|
||||
|
||||
var r = Ui.Root;
|
||||
gameRoot = r.Get("OBSERVER_ROOT");
|
||||
var optionsBG = gameRoot.Get("INGAME_OPTIONS_BG");
|
||||
@@ -59,6 +57,12 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
|
||||
Ui.Root.Get<ButtonWidget>("INGAME_STATS_BUTTON").OnClick = () => gameRoot.Get("OBSERVER_STATS").Visible ^= true;
|
||||
|
||||
if (!world.IsShellmap)
|
||||
{
|
||||
var chatPanel = Game.LoadWidget(world, "CHAT_PANEL", Ui.Root, new WidgetArgs());
|
||||
gameRoot.AddChild(chatPanel);
|
||||
}
|
||||
|
||||
var shroudSelector = Ui.Root.GetOrNull<DropDownButtonWidget>("SHROUD_SELECTOR");
|
||||
if (shroudSelector != null)
|
||||
{
|
||||
@@ -91,17 +95,6 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
}
|
||||
}
|
||||
|
||||
void UnregisterEvents()
|
||||
{
|
||||
Game.AddChatLine -= AddChatLine;
|
||||
Game.BeforeGameStart -= UnregisterEvents;
|
||||
}
|
||||
|
||||
void AddChatLine(Color c, string from, string text)
|
||||
{
|
||||
gameRoot.Get<ChatDisplayWidget>("CHAT_DISPLAY").AddLine(c, from, text);
|
||||
}
|
||||
|
||||
class DropDownOption
|
||||
{
|
||||
public string Title;
|
||||
|
||||
@@ -65,6 +65,7 @@ Assemblies:
|
||||
ChromeLayout:
|
||||
mods/ra/chrome/gameinit.yaml
|
||||
mods/ra/chrome/ingame.yaml
|
||||
mods/ra/chrome/ingame-chat.yaml
|
||||
mods/ra/chrome/mainmenu.yaml
|
||||
mods/ra/chrome/settings.yaml
|
||||
mods/ra/chrome/lobby.yaml
|
||||
|
||||
@@ -54,6 +54,7 @@ Assemblies:
|
||||
ChromeLayout:
|
||||
mods/d2k/chrome/gameinit.yaml
|
||||
mods/ra/chrome/ingame.yaml
|
||||
mods/ra/chrome/ingame-chat.yaml
|
||||
mods/d2k/chrome/mainmenu.yaml
|
||||
mods/ra/chrome/settings.yaml
|
||||
mods/d2k/chrome/lobby.yaml
|
||||
@@ -114,4 +115,4 @@ Fonts:
|
||||
Size:10
|
||||
TinyBold:
|
||||
Font:FreeSansBold.ttf
|
||||
Size:10
|
||||
Size:10
|
||||
|
||||
@@ -56,6 +56,7 @@ Assemblies:
|
||||
ChromeLayout:
|
||||
mods/ra/chrome/gameinit.yaml
|
||||
mods/ra/chrome/ingame.yaml
|
||||
mods/ra/chrome/ingame-chat.yaml
|
||||
mods/ra/chrome/mainmenu.yaml
|
||||
mods/ra/chrome/settings.yaml
|
||||
mods/ra/chrome/lobby.yaml
|
||||
|
||||
71
mods/ra/chrome/ingame-chat.yaml
Normal file
71
mods/ra/chrome/ingame-chat.yaml
Normal file
@@ -0,0 +1,71 @@
|
||||
Container@CHAT_PANEL:
|
||||
X:(WINDOW_RIGHT - WIDTH) / 2
|
||||
Y:WINDOW_BOTTOM - HEIGHT - 15
|
||||
Width:550
|
||||
Height:180
|
||||
Logic:IngameChatLogic
|
||||
Children:
|
||||
Container@CHAT_OVERLAY:
|
||||
X:0
|
||||
Y:0
|
||||
Width:PARENT_RIGHT
|
||||
Height:PARENT_BOTTOM-30
|
||||
Visible: false
|
||||
Children:
|
||||
ChatDisplay@CHAT_DISPLAY:
|
||||
X:0
|
||||
Y:0
|
||||
Width: PARENT_RIGHT
|
||||
Height: PARENT_BOTTOM
|
||||
DrawBackground: False
|
||||
RemoveTime:250
|
||||
UseContrast: yes
|
||||
Container@CHAT_CHROME:
|
||||
X:0
|
||||
Y:0
|
||||
Width:PARENT_RIGHT
|
||||
Height:PARENT_BOTTOM
|
||||
Children:
|
||||
Button@CHAT_MODE:
|
||||
X:0
|
||||
Y:PARENT_BOTTOM - HEIGHT
|
||||
Width: 50
|
||||
Height: 25
|
||||
Text: Team
|
||||
Font: Bold
|
||||
TextField@CHAT_TEXTFIELD:
|
||||
X:55
|
||||
Y:PARENT_BOTTOM - HEIGHT
|
||||
Width:465
|
||||
Height:25
|
||||
Button@CHAT_CLOSE:
|
||||
X:525
|
||||
Y:PARENT_BOTTOM - HEIGHT
|
||||
Width: 25
|
||||
Height: 25
|
||||
Text: X
|
||||
Font: Bold
|
||||
ScrollPanel@CHAT_SCROLLPANEL:
|
||||
X:0
|
||||
Y:PARENT_BOTTOM - HEIGHT - 30
|
||||
Width:550
|
||||
Height:150
|
||||
ItemSpacing:1
|
||||
Children:
|
||||
Container@CHAT_TEMPLATE:
|
||||
X:2
|
||||
Y:0
|
||||
Width:PARENT_RIGHT-27
|
||||
Height:16
|
||||
Children:
|
||||
Label@NAME:
|
||||
X:3
|
||||
Width:50
|
||||
Height:15
|
||||
VAlign:Top
|
||||
Label@TEXT:
|
||||
X:10
|
||||
Width:PARENT_RIGHT - 60
|
||||
Height:15
|
||||
WordWrap:true
|
||||
VAlign:Top
|
||||
@@ -206,20 +206,6 @@ Container@INGAME_ROOT:
|
||||
Text:Close
|
||||
Font:Bold
|
||||
Key:escape
|
||||
ChatDisplay@CHAT_DISPLAY:
|
||||
X:250
|
||||
Y:WINDOW_BOTTOM - HEIGHT - 30
|
||||
Width: 760
|
||||
Height: 200
|
||||
DrawBackground: False
|
||||
RemoveTime:250
|
||||
UseContrast: yes
|
||||
ChatEntry@CHAT_ENTRY:
|
||||
X:250
|
||||
Y:WINDOW_BOTTOM - HEIGHT
|
||||
Width: 760
|
||||
Height: 30
|
||||
UseContrast: yes
|
||||
Background@PERF_BG:
|
||||
ClickThrough:true
|
||||
Background:dialog4
|
||||
@@ -373,20 +359,6 @@ Container@OBSERVER_ROOT:
|
||||
Height:25
|
||||
Text:Abort Mission
|
||||
Font:Bold
|
||||
ChatDisplay@CHAT_DISPLAY:
|
||||
X:250
|
||||
Y:WINDOW_BOTTOM - HEIGHT - 30
|
||||
Width: 760
|
||||
Height: 200
|
||||
DrawBackground: False
|
||||
RemoveTime:250
|
||||
UseContrast: yes
|
||||
ChatEntry@CHAT_ENTRY:
|
||||
X:250
|
||||
Y:WINDOW_BOTTOM - HEIGHT
|
||||
Width: 760
|
||||
Height: 30
|
||||
UseContrast: yes
|
||||
Background@PERF_BG:
|
||||
ClickThrough:true
|
||||
Background:dialog4
|
||||
|
||||
@@ -55,6 +55,7 @@ Assemblies:
|
||||
ChromeLayout:
|
||||
mods/ra/chrome/gameinit.yaml
|
||||
mods/ra/chrome/ingame.yaml
|
||||
mods/ra/chrome/ingame-chat.yaml
|
||||
mods/ra/chrome/mainmenu.yaml
|
||||
mods/ra/chrome/settings.yaml
|
||||
mods/ra/chrome/lobby.yaml
|
||||
|
||||
Reference in New Issue
Block a user