-
Notifications
You must be signed in to change notification settings - Fork 0
/
Utilities.cs
173 lines (146 loc) · 5.76 KB
/
Utilities.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using StardewValley;
namespace SMUI
{
public class Utilities
{
public static string NameOfDay(int day, bool shortened = false)
{
return ((day - 1) % 7) switch
{
0 => shortened ? "Mon" : "Monday" ,
1 => shortened ? "Tue" : "Tuesday",
2 => shortened ? "Wed" : "Wednesday",
3 => shortened ? "Thu" : "Thursday",
4 => shortened ? "Fri" : "Friday",
5 => shortened ? "Sat" : "Saturday",
6 => shortened ? "Sun" : "Sunday",
_ => "###"
};
}
public static void InScissorRectangle(SpriteBatch spriteBatch, Rectangle area, Action<SpriteBatch> draw)
{
// render the current sprite batch to the screen
spriteBatch.End();
// start temporary sprite batch
using SpriteBatch contentBatch = new(Game1.graphics.GraphicsDevice);
GraphicsDevice device = Game1.graphics.GraphicsDevice;
Rectangle prevScissorRectangle = device.ScissorRectangle;
// render in scissor rectangle
try
{
device.ScissorRectangle = area;
contentBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, Utility.ScissorEnabled);
draw(contentBatch);
contentBatch.End();
}
finally
{
device.ScissorRectangle = prevScissorRectangle;
}
// resume previous sprite batch
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null);
}
public static Texture2D DoPaletteSwap(Texture2D baseTex, Texture2D from, Texture2D to)
{
var fromCols = new Color[from.Height];
var toCols = new Color[to.Height];
from.GetData(fromCols);
to.GetData(toCols);
return Utilities.DoPaletteSwap(baseTex, fromCols, toCols);
}
public static Texture2D DoPaletteSwap(Texture2D baseTex, Color[] fromCols, Color[] toCols)
{
var colMap = new Dictionary<Color, Color>();
for (int i = 0; i < fromCols.Length; ++i)
{
colMap.Add(fromCols[i], toCols[i]);
}
var cols = new Color[baseTex.Width * baseTex.Height];
baseTex.GetData(cols);
for (int i = 0; i < cols.Length; ++i)
{
if (colMap.TryGetValue(cols[i], out Color color))
cols[i] = color;
}
var newTex = new Texture2D(Game1.graphics.GraphicsDevice, baseTex.Width, baseTex.Height);
newTex.SetData(cols);
return newTex;
}
public static T Clamp<T>(T min, T t, T max)
{
if (Comparer<T>.Default.Compare(min, t) > 0)
return min;
if (Comparer<T>.Default.Compare(max, t) < 0)
return max;
return t;
}
public static T Adjust<T>(T value, T interval)
{
if (value is float vFloat && interval is float iFloat)
value = (T)(object)(float)((decimal)vFloat - ((decimal)vFloat % (decimal)iFloat));
if (value is int vInt && interval is int iInt)
value = (T)(object)(vInt - vInt % iInt);
return value;
}
public static void Swap<T>(ref T lhs, ref T rhs)
{
(rhs, lhs) = (lhs, rhs);
}
// https://stackoverflow.com/a/1626175/17827276
public static Color ColorFromHsv(double hue, double saturation, double value)
{
int hi = Convert.ToInt32(Math.Floor(hue / 60)) % 6;
double f = hue / 60 - Math.Floor(hue / 60);
value *= 255;
int v = Convert.ToInt32(value);
int p = Convert.ToInt32(value * (1 - saturation));
int q = Convert.ToInt32(value * (1 - f * saturation));
int t = Convert.ToInt32(value * (1 - (1 - f) * saturation));
if (hi == 0)
return new Color(v, t, p);
else if (hi == 1)
return new Color(q, v, p);
else if (hi == 2)
return new Color(p, v, t);
else if (hi == 3)
return new Color(p, q, v);
else if (hi == 4)
return new Color(t, p, v);
else
return new Color(v, p, q);
}
// https://stackoverflow.com/a/57385008
public static IEnumerable<Color> GetColorGradient(Color from, Color to, int totalNumberOfColors)
{
if (totalNumberOfColors < 2)
{
throw new ArgumentException("Gradient cannot have less than two colors.", nameof(totalNumberOfColors));
}
double diffA = to.A - from.A;
double diffR = to.R - from.R;
double diffG = to.G - from.G;
double diffB = to.B - from.B;
int steps = totalNumberOfColors - 1;
double stepA = diffA / steps;
double stepR = diffR / steps;
double stepG = diffG / steps;
double stepB = diffB / steps;
yield return from;
for (int i = 1; i < steps; ++i)
{
yield return new Color(
c(from.R, stepR),
c(from.G, stepG),
c(from.B, stepB),
c(from.A, stepA));
int c(int fromC, double stepC)
{
return (int)Math.Round(fromC + stepC * i);
}
}
yield return to;
}
}
}