Skip to content

Improve FlxSprite color transform handling, deprecate FlxColor.to24Bit() #3413

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Apr 28, 2025
113 changes: 66 additions & 47 deletions flixel/FlxSprite.hx
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,10 @@ class FlxSprite extends FlxObject
public var bakedRotationAngle(default, null):Float = 0;

/**
* Set alpha to a number between `0` and `1` to change the opacity of the sprite.
* Set alpha to a number between `0` and `1` to change the opacity of the sprite. Calling
* `setColorTransform` will also change this value
*
* **NOTE:** This value is automatically clamped to 0 <= a <= 1
@see https://snippets.haxeflixel.com/sprites/alpha/
*/
public var alpha(default, set):Float = 1.0;
Expand Down Expand Up @@ -246,7 +249,7 @@ class FlxSprite extends FlxObject
/**
* Change the size of your sprite's graphic.
* NOTE: The hitbox is not automatically adjusted, use `updateHitbox()` for that.
* WARNING: With `FlxG.renderBlit`, scaling sprites decreases rendering performance by a factor of about x10!
* **WARNING:** With `FlxG.renderBlit`, scaling sprites decreases rendering performance by a factor of about x10!
* @see https://snippets.haxeflixel.com/sprites/scale/
*/
public var scale(default, null):FlxPoint;
Expand All @@ -255,19 +258,23 @@ class FlxSprite extends FlxObject
* Blending modes, just like Photoshop or whatever, e.g. "multiply", "screen", etc.
*/
public var blend(default, set):BlendMode;

/**
* Tints the whole sprite to a color (`0xRRGGBB` format) - similar to OpenGL vertex colors. You can use
* `0xAARRGGBB` colors, but the alpha value will simply be ignored. To change the opacity use `alpha`.
* Multiplies this sprite's image by the given red, green and blue components, alpha is ignored.
* To change the opacity use `alpha`. Calling `setColorTransform` will also change this value.
* @see https://snippets.haxeflixel.com/sprites/color/
*/
public var color(default, set):FlxColor = 0xffffff;

public var colorTransform(default, null):ColorTransform;
public var color(default, set):FlxColor = FlxColor.WHITE;

/**
* The color effects of this sprite, changes to `color` or `alplha` will be reflected here
*/
public var colorTransform(default, null) = new ColorTransform();

/**
* Whether or not to use a `ColorTransform` set via `setColorTransform()`.
*/
@:deprecated("useColorTransform is deprecated, use hasColorTransform(), instead")// 6.1.0
public var useColorTransform(default, null):Bool = false;

/**
Expand Down Expand Up @@ -394,7 +401,6 @@ class FlxSprite extends FlxObject
scale = FlxPoint.get(1, 1);
_halfSize = FlxPoint.get();
_matrix = new FlxMatrix();
colorTransform = new ColorTransform();
_scaledOrigin = new FlxPoint();
}

Expand Down Expand Up @@ -428,7 +434,6 @@ class FlxSprite extends FlxObject
_flashRect2 = null;
_flashPointZero = null;
_matrix = null;
colorTransform = null;
blend = null;

frames = null;
Expand Down Expand Up @@ -1008,7 +1013,7 @@ class FlxSprite extends FlxObject
dirty = true;
return positions;
}

/**
* Sets the sprite's color transformation with control over color offsets.
* With `FlxG.renderTile`, offsets are only supported on OpenFL Next version 3.6.0 or higher.
Expand All @@ -1022,33 +1027,48 @@ class FlxSprite extends FlxObject
* @param blueOffset The offset for the blue color channel value, in the range from `-255` to `255`.
* @param alphaOffset The offset for alpha transparency channel value, in the range from `-255` to `255`.
*/
@:haxe.warning("-WDeprecated")
public function setColorTransform(redMultiplier = 1.0, greenMultiplier = 1.0, blueMultiplier = 1.0, alphaMultiplier = 1.0,
redOffset = 0.0, greenOffset = 0.0, blueOffset = 0.0, alphaOffset = 0.0):Void
{
color = FlxColor.fromRGBFloat(redMultiplier, greenMultiplier, blueMultiplier).to24Bit();
alpha = alphaMultiplier;

alphaMultiplier = FlxMath.bound(alphaMultiplier, 0, 1);
@:bypassAccessor color = FlxColor.fromRGBFloat(redMultiplier, greenMultiplier, blueMultiplier, 1.0);
@:bypassAccessor alpha = alphaMultiplier;

colorTransform.setMultipliers(redMultiplier, greenMultiplier, blueMultiplier, alphaMultiplier);
colorTransform.setOffsets(redOffset, greenOffset, blueOffset, alphaOffset);

useColorTransform = alpha != 1 || color != 0xffffff || colorTransform.hasRGBOffsets();
useColorTransform = hasColorTransformRaw();

dirty = true;
}

@:haxe.warning("-WDeprecated")
function updateColorTransform():Void
{
if (colorTransform == null)
return;

useColorTransform = alpha != 1 || color != 0xffffff;
if (useColorTransform)
colorTransform.setMultipliers(color.redFloat, color.greenFloat, color.blueFloat, alpha);
else
colorTransform.setMultipliers(1, 1, 1, 1);

colorTransform.setMultipliers(color.redFloat, color.greenFloat, color.blueFloat, alpha);
useColorTransform = hasColorTransformRaw();

dirty = true;
}


