Skip to content

Commit

Permalink
Implement a slider widget for volume control that returns an exponent…
Browse files Browse the repository at this point in the history
…ially scaled value
  • Loading branch information
netnazgul committed Apr 14, 2018
1 parent cc04ec6 commit ca31d60
Show file tree
Hide file tree
Showing 10 changed files with 124 additions and 29 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ Also thanks to:
* Muh
* Mustafa Alperen Seki (MustaphaTR)
* Neil Shivkar (havok13888)
* Nikolay Fomin (netnazgul)
* Nooze
* Nukem
* Okunev Yu Dmitry (xaionaro)
Expand Down
1 change: 1 addition & 0 deletions OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,7 @@
<Compile Include="UtilityCommands\ExtractZeroBraneStudioLuaAPI.cs" />
<Compile Include="UtilityCommands\ExtractTraitDocsCommand.cs" />
<Compile Include="UtilityCommands\ExtractWeaponDocsCommand.cs" />
<Compile Include="Widgets\ExponentialSliderWidget.cs" />
<Compile Include="Widgets\Logic\MusicHotkeyLogic.cs" />
<Compile Include="WorldExtensions.cs" />
<Compile Include="UtilityCommands\GetMapHashCommand.cs" />
Expand Down
82 changes: 82 additions & 0 deletions OpenRA.Mods.Common/Widgets/ExponentialSliderWidget.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#region Copyright & License Information
/*
* Copyright 2007-2017 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, either version 3 of
* the License, or (at your option) any later version. For more
* information, see COPYING.
*/
#endregion

using System;
using System.Drawing;
using OpenRA.Graphics;
using OpenRA.Widgets;

namespace OpenRA.Mods.Common.Widgets
{
public class ExponentialSliderWidget : SliderWidget
{
public double ExpA = 1.0e-3;
public double ExpB = 6.908;

public ExponentialSliderWidget() { }
public ExponentialSliderWidget(ExponentialSliderWidget other) : base(other) { }

float ExpFromLinear(float x)
{
if (x <= 0)
return 0;

return (float)(ExpA * Math.Exp(ExpB * x)).Clamp(0.0, 1.0);
}

float LinearFromExp(float x)
{
return (float)(Math.Log(x / ExpA) / ExpB).Clamp(0.0, 1.0);
}

protected override float ValueFromPx(int x)
{
return MinimumValue + (MaximumValue - MinimumValue) * ExpFromLinear((x - 0.5f * RenderBounds.Height) / (RenderBounds.Width - RenderBounds.Height));
}

protected override int PxFromValue(float x)
{
return (int)(0.5f * RenderBounds.Height + (RenderBounds.Width - RenderBounds.Height) * LinearFromExp((x - MinimumValue) / (MaximumValue - MinimumValue)));
}

public override void Draw()
{
if (!IsVisible())
return;

Value = GetValue();

var tr = ThumbRect;
var rb = RenderBounds;
var trackWidth = rb.Width - rb.Height;
var trackOrigin = rb.X + rb.Height / 2;
var trackRect = new Rectangle(trackOrigin - 1, rb.Y + (rb.Height - TrackHeight) / 2, trackWidth + 2, TrackHeight);

// Tickmarks
var tick = ChromeProvider.GetImage("slider", "tick");
for (var i = 0; i < Ticks; i++)
{
var tickPos = new float2(
trackOrigin + (ExpFromLinear(1.0f * i / (Ticks - 1)) * (trackRect.Width - (int)tick.Size.X)) - tick.Size.X / 2,
trackRect.Bottom);

WidgetUtils.DrawRGBA(tick, tickPos);
}

// Track
WidgetUtils.DrawPanel(Track, trackRect);

// Thumb
var thumbHover = Ui.MouseOverWidget == this && tr.Contains(Viewport.LastMousePos);
ButtonWidget.DrawBackground(Thumb, tr, IsDisabled(), isMoving, thumbHover, false);
}
}
}
2 changes: 1 addition & 1 deletion OpenRA.Mods.Common/Widgets/Logic/MusicPlayerLogic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public MusicPlayerLogic(Widget widget, ModData modData, World world, Action onEx
if (musicTitle != null)
musicTitle.GetText = () => currentSong != null ? currentSong.Title : "No song playing";

var musicSlider = panel.Get<SliderWidget>("MUSIC_SLIDER");
var musicSlider = panel.Get<ExponentialSliderWidget>("MUSIC_SLIDER");
musicSlider.OnChange += x => Game.Sound.MusicVolume = x;
musicSlider.Value = Game.Sound.MusicVolume;

Expand Down
29 changes: 20 additions & 9 deletions OpenRA.Mods.Common/Widgets/Logic/SettingsLogic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,17 @@ static void BindSliderPref(Widget parent, string id, object group, string pref)
ss.OnChange += x => field.SetValue(group, x);
}

