Skip to content

Commit

Permalink
Fix crash in FlxBitmapFont demo (#3029)
Browse files Browse the repository at this point in the history
* Added `letterSpacing` variable to `FlxText`. (#3027)

* Update FlxText.hx

* `spacing` -> `letterSpacing`.

* Oops

* Update FlxText.hx

* Update FlxText.hx

* Fix negative animation frame number (#3028)

* fix negative anim frame number sorting

* use int abs

* warn when sorting frames with invalid names

* remove typo

---------

Co-authored-by: George FunBook <gkurelic@gmail.com>

* downgrade warnings and prevent more crashes

* fix error in xml attribute check

* pretty up unit test

---------

Co-authored-by: Mihai Alexandru <77043862+MAJigsaw77@users.noreply.github.com>
Co-authored-by: Timur <T1mL3arn@users.noreply.github.com>
  • Loading branch information
3 people committed Feb 10, 2024
1 parent a121130 commit 9941407
Show file tree
Hide file tree
Showing 9 changed files with 142 additions and 119 deletions.
4 changes: 2 additions & 2 deletions flixel/animation/FlxAnimationController.hx
Original file line number Diff line number Diff line change
Expand Up @@ -725,8 +725,8 @@ class FlxAnimationController implements IFlxDestroyable
{
final name = frames[0].name;
final postIndex = name.indexOf(".", prefix.length);
final postFix = name.substring(postIndex == -1 ? name.length : postIndex, name.length);
FlxFrame.sort(frames, prefix.length, postFix.length);
final suffix = name.substring(postIndex == -1 ? name.length : postIndex, name.length);
FlxFrame.sortFrames(frames, prefix, suffix);

for (frame in frames)
{
Expand Down
75 changes: 57 additions & 18 deletions flixel/graphics/frames/FlxFrame.hx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import openfl.display.BitmapData;
import openfl.geom.Point;
import openfl.geom.Rectangle;
import flixel.graphics.FlxGraphic;
import flixel.math.FlxMath;
import flixel.math.FlxMatrix;
import flixel.math.FlxPoint;
import flixel.math.FlxRect;
Expand Down Expand Up @@ -32,29 +33,67 @@ class FlxFrame implements IFlxDestroyable
* Temp matrix helper, used internally
*/
static var _matrix = new FlxMatrix();

/**
* Sorts an array of `FlxFrame` objects by their name, e.g.
* `["tiles-001.png", "tiles-003.png", "tiles-002.png"]`
* with `"tiles-".length == prefixLength` and `".png".length == postfixLength`.
* Sorts frames based on the value of the frames' name between the prefix and suffix.
* Uses `Std.parseInt` to parse the value, if the result is `null`, 0 is used, if the result
* is a negative number, the absolute valute is used.
*
* @param frames The list of frames to sort
* @param prefix Everything in the frames' name *before* the order
* @param suffix Everything in the frames' name *after* the order
* @param warn Whether to warn on invalid names
*/
public static function sort(frames:Array<FlxFrame>, prefixLength:Int, postfixLength:Int):Void
public static inline function sortFrames(frames:Array<FlxFrame>, prefix:String, ?suffix:String, warn = true):Void
{
ArraySort.sort(frames, sortByName.bind(_, _, prefixLength, postfixLength));
sortHelper(frames, prefix.length, suffix == null ? 0 : suffix.length, warn);
}

public static function sortByName(frame1:FlxFrame, frame2:FlxFrame, prefixLength:Int, postfixLength:Int):Int

/**
* Sorts frames based on the value of the frames' name between the prefix and suffix.
* Uses `Std.parseInt` to parse the value, if the result is `null`, 0 is used, if the result
* is a negative number, the absolute valute is used.
*
* @param frames The list of frames to sort
* @param prefix Everything in the frames' name *before* the order
* @param suffix Everything in the frames' name *after* the order
* @param warn Whether to warn on invalid names
*/
public static function sort(frames:Array<FlxFrame>, prefixLength:Int, suffixLength:Int, warn = true):Void
{
var name1:String = frame1.name;
var name2:String = frame2.name;
var num1:Null<Int> = Std.parseInt(name1.substring(prefixLength, name1.length - postfixLength));
var num2:Null<Int> = Std.parseInt(name2.substring(prefixLength, name2.length - postfixLength));
if (num1 == null)
num1 = 0;
if (num2 == null)
num2 = 0;

return num1 - num2;
sortHelper(frames, prefixLength, suffixLength, warn);
}

static function sortHelper(frames:Array<FlxFrame>, prefixLength:Int, suffixLength:Int, warn = true):Void
{
if (warn)
{
for (frame in frames)
checkValidName(frame.name, prefixLength, suffixLength);
}

ArraySort.sort(frames, sortByName.bind(_, _, prefixLength, suffixLength));
}

static inline function checkValidName(name:String, prefixLength:Int, suffixLength:Int)
{
final nameSub = name.substring(prefixLength, name.length - suffixLength);
final num:Null<Int> = Std.parseInt(nameSub);
if (num == null)
FlxG.log.warn('Could not parse frame number of "$nameSub" in frame named "$name"');
else if (num < 0)
FlxG.log.warn('Found negative frame number "$nameSub" in frame named "$name"');
}

public static function sortByName(frame1:FlxFrame, frame2:FlxFrame, prefixLength:Int, suffixLength:Int):Int
{
inline function getNameOrder(name:String):Int
{
final num:Null<Int> = Std.parseInt(name.substring(prefixLength, name.length - suffixLength));
return if (num == null) 0 else FlxMath.absInt(num);
}

return getNameOrder(frame1.name) - getNameOrder(frame2.name);
}

public var name:String;
Expand Down
4 changes: 2 additions & 2 deletions flixel/graphics/frames/FlxTileFrames.hx
Original file line number Diff line number Diff line change
Expand Up @@ -237,9 +237,9 @@ class FlxTileFrames extends FlxFramesCollection
{
var name:String = framesToAdd[0].name;
var postIndex:Int = name.indexOf(".", Prefix.length);
var postFix:String = name.substring(postIndex == -1 ? name.length : postIndex, name.length);
var suffix:String = name.substring(postIndex == -1 ? name.length : postIndex, name.length);

FlxFrame.sort(framesToAdd, Prefix.length, postFix.length);
FlxFrame.sortFrames(framesToAdd, Prefix, suffix);
return FlxTileFrames.fromFrames(framesToAdd);
}

Expand Down
4 changes: 2 additions & 2 deletions flixel/graphics/frames/bmfont/BMFontChar.hx
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ class BMFontChar
xoffset: charNode.att.intSafe("xoffset", 0),
yoffset: charNode.att.intSafe("yoffset", 0),
xadvance: charNode.att.intSafe("xadvance", 0),
page: charNode.att.intWarn("page", -1),
chnl: charNode.att.intWarn("chnl", -1),
page: charNode.att.intSafe("page", -1),
chnl: charNode.att.intSafe("chnl", -1),
letter: charNode.att.stringSafe("letter")
};
}
Expand Down
2 changes: 1 addition & 1 deletion flixel/graphics/frames/bmfont/BMFontCommon.hx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class BMFontCommon
return
{
lineHeight: commonNode.att.int("lineHeight"),
base: commonNode.att.intWarn("base", -1),
base: commonNode.att.intSafe("base", -1),
scaleW: commonNode.att.intWarn("scaleW", 1),
scaleH: commonNode.att.intWarn("scaleH", 1),
pages: commonNode.att.intSafe("pages", 0),
Expand Down
20 changes: 13 additions & 7 deletions flixel/graphics/frames/bmfont/BMFontInfo.hx
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,27 @@ class BMFontInfo

static function fromXml(infoNode:BMFontXml):BMFontInfo
{
return {
final info:BMFontInfo =
{
face: infoNode.att.string("face"),
size: infoNode.att.int("size"),
bold: infoNode.att.boolSafe("bold", false),
italic: infoNode.att.boolSafe("italic", false),
smooth: infoNode.att.boolSafe("smooth", false),
charset: infoNode.att.stringWarn("charset"),
unicode: infoNode.att.boolWarn("unicode", false),
stretchH: infoNode.att.intWarn("stretchH", 100),
aa: infoNode.att.intWarn("aa", 1),
padding: BMFontPadding.fromString(infoNode.att.stringWarn("padding")),
spacing: BMFontSpacing.fromString(infoNode.att.stringWarn("spacing")),
charset: infoNode.att.stringSafe("charset"),
unicode: infoNode.att.boolSafe("unicode", false),
stretchH: infoNode.att.intSafe("stretchH", 100),
aa: infoNode.att.intSafe("aa", 1),
outline: infoNode.att.intSafe("outline", 0),
fixedHeight: infoNode.att.boolSafe("fixedHeight", false)
}

if (infoNode.has("padding"))
info.padding = BMFontPadding.fromString(infoNode.att.string("padding"));
if (infoNode.has("spacing"))
info.spacing = BMFontSpacing.fromString(infoNode.att.string("spacing"));

return info;
}

static function fromText(infoText:String):BMFontInfo
Expand Down
2 changes: 1 addition & 1 deletion flixel/graphics/frames/bmfont/BMFontXml.hx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ abstract BMFontXml(Xml) from Xml
if (this.nodeType == Xml.Document)
throw 'Cannot access document attribute $name';

return this.nodeType == Xml.Document && this.exists(name);
return this.nodeType != Xml.Document && this.exists(name);
}

/** Check the existence of a sub node with the given name. **/
Expand Down
20 changes: 20 additions & 0 deletions flixel/text/FlxText.hx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ class FlxText extends FlxSprite
*/
public var size(get, set):Int;

/**
* A number representing the amount of space that is uniformly distributed
* between all characters. The value specifies the number of pixels that are
* added to the advance after each character.
*/
public var letterSpacing(get, set):Float;

/**
* The font used for this text (assuming that it's using embedded font).
*/
Expand Down Expand Up @@ -219,6 +226,7 @@ class FlxText extends FlxSprite
textField.multiline = true;
textField.wordWrap = true;
_defaultFormat = new TextFormat(null, Size, 0xffffff);
letterSpacing = 0;
font = FlxAssets.FONT_DEFAULT;
_formatAdjusted = new TextFormat();
textField.defaultTextFormat = _defaultFormat;
Expand Down Expand Up @@ -640,6 +648,18 @@ class FlxText extends FlxSprite
return Size;
}

inline function get_letterSpacing():Float
{
return _defaultFormat.letterSpacing;
}

function set_letterSpacing(LetterSpacing:Float):Float
{
_defaultFormat.letterSpacing = LetterSpacing;
updateDefaultFormat();
return LetterSpacing;
}

override function set_color(Color:FlxColor):Int
{
if (_defaultFormat.color == Color.to24Bit())
Expand Down
Loading

0 comments on commit 9941407

Please sign in to comment.