Not possible to adjust decorator color without setting a new array
Ven0maus opened this issue · 5 comments
/// <summary>
/// Sets the foreground alpha on each glyph on the surface that has a valid glyph
/// </summary>
/// <param name="alpha">0.0 - 1.0 where 1 is invisible</param>
private void SetGlyphsAlpha(double alpha)
{
for (int x = 0; x < _surface.Width; x++)
{
for (int y = 0; y < _surface.Height; y++)
{
var foreground = _surface.Surface[x, y].Foreground;
var background = _surface.Surface[x, y].Background;
_surface.Surface[x, y].Foreground = foreground.SetAlpha(ClampTo0_255(alpha));
_surface.Surface[x, y].Background = background.SetAlpha(ClampTo0_255(alpha));
}
}
_surface.IsDirty = true;
}
private static byte ClampTo0_255(double value)
{
double scaledValue = value * 255.0;
int roundedValue = (int)Math.Round(scaledValue);
byte clampedValue = (byte)Math.Max(0, Math.Min(255, roundedValue));
return clampedValue;
}
Not possible to efficiently adjust decorator color without setting a new decorator array.
- Which version are you using?
- Which host renderer are you using?
I looked at the monogame (linked below) and the SFML code but they both keep everything inside of the cell.IsVisible
check.
Oh wait I see what is happening, I noticed it during my scene transition fade effect. What I'm doing is fading the alpha on the foreground and background color of the surface cell.
I suppose the only way to fade the decorator is to set a new array of decorators on each step (since the color is a readonly field)
I'm afraid it might give some GC overhead..
I've updated the github issue, to reflect the real problem.
private static CellDecorator[] AdjustDecoratorsColor(CellDecorator[] decorators, byte alpha)
{
if (decorators == null || decorators.Length == 0) return decorators;
CellDecorator[] newDecorators = new CellDecorator[decorators.Length];
for (int i=0; i < decorators.Length; i++)
{
var dec = decorators[i];
newDecorators[i] = new CellDecorator(dec.Color.SetAlpha(alpha), dec.Glyph, dec.Mirror);
}
return newDecorators;
}
_surface.Surface[x, y].Decorators = AdjustDecoratorsColor(_surface.Surface[x, y].Decorators, ClampTo0_255(alpha));
This works but needs to be profiled to see how much impact this has if it runs as like an effect for example.
@Ven0maus actually I can alter the structure a bit for the next alpha release. Since SadConsole is .NET 6, I can convert the struct members from fields to properties and add { get; init; }
which lets you do nondestructive mutation. This lets you do this (considering the next alpha will use lists instead of arrays for decorators. Here's an extension method for a surface:
public static void SetDecoratorAlpha(this ISurface obj, int x, int y, byte alpha)
{
if (obj.IsValidCell(x, y, out int index) && obj.Surface[index].Decorators != null)
{
for (int i = 0; i < obj.Surface[index].Decorators!.Count; i++)
{
CellDecorator temp = obj.Surface[index].Decorators![i];
obj.Surface[index].Decorators![i] = temp with { Color = temp.Color.SetAlpha(alpha) };
}
}
}
Closing as not a bug. The decorator enhancements have been pushed to the develop branch that let you mutate a decorator.