static void BindExpSliderPref(Widget parent, string id, object group, string pref)
{
var field = group.GetType().GetField(pref);
if (field == null)
throw new InvalidOperationException("{0} does not contain a preference type {1}".F(group.GetType().Name, pref));

var ss = parent.Get<ExponentialSliderWidget>(id);
ss.Value = (float)field.GetValue(group);
ss.OnChange += x => field.SetValue(group, x);
}

static void BindHotkeyPref(HotkeyDefinition hd, HotkeyManager manager, Widget template, Widget parent)
{
var key = template.Clone() as Widget;
Expand Down Expand Up @@ -310,9 +321,9 @@ Action InitAudioPanel(Widget panel)
BindCheckboxPref(panel, "CASH_TICKS", ss, "CashTicks");
BindCheckboxPref(panel, "MUTE_SOUND", ss, "Mute");

BindSliderPref(panel, "SOUND_VOLUME", ss, "SoundVolume");
BindSliderPref(panel, "MUSIC_VOLUME", ss, "MusicVolume");
BindSliderPref(panel, "VIDEO_VOLUME", ss, "VideoVolume");
BindExpSliderPref(panel, "SOUND_VOLUME", ss, "SoundVolume");
BindExpSliderPref(panel, "MUSIC_VOLUME", ss, "MusicVolume");
BindExpSliderPref(panel, "VIDEO_VOLUME", ss, "VideoVolume");

var muteCheckbox = panel.Get<CheckboxWidget>("MUTE_SOUND");
var muteCheckboxOnClick = muteCheckbox.OnClick;
Expand All @@ -328,9 +339,9 @@ Action InitAudioPanel(Widget panel)

if (!ss.Mute)
{
panel.Get<SliderWidget>("SOUND_VOLUME").OnChange += x => Game.Sound.SoundVolume = x;
panel.Get<SliderWidget>("MUSIC_VOLUME").OnChange += x => Game.Sound.MusicVolume = x;
panel.Get<SliderWidget>("VIDEO_VOLUME").OnChange += x => Game.Sound.VideoVolume = x;
panel.Get<ExponentialSliderWidget>("SOUND_VOLUME").OnChange += x => Game.Sound.SoundVolume = x;
panel.Get<ExponentialSliderWidget>("MUSIC_VOLUME").OnChange += x => Game.Sound.MusicVolume = x;
panel.Get<ExponentialSliderWidget>("VIDEO_VOLUME").OnChange += x => Game.Sound.VideoVolume = x;
}

var devices = Game.Sound.AvailableDevices();
Expand Down Expand Up @@ -363,11 +374,11 @@ Action ResetAudioPanel(Widget panel)
ss.Mute = dss.Mute;
ss.Device = dss.Device;
panel.Get<SliderWidget>("SOUND_VOLUME").Value = ss.SoundVolume;
panel.Get<ExponentialSliderWidget>("SOUND_VOLUME").Value = ss.SoundVolume;
Game.Sound.SoundVolume = ss.SoundVolume;
panel.Get<SliderWidget>("MUSIC_VOLUME").Value = ss.MusicVolume;
panel.Get<ExponentialSliderWidget>("MUSIC_VOLUME").Value = ss.MusicVolume;
Game.Sound.MusicVolume = ss.MusicVolume;
panel.Get<SliderWidget>("VIDEO_VOLUME").Value = ss.VideoVolume;
panel.Get<ExponentialSliderWidget>("VIDEO_VOLUME").Value = ss.VideoVolume;
Game.Sound.VideoVolume = ss.VideoVolume;
Game.Sound.UnmuteAudio();
soundDevice = Game.Sound.AvailableDevices().First();
Expand Down
6 changes: 3 additions & 3 deletions OpenRA.Mods.Common/Widgets/SliderWidget.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,19 +84,19 @@ public override bool HandleMouseInput(MouseInput mi)
return ThumbRect.Contains(mi.Location);
}

float ValueFromPx(int x)
protected virtual float ValueFromPx(int x)
{
return MinimumValue + (MaximumValue - MinimumValue) * (x - 0.5f * RenderBounds.Height) / (RenderBounds.Width - RenderBounds.Height);
}

