diff --git a/CHANGELOG.md b/CHANGELOG.md index 0576c90a64..0bd6a4ae7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,21 @@ +5.8.0 (April 19, 2024) + +#### New features: +- `FlxBitmapText`: Add `getRenderedText` ([#3120](https://github.com/HaxeFlixel/flixel/pull/3120)) + +#### Bugfixes: +- `FlxSpriteGroup`: Fix propegation of `cameras` field to members ([#3118](https://github.com/HaxeFlixel/flixel/pull/3118)) +- `FlxBitmapText`: Fix wrap issues caused from kerning ([#3120](https://github.com/HaxeFlixel/flixel/pull/3120)) + +5.7.2 (April 17, 2024) +#### Bugfixes: +- `FlxSpriteGroup`: Better long term fix for members cameras ([#3116](https://github.com/HaxeFlixel/flixel/pull/3116)) + +5.7.1 (April 16, 2024) +#### Bugfixes: +- `FlxImageFrame`: Prevent null ref from destroyed graphics ([#3113](https://github.com/HaxeFlixel/flixel/pull/3113)) +- `FlxSpriteGroup`: Fix issue where members draw to the wrong cameras ([#3113](https://github.com/HaxeFlixel/flixel/pull/3113)) + 5.7.0 (April 16, 2024) #### New features: diff --git a/flixel/FlxG.hx b/flixel/FlxG.hx index a4f5e57a28..35cea65194 100644 --- a/flixel/FlxG.hx +++ b/flixel/FlxG.hx @@ -106,7 +106,7 @@ class FlxG * The HaxeFlixel version, in semantic versioning syntax. Use `Std.string()` * on it to get a `String` formatted like this: `"HaxeFlixel MAJOR.MINOR.PATCH-COMMIT_SHA"`. */ - public static var VERSION(default, null):FlxVersion = new FlxVersion(5, 7, 0); + public static var VERSION(default, null):FlxVersion = new FlxVersion(5, 8, 0); /** * Internal tracker for game object. diff --git a/flixel/graphics/frames/FlxBitmapFont.hx b/flixel/graphics/frames/FlxBitmapFont.hx index b9874e735e..ed06a3b71a 100644 --- a/flixel/graphics/frames/FlxBitmapFont.hx +++ b/flixel/graphics/frames/FlxBitmapFont.hx @@ -568,4 +568,4 @@ class FlxBitmapFont extends FlxFramesCollection font.updateSourceHeight(); return font; } -} +} \ No newline at end of file diff --git a/flixel/graphics/frames/FlxImageFrame.hx b/flixel/graphics/frames/FlxImageFrame.hx index 3b8f465dfc..6f3fc3c423 100644 --- a/flixel/graphics/frames/FlxImageFrame.hx +++ b/flixel/graphics/frames/FlxImageFrame.hx @@ -91,7 +91,8 @@ class FlxImageFrame extends FlxFramesCollection */ public static function fromGraphic(graphic:FlxGraphic, ?region:FlxRect):FlxImageFrame { - if (graphic == null) + // TODO: look into this + if (graphic == null || graphic.isDestroyed) return null; // find ImageFrame, if there is one already diff --git a/flixel/graphics/tile/FlxDrawTrianglesItem.hx b/flixel/graphics/tile/FlxDrawTrianglesItem.hx index 3bcd950e61..4447294f87 100644 --- a/flixel/graphics/tile/FlxDrawTrianglesItem.hx +++ b/flixel/graphics/tile/FlxDrawTrianglesItem.hx @@ -13,7 +13,7 @@ import openfl.display.ShaderParameter; import openfl.display.TriangleCulling; import openfl.geom.ColorTransform; -typedef DrawData = #if (flash || openfl >= "4.0.0") openfl.Vector #else Array #end; +typedef DrawData = openfl.Vector; /** * @author Zaphod @@ -101,10 +101,10 @@ class FlxDrawTrianglesItem extends FlxDrawBaseItem override public function reset():Void { super.reset(); - vertices.splice(0, vertices.length); - indices.splice(0, indices.length); - uvtData.splice(0, uvtData.length); - colors.splice(0, colors.length); + vertices.length = 0; + indices.length = 0; + uvtData.length = 0; + colors.length = 0; verticesPosition = 0; indicesPosition = 0; diff --git a/flixel/group/FlxSpriteGroup.hx b/flixel/group/FlxSpriteGroup.hx index 94b40b1737..a5e6153797 100644 --- a/flixel/group/FlxSpriteGroup.hx +++ b/flixel/group/FlxSpriteGroup.hx @@ -310,7 +310,7 @@ class FlxTypedSpriteGroup extends FlxSprite sprite.y += y; sprite.alpha *= alpha; sprite.scrollFactor.copyFrom(scrollFactor); - sprite._cameras = _cameras; // _cameras instead of cameras because get_cameras() will not return null + sprite.cameras = _cameras; // _cameras instead of cameras because get_cameras() will not return null if (clipRect != null) clipRectTransform(sprite, clipRect); @@ -358,7 +358,7 @@ class FlxTypedSpriteGroup extends FlxSprite sprite.x -= x; sprite.y -= y; // alpha - sprite._cameras = null; + sprite.cameras = null; return group.remove(sprite, splice); } @@ -1066,7 +1066,7 @@ class FlxTypedSpriteGroup extends FlxSprite Sprite.camera = Camera; inline function camerasTransform(Sprite:FlxSprite, Cameras:Array) - Sprite._cameras = Cameras; + Sprite.cameras = Cameras; inline function offsetTransform(Sprite:FlxSprite, Offset:FlxPoint) Sprite.offset.copyFrom(Offset); diff --git a/flixel/text/FlxBitmapText.hx b/flixel/text/FlxBitmapText.hx index 5fa4c7f949..b4b8aa86f1 100644 --- a/flixel/text/FlxBitmapText.hx +++ b/flixel/text/FlxBitmapText.hx @@ -596,11 +596,11 @@ class FlxBitmapText extends FlxSprite { if (wrap != NONE) { - autoWrap(); + _lines = autoWrap(_lines); } else { - cutLines(); + _lines = cutLines(_lines); } } @@ -712,29 +712,34 @@ class FlxBitmapText extends FlxSprite /** * Just cuts the lines which are too long to fit in the field. */ - function cutLines():Void + function cutLines(lines:Array) { - for (i in 0..._lines.length) + for (i in 0...lines.length) { + final line = lines[i]; var lineWidth = font.minOffsetX; var prevCode = -1; - for (c in 0..._lines[i].length) + for (c in 0...line.length) { - final charCode = _lines[i].charCodeAt(c); + // final char = line.charAt(c); + final charCode = line.charCodeAt(c); if (prevCode == -1) - lineWidth += getCharAdvance(charCode, font.spaceWidth); + { + lineWidth += getCharAdvance(charCode, font.spaceWidth) + letterSpacing; + } else - lineWidth += getCharPairAdvance(prevCode, charCode, font.spaceWidth); + lineWidth += getCharPairAdvance(prevCode, charCode, font.spaceWidth) + letterSpacing; if (lineWidth > _fieldWidth - 2 * padding) { // cut every character after this - _lines[i] = _lines[i].substr(0, c); + lines[i] = lines[i].substr(0, c); break; } } } + return lines; } function getCharAdvance(charCode:Int, spaceWidth:Int) @@ -742,11 +747,11 @@ class FlxBitmapText extends FlxSprite switch (charCode) { case FlxBitmapFont.SPACE_CODE: - return spaceWidth + letterSpacing; + return spaceWidth; case FlxBitmapFont.TAB_CODE: - return spaceWidth * numSpacesInTab + letterSpacing; + return spaceWidth * numSpacesInTab; case charCode: - final advance = font.getCharAdvance(charCode) + letterSpacing; + final advance = font.getCharAdvance(charCode); if (isUnicodeComboMark(charCode)) return -advance; return advance; @@ -757,18 +762,38 @@ class FlxBitmapText extends FlxSprite { return getCharAdvance(prevCode, spaceWidth) + font.getKerning(prevCode, nextCode); } - + + /** + * Adds soft wraps to the text and cuts lines based on how it would be displayed in this field, + * Also converts to upper-case, if `autoUpperCase` is `true` + */ + public function getRenderedText(text:UnicodeString) + { + text = (autoUpperCase) ? (text : UnicodeString).toUpperCase() : text; + + if (!autoSize) + { + var lines = text.split("\n"); + if (wrap != NONE) + return autoWrap(lines).join("\n"); + + return cutLines(lines).join("\n"); + } + + return text; + } + /** * Automatically wraps text by figuring out how many characters can fit on a * single line, and splitting the remainder onto a new line. */ - function autoWrap():Void + function autoWrap(lines:Array) { // subdivide lines var newLines:Array = []; var words:Array; // the array of words in the current line - for (line in _lines) + for (line in lines) { words = []; // split this line into words @@ -785,7 +810,7 @@ class FlxBitmapText extends FlxSprite } } - _lines = newLines; + return newLines; } /** @@ -1013,7 +1038,7 @@ class FlxBitmapText extends FlxSprite { var wordWidth = 0; for (c in 0...word.length) - getCharAdvance(word.charCodeAt(c), font.spaceWidth); + wordWidth += getCharAdvance(word.charCodeAt(c), font.spaceWidth); return wordWidth + (word.length - 1) * letterSpacing; } @@ -1155,7 +1180,7 @@ class FlxBitmapText extends FlxSprite var curX:Float = startX; var curY:Int = startY; - + final lineLength:Int = line.length; final textWidth:Int = this.textWidth; @@ -1187,10 +1212,12 @@ class FlxBitmapText extends FlxSprite if (i + 1 < lineLength) { final nextCode = line.charCodeAt(i + 1); - curX += getCharPairAdvance(charCode, nextCode, spaceWidth); + curX += getCharPairAdvance(charCode, nextCode, spaceWidth) + letterSpacing; } else - curX += getCharAdvance(charCode, spaceWidth); + { + curX += getCharAdvance(charCode, spaceWidth) + letterSpacing; + } } } } diff --git a/flixel/ui/FlxButton.hx b/flixel/ui/FlxButton.hx index dd2bdc1f63..bbf991b869 100644 --- a/flixel/ui/FlxButton.hx +++ b/flixel/ui/FlxButton.hx @@ -354,7 +354,7 @@ class FlxTypedButton extends FlxSprite implements IFlxInput if (_spriteLabel != null && _spriteLabel.visible) { - _spriteLabel._cameras = _cameras; + _spriteLabel.cameras = _cameras; _spriteLabel.draw(); } } diff --git a/flixel/util/FlxPool.hx b/flixel/util/FlxPool.hx index ce74fcfcae..c25a8ca880 100644 --- a/flixel/util/FlxPool.hx +++ b/flixel/util/FlxPool.hx @@ -53,8 +53,10 @@ class FlxPool implements IFlxPool /** Set to false before creating FlxGame to prevent logs */ public var autoLog = true; - final _tracked = new Map(); - final _leakCount = new Map(); + // For some reason, this causes CI errors: `final _tracked = new Map();` + + final _tracked:Map = []; + final _leakCount:Map = []; var _totalCreated = 0; var _autoLogInitted = false; #end diff --git a/haxelib.json b/haxelib.json index ab6ed90f15..44cf3752b3 100644 --- a/haxelib.json +++ b/haxelib.json @@ -4,8 +4,8 @@ "license": "MIT", "tags": ["game", "openfl", "flash", "html5", "neko", "cpp", "android", "ios", "cross"], "description": "HaxeFlixel is a 2D game engine based on OpenFL that delivers cross-platform games.", - "version": "5.7.0", - "releasenote": "Add FlxTimer.wait and loop", + "version": "5.8.0", + "releasenote": "patch wrap errors, add getRenderedText to bitmap text", "contributors": ["haxeflixel", "Gama11", "GeoKureli"], "dependencies": {} } diff --git a/tests/unit/src/flixel/text/FlxBitmapTextTest.hx b/tests/unit/src/flixel/text/FlxBitmapTextTest.hx index b5a2d9abbc..36ba70be36 100644 --- a/tests/unit/src/flixel/text/FlxBitmapTextTest.hx +++ b/tests/unit/src/flixel/text/FlxBitmapTextTest.hx @@ -1,8 +1,10 @@ package flixel.text; -import flixel.text.FlxBitmapText; import flixel.graphics.frames.FlxBitmapFont; +import flixel.math.FlxPoint; +import flixel.text.FlxBitmapText; import massive.munit.Assert; +import openfl.display.BitmapData; class FlxBitmapTextTest extends FlxTest { @@ -29,4 +31,56 @@ class FlxBitmapTextTest extends FlxTest Assert.isNotNull(text1.text); Assert.areEqual(text1.font, text2.font); } + + @Test + function testWrapMono() + { + final image = new BitmapData(112, 60); + final monospaceLetters:String = " !\"#$%&'()*+,-.\\0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[/]^_`abcdefghijklmnopqrstuvwxyz{|}~"; + final charSize = FlxPoint.get(7, 10); + final font = FlxBitmapFont.fromMonospace(image, monospaceLetters, charSize); + + final field = new FlxBitmapText(0, 0, "", font); + field.autoSize = false; + field.fieldWidth = 100; + field.letterSpacing = -1; + field.multiLine = true; + + /* + Note: These tests were made quickly due to my current schedule, later on we may want + to simplify these, and also add tests for: kerning and unicode stuff + */ + + final msg = "The quick brown fox jumps over the lazy dog, "; + final msg1 = msg + "supercal-aphragalist-icexpiala-docious"; // long hyphenate4d word + final msg2 = msg + "supercal-aphragalist\nicexpiala-docious"; // hard wrap and hyphens + final msg3 = msg + "supercalaphragalisticexpialadocious"; // one long word + + assertRenderedText(field, msg1, NONE, "The quick brown "); + assertRenderedText(field, msg2, NONE, "The quick brown \nicexpiala-dociou"); + assertRenderedText(field, msg3, NONE, "The quick brown "); + + assertRenderedText(field, msg1, CHAR, "The quick brown \nfox jumps over t\nhe lazy dog, sup\nercal-aphragalis\nt-icexpiala-doci\nous"); + assertRenderedText(field, msg2, CHAR, "The quick brown \nfox jumps over t\nhe lazy dog, sup\nercal-aphragalis\nt\nicexpiala-dociou\ns"); + assertRenderedText(field, msg3, CHAR, "The quick brown \nfox jumps over t\nhe lazy dog, sup\nercalaphragalist\nicexpialadocious"); + + assertRenderedText(field, msg1, WORD(NEVER), "The quick brown \nfox jumps over \nthe lazy dog, \nsupercal-\naphragalist-\nicexpiala-\ndocious"); + assertRenderedText(field, msg2, WORD(NEVER), "The quick brown \nfox jumps over \nthe lazy dog, \nsupercal-\naphragalist\nicexpiala-\ndocious"); + assertRenderedText(field, msg3, WORD(NEVER), "The quick brown \nfox jumps over \nthe lazy dog, \nsupercalaphragalisticexpialadocious"); + + assertRenderedText(field, msg1, WORD(LINE_WIDTH), "The quick brown \nfox jumps over \nthe lazy dog, \nsupercal-\naphragalist-\nicexpiala-\ndocious"); + assertRenderedText(field, msg2, WORD(LINE_WIDTH), "The quick brown \nfox jumps over \nthe lazy dog, \nsupercal-\naphragalist\nicexpiala-\ndocious"); + assertRenderedText(field, msg3, WORD(LINE_WIDTH), "The quick brown \nfox jumps over \nthe lazy dog, su\npercalaphragalis\nticexpialadociou\ns"); + + assertRenderedText(field, msg1, WORD(LENGTH(10)), "The quick brown \nfox jumps over \nthe lazy dog, \nsupercal-aphraga\nlist-icexpiala-\ndocious"); + assertRenderedText(field, msg2, WORD(LENGTH(10)), "The quick brown \nfox jumps over \nthe lazy dog, \nsupercal-aphraga\nlist\nicexpiala-\ndocious"); + assertRenderedText(field, msg3, WORD(LENGTH(10)), "The quick brown \nfox jumps over \nthe lazy dog, su\npercalaphragalis\nticexpialadociou\ns"); + } + + function assertRenderedText(field:FlxBitmapText, text:UnicodeString, wrap:FlxBitmapText.Wrap, expected:UnicodeString, ?info:haxe.PosInfos) + { + field.wrap = wrap; + final actual = field.getRenderedText(text); + Assert.areEqual(expected, actual, info); + } }