New slider Range parameter. Palette modifications. Potential crash fix. Clamp function.

Range parameter added to slider. Supports returning a range of values
rather than just 0-1. Allows you to not have to post process the offset.
Modified palette selector to not have full range, which was causing
blown out units.
Introduced exension method Clamp<T>(min, max)
Fixed crash deserializing out of bound color value using above
extension.
This commit is contained in:
Caleb Anderson
2010-10-04 02:30:04 -05:00
committed by Paul Chote
parent 06b20c8ba5
commit 7bdf6a953f
9 changed files with 184 additions and 126 deletions

10
OpenRA.FileFormats/Exts.cs Normal file → Executable file
View File

@@ -85,5 +85,15 @@ namespace OpenRA
{
return (T[])mi.GetCustomAttributes( typeof( T ), true );
}
public static T Clamp<T>(this T val, T min, T max) where T : IComparable<T>
{
if (val.CompareTo(min) < 0)
return min;
else if (val.CompareTo(max) > 0)
return max;
else
return val;
}
}
}

9
OpenRA.FileFormats/FieldLoader.cs Normal file → Executable file
View File

@@ -112,9 +112,9 @@ namespace OpenRA.FileFormats
{
var parts = x.Split(',');
if (parts.Length == 3)
return Color.FromArgb(int.Parse(parts[0]), int.Parse(parts[1]), int.Parse(parts[2]));
return Color.FromArgb(int.Parse(parts[0]).Clamp(0, 255), int.Parse(parts[1]).Clamp(0, 255), int.Parse(parts[2]).Clamp(0, 255));
if (parts.Length == 4)
return Color.FromArgb(int.Parse(parts[0]), int.Parse(parts[1]), int.Parse(parts[2]), int.Parse(parts[3]));
return Color.FromArgb(int.Parse(parts[0]).Clamp(0, 255), int.Parse(parts[1]).Clamp(0, 255), int.Parse(parts[2]).Clamp(0, 255), int.Parse(parts[3]).Clamp(0, 255));
return InvalidValueAction(x,fieldType, field);
}
@@ -264,7 +264,10 @@ namespace OpenRA.FileFormats
if (f.FieldType == typeof(Color))
{
var c = (Color)v;
return "{0},{1},{2},{3}".F(c.A,c.R,c.G,c.B);
return "{0},{1},{2},{3}".F(((int)c.A).Clamp(0, 255),
((int)c.R).Clamp(0, 255),
((int)c.G).Clamp(0, 255),
((int)c.B).Clamp(0, 255));
}
return f.FieldType.IsArray

View File

@@ -3,7 +3,7 @@
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{BDAEAB25-991E-46A7-AF1E-4F0E03358DAA}</ProjectGuid>
<OutputType>Library</OutputType>

30
OpenRA.Game/Exts.cs Normal file → Executable file
View File

@@ -34,17 +34,17 @@ namespace OpenRA
return xs.Aggregate(1f, (a, x) => a * x);
}
public static V GetOrAdd<K, V>( this Dictionary<K, V> d, K k )
public static V GetOrAdd<K, V>(this Dictionary<K, V> d, K k)
where V : new()
{
return d.GetOrAdd( k, _ => new V() );
return d.GetOrAdd(k, _ => new V());
}
public static V GetOrAdd<K, V>( this Dictionary<K, V> d, K k, Func<K, V> createFn )
public static V GetOrAdd<K, V>(this Dictionary<K, V> d, K k, Func<K, V> createFn)
{
V ret;
if( !d.TryGetValue( k, out ret ) )
d.Add( k, ret = createFn( k ) );
if (!d.TryGetValue(k, out ret))
d.Add(k, ret = createFn(k));
return ret;
}
@@ -54,18 +54,28 @@ namespace OpenRA
return xs[r.Next(xs.Length)];
}
public static void DoTimed<T>( this IEnumerable<T> e, Action<T> a, string text, double time )
public static void DoTimed<T>(this IEnumerable<T> e, Action<T> a, string text, double time)
{
var sw = new Stopwatch();
e.Do( x =>
e.Do(x =>
{
var t = sw.ElapsedTime();
a( x );
a(x);
var dt = sw.ElapsedTime() - t;
if( dt > time )
if (dt > time)
Log.Write("perf", text, x, dt * 1000, Game.LocalTick);
} );
});
}
public static T Clamp<T>(this T val, T min, T max) where T : IComparable<T>
{
if (val.CompareTo(min) < 0)
return min;
else if (val.CompareTo(max) > 0)
return max;
else
return val;
}
}
}