protected int PxFromValue(float x)
protected virtual int PxFromValue(float x)
{
return (int)(0.5f * RenderBounds.Height + (RenderBounds.Width - RenderBounds.Height) * (x - MinimumValue) / (MaximumValue - MinimumValue));
}

public override Widget Clone() { return new SliderWidget(this); }

Rectangle ThumbRect
protected Rectangle ThumbRect
{
get
{
Expand Down
4 changes: 2 additions & 2 deletions mods/cnc/chrome/lobby-music.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -138,12 +138,12 @@ Container@LOBBY_MUSIC_BIN:
Height: 25
Align: Right
Text: Volume:
Slider@MUSIC_SLIDER:
ExponentialSlider@MUSIC_SLIDER:
X: 70
Y: 186
Width: PARENT_RIGHT - 80
Height: 20
Ticks: 5
Ticks: 10
ScrollPanel@MUSIC_LIST:
X: 307
Width: PARENT_RIGHT - 307
Expand Down
12 changes: 6 additions & 6 deletions mods/cnc/chrome/settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -274,12 +274,12 @@ Container@SETTINGS_PANEL:
Height: 25
Align: Right
Text: Sound Volume:
Slider@SOUND_VOLUME:
ExponentialSlider@SOUND_VOLUME:
X: PARENT_RIGHT - WIDTH - 15
Y: 43
Width: 250
Height: 20
Ticks: 5
Ticks: 10
Checkbox@CASH_TICKS:
X: 15
Y: 40
Expand All @@ -301,25 +301,25 @@ Container@SETTINGS_PANEL:
Height: 25
Align: Right
Text: Music Volume:
Slider@MUSIC_VOLUME:
ExponentialSlider@MUSIC_VOLUME:
X: PARENT_RIGHT - WIDTH - 15
Y: 73
Width: 250
Height: 20
Ticks: 5
Ticks: 10
Label@VIDEO_LABEL:
X: PARENT_RIGHT - WIDTH - 270
Y: 97
Width: 95
Height: 25
Align: Right
Text: Video Volume:
Slider@VIDEO_VOLUME:
ExponentialSlider@VIDEO_VOLUME:
X: PARENT_RIGHT - WIDTH - 15
Y: 103
Width: 250
Height: 20
Ticks: 5
Ticks: 10
Label@AUDIO_DEVICE_LABEL:
X: 190 - WIDTH - 5
Y: 244
Expand Down
4 changes: 2 additions & 2 deletions mods/common/chrome/lobby-music.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,12 @@ Container@LOBBY_MUSIC_BIN:
Height: 25
Align: Right
Text: Volume:
Slider@MUSIC_SLIDER:
ExponentialSlider@MUSIC_SLIDER:
X: 70
Y: 186
Width: PARENT_RIGHT - 80
Height: 20
Ticks: 5
Ticks: 10
ScrollPanel@MUSIC_LIST:
X: 268
Width: PARENT_RIGHT - 268
Expand Down
12 changes: 6 additions & 6 deletions mods/common/chrome/settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -282,12 +282,12 @@ Background@SETTINGS_PANEL:
Height: 25
Align: Right
Text: Sound Volume:
Slider@SOUND_VOLUME:
ExponentialSlider@SOUND_VOLUME:
X: PARENT_RIGHT - WIDTH - 15
Y: 43
Width: 250
Height: 20
Ticks: 5
Ticks: 10
Checkbox@CASH_TICKS:
X: 15
Y: 40
Expand All @@ -309,25 +309,25 @@ Background@SETTINGS_PANEL:
Height: 25
Align: Right
Text: Music Volume:
Slider@MUSIC_VOLUME:
ExponentialSlider@MUSIC_VOLUME:
X: PARENT_RIGHT - WIDTH - 15
Y: 73
Width: 250
Height: 20
Ticks: 5
Ticks: 10
Label@VIDEO_LABEL:
X: PARENT_RIGHT - WIDTH - 270
Y: 97
Width: 95
Height: 25
Align: Right
Text: Video Volume:
Slider@VIDEO_VOLUME:
ExponentialSlider@VIDEO_VOLUME:
X: PARENT_RIGHT - WIDTH - 15
Y: 103
Width: 250
Height: 20
Ticks: 5
Ticks: 10
Label@AUDIO_DEVICE_LABEL:
X: 190 - WIDTH - 5
Y: 244
Expand Down

0 comments on commit ca31d60

Please sign in to comment.