diff --git a/OpenRA.Game/GameRules/Settings.cs b/OpenRA.Game/GameRules/Settings.cs index 54a725baaa..c858b8810e 100755 --- a/OpenRA.Game/GameRules/Settings.cs +++ b/OpenRA.Game/GameRules/Settings.cs @@ -81,17 +81,19 @@ namespace OpenRA.GameRules public string LastServer = "localhost:1234"; } + public enum MouseScrollType { Disabled, Standard, Inverted } public class GameSettings { public string[] Mods = { "ra" }; public bool MatchTimer = true; + public bool ShellmapMusic = true; // Chat settings public bool TeamChatToggle = false; // Behaviour settings public bool ViewportEdgeScroll = true; - public bool InverseDragScroll = false; + public MouseScrollType MouseScroll = MouseScrollType.Standard; public float ViewportEdgeScrollStep = 10f; // Internal game settings diff --git a/OpenRA.Game/Widgets/SliderWidget.cs b/OpenRA.Game/Widgets/SliderWidget.cs index 53f3975cb9..feaf91c233 100755 --- a/OpenRA.Game/Widgets/SliderWidget.cs +++ b/OpenRA.Game/Widgets/SliderWidget.cs @@ -20,6 +20,9 @@ namespace OpenRA.Widgets public Func GetOffset; public int Ticks = 0; public int TrackHeight = 5; + + // TODO: Changing this breaks the semantics of Get/SetOffset + // This is bogus public float2 Range = new float2(0f, 1f); private float Offset = 0; diff --git a/OpenRA.Game/Widgets/ViewportScrollControllerWidget.cs b/OpenRA.Game/Widgets/ViewportScrollControllerWidget.cs index 3e3f5af8f4..0c2e822c9a 100755 --- a/OpenRA.Game/Widgets/ViewportScrollControllerWidget.cs +++ b/OpenRA.Game/Widgets/ViewportScrollControllerWidget.cs @@ -37,11 +37,15 @@ namespace OpenRA.Widgets // TODO: ViewportScrollController doesn't support delegate methods for mouse input public override bool HandleMouseInput(MouseInput mi) { + var scrolltype = Game.Settings.Game.MouseScroll; + if (scrolltype == OpenRA.GameRules.MouseScrollType.Disabled) + return false; + if (mi.Event == MouseInputEvent.Move && (mi.Button == MouseButton.Middle || mi.Button == (MouseButton.Left | MouseButton.Right))) { - int InverseScroll = Game.Settings.Game.InverseDragScroll ? -1 : 1; - Game.viewport.Scroll((Viewport.LastMousePos - mi.Location) * InverseScroll); + var d = scrolltype == OpenRA.GameRules.MouseScrollType.Inverted ? -1 : 1; + Game.viewport.Scroll((Viewport.LastMousePos - mi.Location) * d); return true; } return false; diff --git a/OpenRA.Mods.Cnc/Widgets/CncIngameChromeLogic.cs b/OpenRA.Mods.Cnc/Widgets/CncIngameChromeLogic.cs index 92ead60628..d9c7a3f3bb 100755 --- a/OpenRA.Mods.Cnc/Widgets/CncIngameChromeLogic.cs +++ b/OpenRA.Mods.Cnc/Widgets/CncIngameChromeLogic.cs @@ -127,6 +127,7 @@ namespace OpenRA.Mods.Cnc.Widgets hideButtons = true; Widget.OpenWindow("SETTINGS_PANEL", new WidgetArgs() { + { "world", world }, { "onExit", () => hideButtons = false }, }); }; diff --git a/OpenRA.Mods.Cnc/Widgets/CncMenuLogic.cs b/OpenRA.Mods.Cnc/Widgets/CncMenuLogic.cs index 5117f81e85..08ff7d0cd2 100755 --- a/OpenRA.Mods.Cnc/Widgets/CncMenuLogic.cs +++ b/OpenRA.Mods.Cnc/Widgets/CncMenuLogic.cs @@ -123,6 +123,7 @@ namespace OpenRA.Mods.Cnc.Widgets Menu = MenuType.None; Widget.OpenWindow("SETTINGS_PANEL", new WidgetArgs() { + { "world", world }, { "onExit", () => Menu = MenuType.Settings }, }); }; diff --git a/OpenRA.Mods.Cnc/Widgets/CncSettingsLogic.cs b/OpenRA.Mods.Cnc/Widgets/CncSettingsLogic.cs index e7d5cc1ca9..74e03a43d7 100755 --- a/OpenRA.Mods.Cnc/Widgets/CncSettingsLogic.cs +++ b/OpenRA.Mods.Cnc/Widgets/CncSettingsLogic.cs @@ -9,9 +9,12 @@ #endregion using System; +using OpenRA.FileFormats; using OpenRA.FileFormats.Graphics; using OpenRA.GameRules; using OpenRA.Widgets; +using System.Collections.Generic; +using System.Drawing; namespace OpenRA.Mods.Cnc.Widgets { @@ -23,29 +26,262 @@ namespace OpenRA.Mods.Cnc.Widgets Input } PanelType Settings = PanelType.General; + ColorRamp playerColor; + Modifiers groupAddModifier; + MouseScrollType mouseScroll; + WindowMode windowMode; + + CncColorPickerPaletteModifier playerPalettePreview; + World world; [ObjectCreator.UseCtor] public CncSettingsLogic([ObjectCreator.Param] Widget widget, - [ObjectCreator.Param] Action onExit) + [ObjectCreator.Param] World world, + [ObjectCreator.Param] Action onExit) { - + this.world = world; var panel = widget.GetWidget("SETTINGS_PANEL"); + + // General pane + var generalButton = panel.GetWidget("GENERAL_BUTTON"); + generalButton.OnClick = () => Settings = PanelType.General; + generalButton.IsDisabled = () => Settings == PanelType.General; - panel.GetWidget("SAVE_BUTTON").OnClick = () => { - Widget.CloseWindow(); - onExit(); - }; + var generalPane = panel.GetWidget("GENERAL_CONTROLS"); + generalPane.IsVisible = () => Settings == PanelType.General; - panel.GetWidget("GENERAL_CONTROLS").IsVisible = () => Settings == PanelType.General; - panel.GetWidget("INPUT_CONTROLS").IsVisible = () => Settings == PanelType.Input; + // Player profile + var nameTextfield = generalPane.GetWidget("NAME_TEXTFIELD"); + nameTextfield.Text = Game.Settings.Player.Name; + playerColor = Game.Settings.Player.ColorRamp; + playerPalettePreview = world.WorldActor.Trait(); + playerPalettePreview.Ramp = playerColor; + + var colorDropdown = generalPane.GetWidget("COLOR_DROPDOWN"); + colorDropdown.OnMouseUp = _ => ShowColorPicker(colorDropdown); + colorDropdown.GetWidget("COLORBLOCK").GetColor = () => playerColor.GetColor(0); + + // Debug + var perftext = Game.Settings.Debug.PerfText; + var perftextCheckbox = generalPane.GetWidget("PERFTEXT_CHECKBOX"); + perftextCheckbox.IsChecked = () => perftext; + perftextCheckbox.OnClick = () => perftext ^= true; + + var perfgraph = Game.Settings.Debug.PerfGraph; + var perfgraphCheckbox = generalPane.GetWidget("PERFGRAPH_CHECKBOX"); + perfgraphCheckbox.IsChecked = () => perfgraph; + perfgraphCheckbox.OnClick = () => perfgraph ^= true; + + var matchtimer = Game.Settings.Game.MatchTimer; + var matchtimerCheckbox = generalPane.GetWidget("MATCHTIME_CHECKBOX"); + matchtimerCheckbox.IsChecked = () => matchtimer; + matchtimerCheckbox.OnClick = () => matchtimer ^= true; + + var checkunsynced = Game.Settings.Debug.SanityCheckUnsyncedCode; + var checkunsyncedCheckbox = generalPane.GetWidget("CHECKUNSYNCED_CHECKBOX"); + checkunsyncedCheckbox.IsChecked = () => checkunsynced; + checkunsyncedCheckbox.OnClick = () => checkunsynced ^= true; + + // Video + windowMode = Game.Settings.Graphics.Mode; + var windowModeDropdown = generalPane.GetWidget("MODE_DROPDOWN"); + windowModeDropdown.OnMouseUp = _ => ShowWindowModeDropdown(windowModeDropdown); + windowModeDropdown.GetText = () => windowMode == WindowMode.Windowed ? "Windowed" : windowMode == WindowMode.Fullscreen ? "Fullscreen" : "Pseudo-Fullscreen"; + + generalPane.GetWidget("WINDOW_RESOLUTION").IsVisible = () => windowMode == WindowMode.Windowed; + var windowWidth = generalPane.GetWidget("WINDOW_WIDTH"); + windowWidth.Text = Game.Settings.Graphics.WindowedSize.X.ToString(); + + var windowHeight = generalPane.GetWidget("WINDOW_HEIGHT"); + windowHeight.Text = Game.Settings.Graphics.WindowedSize.Y.ToString(); + + // Audio + var soundVolume = Game.Settings.Sound.SoundVolume; + var soundSlider = generalPane.GetWidget("SOUND_SLIDER"); + soundSlider.OnChange += x => { soundVolume = x; Sound.SoundVolume = x;}; + soundSlider.GetOffset = () => { return soundVolume; }; + soundSlider.SetOffset(soundVolume); + + var musicVolume = Game.Settings.Sound.MusicVolume; + var musicSlider = generalPane.GetWidget("MUSIC_SLIDER"); + musicSlider.OnChange += x => { musicVolume = x; Sound.MusicVolume = x; }; + musicSlider.GetOffset = () => { return musicVolume; }; + musicSlider.SetOffset(musicVolume); + + var shellmapMusic = Game.Settings.Game.ShellmapMusic; + var shellmapMusicCheckbox = generalPane.GetWidget("SHELLMAP_MUSIC"); + shellmapMusicCheckbox.IsChecked = () => shellmapMusic; + shellmapMusicCheckbox.OnClick = () => shellmapMusic ^= true; + + + // Input pane + var inputPane = panel.GetWidget("INPUT_CONTROLS"); + inputPane.IsVisible = () => Settings == PanelType.Input; + var inputButton = panel.GetWidget("INPUT_BUTTON"); inputButton.OnClick = () => Settings = PanelType.Input; inputButton.IsDisabled = () => Settings == PanelType.Input; - var generalButton = panel.GetWidget("GENERAL_BUTTON"); - generalButton.OnClick = () => Settings = PanelType.General; - generalButton.IsDisabled = () => Settings == PanelType.General; + inputPane.GetWidget("CLASSICORDERS_CHECKBOX").IsDisabled = () => true; + + var scrollStrength = Game.Settings.Game.ViewportEdgeScrollStep; + var scrollSlider = inputPane.GetWidget("SCROLLSPEED_SLIDER"); + scrollSlider.OnChange += x => scrollStrength = scrollSlider.GetOffset(); + scrollSlider.SetOffset(scrollStrength); + + var edgescroll = Game.Settings.Game.ViewportEdgeScroll; + var edgescrollCheckbox = inputPane.GetWidget("EDGESCROLL_CHECKBOX"); + edgescrollCheckbox.IsChecked = () => edgescroll; + edgescrollCheckbox.OnClick = () => edgescroll ^= true; + + mouseScroll = Game.Settings.Game.MouseScroll; + var mouseScrollDropdown = inputPane.GetWidget("MOUSE_SCROLL"); + mouseScrollDropdown.OnMouseUp = _ => ShowMouseScrollDropdown(mouseScrollDropdown); + mouseScrollDropdown.GetText = () => mouseScroll.ToString(); + + var teamchat = Game.Settings.Game.TeamChatToggle; + var teamchatCheckbox = inputPane.GetWidget("TEAMCHAT_CHECKBOX"); + teamchatCheckbox.IsChecked = () => teamchat; + teamchatCheckbox.OnClick = () => teamchat ^= true; + + groupAddModifier = Game.Settings.Keyboard.ControlGroupModifier; + var groupModifierDropdown = inputPane.GetWidget("GROUPADD_MODIFIER"); + groupModifierDropdown.OnMouseUp = _ => ShowGroupModifierDropdown(groupModifierDropdown); + groupModifierDropdown.GetText = () => groupAddModifier.ToString(); + + + panel.GetWidget("CANCEL_BUTTON").OnClick = () => + { + Widget.CloseWindow(); + onExit(); + }; + + panel.GetWidget("SAVE_BUTTON").OnClick = () => + { + var s = Game.Settings; + s.Player.Name = nameTextfield.Text; + s.Player.ColorRamp = playerColor; + + s.Debug.PerfText = perftext; + s.Debug.PerfGraph = perfgraph; + s.Game.MatchTimer = matchtimer; + s.Debug.SanityCheckUnsyncedCode = checkunsynced; + + s.Graphics.Mode = windowMode; + + int x = s.Graphics.WindowedSize.X, y = s.Graphics.WindowedSize.Y; + int.TryParse(windowWidth.Text, out x); + int.TryParse(windowHeight.Text, out y); + s.Graphics.WindowedSize = new int2(x,y); + + s.Sound.SoundVolume = soundVolume; + Sound.SoundVolume = soundVolume; + s.Sound.MusicVolume = musicVolume; + Sound.MusicVolume = musicVolume; + s.Game.ShellmapMusic = shellmapMusic; + + + s.Game.ViewportEdgeScrollStep = scrollStrength; + s.Game.ViewportEdgeScroll = edgescroll; + s.Game.MouseScroll = mouseScroll; + + s.Game.TeamChatToggle = teamchat; + s.Keyboard.ControlGroupModifier = groupAddModifier; + s.Save(); + Widget.CloseWindow(); + onExit(); + }; + } + + bool ShowColorPicker(Widget colorDropdown) + { + Action onSelect = c => + { + playerColor = c; + }; + + Action onChange = c => + { + playerPalettePreview.Ramp = c; + }; + + var colorChooser = Game.LoadWidget(world, "COLOR_CHOOSER", null, new WidgetArgs() + { + { "onSelect", onSelect }, + { "onChange", onChange }, + { "initialRamp", playerColor } + }); + + CncDropDownButtonWidget.ShowDropPanel(colorDropdown, colorChooser, new List() { colorChooser.GetWidget("SAVE_BUTTON") }, () => true); + return true; + } + + bool ShowGroupModifierDropdown(Widget dropdown) + { + var dropDownOptions = new List>() + { + Pair.New("Ctrl", new Action(() => groupAddModifier = Modifiers.Ctrl)), + Pair.New("Alt", new Action(() => groupAddModifier = Modifiers.Alt)), + Pair.New("Shift", new Action(() => groupAddModifier = Modifiers.Shift)), + // TODO: Display this as Cmd on osx once we have platform detection + Pair.New("Meta", new Action(() => groupAddModifier = Modifiers.Meta)), + }; + + + CncDropDownButtonWidget.ShowDropDown(dropdown, + dropDownOptions, + (ac, w) => new LabelWidget + { + Bounds = new Rectangle(0, 0, w, 24), + Text = ac.First, + Align = LabelWidget.TextAlign.Center, + OnMouseUp = mi => { ac.Second(); return true; }, + }); + return true; + } + + bool ShowWindowModeDropdown(Widget dropdown) + { + var dropDownOptions = new List>() + { + Pair.New("Pseudo-Fullscreen", new Action(() => windowMode = WindowMode.PseudoFullscreen)), + Pair.New("Fullscreen", new Action(() => windowMode = WindowMode.Fullscreen)), + Pair.New("Windowed", new Action(() => windowMode = WindowMode.Windowed)), + }; + + CncDropDownButtonWidget.ShowDropDown(dropdown, + dropDownOptions, + (ac, w) => new LabelWidget + { + Bounds = new Rectangle(0, 0, w, 24), + Text = ac.First, + Align = LabelWidget.TextAlign.Center, + OnMouseUp = mi => { ac.Second(); return true; }, + }); + return true; + } + + + bool ShowMouseScrollDropdown(Widget dropdown) + { + var dropDownOptions = new List>() + { + Pair.New("Disabled", new Action(() => mouseScroll = MouseScrollType.Disabled)), + Pair.New("Standard", new Action(() => mouseScroll = MouseScrollType.Standard)), + Pair.New("Inverted", new Action(() => mouseScroll = MouseScrollType.Inverted)), + }; + + CncDropDownButtonWidget.ShowDropDown(dropdown, + dropDownOptions, + (ac, w) => new LabelWidget + { + Bounds = new Rectangle(0, 0, w, 24), + Text = ac.First, + Align = LabelWidget.TextAlign.Center, + OnMouseUp = mi => { ac.Second(); return true; }, + }); + return true; } } } diff --git a/OpenRA.Mods.RA/Widgets/Delegates/SettingsMenuDelegate.cs b/OpenRA.Mods.RA/Widgets/Delegates/SettingsMenuDelegate.cs index d74c0db26d..f7f6989f09 100755 --- a/OpenRA.Mods.RA/Widgets/Delegates/SettingsMenuDelegate.cs +++ b/OpenRA.Mods.RA/Widgets/Delegates/SettingsMenuDelegate.cs @@ -57,7 +57,11 @@ namespace OpenRA.Mods.RA.Widgets.Delegates Game.Settings.Game.ViewportEdgeScrollStep = edgeScrollSlider.GetOffset(); } - general.GetWidget("INVERSE_SCROLL").Bind(Game.Settings.Game, "InverseDragScroll"); + var inversescroll = general.GetWidget("INVERSE_SCROLL"); + + inversescroll.IsChecked = () => Game.Settings.Game.MouseScroll == MouseScrollType.Inverted; + inversescroll.OnChange += c => Game.Settings.Game.MouseScroll = (Game.Settings.Game.MouseScroll == MouseScrollType.Inverted) ? MouseScrollType.Standard : MouseScrollType.Inverted; + general.GetWidget("TEAMCHAT_TOGGLE").Bind(Game.Settings.Game, "TeamChatToggle"); diff --git a/mods/cnc/chrome/preferences.yaml b/mods/cnc/chrome/preferences.yaml index 932d18c67c..dd82bf58ab 100644 --- a/mods/cnc/chrome/preferences.yaml +++ b/mods/cnc/chrome/preferences.yaml @@ -61,7 +61,7 @@ Container@SETTINGS_PANEL: Text:Debug Align:Center CncCheckbox@PERFINFO_CHECKBOX: - Id:PERFINFO_CHECKBOX + Id:PERFTEXT_CHECKBOX X:15 Y:120 Width:300 @@ -76,14 +76,14 @@ Container@SETTINGS_PANEL: Height:20 Font:Regular Text:Show Performance Graph - CncCheckbox@GAMETIME_CHECKBOX: - Id:GAMETIME_CHECKBOX + CncCheckbox@MATCHTIME_CHECKBOX: + Id:MATCHTIME_CHECKBOX X:15 Y:180 Width:300 Height:20 Font:Regular - Text:Show Game Time Counter + Text:Show Match Timer CncCheckbox@CHECKUNSYNCED_CHECKBOX: Id:CHECKUNSYNCED_CHECKBOX X:15 @@ -114,36 +114,39 @@ Container@SETTINGS_PANEL: Height:25 Font:Regular Text:Windowed - Label@At: - Text:@ - Font:Bold - X:575 - Y:39 - Height:25 - Width:25 - Align:Center - CncTextField@SCREEN_WIDTH: - Id:SCREEN_WIDTH - X:600 - Y:40 - Width:45 - Height:25 - MaxLength:5 - Label@X: - Text:x - Font:Bold - X:645 - Y:39 - Height:25 - Width:25 - Align:Center - CncTextField@SCREEN_HEIGHT: - Id:SCREEN_HEIGHT - X:670 - Y:40 - Width:45 - Height:25 - MaxLength:5 + Container@WINDOWRES: + Id:WINDOW_RESOLUTION + Children: + Label@At: + Text:@ + Font:Bold + X:575 + Y:39 + Height:25 + Width:25 + Align:Center + CncTextField@SCREEN_WIDTH: + Id:WINDOW_WIDTH + X:600 + Y:40 + Width:45 + Height:25 + MaxLength:5 + Label@X: + Text:x + Font:Bold + X:645 + Y:39 + Height:25 + Width:25 + Align:Center + CncTextField@SCREEN_HEIGHT: + Id:WINDOW_HEIGHT + X:670 + Y:40 + Width:45 + Height:25 + MaxLength:5 Label@VIDEO_DESC: X:375 Y:65 @@ -194,7 +197,7 @@ Container@SETTINGS_PANEL: Width:200 Height:20 Font:Regular - Text:Disable Shellmap Music + Text:Shellmap Music Background@INPUT_CONTROLS: Id:INPUT_CONTROLS Width:740 @@ -209,8 +212,8 @@ Container@SETTINGS_PANEL: X:15 Y:20 Width:340 - CncCheckbox@CLASSIC_ORDERS: - Id:CLASSIC_ORDERS + CncCheckbox@CLASSICORDERS_CHECKBOX: + Id:CLASSICORDERS_CHECKBOX X:15 Y:35 Width:250 @@ -230,16 +233,16 @@ Container@SETTINGS_PANEL: Width:95 Height:25 Text:Scroll Speed: - CncSlider@SCROLL_SPEED: - Id:SCROLL_SPEED + CncSlider@SCROLLSPEED_SLIDER: + Id:SCROLLSPEED_SLIDER X:100 Y:120 Width:240 Height:20 Ticks:5 Range:10,50 - CncCheckbox@EDGE_SCROLL: - Id:EDGE_SCROLL + CncCheckbox@EDGESCROLL_CHECKBOX: + Id:EDGESCROLL_CHECKBOX X:15 Y:150 Width:130 @@ -262,22 +265,22 @@ Container@SETTINGS_PANEL: Height:25 Font:Regular Text:Enabled - Label@MULTITOUCH_SCROLL_LABEL: - X:15 - Y:210 - Width:160 - Height:20 - Font:Regular - Text:Multitouch Scrolling: - Align:Right - CncDropDownButton@MULTITOUCH_SCROLL: - Id:MULTITOUCH_SCROLL - X:180 - Y:210 - Width:100 - Height:25 - Font:Regular - Text:Enabled +# Label@MULTITOUCH_SCROLL_LABEL: +# X:15 +# Y:210 +# Width:160 +# Height:20 +# Font:Regular +# Text:Multitouch Scrolling: +# Align:Right +# CncDropDownButton@MULTITOUCH_SCROLL: +# Id:MULTITOUCH_SCROLL +# X:180 +# Y:210 +# Width:100 +# Height:25 +# Font:Regular +# Text:Enabled Label@KEYBOARD_TITLE: X:375 Y:20 @@ -285,36 +288,51 @@ Container@SETTINGS_PANEL: Font:Bold Text:Keyboard Input Align:Center - CncCheckbox@TEAMCHAT_TOGGLE: - Id:TEAMCHAT_TOGGLE + CncCheckbox@TEAMCHAT_CHECKBOX: + Id:TEAMCHAT_CHECKBOX X:375 Y:35 Width:240 Height:20 Font:Regular Text:Shift-Enter Toggles Team Chat - Label@BINDING_LABEL: - Font:Bold + Label@GROUP_MODIFIER_LABEL: X:375 - Y:60 - Width:200 - Height:25 - Align:Center - Text:Action - Label@KEY_LABEL: - Font:Bold - X:640 - Y:60 - Width:30 - Height:25 + Y:65 + Width:160 + Height:20 + Font:Regular + Text:Group Addition Modifier: Align:Right - Text:Key - CncScrollPanel@KEYBINDINGS: - Id:KEYBINDINGS - X:375 - Y:85 - Width:350 - Height:150 + CncDropDownButton@GROUPADD_MODIFIER: + Id:GROUPADD_MODIFIER + X:540 + Y:65 + Width:100 + Height:25 + Font:Regular +# Label@BINDING_LABEL: +# Font:Bold +# X:375 +# Y:60 +# Width:200 +# Height:25 +# Align:Center +# Text:Action +# Label@KEY_LABEL: +# Font:Bold +# X:640 +# Y:60 +# Width:30 +# Height:25 +# Align:Right +# Text:Key +# CncScrollPanel@KEYBINDINGS: +# Id:KEYBINDINGS +# X:375 +# Y:85 +# Width:350 +# Height:150 CncMenuButton@GENERAL_BUTTON: Id:GENERAL_BUTTON Y:249 @@ -328,13 +346,13 @@ Container@SETTINGS_PANEL: Width:140 Height:35 Text:Input - CncMenuButton@RESET_BUTTON: - Id:RESET_BUTTON + CncMenuButton@CANCEL_BUTTON: + Id:CANCEL_BUTTON X:450 Y:249 Width:140 Height:35 - Text:Reset + Text:Cancel CncMenuButton@SAVE_BUTTON: Id:SAVE_BUTTON X:600