11
OpenRA.Game/Server/Exts.cs Normal file → Executable file
View File

@@ -11,6 +11,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System;
namespace OpenRA.Server
{
@@ -32,5 +33,15 @@ namespace OpenRA.Server
{
return ts.Except( new[] { t } );
}
public static T Clamp<T>(this T val, T min, T max) where T : IComparable<T>
{
if (val.CompareTo(min) < 0)
return min;
else if (val.CompareTo(max) > 0)
return max;
else
return val;
}
}
}

202
OpenRA.Game/Widgets/Delegates/LobbyDelegate.cs Normal file → Executable file
View File

@@ -12,7 +12,7 @@ using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Network;
using OpenRA.Network;
namespace OpenRA.Widgets.Delegates
{
@@ -22,7 +22,7 @@ namespace OpenRA.Widgets.Delegates
Dictionary<string, string> CountryNames;
string MapUid;
MapStub Map;
MapStub Map;
public static Color CurrentColorPreview1;
public static Color CurrentColorPreview2;
@@ -133,74 +133,74 @@ namespace OpenRA.Widgets.Delegates
teamChat ^= true;
chatLabel.Text = (teamChat) ? "Team:" : "Chat:";
return true;
};
var colorChooser = lobby.GetWidget("COLOR_CHOOSER");
var hueSlider = colorChooser.GetWidget<SliderWidget>("HUE_SLIDER");
var satSlider = colorChooser.GetWidget<SliderWidget>("SAT_SLIDER");
var lumSlider = colorChooser.GetWidget<SliderWidget>("LUM_SLIDER");
var rangeSlider = colorChooser.GetWidget<SliderWidget>("RANGE_SLIDER");
hueSlider.OnChange += _ => UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
satSlider.OnChange += _ => UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
lumSlider.OnChange += _ => UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
rangeSlider.OnChange += _ => UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
colorChooser.GetWidget<ButtonWidget>("BUTTON_OK").OnMouseUp = mi =>
{
colorChooser.IsVisible = () => false;
UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
UpdatePlayerColor(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
return true;
};
}
void UpdatePlayerColor(float hf, float sf, float lf, float r)
{
var c1 = ColorFromHSL(hf, sf, lf);
var c2 = ColorFromHSL(hf, sf, r*lf);
Game.Settings.Player.Color1 = c1;
Game.Settings.Player.Color2 = c2;
Game.Settings.Save();
Game.IssueOrder(Order.Command("color {0},{1},{2},{3},{4},{5}".F(c1.R,c1.G,c1.B,c2.R,c2.G,c2.B)));
}
void UpdateColorPreview(float hf, float sf, float lf, float r)
{
CurrentColorPreview1 = ColorFromHSL(hf, sf, lf);
CurrentColorPreview2 = ColorFromHSL(hf, sf, r*lf);
Game.viewport.RefreshPalette();
}
var colorChooser = lobby.GetWidget("COLOR_CHOOSER");
var hueSlider = colorChooser.GetWidget<SliderWidget>("HUE_SLIDER");
var satSlider = colorChooser.GetWidget<SliderWidget>("SAT_SLIDER");
var lumSlider = colorChooser.GetWidget<SliderWidget>("LUM_SLIDER");
var rangeSlider = colorChooser.GetWidget<SliderWidget>("RANGE_SLIDER");
hueSlider.OnChange += _ => UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
satSlider.OnChange += _ => UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
lumSlider.OnChange += _ => UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
rangeSlider.OnChange += _ => UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
colorChooser.GetWidget<ButtonWidget>("BUTTON_OK").OnMouseUp = mi =>
{
colorChooser.IsVisible = () => false;
UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
UpdatePlayerColor(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
return true;
};
}
// hk is hue in the range [0,1] instead of [0,360]
Color ColorFromHSL(float hk, float s, float l)
{
// Convert from HSL to RGB
var q = (l < 0.5f) ? l * (1 + s) : l + s - (l * s);
var p = 2 * l - q;
float[] trgb = { hk + 1 / 3.0f,
hk,
hk - 1/3.0f };
float[] rgb = { 0, 0, 0 };
for (int k = 0; k < 3; k++)
{
while (trgb[k] < 0) trgb[k] += 1.0f;
while (trgb[k] > 1) trgb[k] -= 1.0f;
}
for (int k = 0; k < 3; k++)
{
if (trgb[k] < 1 / 6.0f) { rgb[k] = (p + ((q - p) * 6 * trgb[k])); }
else if (trgb[k] >= 1 / 6.0f && trgb[k] < 0.5) { rgb[k] = q; }
else if (trgb[k] >= 0.5f && trgb[k] < 2.0f / 3) { rgb[k] = (p + ((q - p) * 6 * (2.0f / 3 - trgb[k]))); }
else { rgb[k] = p; }
}
return Color.FromArgb((int)(rgb[0] * 255), (int)(rgb[1] * 255), (int)(rgb[2] * 255));
}
void UpdatePlayerColor(float hf, float sf, float lf, float r)
{
var c1 = ColorFromHSL(hf, sf, lf);
var c2 = ColorFromHSL(hf, sf, r*lf);
Game.Settings.Player.Color1 = c1;
Game.Settings.Player.Color2 = c2;
Game.Settings.Save();
Game.IssueOrder(Order.Command("color {0},{1},{2},{3},{4},{5}".F(c1.R,c1.G,c1.B,c2.R,c2.G,c2.B)));
}
void UpdateColorPreview(float hf, float sf, float lf, float r)
{
CurrentColorPreview1 = ColorFromHSL(hf, sf, lf);
CurrentColorPreview2 = ColorFromHSL(hf, sf, r*lf);
Game.viewport.RefreshPalette();
}
// hk is hue in the range [0,1] instead of [0,360]
Color ColorFromHSL(float hk, float s, float l)
{
// Convert from HSL to RGB
var q = (l < 0.5f) ? l * (1 + s) : l + s - (l * s);
var p = 2 * l - q;
float[] trgb = { hk + 1 / 3.0f,
hk,
hk - 1/3.0f };
float[] rgb = { 0, 0, 0 };
for (int k = 0; k < 3; k++)
{
while (trgb[k] < 0) trgb[k] += 1.0f;
while (trgb[k] > 1) trgb[k] -= 1.0f;
}
for (int k = 0; k < 3; k++)
{
if (trgb[k] < 1 / 6.0f) { rgb[k] = (p + ((q - p) * 6 * trgb[k])); }
else if (trgb[k] >= 1 / 6.0f && trgb[k] < 0.5) { rgb[k] = q; }
else if (trgb[k] >= 0.5f && trgb[k] < 2.0f / 3) { rgb[k] = (p + ((q - p) * 6 * (2.0f / 3 - trgb[k]))); }
else { rgb[k] = p; }
}
return Color.FromArgb((int)(rgb[0] * 255), (int)(rgb[1] * 255), (int)(rgb[2] * 255));
}
void UpdateCurrentMap()
@@ -209,23 +209,23 @@ namespace OpenRA.Widgets.Delegates
MapUid = Game.LobbyInfo.GlobalSettings.Map;
Map = Game.modData.AvailableMaps[MapUid];
}
bool hasJoined = false;
void JoinedServer()
{
if (hasJoined)
return;
hasJoined = true;
if (Game.LocalClient.Name != Game.Settings.Player.Name)
Game.IssueOrder(Order.Command("name " + Game.Settings.Player.Name));
bool hasJoined = false;
void JoinedServer()
{
if (hasJoined)
return;
hasJoined = true;
if (Game.LocalClient.Name != Game.Settings.Player.Name)
Game.IssueOrder(Order.Command("name " + Game.Settings.Player.Name));
var c1 = Game.Settings.Player.Color1;
var c2 = Game.Settings.Player.Color2;
if (Game.LocalClient.Color1 != c1 || Game.LocalClient.Color2 != c2)
Game.IssueOrder(Order.Command("color {0},{1},{2},{3},{4},{5}".F(c1.R,c1.G,c1.B,c2.R,c2.G,c2.B)));
if (Game.LocalClient.Color1 != c1 || Game.LocalClient.Color2 != c2)
Game.IssueOrder(Order.Command("color {0},{1},{2},{3},{4},{5}".F(c1.R,c1.G,c1.B,c2.R,c2.G,c2.B)));
}
void ResetConnectionState()
@@ -313,24 +313,24 @@ namespace OpenRA.Widgets.Delegates
name.OnLoseFocus = () => name.OnEnterKey();
var color = template.GetWidget<ButtonWidget>("COLOR");
color.OnMouseUp = mi =>
{
var colorChooser = Widget.RootWidget.GetWidget("SERVER_LOBBY").GetWidget("COLOR_CHOOSER");
var hueSlider = colorChooser.GetWidget<SliderWidget>("HUE_SLIDER");
hueSlider.Offset = Game.LocalClient.Color1.GetHue()/360f;
var satSlider = colorChooser.GetWidget<SliderWidget>("SAT_SLIDER");
satSlider.Offset = Game.LocalClient.Color1.GetSaturation();
var lumSlider = colorChooser.GetWidget<SliderWidget>("LUM_SLIDER");
lumSlider.Offset = Game.LocalClient.Color1.GetBrightness();
var rangeSlider = colorChooser.GetWidget<SliderWidget>("RANGE_SLIDER");
rangeSlider.Offset = Game.LocalClient.Color1.GetBrightness() == 0 ? 0 : Game.LocalClient.Color2.GetBrightness()/Game.LocalClient.Color1.GetBrightness();
UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
colorChooser.IsVisible = () => true;
return true;
color.OnMouseUp = mi =>
{
var colorChooser = Widget.RootWidget.GetWidget("SERVER_LOBBY").GetWidget("COLOR_CHOOSER");
var hueSlider = colorChooser.GetWidget<SliderWidget>("HUE_SLIDER");
hueSlider.SetOffset(Game.LocalClient.Color1.GetHue()/360f);
var satSlider = colorChooser.GetWidget<SliderWidget>("SAT_SLIDER");
satSlider.SetOffset(Game.LocalClient.Color1.GetSaturation());
var lumSlider = colorChooser.GetWidget<SliderWidget>("LUM_SLIDER");
lumSlider.SetOffset(Game.LocalClient.Color1.GetBrightness());
var rangeSlider = colorChooser.GetWidget<SliderWidget>("RANGE_SLIDER");
rangeSlider.SetOffset(Game.LocalClient.Color1.GetBrightness() == 0 ? 0 : Game.LocalClient.Color2.GetBrightness()/Game.LocalClient.Color1.GetBrightness());
UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
colorChooser.IsVisible = () => true;
return true;
};
var colorBlock = color.GetWidget<ColorBlockWidget>("COLORBLOCK");
@@ -422,4 +422,4 @@ namespace OpenRA.Widgets.Delegates
return true;
}
}
}
}