/**
* Whether this sprite has a color transform, menaing any of the following: less than full
* `alpha`, a `color` tint, or a `colorTransform` whos values are not the default.
*/
@:haxe.warning("-WDeprecated")
public function hasColorTransform()
{
return useColorTransform || hasColorTransformRaw();
}

/**
* Helper for the non-deprecated component of `hasColorTransform`
*/
function hasColorTransformRaw()
{
return alpha != 1 || color.rgb != 0xffffff || colorTransform.hasRGBAOffsets();
}

/**
* Checks to see if a point in 2D world space overlaps this `FlxSprite` object's
* current displayed pixels. This check is ALWAYS made in screen space, and
Expand Down Expand Up @@ -1209,18 +1229,18 @@ class FlxSprite extends FlxObject
{
if (_frame == null || !dirty)
return framePixels;

// don't try to regenerate frame pixels if _frame already uses it as source of graphics
// if you'll try then it will clear framePixels and you won't see anything
if (FlxG.renderTile && _frameGraphic != null)
{
dirty = false;
return framePixels;
}

var doFlipX:Bool = checkFlipX();
var doFlipY:Bool = checkFlipY();

final doFlipX = checkFlipX();
final doFlipY = checkFlipY();
if (!doFlipX && !doFlipY && _frame.type == FlxFrameType.REGULAR)
{
framePixels = _frame.paint(framePixels, _flashPointZero, false, true);
Expand All @@ -1229,20 +1249,20 @@ class FlxSprite extends FlxObject
{
framePixels = _frame.paintRotatedAndFlipped(framePixels, _flashPointZero, FlxFrameAngle.ANGLE_0, doFlipX, doFlipY, false, true);
}

if (useColorTransform)
if (FlxG.renderBlit && hasColorTransform())
{
framePixels.colorTransform(_flashRect, colorTransform);
}

if (FlxG.renderTile && useFramePixels)
{
// recreate _frame for native target, so it will use modified framePixels
_frameGraphic = FlxDestroyUtil.destroy(_frameGraphic);
_frameGraphic = FlxGraphic.fromBitmapData(framePixels, false, null, false);
_frame = _frameGraphic.imageFrame.frame.copyTo(_frame);
}

dirty = false;
return framePixels;
}
Expand Down Expand Up @@ -1504,25 +1524,24 @@ class FlxSprite extends FlxObject
}

@:noCompletion
function set_alpha(Alpha:Float):Float
function set_alpha(value:Float):Float
{
if (alpha == Alpha)
{
return Alpha;
}
alpha = FlxMath.bound(Alpha, 0, 1);
value = FlxMath.bound(value, 0, 1);
if (alpha == value)
return value;

alpha = value;
updateColorTransform();
return alpha;
}

@:noCompletion
function set_color(Color:FlxColor):Int
function set_color(value:FlxColor):Int
{
if (color == Color)
{
return Color;
}
color = Color;
if (color == value)
return value;

color = value;
updateColorTransform();
return color;
}
Expand Down
2 changes: 1 addition & 1 deletion flixel/system/debug/DebuggerUtil.hx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class DebuggerUtil
tf.antiAliasType = AntiAliasType.NORMAL;
tf.gridFitType = GridFitType.PIXEL;
#end
tf.defaultTextFormat = new TextFormat(FlxAssets.FONT_DEBUGGER, Size, Color.to24Bit());
tf.defaultTextFormat = new TextFormat(FlxAssets.FONT_DEBUGGER, Size, Color.rgb);
tf.alpha = Color.alphaFloat;
tf.autoSize = TextFieldAutoSize.LEFT;
return tf;
Expand Down
2 changes: 1 addition & 1 deletion flixel/system/frontEnds/CameraFrontEnd.hx
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ class CameraFrontEnd
}
else
{
camera.fill(camera.bgColor.to24Bit(), camera.useBgAlphaBlending, camera.bgColor.alphaFloat);
camera.fill(camera.bgColor.rgb, camera.useBgAlphaBlending, camera.bgColor.alphaFloat);
}
}
}
Expand Down
37 changes: 16 additions & 21 deletions flixel/text/FlxText.hx
Original file line number Diff line number Diff line change
Expand Up @@ -664,17 +664,24 @@ class FlxText extends FlxSprite
updateDefaultFormat();
return LetterSpacing;
}

override function setColorTransform(redMultiplier = 1.0, greenMultiplier = 1.0, blueMultiplier = 1.0, alphaMultiplier = 1.0, redOffset = 0.0, greenOffset = 0.0, blueOffset = 0.0, alphaOffset = 0.0)
{
super.setColorTransform(1, 1, 1, 1, redOffset, greenOffset, blueOffset, alphaOffset);
_defaultFormat.color = FlxColor.fromRGBFloat(redMultiplier, greenMultiplier, blueMultiplier, 0);
updateDefaultFormat();
}

override function set_color(Color:FlxColor):Int
override function set_color(value:FlxColor):Int
{
if (_defaultFormat.color == Color.to24Bit())
if (_defaultFormat.color == value.rgb)
{
return Color;
return value;
}
_defaultFormat.color = Color.to24Bit();
color = Color;
_defaultFormat.color = value.rgb;
color = value;
updateDefaultFormat();
return Color;
return value;
}

inline function get_font():String
Expand Down Expand Up @@ -855,19 +862,7 @@ class FlxText extends FlxSprite

override function updateColorTransform():Void
{
if (colorTransform == null)
colorTransform = new ColorTransform();

if (alpha != 1)
{
colorTransform.alphaMultiplier = alpha;
useColorTransform = true;
}
else
{
colorTransform.alphaMultiplier = 1;
useColorTransform = false;
}
colorTransform.alphaMultiplier = alpha;

dirty = true;
}
Expand Down Expand Up @@ -1232,7 +1227,7 @@ class FlxText extends FlxSprite
{
// Apply the default format
copyTextFormat(_defaultFormat, FormatAdjusted, false);
FormatAdjusted.color = UseBorderColor ? borderColor.to24Bit() : _defaultFormat.color;
FormatAdjusted.color = UseBorderColor ? borderColor.rgb : _defaultFormat.color;
textField.setTextFormat(FormatAdjusted);

// Apply other formats
Expand All @@ -1247,7 +1242,7 @@ class FlxText extends FlxSprite
{
var textFormat:TextFormat = formatRange.format.format;
copyTextFormat(textFormat, FormatAdjusted, false);
FormatAdjusted.color = UseBorderColor ? formatRange.format.borderColor.to24Bit() : textFormat.color;
FormatAdjusted.color = UseBorderColor ? formatRange.format.borderColor.rgb : textFormat.color;
}

textField.setTextFormat(FormatAdjusted, formatRange.range.start, Std.int(Math.min(formatRange.range.end, textField.text.length)));
Expand Down
2 changes: 1 addition & 1 deletion flixel/util/FlxBitmapDataUtil.hx
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ class FlxBitmapDataUtil
{
identical = false;

if (pixel1.to24Bit() != pixel2.to24Bit())
if (pixel1.rgb != pixel2.rgb)
{
result.setPixel32(i, j,
FlxColor.fromRGB(getDiff(pixel1.red, pixel2.red), getDiff(pixel1.green, pixel2.green), getDiff(pixel1.blue, pixel2.blue)));
Expand Down
9 changes: 4 additions & 5 deletions flixel/util/FlxColor.hx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package flixel.util;

import flixel.tweens.FlxEase;
import flixel.math.FlxMath;
import flixel.system.macros.FlxMacroUtil;

Expand Down Expand Up @@ -258,16 +259,13 @@ abstract FlxColor(Int) from Int from UInt to Int to UInt
* @param Ease An optional easing function, such as those provided in FlxEase
* @return An array of colors of length Steps, shifting from Color1 to Color2
*/
public static function gradient(Color1:FlxColor, Color2:FlxColor, Steps:Int, ?Ease:Float->Float):Array<FlxColor>
public static function gradient(Color1:FlxColor, Color2:FlxColor, Steps:Int, ?Ease:EaseFunction):Array<FlxColor>
{
var output = new Array<FlxColor>();

if (Ease == null)
{
Ease = function(t:Float):Float
{
return t;
}
Ease = FlxEase.linear;
}

for (step in 0...Steps)
Expand Down Expand Up @@ -366,6 +364,7 @@ abstract FlxColor(Int) from Int from UInt to Int to UInt
*
* @return A 24 bit version of this color
*/
@:deprecated("to24Bit() is deprecated, use rgb field, instead.")
public inline function to24Bit():FlxColor
{
return this & 0xffffff;
Expand Down
4 changes: 2 additions & 2 deletions flixel/util/FlxSpriteUtil.hx
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,7 @@ class FlxSpriteUtil

if (FillColor != FlxColor.TRANSPARENT)
{
flashGfx.beginFill(FillColor.to24Bit(), FillColor.alphaFloat);
flashGfx.beginFill(FillColor.rgb, FillColor.alphaFloat);
}
}

Expand Down Expand Up @@ -634,7 +634,7 @@ class FlxSpriteUtil
if (lineStyle.miterLimit == null)
lineStyle.miterLimit = 3;

flashGfx.lineStyle(lineStyle.thickness, color.to24Bit(), color.alphaFloat, lineStyle.pixelHinting, lineStyle.scaleMode, lineStyle.capsStyle,
flashGfx.lineStyle(lineStyle.thickness, color.rgb, color.alphaFloat, lineStyle.pixelHinting, lineStyle.scaleMode, lineStyle.capsStyle,
lineStyle.jointStyle, lineStyle.miterLimit);
}
}
Expand Down
2 changes: 1 addition & 1 deletion flixel/util/FlxStringUtil.hx
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ class FlxStringUtil
{
for (i in 0...ColorMap.length)
{
ColorMap[i] = ColorMap[i].to24Bit();
ColorMap[i] = ColorMap[i].rgb;
}
}

Expand Down
Loading