40
OpenRA.Game/Widgets/SliderWidget.cs Normal file → Executable file
View File

@@ -6,9 +6,9 @@
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
using System;
#endregion
using System;
using System.Drawing;
namespace OpenRA.Widgets
@@ -17,9 +17,11 @@ namespace OpenRA.Widgets
{
public event Action<float> OnChange;
public Func<float> GetOffset;
public float Offset = 0;
public int Ticks = 0;
public int TrackHeight = 5;
public float2 Range = new float2(0f, 1f);
private float Offset = 0;
int2 lastMouseLocation;
bool isMoving = false;
@@ -27,7 +29,14 @@ namespace OpenRA.Widgets
public SliderWidget()
: base()
{
GetOffset = () => Offset;
GetOffset = () =>
{
var Big = Math.Max(Range.X, Range.Y);
var Little = Math.Min(Range.X, Range.Y);
var Spread = Big - Little;
return Spread * Offset + Little;
};
OnChange = x => Offset = x;
}
@@ -43,6 +52,15 @@ namespace OpenRA.Widgets
isMoving = other.isMoving;
}
public void SetOffset(float newOffset)
{
var Big = Math.Max(Range.X, Range.Y);
var Little = Math.Min(Range.X, Range.Y);
var Spread = Big - Little;
Offset = (newOffset - Little) / Spread;
}
public override bool HandleInputInner(MouseInput mi)
{
if (mi.Event == MouseInputEvent.Down && !TakeFocus(mi))
@@ -72,7 +90,7 @@ namespace OpenRA.Widgets
}
else if (Ticks != 0)
{
var pos = GetOffset();
var pos = Offset;
// Offset slightly the direction we want to move so we don't get stuck on a tick
var delta = 0.001;
@@ -92,7 +110,7 @@ namespace OpenRA.Widgets
var thumb = thumbRect;
var center = thumb.X + thumb.Width / 2;
var newOffset = OffsetBy((mi.Location.X - center) * 1f / (RenderBounds.Width - thumb.Width));
if (newOffset != GetOffset())
if (newOffset != Offset)
{
OnChange(newOffset);
@@ -127,7 +145,7 @@ namespace OpenRA.Widgets
float OffsetBy(float amount)
{
var centerPos = GetOffset() + amount;
var centerPos = Offset + amount;
if (centerPos < 0) centerPos = 0;
if (centerPos > 1) centerPos = 1;
return centerPos;
@@ -141,7 +159,7 @@ namespace OpenRA.Widgets
{
var width = RenderBounds.Height;
var height = RenderBounds.Height;
var origin = (int)((RenderBounds.X + width / 2) + GetOffset() * (RenderBounds.Width - width) - width / 2f);
var origin = (int)((RenderBounds.X + width / 2) + Offset * (RenderBounds.Width - width) - width / 2f);
return new Rectangle(origin, RenderBounds.Y, width, height);
}
}
@@ -169,5 +187,5 @@ namespace OpenRA.Widgets
WidgetUtils.DrawPanel("dialog2", thumbRect);
}
}
}
}

View File

@@ -370,10 +370,12 @@ Background@SERVER_LOBBY:
Slider@LUM:
Id:LUM_SLIDER
X:120
Id:LUM_SLIDER
Y:90
Width:260
Height:20
Ticks:5
Range:0.2,1
Label@RANGE_LABEL:
X:0
Y:120
@@ -388,6 +390,7 @@ Background@SERVER_LOBBY:
Width:260
Height:20
Ticks:5
Range:0,0.25
Background@MAP_CHOOSER:
Id:MAP_CHOOSER
X:(WINDOW_RIGHT - WIDTH)/2

View File

@@ -371,10 +371,12 @@ Background@SERVER_LOBBY:
Slider@LUM:
Id:LUM_SLIDER
X:120
Id:LUM_SLIDER
Y:90
Width:260
Height:20
Ticks:5
Range:0.2,1
Label@RANGE_LABEL:
X:0
Y:120
@@ -389,6 +391,7 @@ Background@SERVER_LOBBY:
Width:260
Height:20
Ticks:5
Range:0,0.25
Background@MAP_CHOOSER:
Id:MAP_CHOOSER
X:(WINDOW_RIGHT - WIDTH)/2