From 7cf3ab54bde3b8e3a1ede210b8542e80935537b4 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Wed, 12 Jun 2024 09:59:51 -0500 Subject: [PATCH 01/99] prevent deprecation warnings --- tests/unit/src/flixel/util/FlxArrayUtilTest.hx | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit/src/flixel/util/FlxArrayUtilTest.hx b/tests/unit/src/flixel/util/FlxArrayUtilTest.hx index 550a7355ce..18271fb889 100644 --- a/tests/unit/src/flixel/util/FlxArrayUtilTest.hx +++ b/tests/unit/src/flixel/util/FlxArrayUtilTest.hx @@ -104,6 +104,7 @@ class FlxArrayUtilTest } @Test + @:haxe.warning("-WDeprecated") function testSetLength() { final arr = [0, 1, 2, 3, 4, 5]; From b0b6576747c8b2cdf4f0b5160a4c7fbf3fa56643 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Wed, 12 Jun 2024 15:48:00 -0500 Subject: [PATCH 02/99] Add trackingInfo to FlxGraphic for debugging (#3183) * add trackingInfo to FlxGraphic for debugging * add color * use hex --- flixel/FlxSprite.hx | 37 ++++++++++++++++++++---------- flixel/graphics/FlxGraphic.hx | 7 +++++- flixel/system/macros/FlxDefines.hx | 11 ++++++++- flixel/text/FlxText.hx | 6 ++++- 4 files changed, 46 insertions(+), 15 deletions(-) diff --git a/flixel/FlxSprite.hx b/flixel/FlxSprite.hx index 8792a468d6..ea5c2b7e50 100644 --- a/flixel/FlxSprite.hx +++ b/flixel/FlxSprite.hx @@ -569,7 +569,11 @@ class FlxSprite extends FlxObject var bitmap:BitmapData = FlxBitmapDataUtil.generateRotations(brush, Rotations, AntiAliasing, AutoBuffer); tempGraph = FlxGraphic.fromBitmapData(bitmap, false, key); } - + + #if FLX_TRACK_GRAPHICS + tempGraph.trackingInfo = 'loadRotatedGraphic($ID, $Rotations, $Frame, $AntiAliasing, $AutoBuffer)'; + #end + var max:Int = (brush.height > brush.width) ? brush.height : brush.width; max = AutoBuffer ? Std.int(max * 1.5) : max; @@ -598,19 +602,23 @@ class FlxSprite extends FlxObject * Will create frames that are 150% larger on each axis than the original frame or graphic. * @return this FlxSprite with loaded rotated graphic in it. */ - public function loadRotatedFrame(Frame:FlxFrame, Rotations:Int = 16, AntiAliasing:Bool = false, AutoBuffer:Bool = false):FlxSprite + public function loadRotatedFrame(frame:FlxFrame, rotations = 16, antiAliasing = false, autoBuffer = false):FlxSprite { - var key:String = Frame.parent.key; - if (Frame.name != null) - key += ":" + Frame.name; + var key:String = frame.parent.key; + if (frame.name != null) + key += ":" + frame.name; else - key += ":" + Frame.frame.toString(); - + key += ":" + frame.frame.toString(); + var graphic:FlxGraphic = FlxG.bitmap.get(key); if (graphic == null) - graphic = FlxGraphic.fromBitmapData(Frame.paint(), false, key); - - return loadRotatedGraphic(graphic, Rotations, -1, AntiAliasing, AutoBuffer); + graphic = FlxGraphic.fromBitmapData(frame.paint(), false, key); + + #if FLX_TRACK_GRAPHICS + graphic.trackingInfo = 'loadRotatedFrame($ID, $rotations, $antiAliasing, $autoBuffer)'; + #end + + return loadRotatedGraphic(graphic, rotations, -1, antiAliasing, autoBuffer); } /** @@ -635,10 +643,15 @@ class FlxSprite extends FlxObject * it is used as a prefix to find a new unique name like `"Key3"`. * @return This `FlxSprite` instance (nice for chaining stuff together, if you're into that). */ - public function makeGraphic(Width:Int, Height:Int, Color:FlxColor = FlxColor.WHITE, Unique:Bool = false, ?Key:String):FlxSprite + public function makeGraphic(width:Int, height:Int, color = FlxColor.WHITE, unique = false, ?key:String):FlxSprite { - var graph:FlxGraphic = FlxG.bitmap.create(Width, Height, Color, Unique, Key); + var graph:FlxGraphic = FlxG.bitmap.create(width, height, color, unique, key); frames = graph.imageFrame; + + #if FLX_TRACK_GRAPHICS + graph.trackingInfo = 'makeGraphic($ID, ${color.toHexString()})'; + #end + return this; } diff --git a/flixel/graphics/FlxGraphic.hx b/flixel/graphics/FlxGraphic.hx index 587eb18ebf..b41409ad3f 100644 --- a/flixel/graphics/FlxGraphic.hx +++ b/flixel/graphics/FlxGraphic.hx @@ -367,7 +367,12 @@ class FlxGraphic implements IFlxDestroyable * It is `false` by default, since it significantly increases memory consumption. */ public var unique:Bool = false; - + + #if FLX_TRACK_GRAPHICS + /** Any info about the creation or intended usage of this graphic, for debugging purposes */ + public var trackingInfo:String = ""; + #end + /** * Internal var holding `FlxImageFrame` for the whole bitmap of this graphic. * Use public `imageFrame` var to access/generate it. diff --git a/flixel/system/macros/FlxDefines.hx b/flixel/system/macros/FlxDefines.hx index 5b6e2642e3..8dd13e2fe4 100644 --- a/flixel/system/macros/FlxDefines.hx +++ b/flixel/system/macros/FlxDefines.hx @@ -39,8 +39,10 @@ private enum UserDefines FLX_NO_POINT_POOL; FLX_NO_PITCH; FLX_NO_SAVE; - /** Adds trackers to FlxPool instances, only available on debug*/ + /** Adds trackers to FlxPool instances, only available on debug */ FLX_TRACK_POOLS; + /** Adds `creationInfo` to FlxGraphic instances, automatically defined with FLX_DEBUG */ + FLX_TRACK_GRAPHICS; } /** @@ -83,6 +85,7 @@ private enum HelperDefines FLX_SAVE; FLX_HEALTH; FLX_NO_TRACK_POOLS; + FLX_NO_TRACK_GRAPHICS; } class FlxDefines @@ -183,6 +186,7 @@ class FlxDefines defineInversion(FLX_SWF_VERSION_TEST, FLX_NO_SWF_VERSION_TEST); defineInversion(FLX_NO_HEALTH, FLX_HEALTH); defineInversion(FLX_TRACK_POOLS, FLX_NO_TRACK_POOLS); + // defineInversion(FLX_TRACK_GRAPHICS, FLX_NO_TRACK_GRAPHICS); // special case } static function defineHelperDefines() @@ -244,6 +248,11 @@ class FlxDefines if (defined(FLX_TRACK_POOLS) && !defined("debug")) abort("Can only define FLX_TRACK_POOLS on debug mode", (macro null).pos); + + if (defined(FLX_DEBUG)) + define(FLX_TRACK_GRAPHICS); + + defineInversion(FLX_TRACK_GRAPHICS, FLX_NO_TRACK_GRAPHICS); } static function defineInversion(userDefine:UserDefines, invertedDefine:HelperDefines) diff --git a/flixel/text/FlxText.hx b/flixel/text/FlxText.hx index d1f34a62e9..bf07d57b35 100644 --- a/flixel/text/FlxText.hx +++ b/flixel/text/FlxText.hx @@ -892,7 +892,11 @@ class FlxText extends FlxSprite // Need to generate a new buffer to store the text graphic var key:String = FlxG.bitmap.getUniqueKey("text"); makeGraphic(newWidth, newHeight, FlxColor.TRANSPARENT, false, key); - + + #if FLX_TRACK_GRAPHICS + graphic.trackingInfo = 'text($ID, $text)'; + #end + if (_hasBorderAlpha) _borderPixels = graphic.bitmap.clone(); From f515d2b3e32adce5f785326fa4841c2c82b34acb Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Wed, 12 Jun 2024 15:49:01 -0500 Subject: [PATCH 03/99] ignore alpha when point-selecting sprites (#3184) * ignore alpha when point-selecting sprites * typo --- .../system/debug/interaction/Interaction.hx | 33 +++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/flixel/system/debug/interaction/Interaction.hx b/flixel/system/debug/interaction/Interaction.hx index 36b7bae6e0..87a7745a70 100644 --- a/flixel/system/debug/interaction/Interaction.hx +++ b/flixel/system/debug/interaction/Interaction.hx @@ -679,6 +679,19 @@ class Interaction extends Window addItemsWithinArea(cast items, members, area); } + inline function isOverObject(object:FlxObject, area:FlxRect):Bool + { + return area.overlaps(object.getHitbox(FlxRect.weak())); + } + + inline function isOverSprite(sprite:FlxSprite, area:FlxRect):Bool + { + // Ignore sprites' alpha when clicking a point + return (area.width <= 1 && area.height <= 1) + ? sprite.pixelsOverlapPoint(flixelPointer, 0xEE) + : isOverObject(sprite, area); + } + /** * Find all items within an area. In order to improve performance and reduce temporary allocations, * the method has no return, you must pass an array where items will be placed. The method decides @@ -703,11 +716,19 @@ class Interaction extends Window final group = FlxTypedGroup.resolveSelectionGroup(member); if (group != null) + { addItemsWithinArea(items, group.members, area); + } + else if (member is FlxSprite) + { + final sprite:FlxSprite = cast member; + if (isOverSprite(sprite, area)) + items.push(sprite); + } else if (member is FlxObject) { final object:FlxObject = cast member; - if (area.overlaps(object.getHitbox())) + if (isOverObject(object, area)) items.push(object); } } @@ -737,10 +758,16 @@ class Interaction extends Window if (group != null) return getTopItemWithinArea(group.members, area); - if (member is FlxObject) + if (member is FlxSprite) + { + final sprite:FlxSprite = cast member; + if (isOverSprite(sprite, area)) + return sprite; + } + else if (member is FlxObject) { final object:FlxObject = cast member; - if (area.overlaps(object.getHitbox())) + if (isOverObject(object, area)) return object; } } From 7d38b4a350627a3ed41b0c9cb04720b649aab8af Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 12 Jun 2024 22:22:49 -0400 Subject: [PATCH 04/99] Implement FlxFlicker.pause() and FlxFlicker.resume() (#3179) * Add FlxFlicker.pause() and FlxFlicker.resume() * Apply suggestions from code review Co-authored-by: George Kurelic --------- Co-authored-by: George Kurelic --- flixel/effects/FlxFlicker.hx | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/flixel/effects/FlxFlicker.hx b/flixel/effects/FlxFlicker.hx index 8997bfd397..0faf3b9ecc 100644 --- a/flixel/effects/FlxFlicker.hx +++ b/flixel/effects/FlxFlicker.hx @@ -144,6 +144,28 @@ class FlxFlicker implements IFlxDestroyable timer = new FlxTimer().start(interval, flickerProgress, Std.int(duration / interval)); } + /** + * Temporarily pause the flickering, so it can be resumed later. + */ + public function pause():Void + { + if (timer == null) + return; + + timer.active = false; + } + + /** + * Resume the flickering after it has been temporarily paused. + */ + public function resume():Void + { + if (timer == null) + return; + + timer.active = true; + } + /** * Prematurely ends flickering. */ From af5e15d1e8f604cc6283ac4a87621ffee0fbc1bd Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 12 Jun 2024 22:36:05 -0400 Subject: [PATCH 05/99] Don't attempt to retrieve frameCollections on a destroyed graphic. (#3180) * Don't attempt to retrieve frameCollections on a destroyed graphic. * Update flixel/graphics/FlxGraphic.hx Co-authored-by: George Kurelic --------- Co-authored-by: George Kurelic --- flixel/graphics/FlxGraphic.hx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/flixel/graphics/FlxGraphic.hx b/flixel/graphics/FlxGraphic.hx index b41409ad3f..b2d8bfdf91 100644 --- a/flixel/graphics/FlxGraphic.hx +++ b/flixel/graphics/FlxGraphic.hx @@ -519,6 +519,12 @@ class FlxGraphic implements IFlxDestroyable */ public inline function getFramesCollections(type:FlxFrameCollectionType):Array { + if (this.isDestroyed) + { + FlxG.log.warn('Invalid call to getFramesCollections on a destroyed graphic'); + return []; + } + var collections:Array = frameCollections.get(type); if (collections == null) { From 0671ad91d134e462fe0429203685bbe4887e7955 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Fri, 14 Jun 2024 09:55:42 -0500 Subject: [PATCH 06/99] add since --- flixel/graphics/FlxGraphic.hx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/flixel/graphics/FlxGraphic.hx b/flixel/graphics/FlxGraphic.hx index b2d8bfdf91..18ff89f271 100644 --- a/flixel/graphics/FlxGraphic.hx +++ b/flixel/graphics/FlxGraphic.hx @@ -369,7 +369,11 @@ class FlxGraphic implements IFlxDestroyable public var unique:Bool = false; #if FLX_TRACK_GRAPHICS - /** Any info about the creation or intended usage of this graphic, for debugging purposes */ + /** + * **Debug only** + * Any info about the creation or intended usage of this graphic, for debugging purposes + * @since 5.9.0 + */ public var trackingInfo:String = ""; #end From c9438e1ff2ed81cf6a60daf6122a6010711394b3 Mon Sep 17 00:00:00 2001 From: George FunBook Date: Fri, 14 Jun 2024 10:26:18 -0500 Subject: [PATCH 07/99] Update Changelog --- CHANGELOG.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a2dbd9b9d3..7d3dfb007b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,8 @@ - Create base class for `FlxPath` for simpler custom path following logic - Add signals `onEndReached`, `onFinished` and `onNodeReached` - Replacement fields: `startAt`, `direction`, `loopType`, `target`, `currentIndex`, `nextIndex`, `current` and `next` -- +- `FlxGraphic`: Add `trackingInfo` to help debugging graphics ([#3183](https://github.com/HaxeFlixel/flixel/pull/3183)) +- `FlxFlicker`: Add `pause` and `resume` ([#3179](https://github.com/HaxeFlixel/flixel/pull/3179)) #### Changes and improvements: - `FlxKey`: Add `NONE` to `fromStringMap` and `toStringMap` ([#3119](https://github.com/HaxeFlixel/flixel/pull/3119)) @@ -37,11 +38,14 @@ - Debug Drawing: Various improvements to debug drawing tilemaps - Now honors tiles' `ignoreDrawDebug` and `debugBoundingBoxColor` fields - New `getDebugBoundingBoxColor` in `FlxObject`. Meant to eventually replace `drawDebugBoundingBox` - +- `FlxBGSprite`: Prevent draw call when transparent ([#3173](https://github.com/HaxeFlixel/flixel/pull/3173)) +- `FlxArrayUtil`: Deprecate `resize`, use `array.setLength` ([#3094](https://github.com/HaxeFlixel/flixel/pull/3094)) +- Debugging: Check alpha when point-selecting sprites ([#3184](https://github.com/HaxeFlixel/flixel/pull/3184)) #### Bugfixes: - `FlxFlickerTween`: Fix "Unsupported recursive type" error on hl ([#3170](https://github.com/HaxeFlixel/flixel/pull/3170)) - `FlxBGSprite`: Fix draw size when scale is not `1.0` ([#3142](https://github.com/HaxeFlixel/flixel/pull/3142)) +- `FlxGraphic`: Prevent null ref in `getFramesCollections` with destroyed graphics ([#3180](https://github.com/HaxeFlixel/flixel/pull/3180)) 5.8.0 (April 19, 2024) From c4d168e98d53c8125033fc9ac2a82e0a1d5acbd7 Mon Sep 17 00:00:00 2001 From: George FunBook Date: Fri, 14 Jun 2024 10:30:42 -0500 Subject: [PATCH 08/99] style --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc631670f0..954476ad93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -223,7 +223,7 @@ We removed many features and utilities that were previously deprecated - **README.md**: Add Turkish translations - `AssetPaths`: Add `allFiles` field, and an arg in `FlxAssets.buildFileReferences` to change the identifier ([#2807](https://github.com/HaxeFlixel/flixel/pull/2807)) - Debug tools: Add ways to remove custom debug tools ([#2792](https://github.com/HaxeFlixel/flixel/pull/2792)) - - `FlxG.console`: Add `removeByAlias`, `removeEnum`, `removeClass`, `removeObject` and `removeFunction` + - `FlxG.console`: Add `removeByAlias`, `removeEnum`, `removeClass`, `removeObject` and `removeFunction` - `FlxG.game.debugger.interaction`: Add `removeTool` - `FlxText`: Add `fieldHeight` field ([#2789](https://github.com/HaxeFlixel/flixel/pull/2789)) - `FlxG`: Add compiler flag `FLX_NO_SAVE` to remove `FlxG.save` (also counter-flag `FLX_SAVE`) ([#2840](https://github.com/HaxeFlixel/flixel/pull/2840)) @@ -363,7 +363,7 @@ We removed many features and utilities that were previously deprecated - `AssetPaths`: various fixes ([#2680](https://github.com/HaxeFlixel/flixel/pull/2680)) - apply `include`/`exclude` args to files, not directories - default file renamer will replace spaces with underscore - + #### New features: - `FlxKeys`: Added `SCROLL_LOCK`, `NUMLOCK`, `WINDOWS`, `MENU`, `BREAK` and `NUMPADSLASH` keys ([#2638](https://github.com/HaxeFlixel/flixel/pull/2638)) From 56aa45173be02d1b836884fa51a8197e111ba512 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Sat, 15 Jun 2024 15:19:06 -0500 Subject: [PATCH 09/99] More new features and overloads to tilemaps (#3189) * More new features and overloads * add setTileIndex overload and setTileIndexAt * ver * changelog --- CHANGELOG.md | 7 +- flixel/FlxG.hx | 2 +- flixel/path/FlxPathfinder.hx | 6 +- flixel/tile/FlxBaseTilemap.hx | 472 ++++++++++++++---- flixel/tile/FlxTile.hx | 2 +- flixel/tile/FlxTilemap.hx | 79 +-- .../unit/src/flixel/path/FlxPathfinderTest.hx | 2 +- tests/unit/src/flixel/tile/FlxTilemapTest.hx | 126 ++++- 8 files changed, 539 insertions(+), 157 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d3dfb007b..52d0ed6969 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,17 +23,18 @@ - `FlxCamera`: Improve doc ([#3161](https://github.com/HaxeFlixel/flixel/pull/3161)) - `NextState`: Improve doc ([#3160](https://github.com/HaxeFlixel/flixel/pull/3160)) - `FlxSprite`: Account for `scale`, `origin`, `offset`, `angle` and `pixelPerfectPosition` in `getGraphicMidpoint` ([#3125](https://github.com/HaxeFlixel/flixel/pull/3125)) -- Major change to `FlxTilemap` and `FlxTiles` collision ([#3158](https://github.com/HaxeFlixel/flixel/pull/3158)) +- Major change to `FlxTilemap` and `FlxTiles` collision ([#3158](https://github.com/HaxeFlixel/flixel/pull/3158)) ([#3189](https://github.com/HaxeFlixel/flixel/pull/3189)) - `FlxTile`: Various features for allowing custom overlap/collision logic - Add dynamic methods `overlapsObject` and `orientAt` with helpers `orient`, `orientByIndex` and `orientAtByIndex` - Add `onCollide` signal, when overlaps are detected for collision purposes - Tilemaps: Add various new tools and helpers to `FlxTilemap` and `FlxBaseTilemap` - - Added new `forEachOverlappingTile` calls a method with every tile that overlaps an object + - Added new `forEachOverlappingTile` which calls a method with every tile that overlaps an object + - Added new `forEachMapIndex` which calls a method with every tile of a certain tile index - Added new `isOverlappingTile` method, allows you to check all tiles overlapping an object - Added new `objectOverlapsTiles` to replace the now deprecated `overlapsWithCallbacks` - Eschews `flipCallbackParams` arg, allowing better typing of both callback params - Adds `isCollision` flag to control whether the Tiles' collision callbacks are fired and allows for processing non-solid tiles - - Added new helpers: `getMapIndex`, `getRow`, `getColumn`, `getTileIndex`, `getTileData`, `tileExists`, `setTileIndex`, `getColumnAt`, `getRowAt`, `columnExists` and `rowExists` + - Added new helpers: `getMapIndex`, `getMapIndexAt`, `getRow`, `getColumn`, `getTileIndex`, `getTileIndexAt`, `getTileData`, `getTileDataAt`, `tileExists`, `tileExistsAt`, `setTileIndex`, `setTileIndexAt`, `getColumnAt`, `getRowAt`, `columnExists`, `rowExists`, `columnExistsAt`, `rowExistsAt`, `getColumnPos`, `getRowPos`, `getColumnPosAt`, `getRowPosAt`, `getTilePos`, `getTilePosAt` and `getAllTilePos` - `FlxObject`: Add internal helpers for processing tilemaps in `separate`, `updateTouchingFlags` and similar functions - Debug Drawing: Various improvements to debug drawing tilemaps - Now honors tiles' `ignoreDrawDebug` and `debugBoundingBoxColor` fields diff --git a/flixel/FlxG.hx b/flixel/FlxG.hx index 705819cc52..e855617a4c 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, 8, 1); + public static var VERSION(default, null):FlxVersion = new FlxVersion(5, 9, 0); /** * Internal tracker for game object. diff --git a/flixel/path/FlxPathfinder.hx b/flixel/path/FlxPathfinder.hx index 56a77fe2bf..50afb53d9b 100644 --- a/flixel/path/FlxPathfinder.hx +++ b/flixel/path/FlxPathfinder.hx @@ -60,8 +60,8 @@ class FlxTypedPathfinder, Data:FlxTypedPathfin public function findPath(map:Tilemap, start:FlxPoint, end:FlxPoint, simplify:FlxPathSimplifier = LINE):Null> { // Figure out what tile we are starting and ending on. - var startIndex = map.getTileIndexByCoords(start); - var endIndex = map.getTileIndexByCoords(end); + final startIndex = map.getMapIndex(start); + final endIndex = map.getMapIndex(end); var data = createData(map, startIndex, endIndex); var indices = findPathIndicesHelper(data); @@ -119,7 +119,7 @@ class FlxTypedPathfinder, Data:FlxTypedPathfin function getPathPointsFromIndices(data:Data, indices:Array) { // convert indices to world coordinates - return indices.map(data.map.getTileCoordsByIndex.bind(_, true)); + return indices.map((i)->data.map.getTilePos(i, true)); } /** diff --git a/flixel/tile/FlxBaseTilemap.hx b/flixel/tile/FlxBaseTilemap.hx index 6ad1ac97d8..590095422c 100644 --- a/flixel/tile/FlxBaseTilemap.hx +++ b/flixel/tile/FlxBaseTilemap.hx @@ -4,11 +4,11 @@ import flixel.FlxObject; import flixel.group.FlxGroup; import flixel.math.FlxPoint; import flixel.math.FlxRect; -import flixel.system.FlxAssets; import flixel.path.FlxPathfinder; +import flixel.system.FlxAssets; import flixel.util.FlxArrayUtil; -import flixel.util.FlxColor; import flixel.util.FlxCollision; +import flixel.util.FlxColor; import flixel.util.FlxDirectionFlags; import flixel.util.FlxStringUtil; import openfl.Assets; @@ -136,8 +136,22 @@ class FlxBaseTilemap extends FlxObject throw "computeDimensions must be implemented"; } + /** + * Finds the column number that overlaps the given X in world space + * + * @param worldX An X coordinate in the world + * @param bind If true, it will prevent out of range values + * @return A column index, where 0 is the left-most column + * @since 5.9.0 + */ + public function getColumnAt(worldX:Float, bind = false):Int + { + throw "getColumnAt must be implemented"; + } + /** * Finds the row number that overlaps the given Y in world space + * * @param worldY A Y coordinate in the world * @param bind If true, it will prevent out of range values * @return A row index, where 0 is the top-most row @@ -149,31 +163,51 @@ class FlxBaseTilemap extends FlxObject } /** - * Finds the row number that overlaps the given X in world space - * @param worldX A X coordinate in the world - * @param bind If true, it will prevent out of range values - * @return A column index, where 0 is the left-most column + * Get the world position of the specified column + * + * @param column The grid X location, in tiles + * @param midpoint Whether to use the tile's midpoint, or upper left corner * @since 5.9.0 */ - public function getColumnAt(worldX:Float, bind = false):Int + public function getColumnPos(column:Float, midPoint = false):Float { - throw "getColumnAt must be implemented"; + throw "getColumnPos must be implemented"; + } + + /** + * Get the world position of the specified row + * + * @param row The grid Y location, in tiles + * @param midpoint Whether to use the tile's midpoint, or upper left corner + * @since 5.9.0 + */ + public function getRowPos(row:Int, midPoint = false):Float + { + throw "getRowPos must be implemented"; } - public function getTileIndexByCoords(coord:FlxPoint):Int + /** + * **Note:** This method name is misleading! It does not return a `tileIndex`, it returns a `mapIndex` + * + * @param worldPos A location in the world + * @return The `mapIndex` placed at the given world location + */ + @:deprecated("getTileIndexByCoords is deprecated, use getMapIndex, instead") // 5.9.0 + public function getTileIndexByCoords(worldPos:FlxPoint):Int { - throw "getTileIndexByCoords must be implemented"; + return getMapIndex(worldPos); } - - public function getTileCoordsByIndex(index:Int, midpoint = true):FlxPoint + @:deprecated("getTileCoordsByIndex is deprecated, use getTilePos, instead") // 5.9.0 + public function getTileCoordsByIndex(mapIndex:Int, midpoint = true):FlxPoint { - throw "getTileCoordsByIndex must be implemented"; + return getTilePos(mapIndex, midpoint); } /** * Shoots a ray from the start point to the end point. * If/when it passes through a tile, it stores that point and returns false. - * Note: In flixel 5.0.0, this was redone, the old method is now `rayStep` + * + * **Note:** In flixel 5.0.0, this was redone, the old method is now `rayStep` * * @param start The world coordinates of the start of the ray. * @param end The world coordinates of the end of the ray. @@ -213,7 +247,7 @@ class FlxBaseTilemap extends FlxObject * If the line starts inside the tilemap, a copy of start is returned. * If the line never enters the tilemap, null is returned. * - * Note: If a result vector is supplied and the line is outside the tilemap, null is returned + * **Note:** If a result vector is supplied and the line is outside the tilemap, null is returned * and the supplied result is unchanged * @since 5.0.0 * @@ -238,7 +272,7 @@ class FlxBaseTilemap extends FlxObject * If the line ends inside the tilemap, a copy of end is returned. * If the line is never inside the tilemap, null is returned. * - * Note: If a result vector is supplied and the line is outside the tilemap, null is returned + * **Note:** If a result vector is supplied and the line is outside the tilemap, null is returned * and the supplied result is unchanged * @since 5.0.0 * @@ -284,7 +318,7 @@ class FlxBaseTilemap extends FlxObject throw "overlapsWithCallback must be implemented"; } - @:deprecated("overlapsWithCallback is deprecated, use objectOverlapsTiles(object, callback, pos), instead") + @:deprecated("overlapsWithCallback is deprecated, use objectOverlapsTiles(object, callback, pos), instead") // 5.9.0 public function overlapsWithCallback(object:FlxObject, ?callback:(FlxObject, FlxObject)->Bool, flipCallbackParams = false, ?position:FlxPoint):Bool { return objectOverlapsTiles(object, (t, o)->{ return flipCallbackParams ? callback(o, t) : callback(t, o); }, position); @@ -328,7 +362,7 @@ class FlxBaseTilemap extends FlxObject moves = false; } - override public function destroy():Void + override function destroy():Void { _data = null; super.destroy(); @@ -742,21 +776,50 @@ class FlxBaseTilemap extends FlxObject } /** - * Calculates a mapIndex via `row * widthInTiles + column` + * Calculates a `mapIndex` via `row * widthInTiles + column`, + * if the column or row is not valid, the result is `-1` + * + * @param column The grid X location, in tiles + * @param row The grid Y location, in tiles + * @since 5.9.0 + */ + public overload extern inline function getMapIndex(column:Int, row:Int):Int + { + return tileExists(column, row) ? (row * widthInTiles + column) : -1; + } + + /** + * Calculates a `mapIndex` of the given location, if the coordinate + * does not overlap the tilemap, the result is `-1` + * + * **Note:** A tile's `mapIndex` can be calculated via `row * widthInTiles + column` * - * @param column the grid X location, in tiles - * @param row the grid Y location, in tiles + * @param worldPos A location in the world * @since 5.9.0 */ - public inline function getMapIndex(column:Int, row:Int):Int + public overload extern inline function getMapIndex(worldPos:FlxPoint):Int { - return row * widthInTiles + column; + return getMapIndexAt(worldPos.x, worldPos.y); } + /** + * Calculates a `mapIndex` of the given location, if the coordinate + * does not overlap the tilemap, the result is `-1` + * + * **Note:** A tile's `mapIndex` can be calculated via `row * widthInTiles + column` + * + * @param worldX An X coordinate in the world + * @param worldY A Y coordinate in the world + * @since 5.9.0 + */ + public inline function getMapIndexAt(worldX:Float, worldY:Float):Int + { + return getMapIndex(getColumnAt(worldX), getRowAt(worldY)); + } /** * Calculates the column from a map location * - * @param mapIndex The location in the map where `mapIndex = row * widthInTiles + column` + * @param mapIndex The location in the map where `mapIndex = row * widthInTiles + column` * @since 5.9.0 */ public inline function getColumn(mapIndex:Int):Int @@ -767,7 +830,7 @@ class FlxBaseTilemap extends FlxObject /** * Calculates the column from a map location * - * @param mapIndex The location in the map where `mapIndex = row * widthInTiles + column` + * @param mapIndex The location in the map where `mapIndex = row * widthInTiles + column` * @since 5.9.0 */ public inline function getRow(mapIndex:Int):Int @@ -778,8 +841,8 @@ class FlxBaseTilemap extends FlxObject /** * Whether a tile exists at the given map location * - * @param row The grid X coordinate of the tile (in tiles, not pixels) - * @param column The grid Y coordinate of the tile (in tiles, not pixels) + * @param column The grid X location, in tiles + * @param row The grid Y location, in tiles * @since 5.9.0 */ public overload extern inline function tileExists(column:Int, row:Int):Bool @@ -790,7 +853,7 @@ class FlxBaseTilemap extends FlxObject /** * Whether a tile exists at the given map location * - * **Note:** A tile's mapIndex can be calculated via `row * widthInTiles + column` + * **Note:** A tile's `mapIndex` can be calculated via `row * widthInTiles + column` * * @param mapIndex The desired location in the map * @since 5.9.0 @@ -800,10 +863,33 @@ class FlxBaseTilemap extends FlxObject return mapIndex >= 0 && mapIndex < _data.length; } + /** + * Whether a tile exists at the given map location + * + * @param worldPos A location in the map + * @since 5.9.0 + */ + public overload extern inline function tileExists(worldPos:FlxPoint):Bool + { + return tileExistsAt(worldPos.x, worldPos.y); + } + + /** + * Whether a tile exists at the given map location + * + * @param worldX An X coordinate in the world + * @param worldY A Y coordinate in the world + * @since 5.9.0 + */ + public inline function tileExistsAt(worldX:Float, worldY:Float):Bool + { + return columnExistsAt(worldX) && rowExistsAt(worldY); + } + /** * Whether a row exists at the given map location * - * @param column The desired location in the map + * @param column The grid X location, in tiles * @since 5.9.0 */ public overload extern inline function columnExists(column:Int):Bool @@ -811,10 +897,21 @@ class FlxBaseTilemap extends FlxObject return column >= 0 && column < widthInTiles; } + /** + * Whether a column exists at the given map location + * + * @param worldX An X coordinate in the world + * @since 5.9.0 + */ + public inline function columnExistsAt(worldX:Float):Bool + { + return columnExists(getColumnAt(worldX)); + } + /** * Whether a row exists at the given map location * - * @param row The desired location in the map + * @param row The grid Y location, in tiles * @since 5.9.0 */ public overload extern inline function rowExists(row:Int):Bool @@ -823,11 +920,22 @@ class FlxBaseTilemap extends FlxObject } /** - * Finds the tile instance at a particular column and row + * Whether a row exists at the given map location * - * @param row The grid X coordinate of the tile (in tiles, not pixels) - * @param column The grid Y coordinate of the tile (in tiles, not pixels) - * @return The tile index of the tile at this location + * @param worldY A Y coordinate in the world + * @since 5.9.0 + */ + public inline function rowExistsAt(worldY:Float):Bool + { + return rowExists(getRowAt(worldY)); + } + + /** + * Finds the tile instance at a particular column and row, + * if the column or row is invalid, the result is `null` + * + * @param column The grid X location, in tiles + * @param row The grid Y location, in tiles * @since 5.9.0 */ public overload extern inline function getTileData(column:Int, row:Int):Null @@ -836,15 +944,15 @@ class FlxBaseTilemap extends FlxObject } /** - * Finds the tile instance with the given mapIndex + * Finds the tile instance with the given `mapIndex`, + * if the `mapIndex` is invalid, the result is `null` * - * **Note:** A tile's mapIndex can be calculated via `row * widthInTiles + column` + * **Note:** A tile's `mapIndex` can be calculated via `row * widthInTiles + column` * * **Note:** The reulting tile's `x`, `y`, `width` and `height` will not be accurate. * You can call `tile.orient` or similar methods * * @param mapIndex The desired location in the map - * @return An integer containing the value of the tile at this spot in the array. * @since 5.9.0 */ public overload extern inline function getTileData(mapIndex:Int):Null @@ -853,10 +961,42 @@ class FlxBaseTilemap extends FlxObject } /** - * Check the value of a particular tile. + * Finds the tile instance with the given world location, if the + * coordinate does not overlap the tilemap, the result is `null` + * + * **Note:** The reulting tile's `x`, `y`, `width` and `height` will not be accurate. + * You can call `tile.orient` or similar methods + * + * @param worldPos A location in the world + * @since 5.9.0 + */ + public overload extern inline function getTileData(worldPos:FlxPoint):Null + { + return getTileDataAt(worldPos.x, worldPos.y); + } + + /** + * Finds the tile instance with the given world location, if the + * coordinate does not overlap the tilemap, the result is `null` + * + * **Note:** The reulting tile's `x`, `y`, `width` and `height` will not be accurate. + * You can call `tile.orient` or similar methods + * + * @param worldX An X coordinate in the world + * @param worldY A Y coordinate in the world + * @since 5.9.0 + */ + public overload extern inline function getTileDataAt(worldX:Float, worldY:Float):Null + { + return _tileObjects[getTileIndexAt(worldX, worldY)]; + } + + /** + * Check the value of a particular tile, if the + * column or row is invalid, the result is `-1` * - * @param row The grid X coordinate of the tile (in tiles, not pixels) - * @param column The grid Y coordinate of the tile (in tiles, not pixels) + * @param column The grid X location, in tiles + * @param row The grid Y location, in tiles * @return The tile index of the tile at this location * @since 5.9.0 */ @@ -866,7 +1006,8 @@ class FlxBaseTilemap extends FlxObject } /** - * Get the `tileIndex` at the given map location + * Get the `tileIndex` at the given map location, + * if the `mapIndex` is invalid, the result is `-1` * * **Note:** A tile's `mapIndex` can be calculated via `row * widthInTiles + column` * @@ -876,17 +1017,133 @@ class FlxBaseTilemap extends FlxObject */ public overload extern inline function getTileIndex(mapIndex:Int):Int { - return _data[mapIndex]; + return tileExists(mapIndex) ? _data[mapIndex] : -1; + } + + /** + * Get the `tileIndex` at the given location, if the coordinate + * does not overlap the tilemap, the result is `-1` + * + * @param worldPos A location in the world + * @return The tileIndex of the tile at this location + * @since 5.9.0 + */ + public overload extern inline function getTileIndex(worldPos:FlxPoint):Int + { + return getTileIndexAt(worldPos.x, worldPos.y); + } + + /** + * Get the `tileIndex` at the given location, if the coordinate + * does not overlap the tilemap, the result is `-1` + * + * @param worldX An X coordinate in the world + * @param worldY A Y coordinate in the world + * @return The tileIndex of the tile at this location + * @since 5.9.0 + */ + public inline function getTileIndexAt(worldX:Float, worldY:Float):Int + { + return getTileIndex(getColumnAt(worldX), getRowAt(worldY)); + } + + /** + * Get the world position of the specified tile, if the `mapIndex` is invalid, + * the result is `null` + * + * **Note:** A tile's `mapIndex` can be calculated via `row * widthInTiles + column` + * + * @param mapIndex The desired location in the map + * @param midpoint Whether to use the tile's midpoint, or upper left corner + * @return The world position of the matching tile + * @since 5.9.0 + */ + public overload extern inline function getTilePos(mapIndex:Int, midpoint = false):Null + { + return tileExists(mapIndex) ? getTilePos(getColumn(mapIndex), getRow(mapIndex), midpoint) : null; + } + + /** + * Get the world position of the specified tile + * + * **Note:** The column or row does not need to be valid, to ensure a + * valid tile, use `if (tileExists(column, row))`, first + * + * @param column The grid X location, in tiles + * @param row The grid Y location, in tiles + * @param midpoint Whether to use the tile's midpoint, or upper left corner + * @return The world position of the matching tile + * @since 5.9.0 + */ + public overload extern inline function getTilePos(column:Int, row:Int, midpoint = false):FlxPoint + { + return FlxPoint.get(getColumnPos(column, midpoint), getRowPos(row, midpoint)); + } + + /** + * Get the world position of the tile overlapping the specified position + * + * **Note:** The location does not need to overlap the tilemap, to ensure a + * valid tile, use `if (tileExists(worldPos))`, first + * + * @param worldPos A location in the world + * @param midpoint Whether to use the tile's midpoint, or upper left corner + * @return The world position of the overlapping tile + * @since 5.9.0 + */ + public overload extern inline function getTilePos(worldPos:FlxPoint, midpoint = false):FlxPoint + { + return getTilePosAt(worldPos.x, worldPos.y, midpoint); + } + + /** + * Get the world position of the tile overlapping the specified position + * + * **Note:** The location does not need to overlap the tilemap, to ensure a + * valid tile, use `if (tileExistsAt(worldX, worldY))`, first + * + * @param worldX An X coordinate in the world + * @param worldY A Y coordinate in the world + * @param midpoint Whether to use the tile's midpoint, or upper left corner + * @return The world position of the overlapping tile + * @since 5.9.0 + */ + public inline function getTilePosAt(worldX:Float, worldY:Float, midpoint = false):FlxPoint + { + return getTilePos(getColumnAt(worldX), getRowAt(worldY), midpoint); + } + + /** + * Returns a new array full of every coordinate of the requested tile type. + * + * @param tileIndex The requested tile type + * @param midpoint Whether to use the tiles' midpoints, or upper left corner + * @return An Array with a list of all the coordinates of that tile type + * @since 5.9.0 + */ + public function getAllTilePos(tileIndex:Int, midpoint = false):Array + { + final result = []; + + final length = _data.length; + for (mapIndex in 0...length) + { + if (getTileIndex(mapIndex) == tileIndex) + { + result.push(getTilePos(mapIndex, midpoint)); + } + } + return result; } /** * Check the value of a particular tile. * - * @param row The grid X coordinate of the tile (in tiles, not pixels) - * @param column The grid Y coordinate of the tile (in tiles, not pixels) + * @param column The grid X location, in tiles + * @param row The grid Y location, in tiles * @return The tile index of the tile at this location */ - @:deprecated("getTile is deprecated use getTileIndex(column, row), instead") + @:deprecated("getTile is deprecated use getTileIndex(column, row), instead") // 5.9.0 public function getTile(column:Int, row:Int):Int { return getTileIndex(column, row); @@ -900,7 +1157,7 @@ class FlxBaseTilemap extends FlxObject * @param mapIndex The desired location in the map * @return An integer containing the value of the tile at this spot in the array. */ - @:deprecated("getTileByIndex is deprecated use getTileIndex(mapIndex), instead") + @:deprecated("getTileByIndex is deprecated use getTileIndex(mapIndex), instead") // 5.9.0 public function getTileByIndex(mapIndex:Int):Int { return getTileIndex(mapIndex); @@ -950,85 +1207,132 @@ class FlxBaseTilemap extends FlxObject public function getAllMapIndices(tileIndex:Int):Array { final result:Array = []; - var i:Int = widthInTiles * heightInTiles; - while (i-- > 0) + final length = _data.length; + for (mapIndex in 0...length) { - if (_data[i] == tileIndex) + if (getTileIndex(mapIndex) == tileIndex) { - result.unshift(i); + result.push(mapIndex); } } - return result; } + + /** + * Calls the desired function with every `mapIndex` that uses the given `tileIndex` + * + * @param tileIndex The desired tile type + * @param function The function called with each mapIndex + * @since 5.9.0 + */ + public function forEachMapIndex(tileIndex:Int, f:(mapIndex:Int) -> Void) + { + final length = _data.length; + for (mapIndex in 0...length) + { + if (getTileIndex(mapIndex) == tileIndex) + { + f(mapIndex); + } + } + } /** * Change the data and graphic of a tile in the tilemap. * - * @param mapIndex The slot in the data array (Y * widthInTiles + X) where this tile is stored. - * @param tileIndex The new tileIndex to place at the mapIndex - * @param updateGraphics Whether the graphical representation of this tile should change. + * @param mapIndex The slot in the data array (Y * widthInTiles + X) where this tile is stored. + * @param tileIndex The new tileIndex to place at the mapIndex + * @param redraw Whether the graphical representation of this tile should change. * @return Whether or not the tile was actually changed. * @since 5.9.0 */ - public overload extern inline function setTileIndex(mapIndex:Int, tileIndex:Int, updateGraphics = true):Bool + public overload extern inline function setTileIndex(mapIndex:Int, tileIndex:Int, redraw = true):Bool { - return setTileHelper(mapIndex, tileIndex, updateGraphics); + return setTileHelper(mapIndex, tileIndex, redraw); } /** * Change the data and graphic of a tile in the tilemap. * - * @param row The grid X coordinate of the tile (in tiles, not pixels) - * @param column The grid Y coordinate of the tile (in tiles, not pixels) - * @param tileIndex The new integer data you wish to inject. - * @param updateGraphics Whether the graphical representation of this tile should change. + * @param column The grid X location, in tiles + * @param row The grid Y location, in tiles + * @param tileIndex The new integer data you wish to inject. + * @param redraw Whether the graphical representation of this tile should change. * @return Whether or not the tile was actually changed. * @since 5.9.0 */ - public overload extern inline function setTileIndex(column:Int, row:Int, tileIndex:Int, updateGraphics = true):Bool + public overload extern inline function setTileIndex(column:Int, row:Int, tileIndex:Int, redraw = true):Bool { - return setTileHelper(getMapIndex(column, row), tileIndex, updateGraphics); + return setTileHelper(getMapIndex(column, row), tileIndex, redraw); } /** * Change the data and graphic of a tile in the tilemap. * - * @param row The grid X coordinate of the tile (in tiles, not pixels) - * @param column The grid Y coordinate of the tile (in tiles, not pixels) - * @param tileIndex The new integer data you wish to inject. - * @param updateGraphics Whether the graphical representation of this tile should change. + * @param worldPos A location in the world + * @param tileIndex The new integer data you wish to inject. + * @param redraw Whether the graphical representation of this tile should change. * @return Whether or not the tile was actually changed. + * @since 5.9.0 */ - @:deprecated("setTile is deprecated, use setTileIndex(column, row, tileIndex,...), instead") - public function setTile(column:Int, row:Int, tileIndex:Int, updateGraphics = true):Bool + public overload extern inline function setTileIndex(worldPos:FlxPoint, tileIndex:Int, redraw = true):Bool { - return setTileIndex(getMapIndex(column, row), tileIndex, updateGraphics); + return setTileIndexAt(worldPos.x, worldPos.y, tileIndex, redraw); } /** * Change the data and graphic of a tile in the tilemap. * - * @param mapIndex The slot in the data array (Y * widthInTiles + X) where this tile is stored. - * @param tileIndex The new tileIndex to place at the mapIndex - * @param updateGraphics Whether the graphical representation of this tile should change. + * @param worldX An X coordinate in the world + * @param worldY A Y coordinate in the world + * @param tileIndex The new integer data you wish to inject. + * @param redraw Whether the graphical representation of this tile should change. * @return Whether or not the tile was actually changed. + * @since 5.9.0 */ - @:deprecated("setTileByIndex is deprecated, use setTileIndex(mapIndex, tileIndex,...), instead") - public function setTileByIndex(mapIndex:Int, tileIndex:Int, updateGraphics = true):Bool + public inline function setTileIndexAt(worldX:Float, worldY:Float, tileIndex:Int, redraw = true):Bool { - return setTileIndex(mapIndex, tileIndex, updateGraphics); + return setTileHelper(getMapIndexAt(worldX, worldY), tileIndex, redraw); } - function setTileHelper(mapIndex:Int, tileIndex:Int, updateGraphics = true):Bool + /** + * Change the data and graphic of a tile in the tilemap. + * + * @param column The grid X location, in tiles + * @param row The grid Y location, in tiles + * @param tileIndex The new integer data you wish to inject. + * @param redraw Whether the graphical representation of this tile should change. + * @return Whether or not the tile was actually changed. + */ + @:deprecated("setTile is deprecated, use setTileIndex(column, row, tileIndex,...), instead") // 5.9.0 + public function setTile(column:Int, row:Int, tileIndex:Int, redraw = true):Bool + { + return setTileIndex(getMapIndex(column, row), tileIndex, redraw); + } + + /** + * Change the data and graphic of a tile in the tilemap. + * + * @param mapIndex The slot in the data array (Y * widthInTiles + X) where this tile is stored. + * @param tileIndex The new tileIndex to place at the mapIndex + * @param redraw Whether the graphical representation of this tile should change. + * @return Whether or not the tile was actually changed. + */ + @:deprecated("setTileByIndex is deprecated, use setTileIndex(mapIndex, tileIndex,...), instead") // 5.9.0 + public function setTileByIndex(mapIndex:Int, tileIndex:Int, redraw = true):Bool + { + return setTileIndex(mapIndex, tileIndex, redraw); + } + + function setTileHelper(mapIndex:Int, tileIndex:Int, redraw = true):Bool { if (!tileExists(mapIndex)) return false; - + _data[mapIndex] = tileIndex; - if (!updateGraphics) + if (!redraw) { return true; } @@ -1179,7 +1483,7 @@ class FlxBaseTilemap extends FlxObject /** * Pathfinding helper function, floods a grid with distance information until it finds the end point. - * NOTE: Currently this process does NOT use any kind of fancy heuristic! It's pretty brute. + * **Note:** Currently this process does NOT use any kind of fancy heuristic! It's pretty brute. * * @param startIndex The starting tile's map index. * @param endIndex The ending tile's map index. @@ -1199,7 +1503,7 @@ class FlxBaseTilemap extends FlxObject /** * Pathfinding helper function, floods a grid with distance information until it finds the end point. - * NOTE: Currently this process does NOT use any kind of fancy heuristic! It's pretty brute. + * **Note:** Currently this process does NOT use any kind of fancy heuristic! It's pretty brute. * @since 5.0.0 * * @param startIndex The starting tile's map index. @@ -1222,7 +1526,7 @@ class FlxBaseTilemap extends FlxObject /** * Checks to see if some FlxObject overlaps this FlxObject object in world space. * If the group has a LOT of things in it, it might be faster to use FlxG.overlaps(). - * WARNING: Currently tilemaps do NOT support screen space overlap checks! + * **Warning:** Currently tilemaps do NOT support screen space overlap checks! * * @param object The object being tested. * @param inScreenSpace Whether to take scroll factors into account when checking for overlap. @@ -1230,7 +1534,7 @@ class FlxBaseTilemap extends FlxObject * @return Whether or not the two objects overlap. */ @:access(flixel.group.FlxTypedGroup) - override public function overlaps(objectOrGroup:FlxBasic, inScreenSpace = false, ?camera:FlxCamera):Bool + override function overlaps(objectOrGroup:FlxBasic, inScreenSpace = false, ?camera:FlxCamera):Bool { final group = FlxTypedGroup.resolveGroup(objectOrGroup); if (group != null) // if it is a group @@ -1293,7 +1597,7 @@ class FlxBaseTilemap extends FlxObject * @param camera Specify which game camera you want. If null getScreenPosition() will just grab the first global camera. * @return Whether or not the point overlaps this object. */ - override public function overlapsPoint(worldPoint:FlxPoint, inScreenSpace = false, ?camera:FlxCamera):Bool + override function overlapsPoint(worldPoint:FlxPoint, inScreenSpace = false, ?camera:FlxCamera):Bool { if (inScreenSpace) { @@ -1309,7 +1613,7 @@ class FlxBaseTilemap extends FlxObject function tileAtPointAllowsCollisions(point:FlxPoint):Bool { - final mapIndex = getTileIndexByCoords(point); + final mapIndex = getMapIndex(point); return tileExists(mapIndex) && getTileData(mapIndex).solid; } diff --git a/flixel/tile/FlxTile.hx b/flixel/tile/FlxTile.hx index b69a929c81..db546d62b8 100644 --- a/flixel/tile/FlxTile.hx +++ b/flixel/tile/FlxTile.hx @@ -124,7 +124,7 @@ class FlxTile extends FlxObject */ public dynamic function orientAt(xPos:Float, yPos:Float, col:Int, row:Int) { - mapIndex = (row * tilemap.widthInTiles) + col; + mapIndex = tilemap.getMapIndex(col, row); width = tilemap.scaledTileWidth; height = tilemap.scaledTileHeight; x = xPos + col * width; diff --git a/flixel/tile/FlxTilemap.hx b/flixel/tile/FlxTilemap.hx index ea702a3cc6..a39d314d98 100644 --- a/flixel/tile/FlxTilemap.hx +++ b/flixel/tile/FlxTilemap.hx @@ -830,7 +830,7 @@ class FlxTypedTilemap extends FlxBaseTilemap override function getColumnAt(worldX:Float, bind = false):Int { - final result = Math.floor(worldX / scaledTileWidth); + final result = Math.floor((worldX - x) / scaledTileWidth); if (bind) return result < 0 ? 0 : (result >= widthInTiles ? widthInTiles - 1 : result); @@ -840,7 +840,7 @@ class FlxTypedTilemap extends FlxBaseTilemap override function getRowAt(worldY:Float, bind = false):Int { - final result = Math.floor(worldY / scaledTileHeight); + final result = Math.floor((worldY - y) / scaledTileHeight); if (bind) return result < 0 ? 0 : (result >= heightInTiles ? heightInTiles -1 : result); @@ -848,27 +848,14 @@ class FlxTypedTilemap extends FlxBaseTilemap return result; } - override public function getTileIndexByCoords(coord:FlxPoint):Int + override function getColumnPos(column:Float, midpoint = false):Float { - var localX = coord.x - x; - var localY = coord.y - y; - coord.putWeak(); - - if ((localX < 0) || (localY < 0) || (localX >= scaledWidth) || (localY >= scaledHeight)) - return -1; - - return Std.int(localY / scaledTileHeight) * widthInTiles + Std.int(localX / scaledTileWidth); + return x + column * scaledTileWidth + (midpoint ? scaledTileWidth * 0.5 : 0); } - override public function getTileCoordsByIndex(index:Int, midpoint = true):FlxPoint + override function getRowPos(row:Int, midpoint = false):Float { - var point = FlxPoint.get(x + (index % widthInTiles) * scaledTileWidth, y + Std.int(index / widthInTiles) * scaledTileHeight); - if (midpoint) - { - point.x += scaledTileWidth * 0.5; - point.y += scaledTileHeight * 0.5; - } - return point; + return y + row * scaledTileHeight + (midpoint ? scaledTileHeight * 0.5 : 0); } /** @@ -878,34 +865,10 @@ class FlxTypedTilemap extends FlxBaseTilemap * @param midpoint Whether to return the coordinates of the tile midpoint, or upper left corner. Default is true, return midpoint. * @return An Array with a list of all the coordinates of that tile type. */ - public function getTileCoords(index:Int, midpoint = true):Array + @:deprecated("getTileCoords is deprecated, use getAllTilePos, instead") + public function getTileCoords(tileIndex:Int, midpoint = true):Array { - var array:Array = null; - - var point:FlxPoint; - var l:Int = widthInTiles * heightInTiles; - - for (i in 0...l) - { - if (_data[i] == index) - { - point = FlxPoint.get(x + (i % widthInTiles) * scaledTileWidth, y + Std.int(i / widthInTiles) * scaledTileHeight); - - if (midpoint) - { - point.x += scaledTileWidth * 0.5; - point.y += scaledTileHeight * 0.5; - } - - if (array == null) - { - array = new Array(); - } - array.push(point); - } - } - - return array; + return getAllTilePos(tileIndex, midpoint); } /** @@ -966,11 +929,11 @@ class FlxTypedTilemap extends FlxBaseTilemap trimmedEnd.put(); } - final startIndex = getTileIndexByCoords(start); - final endIndex = getTileIndexByCoords(end); + final startIndex = getMapIndex(start); + final endIndex = getMapIndex(end); // If the starting tile is solid, return the starting position - if (getTileData(startIndex).allowCollisions != NONE) + if (getTileData(startIndex).solid) { if (result != null) result.copyFrom(start); @@ -979,10 +942,10 @@ class FlxTypedTilemap extends FlxBaseTilemap return false; } - final startTileX = startIndex % widthInTiles; - final startTileY = Std.int(startIndex / widthInTiles); - final endTileX = endIndex % widthInTiles; - final endTileY = Std.int(endIndex / widthInTiles); + final startTileX = getColumn(startIndex); + final startTileY = getRow(startIndex); + final endTileX = getColumn(endIndex); + final endTileY = getRow(endIndex); var hitIndex = -1; if (start.x == end.x) @@ -991,7 +954,7 @@ class FlxTypedTilemap extends FlxBaseTilemap if (hitIndex != -1 && result != null) { // check the bottom - result.copyFrom(getTileCoordsByIndex(hitIndex, false)); + result.copyFrom(getTilePos(hitIndex)); result.x = start.x; if (start.y > end.y) result.y += scaledTileHeight; @@ -1015,9 +978,9 @@ class FlxTypedTilemap extends FlxBaseTilemap while (tileX != endTileX) { - xPos = x + (tileX + offset) * scaledTileWidth; + xPos = getColumnPos(tileX + offset); yPos = m * xPos + b; - tileY = Math.floor((yPos - y) / scaledTileHeight); + tileY = getRowAt(yPos); hitIndex = checkColumn(tileX, lastTileY, tileY); if (hitIndex != -1) break; @@ -1030,7 +993,7 @@ class FlxTypedTilemap extends FlxBaseTilemap if (hitIndex != -1 && result != null) { - result.copyFrom(getTileCoordsByIndex(hitIndex, false)); + result.copyFrom(getTilePos(hitIndex)); if (Std.int(hitIndex / widthInTiles) == lastTileY) { if (start.x > end.x) @@ -1439,7 +1402,7 @@ class FlxTypedTilemap extends FlxBaseTilemap } /** - * Internal function used in setTileByIndex() and the constructor to update the map. + * Internal function used in setTileIndex() and the constructor to update the map. * * @param index The index of the tile object in _tileObjects internal array you want to update. */ diff --git a/tests/unit/src/flixel/path/FlxPathfinderTest.hx b/tests/unit/src/flixel/path/FlxPathfinderTest.hx index d56ed551a5..6c9d414067 100644 --- a/tests/unit/src/flixel/path/FlxPathfinderTest.hx +++ b/tests/unit/src/flixel/path/FlxPathfinderTest.hx @@ -106,7 +106,7 @@ class FlxPathfinderTest extends FlxTest var i = points.length; while (i-- > 0) { - indices.unshift(map.getTileIndexByCoords(points[i])); + indices.unshift(map.getMapIndex(points[i])); if (put) points.pop().put(); } diff --git a/tests/unit/src/flixel/tile/FlxTilemapTest.hx b/tests/unit/src/flixel/tile/FlxTilemapTest.hx index 8536036920..900f103a78 100644 --- a/tests/unit/src/flixel/tile/FlxTilemapTest.hx +++ b/tests/unit/src/flixel/tile/FlxTilemapTest.hx @@ -290,7 +290,7 @@ class FlxTilemapTest extends FlxTest tilemap.loadMapFrom2DArray([[1]], new BitmapData(2, 1)); function overlaps(x, y) return tilemap.overlapsPoint(FlxPoint.get(x, y)); - + Assert.isFalse(overlaps(-1, -1)); Assert.isTrue(overlaps(0, 0)); Assert.isFalse(overlaps(1, 1)); @@ -440,13 +440,26 @@ class FlxTilemapTest extends FlxTest 0, 0, 0 ]; tilemap.loadMapFromArray(mapData, 3, 3, getBitmapData(), 8, 8); + tilemap.x += 10; + tilemap.y += 20; + tilemap.scale.set(2, 2); + + final SIZE = 16; + final HALF = 8; Assert.areEqual(tilemap.getTileIndex(4), tilemap.getTileIndex(1, 1)); Assert.areEqual(1, tilemap.getTileIndex(4)); Assert.areEqual(2, tilemap.getColumn(8)); Assert.areEqual(2, tilemap.getRow(8)); + Assert.areEqual(-1, tilemap.getMapIndex(1000, 1)); + Assert.areEqual(-1, tilemap.getTileIndex(1000, 1)); + Assert.areEqual(8, tilemap.getMapIndexAt(10 + 2 * SIZE + HALF, 20 + 2 * SIZE + HALF)); + Assert.areEqual(0, tilemap.getTileIndexAt(10 + 2 * SIZE + HALF, 20 + 2 * SIZE + HALF)); + Assert.areEqual(-1, tilemap.getTileIndexAt(10 + 1000 * SIZE + HALF, 20 + 2 * SIZE + HALF)); + Assert.areEqual(tilemap.getTileData(4), tilemap.getTileData(1, 1)); + Assert.areEqual(tilemap.getTileData(1, 1), tilemap.getTileDataAt(10 + 1 * SIZE + HALF, 20 + 1 * SIZE + HALF)); } function testGetColumnRowAt() @@ -457,6 +470,7 @@ class FlxTilemapTest extends FlxTest 0, 1, 0, 0, 0, 0, 0, 0, ]; + tilemap.y += 10; tilemap.loadMapFromArray(mapData, 4, 3, getBitmapData(), 8, 8); Assert.areEqual(tilemap.getColumnAt(24, true), tilemap.getColumnAt(24, false)); @@ -465,11 +479,55 @@ class FlxTilemapTest extends FlxTest Assert.areEqual(4, tilemap.getColumnAt(32, true)); Assert.areEqual(5, tilemap.getColumnAt(32, false)); - Assert.areEqual(tilemap.getRowAt(16, true), tilemap.getRowAt(16, false)); - Assert.areEqual(2, tilemap.getRowAt(16)); - Assert.areNotEqual(tilemap.getRowAt(24, true), tilemap.getRowAt(24, false)); - Assert.areEqual(3, tilemap.getRowAt(24, true)); - Assert.areEqual(4, tilemap.getRowAt(24, false)); + Assert.areEqual(tilemap.getRowAt(10 + 16, true), tilemap.getRowAt(10 + 16, false)); + Assert.areEqual(2, tilemap.getRowAt(10 + 16)); + Assert.areNotEqual(tilemap.getRowAt(10 + 24, true), tilemap.getRowAt(10 + 24, false)); + Assert.areEqual(3, tilemap.getRowAt(10 + 24, true)); + Assert.areEqual(4, tilemap.getRowAt(10 + 24, false)); + } + + @Test + function testColumnRowPos() + { + tilemap.loadMapFromArray(sampleMapArray, 4, 3, getBitmapData(), 8, 8); + tilemap.x = 10; + tilemap.y = 20; + tilemap.scale.set(2, 2); + + final SIZE = 16; + final HALF = 8; + + Assert.areEqual(0, tilemap.getColumnAt(tilemap.getColumnPos(0))); + Assert.areEqual(1, tilemap.getColumnAt(tilemap.getColumnPos(1))); + Assert.areEqual(2, tilemap.getColumnAt(tilemap.getColumnPos(2))); + Assert.areEqual(3, tilemap.getColumnAt(tilemap.getColumnPos(3))); + Assert.areEqual(1000, tilemap.getColumnAt(tilemap.getColumnPos(1000))); + Assert.areEqual(10 + 3 * SIZE, tilemap.getColumnPos(3)); + Assert.areEqual(10 + 3 * SIZE + HALF, tilemap.getColumnPos(3, true)); + Assert.areEqual(10 + 1000 * SIZE, tilemap.getColumnPos(1000)); + + Assert.areEqual(0, tilemap.getRowAt(tilemap.getRowPos(0))); + Assert.areEqual(1, tilemap.getRowAt(tilemap.getRowPos(1))); + Assert.areEqual(2, tilemap.getRowAt(tilemap.getRowPos(2))); + Assert.areEqual(1000, tilemap.getRowAt(tilemap.getRowPos(1000))); + Assert.areEqual(20 + 2 * SIZE, tilemap.getRowPos(2)); + Assert.areEqual(20 + 2 * SIZE + HALF, tilemap.getRowPos(2, true)); + Assert.areEqual(20 + 1000 * SIZE, tilemap.getRowPos(1000)); + + Assert.areEqual(null, tilemap.getTilePos(1000)); + Assert.areEqual(null, tilemap.getTilePos(-1)); + + + inline function assertPosEqual(expectedX:Float, expectedY:Float, actual:FlxPoint, ?infos:PosInfos) + { + Assert.areEqual(expectedX, actual.x, 'Point x [${actual.x}] was not equal to expected value [$expectedX]', infos); + Assert.areEqual(expectedY, actual.y, 'Point y [${actual.y}] was not equal to expected value [$expectedY]', infos); + } + + assertPosEqual(10 + -SIZE, 20 + -SIZE, tilemap.getTilePos(-1, -1)); + assertPosEqual(10 + SIZE, 20 + SIZE, tilemap.getTilePos(1, 1)); + assertPosEqual(10 + 1000 * SIZE, 20 + 1000 * SIZE, tilemap.getTilePos(1000, 1000)); + assertPosEqual(10 + 1000 * SIZE, 20 + 1000 * SIZE, tilemap.getTilePosAt(10 + 1000 * SIZE, 20 + 1000 * SIZE)); } @Test @@ -481,6 +539,11 @@ class FlxTilemapTest extends FlxTest 0, 0, 0 ]; tilemap.loadMapFromArray(mapData, 3, 3, getBitmapData(), 8, 8); + tilemap.x = 10; + tilemap.y = 20; + tilemap.scale.set(2, 2); + + final SIZE = 16; Assert.isTrue(tilemap.tileExists(4)); Assert.isTrue(tilemap.tileExists(1, 1)); @@ -488,6 +551,11 @@ class FlxTilemapTest extends FlxTest Assert.isFalse(tilemap.tileExists(3, 1)); Assert.isFalse(tilemap.tileExists(1, 3)); Assert.isFalse(tilemap.tileExists(5, 5)); + + Assert.isTrue(tilemap.tileExistsAt(10 + 1 * SIZE, 20 + 1 * SIZE)); + Assert.isFalse(tilemap.tileExistsAt(10 + 3 * SIZE, 20 + 1 * SIZE)); + Assert.isFalse(tilemap.tileExistsAt(10 + 1 * SIZE, 20 + 3 * SIZE)); + Assert.isFalse(tilemap.tileExistsAt(10 + 5 * SIZE, 20 + 5 * SIZE)); } @Test @@ -499,27 +567,59 @@ class FlxTilemapTest extends FlxTest 0, 0, 0, 0 ]; tilemap.loadMapFromArray(mapData, 4, 3, getBitmapData(), 8, 8); + tilemap.x = 10; + tilemap.y = 20; + tilemap.scale.set(2, 2); + + final SIZE = 16; Assert.isFalse(tilemap.columnExists(5)); Assert.isFalse(tilemap.rowExists(5)); + Assert.isFalse(tilemap.tileExists(5, 5)); + Assert.isFalse(tilemap.columnExistsAt(10 + 5 * SIZE)); + Assert.isFalse(tilemap.rowExistsAt(20 + 5 * SIZE)); + Assert.isFalse(tilemap.tileExistsAt(10 + 5 * SIZE, 20 + 5 * SIZE)); Assert.isFalse(tilemap.columnExists(4)); Assert.isFalse(tilemap.rowExists(4)); + Assert.isFalse(tilemap.tileExists(4, 4)); + Assert.isFalse(tilemap.columnExistsAt(10 + 4 * SIZE)); + Assert.isFalse(tilemap.rowExistsAt(20 + 4 * SIZE)); Assert.isTrue(tilemap.columnExists(3)); Assert.isFalse(tilemap.rowExists(3)); + Assert.isFalse(tilemap.tileExists(3, 3)); + Assert.isTrue(tilemap.columnExistsAt(10 + 3 * SIZE)); + Assert.isFalse(tilemap.rowExistsAt(20 + 3 * SIZE)); + Assert.isFalse(tilemap.tileExistsAt(10 + 3 * SIZE, 20 + 3 * SIZE)); Assert.isTrue(tilemap.columnExists(2)); Assert.isTrue(tilemap.rowExists(2)); + Assert.isTrue(tilemap.tileExists(2, 2)); + Assert.isTrue(tilemap.columnExistsAt(10 + 2 * SIZE)); + Assert.isTrue(tilemap.rowExistsAt(20 + 2 * SIZE)); + Assert.isTrue(tilemap.tileExistsAt(10 + 2 * SIZE, 20 + 2 * SIZE)); Assert.isTrue(tilemap.columnExists(1)); Assert.isTrue(tilemap.rowExists(1)); + Assert.isTrue(tilemap.tileExists(1, 1)); + Assert.isTrue(tilemap.columnExistsAt(10 + 1 * SIZE)); + Assert.isTrue(tilemap.rowExistsAt(20 + 1 * SIZE)); + Assert.isTrue(tilemap.tileExistsAt(10 + 1 * SIZE, 20 + 1 * SIZE)); Assert.isTrue(tilemap.columnExists(0)); Assert.isTrue(tilemap.rowExists(0)); + Assert.isTrue(tilemap.tileExists(0, 0)); + Assert.isTrue(tilemap.columnExistsAt(10)); + Assert.isTrue(tilemap.rowExistsAt(20)); + Assert.isTrue(tilemap.tileExistsAt(10, 20)); Assert.isFalse(tilemap.columnExists(-1)); Assert.isFalse(tilemap.rowExists(-1)); + Assert.isFalse(tilemap.tileExists(-1, -1)); + Assert.isFalse(tilemap.columnExistsAt(10 - 1)); + Assert.isFalse(tilemap.rowExistsAt(20 - 1)); + Assert.isFalse(tilemap.tileExistsAt(10 - 1, 20 - 1)); } @Test @@ -531,9 +631,23 @@ class FlxTilemapTest extends FlxTest 0, 0, 0 ]; tilemap.loadMapFromArray(mapData, 3, 3, getBitmapData(), 8, 8); + tilemap.x = 10; + tilemap.y = 20; + tilemap.scale.set(2, 2); FlxAssert.arraysEqual([4], tilemap.getAllMapIndices(1)); + + final pos = tilemap.getAllTilePos(1); + Assert.areEqual(1, pos.length); + Assert.areEqual(10 + 16, pos[0].x); + Assert.areEqual(20 + 16, pos[0].y); + FlxAssert.arraysEqual([0,1,2,3,5,6,7,8], tilemap.getAllMapIndices(0)); + FlxAssert.arraysEqual([0,1,2,3,5,6,7,8], tilemap.getAllTilePos(0).map((p)->tilemap.getMapIndex(p))); + FlxAssert.arraysEqual([0,1,2,3,5,6,7,8], tilemap.getAllTilePos(0, true).map((p)->tilemap.getMapIndex(p))); + final all = new Array(); + tilemap.forEachMapIndex(0, all.push); + FlxAssert.arraysEqual([0,1,2,3,5,6,7,8], all); } @Test From 4c580e1e11d1488c52e920077110ea9e8210aa0e Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Mon, 17 Jun 2024 13:15:45 -0500 Subject: [PATCH 10/99] Fix rect.intersections, add rect.clipTo (#3190) * fix empty result with passed in result arg * add rect.clipTo --- flixel/math/FlxRect.hx | 46 +++++++++++-------- tests/unit/src/flixel/math/FlxRectTest.hx | 56 +++++++++++++++++++++++ 2 files changed, 82 insertions(+), 20 deletions(-) diff --git a/flixel/math/FlxRect.hx b/flixel/math/FlxRect.hx index 31387c58ed..a21c297040 100644 --- a/flixel/math/FlxRect.hx +++ b/flixel/math/FlxRect.hx @@ -433,39 +433,45 @@ class FlxRect implements IFlxPooled rect.putWeak(); return result; } - + /** * Returns the area of intersection with specified rectangle. * If the rectangles do not intersect, this method returns an empty rectangle. * - * @param rect Rectangle to check intersection against. - * @return The area of intersection of two rectangles. + * @param rect Rectangle to check intersection against + * @param result The resulting instance, if `null`, a new one is created + * @return The area of intersection of two rectangles */ public function intersection(rect:FlxRect, ?result:FlxRect):FlxRect { if (result == null) result = FlxRect.get(); - - var x0:Float = x < rect.x ? rect.x : x; - var x1:Float = right > rect.right ? rect.right : right; - if (x1 <= x0) - { - rect.putWeak(); - return result; - } - - var y0:Float = y < rect.y ? rect.y : y; - var y1:Float = bottom > rect.bottom ? rect.bottom : bottom; - if (y1 <= y0) - { - rect.putWeak(); - return result; - } - + + final x0:Float = x < rect.x ? rect.x : x; + final x1:Float = right > rect.right ? rect.right : right; + final y0:Float = y < rect.y ? rect.y : y; + final y1:Float = bottom > rect.bottom ? rect.bottom : bottom; rect.putWeak(); + + if (x1 <= x0 || y1 <= y0) + return result.set(0, 0, 0, 0); + return result.set(x0, y0, x1 - x0, y1 - y0); } + /** + * Resizes `this` instance so that it fits within the intersection of the this and + * the target rect. If there is no overlap between them, The result is an empty rect. + * + * @param rect Rectangle to check intersection against + * @return This rect, useful for chaining + * @since 5.9.0 + */ + public function clipTo(rect:FlxRect):FlxRect + { + return rect.intersection(this, this); + } + /** * The middle point of this rect * diff --git a/tests/unit/src/flixel/math/FlxRectTest.hx b/tests/unit/src/flixel/math/FlxRectTest.hx index b2faa081ad..2f501a65de 100644 --- a/tests/unit/src/flixel/math/FlxRectTest.hx +++ b/tests/unit/src/flixel/math/FlxRectTest.hx @@ -94,4 +94,60 @@ class FlxRectTest extends FlxTest pivot.put(); expected.put(); } + + @Test + function testIntersection() + { + rect1.set(0, 0, 100, 100); + rect2.set(50, 50, 100, 100); + + final expected = FlxRect.get(50, 50, 50, 50); + final result = FlxRect.get(); + rect1.intersection(rect2, result); + FlxAssert.rectsNear(expected, result, 0.0001); + + expected.put(); + result.put(); + } + + @Test + function testIntersectionEmpty() + { + rect1.set(0, 0, 100, 100); + rect2.set(200, 200, 100, 100); + + final expected = FlxRect.get(0, 0, 0, 0); + final result = FlxRect.get(1000, 1000, 1000, 1000); + rect1.intersection(rect2, result); + FlxAssert.rectsNear(expected, result, 0.0001); + + expected.put(); + result.put(); + } + + @Test + function testClipTo() + { + rect1.set(0, 0, 100, 100); + rect2.set(50, 50, 100, 100); + + final expected = FlxRect.get(50, 50, 50, 50); + rect1.clipTo(rect2); + FlxAssert.rectsNear(expected, rect1, 0.0001); + + expected.put(); + } + + @Test + function testClipToEmpty() + { + rect1.set(0, 0, 100, 100); + rect2.set(200, 200, 100, 100); + + final expected = FlxRect.get(0, 0, 0, 0); + rect1.clipTo(rect2); + FlxAssert.rectsNear(expected, rect1, 0.0001); + + expected.put(); + } } From 55c8c826babaf6fad9d5fb01872946166ec11ca1 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Wed, 19 Jun 2024 09:04:46 -0500 Subject: [PATCH 11/99] test new setup-flixel (#3188) --- .github/workflows/main.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c57248b91b..a51eda1410 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -31,10 +31,9 @@ jobs: haxelib install haxelib 4.0.3 haxelib dev flixel . - - uses: HaxeFlixel/setup-flixel@v1 + - uses: HaxeFlixel/setup-flixel@master with: - haxe-version: current flixel-versions: dev test-location: local target: ${{matrix.target}} - run-tests: true \ No newline at end of file + run-tests: true From 61aac1f9c10055cea38feac0b26e2e33a0b68daa Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Sun, 23 Jun 2024 09:22:14 -0500 Subject: [PATCH 12/99] ignore border outline when computing field size (#3193) --- flixel/text/FlxBitmapText.hx | 40 +++++++++++++++--------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/flixel/text/FlxBitmapText.hx b/flixel/text/FlxBitmapText.hx index b4b8aa86f1..6fcec9169a 100644 --- a/flixel/text/FlxBitmapText.hx +++ b/flixel/text/FlxBitmapText.hx @@ -160,7 +160,8 @@ class FlxBitmapText extends FlxSprite public var shadowOffset(default, null):FlxPoint; /** - * Specifies whether the text should have background + * Specifies whether the text should have a background. It is recommended to use a + * `padding` of `1` or more with a background, especially when using a border style */ public var background(default, set):Bool = false; @@ -618,24 +619,15 @@ class FlxBitmapText extends FlxSprite pendingTextChange = false; pendingTextBitmapChange = true; } - + /** * Calculates the size of text field. */ function computeTextSize():Void { - var txtWidth:Int = textWidth + Std.int(borderSize) * 2; - var txtHeight:Int = textHeight + 2 * padding + Std.int(borderSize) * 2; - - if (autoSize) - { - txtWidth += 2 * padding; - } - else - { - txtWidth = fieldWidth; - } - + final txtWidth = autoSize ? textWidth + padding * 2 : fieldWidth; + final txtHeight = textHeight + padding * 2; + frameWidth = (txtWidth == 0) ? 1 : txtWidth; frameHeight = (txtHeight == 0) ? 1 : txtHeight; } @@ -1475,17 +1467,19 @@ class FlxBitmapText extends FlxSprite /** * Set border's style (shadow, outline, etc), color, and size all in one go! * - * @param Style outline style - * @param Color outline color in flash 0xAARRGGBB format - * @param Size outline size in pixels - * @param Quality outline quality - # of iterations to use when drawing. 0:just 1, 1:equal number to BorderSize + * @param style Outline style, such as `OUTLINE` or `SHADOW` + * @param color Outline color + * @param size Outline size in pixels. + * **If `background` is `true`, you may want to increase this text's `padding`** + * @param quality Outline quality, or the number of iterations to use when drawing. + * `0` means `1` iteration, otherwise it draws `size * quality` iterations */ - public inline function setBorderStyle(Style:FlxTextBorderStyle, Color:FlxColor = 0, Size:Float = 1, Quality:Float = 1):Void + public inline function setBorderStyle(style:FlxTextBorderStyle, color:FlxColor = 0, size = 1.0, quality = 1.0) { - borderStyle = Style; - borderColor = Color; - borderSize = Size; - borderQuality = Quality; + borderStyle = style; + borderColor = color; + borderSize = size; + borderQuality = quality; if (borderStyle == FlxTextBorderStyle.SHADOW) { shadowOffset.set(borderSize, borderSize); From df5e0c2f52231f97715976370b4cfaffd5d8cfb3 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Wed, 26 Jun 2024 17:24:32 -0500 Subject: [PATCH 13/99] Fix crashes from negative tiles (#3194) * fix negative tiles * more unit tests * one more test --- flixel/tile/FlxTilemap.hx | 28 ++++++-------- tests/unit/src/flixel/tile/FlxTilemapTest.hx | 39 ++++++++++++++++++++ 2 files changed, 51 insertions(+), 16 deletions(-) diff --git a/flixel/tile/FlxTilemap.hx b/flixel/tile/FlxTilemap.hx index a39d314d98..b281c742a7 100644 --- a/flixel/tile/FlxTilemap.hx +++ b/flixel/tile/FlxTilemap.hx @@ -781,6 +781,8 @@ class FlxTypedTilemap extends FlxBaseTilemap for (column in minTileX...maxTileX) { final tile = getTileData(column, row); + if (tile == null) + continue; tile.orientAt(xPos, yPos, column, row); if (tile.overlapsObject(object) && (filter == null || filter(tile))) { @@ -933,7 +935,8 @@ class FlxTypedTilemap extends FlxBaseTilemap final endIndex = getMapIndex(end); // If the starting tile is solid, return the starting position - if (getTileData(startIndex).solid) + final tile = getTileData(startIndex); + if (tile != null && tile.solid) { if (result != null) result.copyFrom(start); @@ -971,16 +974,13 @@ class FlxTypedTilemap extends FlxBaseTilemap final inc = movesRight ? 1 : -1; final offset = movesRight ? 1 : 0; var tileX = startTileX; - var tileY = 0; - var xPos = 0.0; - var yPos = 0.0; var lastTileY = startTileY; while (tileX != endTileX) { - xPos = getColumnPos(tileX + offset); - yPos = m * xPos + b; - tileY = getRowAt(yPos); + final xPos = getColumnPos(tileX + offset); + final yPos = m * getColumnPos(tileX + offset) + b; + final tileY = getRowAt(yPos); hitIndex = checkColumn(tileX, lastTileY, tileY); if (hitIndex != -1) break; @@ -1040,8 +1040,9 @@ class FlxTypedTilemap extends FlxBaseTilemap final step = startY <= endY ? 1 : -1; while (true) { - var index = getMapIndex(x, y); - if (getTileData(index).solid) + final index = getMapIndex(x, y); + final tile = getTileData(index); + if (tile != null && tile.solid) return index; if (y == endY) @@ -1102,7 +1103,8 @@ class FlxTypedTilemap extends FlxBaseTilemap var tileX = Math.floor(curX / scaledTileWidth); var tileY = Math.floor(curY / scaledTileHeight); - if (getTileData(tileX, tileY).solid) + final tile = getTileData(tileX, tileY); + if (tile != null && tile.solid) { // Some basic helper stuff tileX *= Std.int(scaledTileWidth); @@ -1395,12 +1397,6 @@ class FlxTypedTilemap extends FlxBaseTilemap } #end - /** Guards against -1 */ - override function setTileHelper(mapIndex:Int, tileIndex:Int, updateGraphics:Bool = true):Bool - { - return super.setTileHelper(mapIndex, tileIndex < 0 ? 0 : tileIndex, updateGraphics); - } - /** * Internal function used in setTileIndex() and the constructor to update the map. * diff --git a/tests/unit/src/flixel/tile/FlxTilemapTest.hx b/tests/unit/src/flixel/tile/FlxTilemapTest.hx index 900f103a78..8642932480 100644 --- a/tests/unit/src/flixel/tile/FlxTilemapTest.hx +++ b/tests/unit/src/flixel/tile/FlxTilemapTest.hx @@ -673,6 +673,45 @@ class FlxTilemapTest extends FlxTest Assert.areEqual(tile.x, tile.last.x); } + @Test + function testNegativeIndex() + { + final mapData = [ + 0, 0, 0, + 0, 1, 0, + 0, 0, 0 + ]; + tilemap.loadMapFromArray(mapData, 3, 3, getBitmapData(), 8, 8); + + tilemap.setTileIndex(0, -2); + Assert.areEqual(-2, tilemap.getTileIndex(0)); + + // cover entire map + final object = new FlxObject(4, 4, 16, 16); + object.last.set(object.x, object.y); + + var overlapResult = true; + var rayResult = false; + var rayStepResult = false; + var getIndexResult:FlxTile = null; + try + { + overlapResult = tilemap.overlaps(object); + rayResult = tilemap.ray(FlxPoint.weak(0, 0), new FlxPoint(tilemap.width, tilemap.height)); + rayStepResult = tilemap.rayStep(FlxPoint.weak(0, 0), new FlxPoint(tilemap.width, tilemap.height)); + getIndexResult = tilemap.getTileData(0); + // TODO: more tests? + } + catch(e) + { + Assert.fail('Exception throw: ' + e.toString()); + } + Assert.isTrue(overlapResult); + Assert.isFalse(rayResult); + Assert.isFalse(rayStepResult); + Assert.isNull(getIndexResult); + } + function getBitmapData() { return new BitmapData(8*16, 8); From 5ee97353cfca85a25bd835588c879fc005a95871 Mon Sep 17 00:00:00 2001 From: Flainn Date: Mon, 1 Jul 2024 10:51:49 -0400 Subject: [PATCH 14/99] Fix `null` text alignment returning as CENTER on HashLink (#3196) * Fix `null` text alignment returning as CENTER on HashLink * Moved null check over to the switch statement * Add comment to explain the bugfix --- flixel/text/FlxText.hx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/flixel/text/FlxText.hx b/flixel/text/FlxText.hx index bf07d57b35..0c643a152a 100644 --- a/flixel/text/FlxText.hx +++ b/flixel/text/FlxText.hx @@ -1273,6 +1273,10 @@ enum abstract FlxTextAlign(String) from String { return switch (align) { + // This `null` check is needed for HashLink, otherwise it will cast + // a `null` alignment to 0 which results in returning `CENTER` + // instead of the default `LEFT`. + case null: LEFT; case TextFormatAlign.LEFT: LEFT; case TextFormatAlign.CENTER: CENTER; case TextFormatAlign.RIGHT: RIGHT; From c839af2da905203c88f216ee8c4b308f76109d88 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Mon, 8 Jul 2024 10:40:58 -0500 Subject: [PATCH 15/99] fix ci i HL (ignore failing, for now) (#3208) --- tests/unit/src/flixel/path/FlxPathfinderTest.hx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/unit/src/flixel/path/FlxPathfinderTest.hx b/tests/unit/src/flixel/path/FlxPathfinderTest.hx index 6c9d414067..62f65862f2 100644 --- a/tests/unit/src/flixel/path/FlxPathfinderTest.hx +++ b/tests/unit/src/flixel/path/FlxPathfinderTest.hx @@ -37,6 +37,10 @@ class FlxPathfinderTest extends FlxTest _end = FlxPoint.get(); } + #if hl + @Ignore("Failing on HL from getInBoundDirections") + // TODO: remove in HL 1.15, fixed here: https://github.com/HaxeFoundation/hashlink/issues/694 + #end @Test function testFindPath() { @@ -60,6 +64,10 @@ class FlxPathfinderTest extends FlxTest } + #if hl + @Ignore("Failing on HL from getInBoundDirections") + // TODO: remove in HL 1.15, fixed here: https://github.com/HaxeFoundation/hashlink/issues/694 + #end @Test // custom pathfinder function testCustomPathfinder() { From ad012fa4155d79567aab583710419453d9abe869 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Wed, 10 Jul 2024 13:47:07 -0400 Subject: [PATCH 16/99] Pointer (#3210) * overhaul pointer * fix debug selection on native fullscreen * fix backwards compat * fix CI on github actions * more CI fixes * D'oh * doc * more doc * more docs --- flixel/input/FlxPointer.hx | 317 ++++++++++++------ flixel/input/mouse/FlxMouse.hx | 70 ++-- flixel/input/mouse/FlxMouseButton.hx | 4 +- flixel/input/mouse/FlxMouseEventManager.hx | 4 +- flixel/input/touch/FlxTouch.hx | 6 +- flixel/math/FlxAngle.hx | 8 +- flixel/math/FlxMath.hx | 18 +- .../system/debug/interaction/Interaction.hx | 2 +- flixel/ui/FlxButton.hx | 2 +- tests/unit/src/flixel/input/FlxPointerTest.hx | 72 ++++ .../input/actions/FlxActionInputAnalogTest.hx | 8 +- .../input/actions/FlxActionManagerTest.hx | 2 +- .../flixel/input/actions/FlxActionSetTest.hx | 2 +- .../src/flixel/input/actions/FlxActionTest.hx | 10 +- .../input/mouse/FlxMouseEventManagerTest.hx | 2 +- 15 files changed, 371 insertions(+), 156 deletions(-) create mode 100644 tests/unit/src/flixel/input/FlxPointerTest.hx diff --git a/flixel/input/FlxPointer.hx b/flixel/input/FlxPointer.hx index 8b91149f1a..3613cf5874 100644 --- a/flixel/input/FlxPointer.hx +++ b/flixel/input/FlxPointer.hx @@ -7,165 +7,276 @@ import flixel.util.FlxStringUtil; class FlxPointer { + /** The position in the world */ public var x(default, null):Int = 0; + /** The position in the world */ public var y(default, null):Int = 0; + + /** The world position relative to the main camera's scroll position */ + @:deprecated("screenX is deprecated, use viewX, instead") + public var screenX(default, never):Int = 0; + /** The world position relative to the main camera's scroll position */ + @:deprecated("screenY is deprecated, use viewY, instead") + public var screenY(default, never):Int = 0; + + /** + * The world position relative to the main camera's scroll position, `cam.viewMarginX` or + * `cam.viewMarginLeft` is the left edge of the camera and `cam.viewMarginRight` is the right + * + * @since 5.9.0 + */ + public var viewX(default, null):Int = 0; + /** + * The world position relative to the main camera's scroll position, `cam.viewMarginY` or + * `cam.viewMarginTop` is the top edge of the camera and `cam.viewMarginBottom` is the bottom + * + * @since 5.9.0 + */ + public var viewY(default, null):Int = 0; + + /** + * The position relative to the `FlxGame`'s position in the window, + * where `0` is the left edge of the game and `FlxG.width` is the right + * + * @since 5.9.0 + */ + public var gameX(default, null):Int = 0; + /** + * The position relative to the `FlxGame`'s position in the window, + * where `0` is the top edge of the game and `FlxG.height` is the bottom + * + * @since 5.9.0 + */ + public var gameY(default, null):Int = 0; - public var screenX(default, null):Int = 0; - public var screenY(default, null):Int = 0; - - var _globalScreenX:Int = 0; - var _globalScreenY:Int = 0; + @:deprecated("_globalScreenX is deprecated, use gameX, instead") // 5.9.0 + var _globalScreenX(get, set):Int; + @:deprecated("_globalScreenY is deprecated, use gameY, instead") // 5.9.0 + var _globalScreenY(get, set):Int; + + var _rawX(default, null):Float = 0; + var _rawY(default, null):Float = 0; static var _cachedPoint:FlxPoint = new FlxPoint(); public function new() {} /** - * Fetch the world position of the pointer on any given camera. - * NOTE: x and y also store the world position of the pointer on the main camera. + * Fetch the world position of the pointer on any given camera + * + * **Note:** Fields `x` and `y` also store this result * - * @param Camera If unspecified, first/main global camera is used instead. - * @param point An existing point object to store the results (if you don't want a new one created). - * @return The touch point's location in world space. + * @param camera If unspecified, `FlxG.camera` is used, instead + * @param result An existing point to store the results, if unspecified, one is created */ - public function getWorldPosition(?Camera:FlxCamera, ?point:FlxPoint):FlxPoint + public function getWorldPosition(?camera:FlxCamera, ?result:FlxPoint):FlxPoint { - if (Camera == null) - { - Camera = FlxG.camera; - } - if (point == null) - { - point = FlxPoint.get(); - } - getScreenPosition(Camera, _cachedPoint); - point.x = _cachedPoint.x + Camera.scroll.x; - point.y = _cachedPoint.y + Camera.scroll.y; - return point; + if (camera == null) + camera = FlxG.camera; + + getViewPosition(camera, result); + result.addPoint(camera.scroll); + return result; } - + /** - * Fetch the screen position of the pointer on any given camera. - * NOTE: screenX and screenY also store the screen position of the pointer on the main camera. - * - * @param Camera If unspecified, first/main global camera is used instead. - * @param point An existing point object to store the results (if you don't want a new one created). - * @return The touch point's location in screen space. + * The position relative to the game's position in the window, where `(0, 0)` is the + * top-left edge of the game and `(FlxG.width, FlxG.height)` is the bottom-right + * + * **Note:** Fields `gameX` and `gameY` also store this result + * + * @param result An existing point to store the results, if unspecified, one is created + * @since 5.9.0 */ - public function getScreenPosition(?Camera:FlxCamera, ?point:FlxPoint):FlxPoint + public function getGamePosition(?result:FlxPoint):FlxPoint { - if (Camera == null) - { - Camera = FlxG.camera; - } - if (point == null) - { - point = FlxPoint.get(); - } - - point.x = (_globalScreenX - Camera.x + 0.5 * Camera.width * (Camera.zoom - Camera.initialZoom)) / Camera.zoom; - point.y = (_globalScreenY - Camera.y + 0.5 * Camera.height * (Camera.zoom - Camera.initialZoom)) / Camera.zoom; - - return point; + if (result == null) + return FlxPoint.get(); + + return result.set(Std.int(_rawX), Std.int(_rawY)); } - + /** - * Fetch the screen position of the pointer relative to given camera's viewport. + * Fetch the world position relative to the main camera's `scroll` position, where + * `(cam.viewMarginLeft, cam.viewMarginTop)` is the top-left of the camera and + * `(cam.viewMarginRight, cam.viewMarginBottom)` is the bottom right + * + * **Note:** Fields `viewX` and `viewY` also store this result * - * @param Camera If unspecified, first/main global camera is used instead. - * @param point An existing point object to store the results (if you don't want a new one created). - * @return The touch point's location relative to camera's viewport. + * @param camera If unspecified, `FlxG.camera` is used, instead + * @param result An existing point to store the results, if unspecified, one is created */ - @:access(flixel.FlxCamera) - public function getPositionInCameraView(?Camera:FlxCamera, ?point:FlxPoint):FlxPoint + public function getViewPosition(?camera:FlxCamera, ?result:FlxPoint):FlxPoint { - if (Camera == null) - Camera = FlxG.camera; - - if (point == null) - point = FlxPoint.get(); - - point.x = (_globalScreenX - Camera.x) / Camera.zoom + Camera.viewMarginX; - point.y = (_globalScreenY - Camera.y) / Camera.zoom + Camera.viewMarginY; - - return point; + if (camera == null) + camera = FlxG.camera; + + if (result == null) + result = FlxPoint.get(); + + result.x = Std.int((gameX - camera.x) / camera.zoom + camera.viewMarginX); + result.y = Std.int((gameY - camera.y) / camera.zoom + camera.viewMarginY); + + return result; } - + + /** + * Fetch the position of the pointer relative to given camera's `scroll` position, where + * `(cam.viewMarginLeft, cam.viewMarginTop)` is the top-left of the camera and + * `(cam.viewMarginRight, cam.viewMarginBottom)` is the bottom right of the camera + * + * **Note:** Fields `viewX` and `viewY` also store this result for `FlxG.camera` + * + * @param camera If unspecified, `FlxG.camera` is used, instead + * @param result An existing point to store the results, if unspecified, one is created + */ + @:deprecated("getScreenPosition is deprecated, use getViewPosition, instead") // 5.9.0 + public function getScreenPosition(?camera:FlxCamera, ?result:FlxPoint):FlxPoint + { + if (camera == null) + camera = FlxG.camera; + + if (result == null) + result = FlxPoint.get(); + + result.x = (gameX - camera.x + 0.5 * camera.width * (camera.zoom - camera.initialZoom)) / camera.zoom; + result.y = (gameY - camera.y + 0.5 * camera.height * (camera.zoom - camera.initialZoom)) / camera.zoom; + + return result; + } + + /** + * Fetch the position of the pointer relative to given camera's `scroll` position, where + * `(cam.viewMarginLeft, cam.viewMarginTop)` is the top-left of the camera and + * `(cam.viewMarginRight, cam.viewMarginBottom)` is the bottom right of the camera + * + * **Note:** Fields `viewX` and `viewY` also store this result for `FlxG.camera` + * + * @param camera If unspecified, `FlxG.camera` is used, instead. + * @param result An existing point to store the results, if unspecified, one is created + * @return The pointer's location relative to camera's viewport. + */ + @:deprecated("getPositionInCameraView is deprecated, use getViewPosition, instead") // 5.9.0 + public function getPositionInCameraView(?camera:FlxCamera, ?result:FlxPoint):FlxPoint + { + if (camera == null) + camera = FlxG.camera; + + if (result == null) + result = FlxPoint.get(); + + result.x = (gameX - camera.x) / camera.zoom + camera.viewMarginX; + result.y = (gameY - camera.y) / camera.zoom + camera.viewMarginY; + + return result; + } + /** * Returns a FlxPoint with this input's x and y. */ - public function getPosition(?point:FlxPoint):FlxPoint + public function getPosition(?result:FlxPoint):FlxPoint { - if (point == null) - point = FlxPoint.get(); - return point.set(x, y); + if (result == null) + return FlxPoint.get(x, y); + + return result.set(x, y); } - + /** - * Checks to see if some FlxObject overlaps this FlxObject or FlxGroup. - * If the group has a LOT of things in it, it might be faster to use FlxG.overlaps(). - * WARNING: Currently tilemaps do NOT support screen space overlap checks! + * Checks to see if this pointer overlaps some `FlxObject` or `FlxGroup`. * - * @param ObjectOrGroup The object or group being tested. - * @param Camera Specify which game camera you want. If null getScreenPosition() will just grab the first global camera. - * @return Whether or not the two objects overlap. + * @param objectOrGroup The object or group being tested + * @param camera Helps determine the world position. If unspecified, `FlxG.camera` is used */ @:access(flixel.group.FlxTypedGroup.resolveGroup) - public function overlaps(ObjectOrGroup:FlxBasic, ?Camera:FlxCamera):Bool + public function overlaps(objectOrGroup:FlxBasic, ?camera:FlxCamera):Bool { - var result:Bool = false; - - var group = FlxTypedGroup.resolveGroup(ObjectOrGroup); + // check group + final group = FlxTypedGroup.resolveGroup(objectOrGroup); if (group != null) { - group.forEachExists(function(basic:FlxBasic) + for (basic in group.members) { - if (overlaps(basic, Camera)) + if (basic != null && overlaps(basic, camera)) { - result = true; - return; + return true; } - }); - } - else - { - getWorldPosition(Camera, _cachedPoint); - var object:FlxObject = cast ObjectOrGroup; - result = object.overlapsPoint(_cachedPoint, true, Camera); + } + return false; } - - return result; + // check object + getWorldPosition(camera, _cachedPoint); + final object = cast (objectOrGroup, FlxObject); + return object.overlapsPoint(_cachedPoint, true, camera); } - + /** * Directly set the underyling screen position variable. WARNING! You should never use * this unless you are trying to manually dispatch low-level mouse / touch events to the stage. */ + @:deprecated("setGlobalScreenPositionUnsafe is deprecated, use setRawPositionUnsafe, instead") public inline function setGlobalScreenPositionUnsafe(newX:Float, newY:Float):Void { - _globalScreenX = Std.int(newX / FlxG.scaleMode.scale.x); - _globalScreenY = Std.int(newY / FlxG.scaleMode.scale.y); - - updatePositions(); + setRawPositionUnsafe(newX, newY); } - - public function toString():String + + /** + * Directly set the underyling position variable. WARNING! You should never use + * this unless you are trying to manually dispatch low-level mouse / touch events to the stage. + * @since 5.9.0 + */ + @:haxe.warning("-WDeprecated") + public function setRawPositionUnsafe(x:Float, y:Float) { - return FlxStringUtil.getDebugString([LabelValuePair.weak("x", x), LabelValuePair.weak("y", y)]); + _rawX = x / FlxG.scaleMode.scale.x; + _rawY = y / FlxG.scaleMode.scale.y; + + updatePositions(); } - + /** * Helper function to update the cursor used by update() and playback(). * Updates the x, y, screenX, and screenY variables based on the default camera. */ function updatePositions():Void { - getScreenPosition(FlxG.camera, _cachedPoint); - screenX = Std.int(_cachedPoint.x); - screenY = Std.int(_cachedPoint.y); - + getGamePosition(_cachedPoint); + gameX = Std.int(_cachedPoint.x); + gameY = Std.int(_cachedPoint.y); + + getViewPosition(FlxG.camera, _cachedPoint); + viewX = Std.int(_cachedPoint.x); + viewY = Std.int(_cachedPoint.y); + getWorldPosition(FlxG.camera, _cachedPoint); x = Std.int(_cachedPoint.x); y = Std.int(_cachedPoint.y); } + + public function toString():String + { + return FlxStringUtil.getDebugString([LabelValuePair.weak("x", x), LabelValuePair.weak("y", y)]); + } + + inline function get__globalScreenX():Int + { + return gameX; + } + + inline function get__globalScreenY():Int + { + return gameY; + } + + inline function set__globalScreenX(value:Int):Int + { + _rawX = value * FlxG.scaleMode.scale.x; + return value; + } + + inline function set__globalScreenY(value:Int):Int + { + _rawY = value * FlxG.scaleMode.scale.y; + return value; + } } diff --git a/flixel/input/mouse/FlxMouse.hx b/flixel/input/mouse/FlxMouse.hx index 53c3ae090f..65f1c984b4 100644 --- a/flixel/input/mouse/FlxMouse.hx +++ b/flixel/input/mouse/FlxMouse.hx @@ -83,16 +83,30 @@ class FlxMouse extends FlxPointer implements IFlxInputManager * Distance in pixels the mouse has moved since the last frame in the Y direction. */ public var deltaY(get, never):Int; - + /** * Distance in pixels the mouse has moved in screen space since the last frame in the X direction. */ + @:deprecated("deltaScreenX is deprecated, use deltaViewX, instead") // 5.9.0 public var deltaScreenX(get, never):Int; - + /** * Distance in pixels the mouse has moved in screen space since the last frame in the Y direction. */ + @:deprecated("deltaScreenY is deprecated, use deltaViewY, instead") // 5.9.0 public var deltaScreenY(get, never):Int; + + /** + * Distance in pixels the mouse has moved in view space since the last frame in the X direction. + * @since 5.9.0 + */ + public var deltaViewX(get, never):Int; + + /** + * Distance in pixels the mouse has moved in view space since the last frame in the Y direction. + * @since 5.9.0 + */ + public var deltaViewY(get, never):Int; /** * Check to see if the left mouse button is currently pressed. @@ -217,8 +231,12 @@ class FlxMouse extends FlxPointer implements IFlxInputManager */ var _prevX:Int = 0; var _prevY:Int = 0; - var _prevScreenX:Int = 0; - var _prevScreenY:Int = 0; + var _prevViewX:Int = 0; + var _prevViewY:Int = 0; + @:deprecated("_prevScreenX is deprecated, use _prevViewX, instead") + var _prevScreenX(get, never):Int; + @:deprecated("_prevScreenY is deprecated, use _prevViewY, instead") + var _prevScreenY(get, never):Int; // Helper variable for cleaning up memory var _stage:Stage; @@ -493,11 +511,13 @@ class FlxMouse extends FlxPointer implements IFlxInputManager { _prevX = x; _prevY = y; - _prevScreenX = screenX; - _prevScreenY = screenY; + _prevViewX = viewX; + _prevViewY = viewY; - #if !FLX_UNIT_TEST // Travis segfaults when game.mouseX / Y is accessed - setGlobalScreenPositionUnsafe(FlxG.game.mouseX, FlxG.game.mouseY); + #if FLX_UNIT_TEST // Travis segfaults when game.mouseX / Y is accessed + setRawPositionUnsafe(0, 0); + #else + setRawPositionUnsafe(FlxG.game.mouseX, FlxG.game.mouseY); // actually position the flixel mouse cursor graphic if (visible) @@ -593,11 +613,23 @@ class FlxMouse extends FlxPointer implements IFlxInputManager inline function get_deltaY():Int return y - _prevY; + inline function get_deltaViewX():Int + return viewX - _prevViewX; + + inline function get_deltaViewY():Int + return viewY - _prevViewY; + + inline function get__prevScreenX():Int + return _prevViewX; + + inline function get__prevScreenY():Int + return _prevViewY; + inline function get_deltaScreenX():Int - return screenX - _prevScreenX; - + return deltaViewX; + inline function get_deltaScreenY():Int - return screenY - _prevScreenY; + return deltaViewY; inline function get_pressed():Bool return _leftButton.pressed; @@ -726,16 +758,16 @@ class FlxMouse extends FlxPointer implements IFlxInputManager @:allow(flixel.system.replay.FlxReplay) function record():MouseRecord { - if ((_lastX == _globalScreenX) - && (_lastY == _globalScreenY) + if ((_lastX == gameX) + && (_lastY == gameY) && (_lastLeftButtonState == _leftButton.current) && (_lastWheel == wheel)) { return null; } - _lastX = _globalScreenX; - _lastY = _globalScreenY; + _lastX = gameX; + _lastY = gameY; _lastLeftButtonState = _leftButton.current; _lastWheel = wheel; return new MouseRecord(_lastX, _lastY, _leftButton.current, _lastWheel); @@ -754,19 +786,19 @@ class FlxMouse extends FlxPointer implements IFlxInputManager } _lastLeftButtonState = _leftButton.current = record.button; wheel = record.wheel; - _globalScreenX = record.x; - _globalScreenY = record.y; + _rawX = record.x; + _rawY = record.y; updatePositions(); } inline function get__cursor() { - return cursor; + return cursor; } inline function set__cursor(value:Bitmap) { - return cursor = value; + return cursor = value; } } #end diff --git a/flixel/input/mouse/FlxMouseButton.hx b/flixel/input/mouse/FlxMouseButton.hx index fed3d03235..0b3a82c2bf 100644 --- a/flixel/input/mouse/FlxMouseButton.hx +++ b/flixel/input/mouse/FlxMouseButton.hx @@ -34,13 +34,13 @@ class FlxMouseButton extends FlxInput implements IFlxDestroyable if (justPressed) { - justPressedPosition.set(FlxG.mouse.screenX, FlxG.mouse.screenY); + justPressedPosition.set(FlxG.mouse.viewX, FlxG.mouse.viewY); justPressedTimeInTicks = FlxG.game.ticks; } #if FLX_POINTER_INPUT else if (justReleased) { - FlxG.swipes.push(new FlxSwipe(ID, justPressedPosition.copyTo(), FlxG.mouse.getScreenPosition(), justPressedTimeInTicks)); + FlxG.swipes.push(new FlxSwipe(ID, justPressedPosition.copyTo(), FlxG.mouse.getViewPosition(), justPressedTimeInTicks)); } #end } diff --git a/flixel/input/mouse/FlxMouseEventManager.hx b/flixel/input/mouse/FlxMouseEventManager.hx index c5d2abf6ac..ab36ef6bc2 100644 --- a/flixel/input/mouse/FlxMouseEventManager.hx +++ b/flixel/input/mouse/FlxMouseEventManager.hx @@ -635,7 +635,7 @@ class FlxMouseEventManager extends FlxBasic for (camera in event.object.getCameras()) { #if FLX_MOUSE - _point = FlxG.mouse.getPositionInCameraView(camera, _point); + _point = FlxG.mouse.getViewPosition(camera, _point); if (camera.containsPoint(_point)) { _point = FlxG.mouse.getWorldPosition(camera, _point); @@ -650,7 +650,7 @@ class FlxMouseEventManager extends FlxBasic #if FLX_TOUCH for (touch in FlxG.touches.list) { - _point = touch.getPositionInCameraView(camera, _point); + _point = touch.getViewPosition(camera, _point); if (camera.containsPoint(_point)) { _point = touch.getWorldPosition(camera, _point); diff --git a/flixel/input/touch/FlxTouch.hx b/flixel/input/touch/FlxTouch.hx index f4cf0e27c5..9cea7f110d 100644 --- a/flixel/input/touch/FlxTouch.hx +++ b/flixel/input/touch/FlxTouch.hx @@ -81,13 +81,13 @@ class FlxTouch extends FlxPointer implements IFlxDestroyable implements IFlxInpu if (justPressed) { - justPressedPosition.set(screenX, screenY); + justPressedPosition.set(viewX, viewY); justPressedTimeInTicks = FlxG.game.ticks; } #if FLX_POINTER_INPUT else if (justReleased) { - FlxG.swipes.push(new FlxSwipe(touchPointID, justPressedPosition.copyTo(), getScreenPosition(), justPressedTimeInTicks)); + FlxG.swipes.push(new FlxSwipe(touchPointID, justPressedPosition.copyTo(), getViewPosition(), justPressedTimeInTicks)); } #end } @@ -103,7 +103,7 @@ class FlxTouch extends FlxPointer implements IFlxDestroyable implements IFlxInpu flashPoint.setTo(X, Y); flashPoint = FlxG.game.globalToLocal(flashPoint); - setGlobalScreenPositionUnsafe(flashPoint.x, flashPoint.y); + setRawPositionUnsafe(flashPoint.x, flashPoint.y); } inline function get_touchPointID():Int diff --git a/flixel/math/FlxAngle.hx b/flixel/math/FlxAngle.hx index f8fbbacee3..af87627640 100644 --- a/flixel/math/FlxAngle.hx +++ b/flixel/math/FlxAngle.hx @@ -246,8 +246,8 @@ class FlxAngle var p:FlxPoint = Object.getScreenPosition(); - var dx:Float = FlxG.mouse.screenX - p.x; - var dy:Float = FlxG.mouse.screenY - p.y; + var dx:Float = FlxG.mouse.viewX - p.x; + var dy:Float = FlxG.mouse.viewY - p.y; p.put(); @@ -296,8 +296,8 @@ class FlxAngle // In order to get the angle between the object and mouse, we need the objects screen coordinates (rather than world coordinates) var p:FlxPoint = Object.getScreenPosition(); - var dx:Float = Touch.screenX - p.x; - var dy:Float = Touch.screenY - p.y; + var dx:Float = Touch.viewX - p.x; + var dy:Float = Touch.viewY - p.y; p.put(); diff --git a/flixel/math/FlxMath.hx b/flixel/math/FlxMath.hx index d171d2190c..f4f7f1ef49 100644 --- a/flixel/math/FlxMath.hx +++ b/flixel/math/FlxMath.hx @@ -213,7 +213,7 @@ class FlxMath } else { - return pointInFlxRect(FlxG.mouse.screenX, FlxG.mouse.screenY, rect); + return pointInFlxRect(FlxG.mouse.viewX, FlxG.mouse.viewY, rect); } } #end @@ -398,8 +398,8 @@ class FlxMath */ public static inline function distanceToMouse(Sprite:FlxSprite):Int { - var dx:Float = (Sprite.x + Sprite.origin.x) - FlxG.mouse.screenX; - var dy:Float = (Sprite.y + Sprite.origin.y) - FlxG.mouse.screenY; + var dx:Float = (Sprite.x + Sprite.origin.x) - FlxG.mouse.viewX; + var dy:Float = (Sprite.y + Sprite.origin.y) - FlxG.mouse.viewY; return Std.int(FlxMath.vectorLength(dx, dy)); } @@ -414,8 +414,8 @@ class FlxMath */ public static inline function isDistanceToMouseWithin(Sprite:FlxSprite, Distance:Float, IncludeEqual:Bool = false):Bool { - var dx:Float = (Sprite.x + Sprite.origin.x) - FlxG.mouse.screenX; - var dy:Float = (Sprite.y + Sprite.origin.y) - FlxG.mouse.screenY; + var dx:Float = (Sprite.x + Sprite.origin.x) - FlxG.mouse.viewX; + var dy:Float = (Sprite.y + Sprite.origin.y) - FlxG.mouse.viewY; if (IncludeEqual) return dx * dx + dy * dy <= Distance * Distance; @@ -434,8 +434,8 @@ class FlxMath */ public static inline function distanceToTouch(Sprite:FlxSprite, Touch:FlxTouch):Int { - var dx:Float = (Sprite.x + Sprite.origin.x) - Touch.screenX; - var dy:Float = (Sprite.y + Sprite.origin.y) - Touch.screenY; + var dx:Float = (Sprite.x + Sprite.origin.x) - Touch.viewX; + var dy:Float = (Sprite.y + Sprite.origin.y) - Touch.viewY; return Std.int(FlxMath.vectorLength(dx, dy)); } @@ -450,8 +450,8 @@ class FlxMath */ public static inline function isDistanceToTouchWithin(Sprite:FlxSprite, Touch:FlxTouch, Distance:Float, IncludeEqual:Bool = false):Bool { - var dx:Float = (Sprite.x + Sprite.origin.x) - Touch.screenX; - var dy:Float = (Sprite.y + Sprite.origin.y) - Touch.screenY; + var dx:Float = (Sprite.x + Sprite.origin.x) - Touch.viewX; + var dy:Float = (Sprite.y + Sprite.origin.y) - Touch.viewY; if (IncludeEqual) return dx * dx + dy * dy <= Distance * Distance; diff --git a/flixel/system/debug/interaction/Interaction.hx b/flixel/system/debug/interaction/Interaction.hx index 87a7745a70..8c6b4c7d77 100644 --- a/flixel/system/debug/interaction/Interaction.hx +++ b/flixel/system/debug/interaction/Interaction.hx @@ -141,7 +141,7 @@ class Interaction extends Window #if FLX_MOUSE // Calculate in-game coordinates based on mouse position and camera. - _flixelPointer.setGlobalScreenPositionUnsafe(event.stageX, event.stageY); + _flixelPointer.setRawPositionUnsafe(Std.int(FlxG.game.mouseX), Std.int(FlxG.game.mouseY)); // Store Flixel mouse coordinates to speed up all // internal calculations (overlap, etc) diff --git a/flixel/ui/FlxButton.hx b/flixel/ui/FlxButton.hx index bbf991b869..6b9722ef50 100644 --- a/flixel/ui/FlxButton.hx +++ b/flixel/ui/FlxButton.hx @@ -472,7 +472,7 @@ class FlxTypedButton extends FlxSprite implements IFlxInput function checkInput(pointer:FlxPointer, input:IFlxInput, justPressedPosition:FlxPoint, camera:FlxCamera):Bool { if (maxInputMovement != Math.POSITIVE_INFINITY - && justPressedPosition.distanceTo(pointer.getScreenPosition(FlxPoint.weak())) > maxInputMovement + && justPressedPosition.distanceTo(pointer.getViewPosition(FlxPoint.weak())) > maxInputMovement && input == currentInput) { currentInput = null; diff --git a/tests/unit/src/flixel/input/FlxPointerTest.hx b/tests/unit/src/flixel/input/FlxPointerTest.hx new file mode 100644 index 0000000000..d6d04a4d32 --- /dev/null +++ b/tests/unit/src/flixel/input/FlxPointerTest.hx @@ -0,0 +1,72 @@ +package flixel.input; + +import flixel.math.FlxPoint; +import flixel.input.FlxPointer; +import massive.munit.Assert; + +class FlxPointerTest +{ + var pointer:FlxPointer; + + @Before + function before() + { + pointer = new FlxPointer(); + + FlxG.game.x = 0; + FlxG.game.y = 0; + FlxG.camera.zoom = 1; + FlxG.camera.scroll.set(0, 0); + FlxG.camera.setSize(640, 480); + FlxG.camera.setPosition(0, 0); + } + + @Test + function testZero() + { + final zero = FlxPoint.get(0, 0); + pointer.setRawPositionUnsafe(0, 0); + final p = FlxPoint.get(); + FlxAssert.pointsEqual(zero, pointer.getGamePosition(p)); + Assert.areEqual(0, pointer.gameX); + Assert.areEqual(0, pointer.gameY); + FlxAssert.pointsEqual(zero, pointer.getViewPosition(p)); + Assert.areEqual(0, pointer.viewX); + Assert.areEqual(0, pointer.viewY); + FlxAssert.pointsEqual(zero, pointer.getWorldPosition(p)); + Assert.areEqual(0, pointer.x); + Assert.areEqual(0, pointer.y); + } + + @Test + function testNonZero() + { + final result = FlxPoint.get(); + final expected = FlxPoint.get(); + inline function p(x, y) return expected.set(x, y); + + //Note: FlxG.scaleMode may be different on github actions compared to local + + FlxG.game.x -= 10; + FlxG.camera.zoom = 2.0; + FlxG.camera.scroll.set(-5, -15); + Assert.areEqual(1, FlxG.camera.initialZoom); + Assert.areEqual(640, FlxG.camera.width); + Assert.areEqual(480, FlxG.camera.height); + FlxG.camera.setSize(560, 480); + FlxG.camera.setPosition(20, 12); + Assert.areEqual(140, FlxG.camera.viewMarginX);// 560/4 + Assert.areEqual(120, FlxG.camera.viewMarginY);// 480/4 + + pointer.setRawPositionUnsafe(50 * FlxG.scaleMode.scale.x, 50 * FlxG.scaleMode.scale.y); + FlxAssert.pointsEqual(p( 50, 50), pointer.getGamePosition (result)); // (50, 50) + FlxAssert.pointsEqual(p(155, 139), pointer.getViewPosition (result)); // ((50, 50) - (20, 12)) / 2 + (140, 120) + FlxAssert.pointsEqual(p(150, 124), pointer.getWorldPosition (result)); // ((50, 50) - (20, 12)) / 2 + (140, 120) - (-5, -15) + Assert.areEqual( 50, pointer.gameX); + Assert.areEqual( 50, pointer.gameY); + Assert.areEqual(155, pointer.viewX); + Assert.areEqual(139, pointer.viewY); + Assert.areEqual(150, pointer.x); + Assert.areEqual(124, pointer.y); + } +} diff --git a/tests/unit/src/flixel/input/actions/FlxActionInputAnalogTest.hx b/tests/unit/src/flixel/input/actions/FlxActionInputAnalogTest.hx index 175a2b8adf..c8231677b3 100644 --- a/tests/unit/src/flixel/input/actions/FlxActionInputAnalogTest.hx +++ b/tests/unit/src/flixel/input/actions/FlxActionInputAnalogTest.hx @@ -505,7 +505,7 @@ class FlxActionInputAnalogTest extends FlxTest { if (FlxG.mouse == null) return; - FlxG.mouse.setGlobalScreenPositionUnsafe(0, 0); + FlxG.mouse.setRawPositionUnsafe(0, 0); var left = @:privateAccess FlxG.mouse._leftButton; var right = @:privateAccess FlxG.mouse._rightButton; @@ -582,7 +582,7 @@ class FlxActionInputAnalogTest extends FlxTest { if (FlxG.mouse == null) return; - FlxG.mouse.setGlobalScreenPositionUnsafe(0, 0); + FlxG.mouse.setRawPositionUnsafe(0, 0); step(); step(); } @@ -602,7 +602,7 @@ class FlxActionInputAnalogTest extends FlxTest if (FlxG.mouse == null) return; step(); - FlxG.mouse.setGlobalScreenPositionUnsafe(X, Y); + FlxG.mouse.setRawPositionUnsafe(X, Y); updateActions(arr); } @@ -629,7 +629,7 @@ class FlxActionInputAnalogTest extends FlxTest if (FlxG.mouse == null) return; step(); - FlxG.mouse.setGlobalScreenPositionUnsafe(X, Y); + FlxG.mouse.setRawPositionUnsafe(X, Y); updateActions(arr); } diff --git a/tests/unit/src/flixel/input/actions/FlxActionManagerTest.hx b/tests/unit/src/flixel/input/actions/FlxActionManagerTest.hx index e802b461a1..ef5f86012c 100644 --- a/tests/unit/src/flixel/input/actions/FlxActionManagerTest.hx +++ b/tests/unit/src/flixel/input/actions/FlxActionManagerTest.hx @@ -981,7 +981,7 @@ class FlxActionManagerTest extends FlxTest if (FlxG.mouse == null) return; step(); - FlxG.mouse.setGlobalScreenPositionUnsafe(X, Y); + FlxG.mouse.setRawPositionUnsafe(X, Y); @:privateAccess manager.update(); } diff --git a/tests/unit/src/flixel/input/actions/FlxActionSetTest.hx b/tests/unit/src/flixel/input/actions/FlxActionSetTest.hx index b08dcfb61a..2b06a71b52 100644 --- a/tests/unit/src/flixel/input/actions/FlxActionSetTest.hx +++ b/tests/unit/src/flixel/input/actions/FlxActionSetTest.hx @@ -315,7 +315,7 @@ class FlxActionSetTest extends FlxTest if (FlxG.mouse == null) return; step(); - FlxG.mouse.setGlobalScreenPositionUnsafe(X, Y); + FlxG.mouse.setRawPositionUnsafe(X, Y); set.update(); } diff --git a/tests/unit/src/flixel/input/actions/FlxActionTest.hx b/tests/unit/src/flixel/input/actions/FlxActionTest.hx index 808cfd893b..cfe8ab069d 100644 --- a/tests/unit/src/flixel/input/actions/FlxActionTest.hx +++ b/tests/unit/src/flixel/input/actions/FlxActionTest.hx @@ -225,18 +225,18 @@ class FlxActionTest extends FlxTest function clearAnalog() { step(); - FlxG.mouse.setGlobalScreenPositionUnsafe(0, 0); + FlxG.mouse.setRawPositionUnsafe(0, 0); step(); - FlxG.mouse.setGlobalScreenPositionUnsafe(0, 0); + FlxG.mouse.setRawPositionUnsafe(0, 0); } @:access(flixel.input.mouse.FlxMouse) function pulseAnalog(a:FlxActionAnalog, X:Float = 10.0, Y:Float = 10.0) { - FlxG.mouse.setGlobalScreenPositionUnsafe(0, 0); + FlxG.mouse.setRawPositionUnsafe(0, 0); step(); a.update(); - FlxG.mouse.setGlobalScreenPositionUnsafe(X, Y); + FlxG.mouse.setRawPositionUnsafe(X, Y); step(); a.update(); } @@ -244,7 +244,7 @@ class FlxActionTest extends FlxTest function moveAnalog(a:FlxActionAnalog, X:Float, Y:Float) { step(); - FlxG.mouse.setGlobalScreenPositionUnsafe(X, Y); + FlxG.mouse.setRawPositionUnsafe(X, Y); a.update(); } } diff --git a/tests/unit/src/flixel/input/mouse/FlxMouseEventManagerTest.hx b/tests/unit/src/flixel/input/mouse/FlxMouseEventManagerTest.hx index 3bed055488..31e7f12560 100644 --- a/tests/unit/src/flixel/input/mouse/FlxMouseEventManagerTest.hx +++ b/tests/unit/src/flixel/input/mouse/FlxMouseEventManagerTest.hx @@ -12,7 +12,7 @@ class FlxMouseEventManagerTest extends FlxTest function before() { FlxMouseEvent.removeAll(); - FlxG.mouse.setGlobalScreenPositionUnsafe(75, 75); // causes a mouse over callback for each test + FlxG.mouse.setRawPositionUnsafe(75, 75); // causes a mouse over callback for each test sprite0 = new FlxSprite(0, 0); sprite0.makeGraphic(100, 100, 0xffffffff, false); From 37cbe807c70d8278aa6ff815d1b34270457657c9 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Wed, 10 Jul 2024 17:15:15 -0400 Subject: [PATCH 17/99] Pointer (#3211) * overhaul pointer * fix debug selection on native fullscreen * fix backwards compat * fix CI on github actions * more CI fixes * D'oh * doc * more doc * more docs * fix warning * remove unneeded check --- flixel/ui/FlxAnalog.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flixel/ui/FlxAnalog.hx b/flixel/ui/FlxAnalog.hx index 5f88d6adcf..c2888b234a 100644 --- a/flixel/ui/FlxAnalog.hx +++ b/flixel/ui/FlxAnalog.hx @@ -220,7 +220,7 @@ class FlxAnalog extends FlxSpriteGroup var offAll:Bool = true; #if FLX_MOUSE - _point.set(FlxG.mouse.screenX, FlxG.mouse.screenY); + _point.set(FlxG.mouse.viewX, FlxG.mouse.viewY); if (!updateAnalog(_point, FlxG.mouse.pressed, FlxG.mouse.justPressed, FlxG.mouse.justReleased)) { @@ -301,7 +301,7 @@ class FlxAnalog extends FlxSpriteGroup // if the control is used in a group, for example. if (Touch != null) { - TouchPoint.set(Touch.screenX, Touch.screenY); + TouchPoint.set(Touch.viewX, Touch.viewY); } #end From 84a7ca5cbaa884a8bc073887ad836b263f42965a Mon Sep 17 00:00:00 2001 From: riconuts <68708956+riconuts@users.noreply.github.com> Date: Fri, 12 Jul 2024 13:14:03 -0400 Subject: [PATCH 18/99] Add version title underlines to the changelog (#3214) --- CHANGELOG.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52d0ed6969..5fd860069f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,5 @@ 5.9.0 (TBD) - +------------------------------ #### New features: - `FlxReplay`: Add `getDuration` ([#3135](https://github.com/HaxeFlixel/flixel/pull/3135)) - `InputFrontEnd`: ([#3134](https://github.com/HaxeFlixel/flixel/pull/3134)) @@ -49,7 +49,7 @@ - `FlxGraphic`: Prevent null ref in `getFramesCollections` with destroyed graphics ([#3180](https://github.com/HaxeFlixel/flixel/pull/3180)) 5.8.0 (April 19, 2024) - +------------------------------ #### New features: - `FlxBitmapText`: Add `getRenderedText` ([#3120](https://github.com/HaxeFlixel/flixel/pull/3120)) @@ -58,16 +58,18 @@ - `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: - `FlxBitmapFont`: Added `setCharFrame` ([#3037](https://github.com/HaxeFlixel/flixel/pull/3037)) - `FlxTimer`: Added static `wait` and `loops` methods ([#3040](https://github.com/HaxeFlixel/flixel/pull/3040)) @@ -106,16 +108,18 @@ - `FlxSound`: Fix sound panning ([#2863](https://github.com/HaxeFlixel/flixel/pull/2863)) 5.6.2 (February 10, 2024) +------------------------------ #### Changes and improvements: - `FlxBitmapFont`: Prevent crashes from missing xml fields in `fromAngelCode` ([#3029](https://github.com/HaxeFlixel/flixel/pull/3029)) 5.6.1 (February 9, 2024) +------------------------------ #### Changes and improvements: - `FlxBitmapFont`: Downgraded crashes of missing xml fields to warnings in `fromAngelCode` ([#3025](https://github.com/HaxeFlixel/flixel/pull/3025)) - Corrected documenation for the recent `FlxG.switchstate` arg changes 5.6.0 (February 2, 2024) - +------------------------------ #### New features: - `FlxGraphic`: Added `isDestroyed` ([#2974](https://github.com/HaxeFlixel/flixel/pull/2974)) - `FlxBitmapFont`: Support for all BMFont output file types ([#2949](https://github.com/HaxeFlixel/flixel/pull/2949)) @@ -155,7 +159,7 @@ - `QuadPath`: Prevent crash by avoiding divide by zero in `getCurveLength` ([#3019](https://github.com/HaxeFlixel/flixel/pull/3019)) 5.5.0 (November 8, 2023) - +------------------------------ #### New features: - `FlxG`: Added `animationTimeScale` ([#2937](https://github.com/HaxeFlixel/flixel/pull/2937)) @@ -170,7 +174,7 @@ 5.4.1 (October 4, 2023) - +------------------------------ #### Changes and improvements: - Various improvements and new features for animations ([#2930](https://github.com/HaxeFlixel/flixel/pull/2930)) - `FlxAnimation`: Make `frameDuration` and `looped` public From 424ad9844009ebfd4ada8c6a22b6c09114bece06 Mon Sep 17 00:00:00 2001 From: rich <87835336+richTrash21@users.noreply.github.com> Date: Fri, 12 Jul 2024 22:21:05 +0400 Subject: [PATCH 19/99] Make FlxAnimationController.callback an FlxTypedSignal (#3205) * deprecate callback and finishCallback by FlxTypedSignal counterparts * aw dang it * fix + doc * remove deprecation warnings * remove some more deprecation warnings * prevent CI errors on final * rename and restructure * add new tests * doc * imports * remove unneeded warning suppression * revert import, hopefully fix CI * retrigger CI (for testing) --------- Co-authored-by: George FunBook --- checkstyle.json | 3 +- flixel/animation/FlxAnimationController.hx | 60 +++++++++++++++---- .../animation/FlxAnimationControllerTest.hx | 41 ++++++++++++- 3 files changed, 88 insertions(+), 16 deletions(-) diff --git a/checkstyle.json b/checkstyle.json index b603612dab..60a10dcb3d 100644 --- a/checkstyle.json +++ b/checkstyle.json @@ -35,7 +35,8 @@ "STATIC", "MACRO", "INLINE", - "DYNAMIC" + "DYNAMIC", + "FINAL" ] } }, diff --git a/flixel/animation/FlxAnimationController.hx b/flixel/animation/FlxAnimationController.hx index 93e31cc191..4002a4db59 100644 --- a/flixel/animation/FlxAnimationController.hx +++ b/flixel/animation/FlxAnimationController.hx @@ -3,7 +3,8 @@ package flixel.animation; import flixel.FlxG; import flixel.FlxSprite; import flixel.graphics.frames.FlxFrame; -import flixel.util.FlxDestroyUtil.IFlxDestroyable; +import flixel.util.FlxDestroyUtil; +import flixel.util.FlxSignal; using StringTools; @@ -55,17 +56,41 @@ class FlxAnimationController implements IFlxDestroyable public var frames(get, never):Int; /** - * If assigned, will be called each time the current animation's frame changes. - * A function that has 3 parameters: a string name, a frame number, and a frame index. + * If assigned, will be called each time the current animation's frame changes + * + * @param animName The name of the current animation + * @param frameNumber The progress of the current animation, in frames + * @param frameIndex The current animation's frameIndex in the tile sheet */ - public var callback:(name:String, frameNumber:Int, frameIndex:Int) -> Void; - + @:deprecated('callback is deprecated, use onFrameChange.add') // 5.9.0 + public var callback:(animName:String, frameNumber:Int, frameIndex:Int)->Void; + /** * If assigned, will be called each time the current animation finishes. - * A function that has 1 parameter: a string name - animation name. + * + * @param animName The name of the current animation */ - public var finishCallback:(name:String) -> Void; - + @:deprecated('finishCallback is deprecated, use onFinish.add') // 5.9.0 + public var finishCallback:(animName:String) -> Void; + + /** + * Dispatches each time the current animation's frame changes + * + * @param animName The name of the current animation + * @param frameNumber The progress of the current animation, in frames + * @param frameIndex The current animation's frameIndex in the tile sheet + * @since 5.9.0 + */ + public final onFrameChange = new FlxTypedSignal<(animName:String, frameNumber:Int, frameIndex:Int)->Void>(); + + /** + * Dispatches each time the current animation finishes. + * + * @param animName The name of the current animation + * @since 5.9.0 + */ + public final onFinish = new FlxTypedSignal<(animName:String)->Void>(); + /** * How fast or slow time should pass for this animation controller */ @@ -144,11 +169,16 @@ class FlxAnimationController implements IFlxDestroyable clearPrerotated(); } + @:haxe.warning("-WDeprecated") public function destroy():Void { + FlxDestroyUtil.destroy(onFrameChange); + FlxDestroyUtil.destroy(onFinish); + destroyAnimations(); _animations = null; callback = null; + finishCallback = null; _sprite = null; } @@ -668,23 +698,29 @@ class FlxAnimationController implements IFlxDestroyable frameIndex = FlxG.random.int(0, numFrames - 1); } - inline function fireCallback():Void + @:haxe.warning("-WDeprecated") + function fireCallback():Void { + final name = (_curAnim != null) ? (_curAnim.name) : null; + final number = (_curAnim != null) ? (_curAnim.curFrame) : frameIndex; if (callback != null) { - var name:String = (_curAnim != null) ? (_curAnim.name) : null; - var number:Int = (_curAnim != null) ? (_curAnim.curFrame) : frameIndex; callback(name, number, frameIndex); } + + onFrameChange.dispatch(name, number, frameIndex); } @:allow(flixel.animation) - inline function fireFinishCallback(?name:String):Void + @:haxe.warning("-WDeprecated") + function fireFinishCallback(?name:String):Void { if (finishCallback != null) { finishCallback(name); } + + onFinish.dispatch(name); } function byNamesHelper(addTo:Array, frameNames:Array):Void diff --git a/tests/unit/src/flixel/animation/FlxAnimationControllerTest.hx b/tests/unit/src/flixel/animation/FlxAnimationControllerTest.hx index e3682dbec8..52e498482d 100644 --- a/tests/unit/src/flixel/animation/FlxAnimationControllerTest.hx +++ b/tests/unit/src/flixel/animation/FlxAnimationControllerTest.hx @@ -33,6 +33,7 @@ class FlxAnimationControllerTest extends FlxTest } @Test + @:haxe.warning("-WDeprecated") function testCallbackAfterFirstLoadGraphic():Void { var timesCalled:Int = 0; @@ -48,12 +49,31 @@ class FlxAnimationControllerTest extends FlxTest Assert.areEqual(1, timesCalled); Assert.areEqual(0, callbackFrameIndex); } + + @Test + function testOnFrameChangeAfterFirstLoadGraphic():Void + { + var timesCalled:Int = 0; + var callbackFrameIndex:Int = -1; + sprite.animation.onFrameChange.add(function(s:String, n:Int, i:Int) + { + timesCalled++; + callbackFrameIndex = i; + }); + + loadSpriteSheet(); + + Assert.areEqual(1, timesCalled); + Assert.areEqual(0, callbackFrameIndex); + } @Test - function testCallbackNoFrameIndexChange():Void + @:haxe.warning("-WDeprecated") + function testOnFrameChangeNoFrameIndexChange():Void { var timesCalled:Int = 0; - sprite.animation.callback = function(_, _, _) timesCalled++; + sprite.animation.callback = function(_, _, _) timesCalled++;// remove later + sprite.animation.onFrameChange.add(function(_, _, _) timesCalled++); sprite.animation.frameIndex = 0; sprite.animation.frameIndex = 0; @@ -75,15 +95,30 @@ class FlxAnimationControllerTest extends FlxTest } @Test // #1781 + @:haxe.warning("-WDeprecated") function testFinishCallbackOnce():Void { loadSpriteSheet(); sprite.animation.add("animation", [0, 1, 2], 3000, false); - + var timesCalled = 0; sprite.animation.finishCallback = function(_) timesCalled++; sprite.animation.play("animation"); + + step(); + Assert.areEqual(1, timesCalled); + } + @Test // #1781 + function testOnFinishOnce():Void + { + loadSpriteSheet(); + sprite.animation.add("animation", [0, 1, 2], 3000, false); + + var timesCalled = 0; + sprite.animation.onFinish.add((_)->timesCalled++); + sprite.animation.play("animation"); + step(); Assert.areEqual(1, timesCalled); } From 34f0d5e6d5fce5a07fbd224ff40a1a8c6d687bd5 Mon Sep 17 00:00:00 2001 From: Davide <7047501+davidetan@users.noreply.github.com> Date: Fri, 12 Jul 2024 21:02:54 +0200 Subject: [PATCH 20/99] Add blend mode support for FlxStrip (fix blend mode in drawTriangles as in #2199) (#3213) --- flixel/FlxCamera.hx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/flixel/FlxCamera.hx b/flixel/FlxCamera.hx index 9e7156cff8..b4b1ad4cdb 100644 --- a/flixel/FlxCamera.hx +++ b/flixel/FlxCamera.hx @@ -674,6 +674,7 @@ class FlxCamera extends FlxBasic && _headTriangles.antialiasing == smoothing && _headTriangles.colored == isColored && _headTriangles.blending == blendInt + && _headTriangles.blend == blend #if !flash && _headTriangles.hasColorOffsets == hasColorOffsets && _headTriangles.shader == shader @@ -708,6 +709,7 @@ class FlxCamera extends FlxBasic itemToReturn.antialiasing = smoothing; itemToReturn.colored = isColored; itemToReturn.blending = blendInt; + itemToReturn.blend = blend; #if !flash itemToReturn.hasColorOffsets = hasColorOffsets; itemToReturn.shader = shader; From c762d99be09d2dab252d021edd8b8c8a07515f69 Mon Sep 17 00:00:00 2001 From: rich <87835336+richTrash21@users.noreply.github.com> Date: Sat, 13 Jul 2024 22:28:12 +0400 Subject: [PATCH 21/99] Add onLoop to FlxAnimationController (#3216) * add onLoopComplete callback signal * small simplification * Revert "small simplification" This reverts commit 4ffbf0bd8db3a470b2edeb89425c00b3bf6d6874. * rename * add unit tests * style --------- Co-authored-by: George FunBook --- flixel/animation/FlxAnimation.hx | 10 +++ flixel/animation/FlxAnimationController.hx | 15 ++++ .../animation/FlxAnimationControllerTest.hx | 90 ++++++++++++++++++- 3 files changed, 111 insertions(+), 4 deletions(-) diff --git a/flixel/animation/FlxAnimation.hx b/flixel/animation/FlxAnimation.hx index 800806a67b..1bb90a335f 100644 --- a/flixel/animation/FlxAnimation.hx +++ b/flixel/animation/FlxAnimation.hx @@ -214,16 +214,26 @@ class FlxAnimation extends FlxBaseAnimation if (reversed) { if (looped && curFrame == loopPoint) + { curFrame = numFrames - 1; + parent.fireLoopCallback(name); + } else + { curFrame--; + } } else { if (looped && curFrame == numFrames - 1) + { curFrame = loopPoint; + parent.fireLoopCallback(name); + } else + { curFrame++; + } } // prevents null ref when the sprite is destroyed on finishCallback (#2782) diff --git a/flixel/animation/FlxAnimationController.hx b/flixel/animation/FlxAnimationController.hx index 4002a4db59..ff8d5da26a 100644 --- a/flixel/animation/FlxAnimationController.hx +++ b/flixel/animation/FlxAnimationController.hx @@ -91,6 +91,14 @@ class FlxAnimationController implements IFlxDestroyable */ public final onFinish = new FlxTypedSignal<(animName:String)->Void>(); + /** + * Dispatches each time the current animation's loop is complete. + * Works only with looped animations. + * + * @param animName The name of the current animation + */ + public final onLoop = new FlxTypedSignal<(animName:String)->Void>(); + /** * How fast or slow time should pass for this animation controller */ @@ -174,6 +182,7 @@ class FlxAnimationController implements IFlxDestroyable { FlxDestroyUtil.destroy(onFrameChange); FlxDestroyUtil.destroy(onFinish); + FlxDestroyUtil.destroy(onLoop); destroyAnimations(); _animations = null; @@ -723,6 +732,12 @@ class FlxAnimationController implements IFlxDestroyable onFinish.dispatch(name); } + @:allow(flixel.animation) + function fireLoopCallback(?name:String):Void + { + onLoop.dispatch(name); + } + function byNamesHelper(addTo:Array, frameNames:Array):Void { for (frameName in frameNames) diff --git a/tests/unit/src/flixel/animation/FlxAnimationControllerTest.hx b/tests/unit/src/flixel/animation/FlxAnimationControllerTest.hx index 52e498482d..8e8f119111 100644 --- a/tests/unit/src/flixel/animation/FlxAnimationControllerTest.hx +++ b/tests/unit/src/flixel/animation/FlxAnimationControllerTest.hx @@ -99,7 +99,7 @@ class FlxAnimationControllerTest extends FlxTest function testFinishCallbackOnce():Void { loadSpriteSheet(); - sprite.animation.add("animation", [0, 1, 2], 3000, false); + sprite.animation.add("animation", [0, 1, 0], 3000, false); var timesCalled = 0; sprite.animation.finishCallback = function(_) timesCalled++; @@ -108,12 +108,12 @@ class FlxAnimationControllerTest extends FlxTest step(); Assert.areEqual(1, timesCalled); } - + @Test // #1781 function testOnFinishOnce():Void { loadSpriteSheet(); - sprite.animation.add("animation", [0, 1, 2], 3000, false); + sprite.animation.add("animation", [0, 1, 0], 3000, false); var timesCalled = 0; sprite.animation.onFinish.add((_)->timesCalled++); @@ -122,7 +122,89 @@ class FlxAnimationControllerTest extends FlxTest step(); Assert.areEqual(1, timesCalled); } - + + @Test // #1781 + function testOnFinishNever():Void + { + loadSpriteSheet(); + sprite.animation.add("animation", [0], 3000, true); + + var timesCalled = 0; + sprite.animation.onFinish.add((_)->timesCalled++); + sprite.animation.play("animation"); + + step(); + Assert.areEqual(0, timesCalled); + } + + @Test + /** Make sure onLoop is called when fps is high enough to loop in one frame */ + function testOnLoopOneFrame():Void + { + loadSpriteSheet(); + sprite.animation.add("animation", [0, 1, 0], 3 * 20 * FlxG.updateFramerate, true); + + var timesCalled = 0; + sprite.animation.onLoop.add((_)->timesCalled++); + sprite.animation.play("animation"); + + step(); + Assert.areEqual(20, timesCalled); + } + + @Test + /** Make sure onLoop is NOT called when anim is not set to loop */ + function testOnLoop():Void + { + loadSpriteSheet(); + sprite.animation.add("animation", [0, 1], 2 * 20 * FlxG.updateFramerate, true); + + var timesCalled = 0; + sprite.animation.onLoop.add(function (_) + { + timesCalled++; + Assert.areEqual(0, sprite.animation.curAnim.curFrame); + }); + sprite.animation.play("animation"); + + step(); + Assert.areEqual(20, timesCalled); + } + + @Test + /** Make sure onLoop is NOT called when anim is not set to loop */ + function testOnLoopReverse():Void + { + loadSpriteSheet(); + sprite.animation.add("animation", [0, 1], 2 * 20 * FlxG.updateFramerate, true); + + var timesCalled = 0; + sprite.animation.onLoop.add(function (_) + { + timesCalled++; + Assert.areEqual(1, sprite.animation.curAnim.curFrame); + }); + sprite.animation.play("animation", false, true); + + step(); + Assert.areEqual(20, timesCalled); + } + + @Test + /** Make sure onLoop is NOT called when anim is not set to loop */ + function testOnLoopNever():Void + { + loadSpriteSheet(); + sprite.animation.add("animation", [0], 3000, false); + + var timesCalled = 0; + sprite.animation.onLoop.add((_)->timesCalled++); + sprite.animation.play("animation"); + + step(); + Assert.areEqual(0, timesCalled); + } + @Test // #1786 function testNullFrameName():Void { From 8b8d40cd212c69875bf27539b02e1792c80533df Mon Sep 17 00:00:00 2001 From: rich <87835336+richTrash21@users.noreply.github.com> Date: Sun, 14 Jul 2024 04:52:59 +0400 Subject: [PATCH 22/99] missing doc (#3218) --- flixel/animation/FlxAnimationController.hx | 1 + 1 file changed, 1 insertion(+) diff --git a/flixel/animation/FlxAnimationController.hx b/flixel/animation/FlxAnimationController.hx index ff8d5da26a..e9b8c440b5 100644 --- a/flixel/animation/FlxAnimationController.hx +++ b/flixel/animation/FlxAnimationController.hx @@ -96,6 +96,7 @@ class FlxAnimationController implements IFlxDestroyable * Works only with looped animations. * * @param animName The name of the current animation + * @since 5.9.0 */ public final onLoop = new FlxTypedSignal<(animName:String)->Void>(); From ac488bf401880dbd5248b04f51a9c3492c8a39b8 Mon Sep 17 00:00:00 2001 From: rich <87835336+richTrash21@users.noreply.github.com> Date: Mon, 15 Jul 2024 19:18:45 +0400 Subject: [PATCH 23/99] Fix FlxCamera.fill() blending (#3217) * remove blend mode from FlxCamera.fill() * more readable FlxCamera.drawFX() * revert alpha overrides * more cleanup --------- Co-authored-by: George FunBook --- flixel/FlxCamera.hx | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/flixel/FlxCamera.hx b/flixel/FlxCamera.hx index b4b1ad4cdb..be352e355d 100644 --- a/flixel/FlxCamera.hx +++ b/flixel/FlxCamera.hx @@ -1705,8 +1705,11 @@ class FlxCamera extends FlxBasic if (FxAlpha == 0) return; - var targetGraphics:Graphics = (graphics == null) ? canvas.graphics : graphics; + final targetGraphics = (graphics == null) ? canvas.graphics : graphics; + #if (openfl > "8.7.0") + targetGraphics.overrideBlendMode(null); + #end targetGraphics.beginFill(Color, FxAlpha); // i'm drawing rect with these parameters to avoid light lines at the top and left of the camera, // which could appear while cameras fading @@ -1721,35 +1724,35 @@ class FlxCamera extends FlxBasic @:allow(flixel.system.frontEnds.CameraFrontEnd) function drawFX():Void { - var alphaComponent:Float; - // Draw the "flash" special effect onto the buffer if (_fxFlashAlpha > 0.0) { - alphaComponent = _fxFlashColor.alpha; - if (FlxG.renderBlit) { - fill((Std.int(((alphaComponent <= 0) ? 0xff : alphaComponent) * _fxFlashAlpha) << 24) + (_fxFlashColor & 0x00ffffff)); + var color = _fxFlashColor; + color.alphaFloat *= _fxFlashAlpha; + fill(color); } else { - fill((_fxFlashColor & 0x00ffffff), true, ((alphaComponent <= 0) ? 0xff : alphaComponent) * _fxFlashAlpha / 255, canvas.graphics); + final alpha = color.alphaFloat * _fxFlashAlpha; + fill(_fxFlashColor.rgb, true, alpha, canvas.graphics); } } - + // Draw the "fade" special effect onto the buffer if (_fxFadeAlpha > 0.0) { - alphaComponent = _fxFadeColor.alpha; - if (FlxG.renderBlit) { - fill((Std.int(((alphaComponent <= 0) ? 0xff : alphaComponent) * _fxFadeAlpha) << 24) + (_fxFadeColor & 0x00ffffff)); + var color = _fxFadeColor; + color.alphaFloat *= _fxFadeAlpha; + fill(color); } else { - fill((_fxFadeColor & 0x00ffffff), true, ((alphaComponent <= 0) ? 0xff : alphaComponent) * _fxFadeAlpha / 255, canvas.graphics); + final alpha = _fxFadeColor.alphaFloat * _fxFadeAlpha; + fill(_fxFadeColor.rgb, true, alpha, canvas.graphics); } } } From 84062744eb2f8ad18699a7a3d154ffdf2abf399a Mon Sep 17 00:00:00 2001 From: Vortex <73261680+Vortex2Oblivion@users.noreply.github.com> Date: Sun, 21 Jul 2024 19:41:17 -0400 Subject: [PATCH 24/99] Update FlxSprite.hx (#3221) --- flixel/FlxSprite.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flixel/FlxSprite.hx b/flixel/FlxSprite.hx index ea5c2b7e50..8fc653620a 100644 --- a/flixel/FlxSprite.hx +++ b/flixel/FlxSprite.hx @@ -446,7 +446,7 @@ class FlxSprite extends FlxObject /** * Load graphic from another `FlxSprite` and copy its tile sheet data. - * This method can useful for non-flash targets. + * This method can be useful for non-flash targets. * * @param Sprite The `FlxSprite` from which you want to load graphic data. * @return This `FlxSprite` instance (nice for chaining stuff together, if you're into that). From 64967e3d8f04e58ea96590206556b54e7cd7caf6 Mon Sep 17 00:00:00 2001 From: DetectiveBaldi <86160807+DetectiveBaldi@users.noreply.github.com> Date: Tue, 6 Aug 2024 11:35:02 -0400 Subject: [PATCH 25/99] Little changes to `FlxDebugger` code completion. (#3222) * Update CompletionList.hx * Update CompletionHandler.hx --- flixel/system/debug/completion/CompletionHandler.hx | 2 +- flixel/system/debug/completion/CompletionList.hx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/flixel/system/debug/completion/CompletionHandler.hx b/flixel/system/debug/completion/CompletionHandler.hx index 4bc052b37d..56b2369836 100644 --- a/flixel/system/debug/completion/CompletionHandler.hx +++ b/flixel/system/debug/completion/CompletionHandler.hx @@ -48,7 +48,7 @@ class CompletionHandler var text = getTextUntilCaret(); // close completion so that enter works - if (text.endsWith(")") || text.endsWith("\"") || text.endsWith("'")) + if (text.endsWith(")") || text.endsWith("\"") || text.endsWith("'") || text.endsWith(";")) { completionList.close(); return; diff --git a/flixel/system/debug/completion/CompletionList.hx b/flixel/system/debug/completion/CompletionList.hx index 7d8547bd19..6afa57c2ac 100644 --- a/flixel/system/debug/completion/CompletionList.hx +++ b/flixel/system/debug/completion/CompletionList.hx @@ -95,7 +95,7 @@ class CompletionList extends Sprite case Keyboard.UP: updateIndices(-1); - case Keyboard.ENTER: + case Keyboard.ENTER | Keyboard.TAB: if (completed != null) completed(items[selectedIndex]); close(); From 94dbde53ba0f6a7f3f86a4d53873197a94fdecd8 Mon Sep 17 00:00:00 2001 From: Flainn Date: Tue, 6 Aug 2024 11:37:22 -0400 Subject: [PATCH 26/99] Improved FlxInputText (#3219) * Initial text input implementation * Fix code climate? * Add missing FLX_MOUSE check * Add multiline variable - Regenerate text graphic when `passwordMode` changes * Place caret at closest character to mouse * Selection boxes + selected text color - Add `setSelection()` function - `FlxInputText` variables are now destroyed properly * Implement text selection with mouse & text scrolling - Added `scrollH`, `scrollV`, `bottomScrollV`, `maxScrollH` & `maxScrollV` variables - Return end of text if character isn't found at position * Fix selection not working correctly when mouse is out of bounds - Selection boxes are now clipped inside the text bounds - Simplified getting the Y offset of a line * Mouse wheel scrolling - Fix scrollV not being able to be modified directly * Implemented double press and dragging - Selection sprites now just change their color instead of making new graphics - scrollH can now be modified properly as well - Word wrap no longer changes with multiline (multiline only affects adding new lines) * Action callbacks * Fix "final" keyword screwing up code climate * Various fixes & improvements - Caret is now positioned properly with different alignments - Caret is now clipped inside the text bounds - Caret is now automatically resized when changing `bold`, `font`, `italic`, `size` or `systemFont` variables - Fixed crash when pressing down a key while there isn't a focused input text - Fixed selected text format overwriting the border color - Fixed caret not being visible when text is empty - Fixed selection boxes sometimes not being updated immediately - Added `useSelectedTextFormat` variable - Double press check is now when the mouse is released (same as OpenFL) * Add `forceCase` and filterMode` - Moved action callback types to an enum abstract * Added background for text input - Added `focusGained` and `focusLost` callbacks - Fixed selection boxes not being clipped properly when they're compeletely out of bounds * Some improvements - Added bounds check while changing `caretIndex`, `caretWidth`, `fieldBorderThickness` and `maxLength` - FlxInputText is now single-line by default - Fixed text scroll being reset while moving selection with mouse - Caret index now starts at the end of the text if focus is enabled through code - Background now gets regenerated in `regenGraphic` instead of instantly after changing a related variable * Added `editable` and selectable` variables - Added change and scroll action callbacks - Made `replaceSelectedText()` public * Flixel hotkeys (volume & debugger) are now disabled while inputting text - Fixed space not being inputted on HTML5 * Caret flashing timer - Fixed text going out of bounds when enabling multiline without a field height set - Last click time for double click now resets if the mouse clicked on something else * Optimized selection box sprites (only visible lines are accounted for now) - Fixed untypeable characters being added to text input on Flash * Various fixes for Flash - Fixed text selection and caret positioning on Flash - Copy, cut, paste and select all commands now work on Flash - Fixed horizontal scroll not being set automatically on Flash - Moved to using Flash's `TextEvent.TEXT_INPUT` event (does not dispatch with invalid characters) * Fixed text selection and scrolling on other platforms * Fixed text selection with word wrapping enabled * Added touch support - Now uses `window.setTextInputRect()` to prevent keyboard overlay from blocking the text field - Fixed pointer position being inaccurate with camera scrolling - Fixed `getCharBoundaries()` not giving the correct Y position * Added documentation - Fixed not being able to add text if the field starts out empty - Fixed the caret being the wrong size if the text field is empty - Fixed the background not being resized when auto size is enabled - Changing `customFilterPattern` now automatically sets `filterMode` to `CUSTOM_FILTER` - Renamed `_lastClickTime` to `_lastPressTime` * Add documentation to `multiline` variable - Remove setting `_autoHeight` to false after setting multiline to true as its no longer needed * Add `mouseWheelEnabled` variable - Remove unneeded `selectable` comment * Replaced `PREVIOUS_LINE` and `NEXT_LINE` with `WORD_LEFT` and `WORD_RIGHT` - Ctrl + Up/Down now dispatches `LINE_LEFT` or `LINE_RIGHT` instead of `HOME` or `END` - Renamed `LINE_BEGINNING` and `LINE_END` to `LINE_LEFT` and `LINE_RIGHT` * Various fixes - Clip rect should now work properly - Fixed caret showing up after changing `text` through code - Focus will not be removed due to clicking outside of the text field if it has been granted via code in the same frame - Caret will no longer be visible if the text field isn't editable - Fixed some html5 tests not compiling on CI * Various more fixes - Fixed crash from recursive calls to `regenBackground()` due to `clipSprite()` - Fixed crash from `pointer.getWorldPosition()` - Fixed background not being updated after changing text format - Moved caret sprite regeneration to `regenGraphic()` * Move input text "frontend" to a manager plugin * Fixed missing rename * Replace `callback` with `onTextChange` and `onScrollChange` signals - Replace `focusGained` and `focusLost` with `onFocusChange` signal - Renamed filter mode options and added `CHARS` option - Removed `customFilterPattern` as its now defined in the enum itself * Move `ENTER_ACTION` over to `onEnter` * Implement `destroy()` for FlxInputTextManager - Add `unregisterAll()` to FlxInputTextManager * add onTypingAction * allow custom manager * add setManager * remove focus setter for setFocus * better destroy/init * use case ifs * improve mac key behavior * fix selection start/end issue * remove set_hasFocus for startFocus and endFocus * use final signals * let openfl handle maxChars * inline setters remove redundancies * simplify caret blink --------- Co-authored-by: George FunBook --- flixel/FlxG.hx | 10 +- flixel/input/keyboard/FlxKeyboard.hx | 10 +- flixel/system/frontEnds/PluginFrontEnd.hx | 3 + flixel/system/frontEnds/SoundFrontEnd.hx | 18 +- flixel/text/FlxInputText.hx | 2218 +++++++++++++++++++++ flixel/text/FlxInputTextManager.hx | 424 ++++ 6 files changed, 2668 insertions(+), 15 deletions(-) create mode 100644 flixel/text/FlxInputText.hx create mode 100644 flixel/text/FlxInputTextManager.hx diff --git a/flixel/FlxG.hx b/flixel/FlxG.hx index e855617a4c..a7dd006d2a 100644 --- a/flixel/FlxG.hx +++ b/flixel/FlxG.hx @@ -1,10 +1,5 @@ package flixel; -import openfl.Lib; -import openfl.display.DisplayObject; -import openfl.display.Stage; -import openfl.display.StageDisplayState; -import openfl.net.URLRequest; import flixel.effects.postprocess.PostProcess; import flixel.math.FlxMath; import flixel.math.FlxRandom; @@ -28,6 +23,11 @@ import flixel.system.scaleModes.RatioScaleMode; import flixel.util.FlxCollision; import flixel.util.FlxSave; import flixel.util.typeLimit.NextState; +import openfl.Lib; +import openfl.display.DisplayObject; +import openfl.display.Stage; +import openfl.display.StageDisplayState; +import openfl.net.URLRequest; #if FLX_TOUCH import flixel.input.touch.FlxTouchManager; #end diff --git a/flixel/input/keyboard/FlxKeyboard.hx b/flixel/input/keyboard/FlxKeyboard.hx index a21a40fe73..14f8684765 100644 --- a/flixel/input/keyboard/FlxKeyboard.hx +++ b/flixel/input/keyboard/FlxKeyboard.hx @@ -1,10 +1,11 @@ package flixel.input.keyboard; #if FLX_KEYBOARD -import openfl.events.KeyboardEvent; import flixel.FlxG; import flixel.input.FlxInput; import flixel.system.replay.CodeValuePair; +import flixel.text.FlxInputText; +import openfl.events.KeyboardEvent; /** * Keeps track of what keys are pressed and how with handy Bools or strings. @@ -101,7 +102,7 @@ class FlxKeyboard extends FlxKeyManager // Debugger toggle #if FLX_DEBUG - if (FlxG.game.debugger != null && inKeyArray(FlxG.debugger.toggleKeys, event)) + if (FlxG.game.debugger != null && inKeyArray(FlxG.debugger.toggleKeys, event) && !FlxInputText.globalManager.isTyping) { FlxG.debugger.visible = !FlxG.debugger.visible; } @@ -114,7 +115,10 @@ class FlxKeyboard extends FlxKeyManager // Attempted to cancel the replay? #if FLX_RECORD - if (FlxG.game.replaying && !inKeyArray(FlxG.debugger.toggleKeys, event) && inKeyArray(FlxG.vcr.cancelKeys, event)) + if (FlxG.game.replaying + && !inKeyArray(FlxG.debugger.toggleKeys, event) + && inKeyArray(FlxG.vcr.cancelKeys, event) + && !FlxInputText.globalManager.isTyping) { FlxG.vcr.cancelReplay(); } diff --git a/flixel/system/frontEnds/PluginFrontEnd.hx b/flixel/system/frontEnds/PluginFrontEnd.hx index 5195b50478..e34aefef17 100644 --- a/flixel/system/frontEnds/PluginFrontEnd.hx +++ b/flixel/system/frontEnds/PluginFrontEnd.hx @@ -2,6 +2,8 @@ package flixel.system.frontEnds; import flixel.input.mouse.FlxMouseEvent; import flixel.input.mouse.FlxMouseEventManager; +import flixel.text.FlxInputText; +import flixel.text.FlxInputTextManager; import flixel.tweens.FlxTween; import flixel.util.FlxStringUtil; import flixel.util.FlxTimer; @@ -138,6 +140,7 @@ class PluginFrontEnd addPlugin(FlxTimer.globalManager = new FlxTimerManager()); addPlugin(FlxTween.globalManager = new FlxTweenManager()); addPlugin(FlxMouseEvent.globalManager = new FlxMouseEventManager()); + addPlugin(FlxInputText.globalManager = new FlxInputTextManager()); } /** diff --git a/flixel/system/frontEnds/SoundFrontEnd.hx b/flixel/system/frontEnds/SoundFrontEnd.hx index 0a5e6bb07f..9784d759bb 100644 --- a/flixel/system/frontEnds/SoundFrontEnd.hx +++ b/flixel/system/frontEnds/SoundFrontEnd.hx @@ -5,10 +5,11 @@ import flixel.FlxG; import flixel.group.FlxGroup; import flixel.input.keyboard.FlxKey; import flixel.math.FlxMath; -import flixel.system.FlxAssets; import flixel.sound.FlxSound; import flixel.sound.FlxSoundGroup; +import flixel.system.FlxAssets; import flixel.system.ui.FlxSoundTray; +import flixel.text.FlxInputText; import flixel.util.FlxSignal; import openfl.Assets; import openfl.media.Sound; @@ -394,12 +395,15 @@ class SoundFrontEnd list.update(elapsed); #if FLX_KEYBOARD - if (FlxG.keys.anyJustReleased(muteKeys)) - toggleMuted(); - else if (FlxG.keys.anyJustReleased(volumeUpKeys)) - changeVolume(0.1); - else if (FlxG.keys.anyJustReleased(volumeDownKeys)) - changeVolume(-0.1); + if (!FlxInputText.globalManager.isTyping) + { + if (FlxG.keys.anyJustReleased(muteKeys)) + toggleMuted(); + else if (FlxG.keys.anyJustReleased(volumeUpKeys)) + changeVolume(0.1); + else if (FlxG.keys.anyJustReleased(volumeDownKeys)) + changeVolume(-0.1); + } #end } diff --git a/flixel/text/FlxInputText.hx b/flixel/text/FlxInputText.hx new file mode 100644 index 0000000000..86180d4dd7 --- /dev/null +++ b/flixel/text/FlxInputText.hx @@ -0,0 +1,2218 @@ +package flixel.text; + +import flixel.input.FlxPointer; +import flixel.input.touch.FlxTouch; +import flixel.math.FlxMath; +import flixel.math.FlxPoint; +import flixel.math.FlxRect; +import flixel.text.FlxInputTextManager; +import flixel.util.FlxColor; +import flixel.util.FlxDestroyUtil; +import flixel.util.FlxSignal; +import flixel.util.FlxSpriteUtil; +import flixel.util.FlxTimer; +import lime.system.Clipboard; +import openfl.display.BitmapData; +import openfl.geom.Rectangle; +import openfl.text.TextFormat; +import openfl.utils.QName; + +using StringTools; + +/** + * An `FlxText` object that can be selected and edited by the user. + */ +class FlxInputText extends FlxText implements IFlxInputText +{ + /** + * The global manager that handles input text objects. + */ + public static var globalManager:FlxInputTextManager; + + /** + * The gaps at the sides of the text field (2px). + */ + static inline var GUTTER:Int = 2; + + /** + * Characters that break up the words to select. + */ + static final DELIMITERS:Array = ['\n', '.', '!', '?', ',', ' ', ';', ':', '(', ')', '-', '_', '/']; + + /** + * Whether or not the text field has a background. + */ + public var background(default, set):Bool = false; + + /** + * The color of the background of the text field, if it's enabled. + */ + public var backgroundColor(default, set):FlxColor = FlxColor.WHITE; + + /** + * Indicates the bottommost line (1-based index) that is currently + * visible in the text field. + */ + public var bottomScrollV(get, never):Int; + + /** + * The selection cursor's color. Has the same color as the text field by default, and + * it's automatically set whenever it changes. + */ + public var caretColor(default, set):FlxColor; + + /** + * The position of the selection cursor. An index of 0 means the caret is before the + * character at position 0. + * + * Modifying this will reset the current selection (no text will be selected). + */ + public var caretIndex(get, set):Int; + + /** + * The selection cursor's width. + */ + public var caretWidth(default, set):Int = 1; + + /** + * Whether or not the text field can be edited by the user. + */ + public var editable:Bool = true; + + /** + * The color of the border for the text field, if it has a background. + */ + public var fieldBorderColor(default, set):FlxColor = FlxColor.BLACK; + + /** + * The thickness of the border for the text field, if it has a background. + * + * Setting this to 0 will remove the border entirely. + */ + public var fieldBorderThickness(default, set):Int = 1; + + /** + * Defines how to filter the text (remove unwanted characters). + */ + public var filterMode(default, set):FlxInputTextFilterMode = NONE; + + /** + * Defines whether a letter case is enforced on the text. + */ + public var forceCase(default, set):FlxInputTextCase = ALL_CASES; + + /** + * Whether or not the text field is the current active one on the screen. + */ + public var hasFocus(default, null):Bool = false; + + /** + * Set the maximum length for the text field. 0 means unlimited. + */ + public var maxChars(get, set):Int; + + /** + * The maximum value of `scrollH`. + */ + public var maxScrollH(get, never):Int; + + /** + * The maximum value of `scrollV`. + */ + public var maxScrollV(get, never):Int; + + /** + * Whether or not the text field will automatically be scrolled + * when the user rolls the mouse wheel on the text field. + */ + public var mouseWheelEnabled:Bool = true; + + /** + * Whether or not the user can create a new line in the text field + * with the enter key. + */ + public var multiline(get, set):Bool; + + /** + * Whether or not the text field is a password text field. This will + * hide all characters behind asterisks (*), and prevent any text + * from being copied. + */ + public var passwordMode(get, set):Bool; + + /** + * Gets dispatched whenever the enter key is pressed on the text field + * + * @param text The current text + */ + public final onEnter = new FlxTypedSignal<(text:String)->Void>(); + + /** + * Gets dispatched whenever this text field gains/loses focus + * + * @param focused Whether the text is focused + */ + public final onFocusChange = new FlxTypedSignal<(focused:Bool)->Void>(); + + /** + * Gets dispatched whenever the horizontal and/or vertical scroll is changed + * + * @param scrollH The current horizontal scroll + * @param scrollV The current vertical scroll + */ + public final onScrollChange = new FlxTypedSignal<(scrollH:Int, scrollV:Int)->Void>(); + + /** + * Gets dispatched whenever the text is changed by the user + * + * @param text The current text + * @param text What type of change occurred + */ + public final onTextChange = new FlxTypedSignal<(text:String, change:FlxInputTextChange)->Void>(); + + /** + * The current horizontal scrolling position, in pixels. Defaults to + * 0, which means the text is not horizontally scrolled. + */ + public var scrollH(get, set):Int; + + /** + * The current vertical scrolling position, by line number. If the first + * line displayed is the first line in the text field, `scrollV` + * is set to 1 (not 0). + */ + public var scrollV(get, set):Int; + + /** + * Whether or not the text can be selected by the user. + */ + public var selectable:Bool = true; + + /** + * The color that the text inside the selection will change into, if + * `useSelectedTextFormat` is enabled. + */ + public var selectedTextColor(default, set):FlxColor = FlxColor.WHITE; + + /** + * The beginning index of the current selection. + * + * **Warning:** Will be -1 if the text hasn't been selected yet! + */ + public var selectionBeginIndex(get, never):Int; + + /** + * The color of the selection, shown behind the currently selected text. + */ + public var selectionColor(default, set):FlxColor = FlxColor.BLACK; + + /** + * The ending index of the current selection. + * + * **Warning:** Will be -1 if the text hasn't been selected yet! + */ + public var selectionEndIndex(get, never):Int; + + /** + * If `false`, no extra format will be applied for selected text. + * + * Useful if you are using `addFormat()`, as the selected text format might + * overwrite some of their properties. + */ + public var useSelectedTextFormat(default, set):Bool = true; + + /** + * The input text manager powering this instance + */ + public var manager(default, null):FlxInputTextManager; + + /** + * An FlxSprite representing the background of the text field. + */ + var _backgroundSprite:FlxSprite; + /** + * An FlxSprite representing the selection cursor. + */ + var _caret:FlxSprite; + /** + * Internal variable for the current index of the selection cursor. + */ + var _caretIndex:Int = -1; + /** + * The timer used to flash the caret while the text field has focus. + */ + var _caretTimer:Float = 0; + /** + * An FlxSprite representing the border of the text field. + */ + var _fieldBorderSprite:FlxSprite; + /** + * Helper variable to prevent the text field from being unfocused from + * clicking outside of the fieldif the focus has just been granted + * through code (e.g. a separate focusing system). + */ + var _justGainedFocus:Bool = false; + + /** + * Internal variable that holds the camera that the text field is being pressed on. + */ + var _pointerCamera:FlxCamera; + /** + * Indicates whether or not the background sprites need to be regenerated due to a + * change. + */ + var _regenBackground:Bool = false; + /** + * Indicates whether or not the selection cursor's size needs to be regenerated due + * to a change. + */ + var _regenCaretSize:Bool = false; + + /** + * An array holding the selection box sprites for the text field. It will only be as + * long as the amount of lines that are currently visible. Some items may be null if + * the respective line hasn't been selected yet. + */ + var _selectionBoxes:Array = []; + /** + * The format that will be used for text inside the current selection. + */ + var _selectionFormat:TextFormat = new TextFormat(); + /** + * The current index of the selection from the caret. + */ + var _selectionIndex:Int = -1; + #if FLX_POINTER_INPUT + /** + * Stores the last time that this text field was pressed on, which helps to check for double-presses. + */ + var _lastPressTime:Int = 0; + + /** + * Timer for the text field to scroll vertically when dragging over it. + */ + var _scrollVCounter:Float = 0; + #if FLX_MOUSE + /** + * Indicates whether the mouse is pressing down on this text field. + */ + var _mouseDown:Bool = false; + #end + #if FLX_TOUCH + /** + * Stores the FlxTouch that is pressing down on this text field, if there is one. + */ + var _currentTouch:FlxTouch; + /** + * Used for checking if the current touch has just moved on the X axis. + */ + var _lastTouchX:Null; + /** + * Used for checking if the current touch has just moved on the Y axis. + */ + var _lastTouchY:Null; + #end + #end + + /** + * Creates a new `FlxInputText` object at the specified position. + * @param x The X position of the text. + * @param y The Y position of the text. + * @param fieldWidth The `width` of the text object. Enables `autoSize` if `<= 0`. + * (`height` is determined automatically). + * @param text The actual text you would like to display initially. + * @param size The font size for this text object. + * @param textColor The color of the text + * @param backgroundColor The color of the background (`FlxColor.TRANSPARENT` for no background color) + * @param embeddedFont Whether this text field uses embedded fonts or not. + * @param manager Optional input text manager that will power this input text. + * If `null`, `globalManager` is used + */ + public function new(x:Float = 0, y:Float = 0, fieldWidth:Float = 0, ?text:String, size:Int = 8, textColor:FlxColor = FlxColor.BLACK, + backgroundColor:FlxColor = FlxColor.WHITE, embeddedFont:Bool = true, ?manager:FlxInputTextManager) + { + super(x, y, fieldWidth, text, size, embeddedFont); + if (text == null || text == "") + { + textField.text = ""; + _regen = true; + } + this.backgroundColor = backgroundColor; + + // Default to a single-line text field + wordWrap = multiline = false; + // If the text field's type isn't INPUT and there's a new line at the end + // of the text, it won't be counted for in `numLines` + textField.type = INPUT; + + _selectionFormat.color = selectedTextColor; + + _caret = new FlxSprite().makeGraphic(1, 1); + _caret.visible = false; + updateCaretSize(); + updateCaretPosition(); + + color = textColor; + + if (backgroundColor != FlxColor.TRANSPARENT) + { + background = true; + } + + if (manager == null) + { + manager = FlxInputText.globalManager; + } + + this.manager = manager; + manager.registerInputText(this); + } + + public function setManager(manager:FlxInputTextManager) + { + if (this.manager == null) + { + FlxG.log.error("Cannot set manager once destroyed"); + return; + } + + if (manager == this.manager) + return; + + final hasFocus = this.manager.focus == this; + this.manager.unregisterInputText(this); + + manager.registerInputText(this); + if (hasFocus) + { + manager.setFocus(this); + } + + this.manager = manager; + } + + public function startFocus() + { + if (!hasFocus) + { + // set first to avoid infinite loop + hasFocus = true; + + // Ensure that the text field isn't hidden by a keyboard overlay + final bounds = getLimeBounds(_pointerCamera); + FlxG.stage.window.setTextInputRect(bounds); + + manager.setFocus(this); + + if (_caretIndex < 0) + { + _caretIndex = text.length; + _selectionIndex = _caretIndex; + updateSelection(true); + } + + restartCaretTimer(); + + _justGainedFocus = true; + onFocusChange.dispatch(hasFocus); + } + } + + public function endFocus() + { + if (hasFocus) + { + // set first to avoid infinite loop + hasFocus = false; + + // make sure we have not already switched to a new focus (probably not needed, but may in the future) + if (manager.focus == this) + { + manager.setFocus(null); + } + + if (_selectionIndex != _caretIndex) + { + _selectionIndex = _caretIndex; + updateSelection(true); + } + + onFocusChange.dispatch(hasFocus); + } + } + + override function update(elapsed:Float):Void + { + super.update(elapsed); + + _caretTimer += elapsed; + final showCaret = (_caretTimer % 1.2) < 0.6; + _caret.visible = showCaret && hasFocus && editable && _selectionIndex == _caretIndex && isCaretLineVisible(); + + #if FLX_POINTER_INPUT + if (visible) + { + if (!updateMouseInput(elapsed)) + updateTouchInput(elapsed); + } + #end + if (_justGainedFocus) + { + _justGainedFocus = false; + } + } + + override function draw():Void + { + regenGraphic(); + + drawSprite(_fieldBorderSprite); + drawSprite(_backgroundSprite); + + for (box in _selectionBoxes) + drawSprite(box); + + super.draw(); + + drawSprite(_caret); + } + + /** + * Clean up memory. + */ + override function destroy():Void + { + manager.unregisterInputText(this); + + FlxDestroyUtil.destroy(onEnter); + FlxDestroyUtil.destroy(onFocusChange); + FlxDestroyUtil.destroy(onScrollChange); + FlxDestroyUtil.destroy(onTextChange); + + _backgroundSprite = FlxDestroyUtil.destroy(_backgroundSprite); + _caret = FlxDestroyUtil.destroy(_caret); + _fieldBorderSprite = FlxDestroyUtil.destroy(_fieldBorderSprite); + _pointerCamera = null; + while (_selectionBoxes.length > 0) + FlxDestroyUtil.destroy(_selectionBoxes.pop()); + _selectionBoxes = null; + _selectionFormat = null; + #if FLX_TOUCH + _currentTouch = null; + #end + + super.destroy(); + } + + override function applyFormats(formatAdjusted:TextFormat, useBorderColor:Bool = false):Void + { + // scroll variables will be reset when `textField.setTextFormat()` is called, + // cache the current ones first + var cacheScrollH = scrollH; + var cacheScrollV = scrollV; + + super.applyFormats(formatAdjusted, useBorderColor); + + if (!useBorderColor && useSelectedTextFormat && selectionEndIndex > selectionBeginIndex) + textField.setTextFormat(_selectionFormat, selectionBeginIndex, selectionEndIndex); + + // set the scroll back to how it was + scrollH = cacheScrollH; + scrollV = cacheScrollV; + } + + override function regenGraphic():Void + { + var regenSelection = _regen; + + super.regenGraphic(); + + if (_regenCaretSize) + updateCaretSize(); + if (regenSelection) + updateSelectionSprites(); + if (_regenBackground) + regenBackground(); + } + + public function dispatchTypingAction(action:TypingAction):Void + { + switch (action) + { + case ADD_TEXT(newText): + if (editable) + { + addText(newText); + } + case MOVE_CURSOR(type, shiftKey): + moveCursor(type, shiftKey); + case COMMAND(cmd): + runCommand(cmd); + } + } + + /** + * Replaces the currently selected text with `newText`, or just inserts it at + * the selection cursor if there isn't any text selected. + */ + public function replaceSelectedText(newText:String):Void + { + if (newText == null) + newText = ""; + if (newText == "" && _selectionIndex == _caretIndex) + return; + + var beginIndex = selectionBeginIndex; + var endIndex = selectionEndIndex; + + if (beginIndex == endIndex && maxChars > 0 && text.length == maxChars) + return; + + if (beginIndex < 0) + { + beginIndex = 0; + } + + replaceText(beginIndex, endIndex, newText); + } + + /** + * Sets the selection to span from `beginIndex` to `endIndex`. The selection cursor + * will end up at `endIndex`. + */ + public function setSelection(beginIndex:Int, endIndex:Int):Void + { + _selectionIndex = beginIndex; + _caretIndex = endIndex; + + if (textField == null) + return; + + updateSelection(); + } + + /** + * Filters the specified text and adds it to the field at the current selection. + */ + function addText(newText:String):Void + { + newText = filterText(newText, true); + if (newText.length > 0) + { + replaceSelectedText(newText); + onTextChange.dispatch(text, INPUT_ACTION); + } + } + + /** + * Clips the sprite inside the bounds of the text field, taking + * `clipRect` into account. + */ + function clipSprite(sprite:FlxSprite) + { + if (sprite == null) + return; + + var rect = sprite.clipRect; + if (rect == null) + rect = FlxRect.get(); + rect.set(0, 0, sprite.width, sprite.height); + + var bounds = FlxRect.get(0, 0, width, height); + if (clipRect != null) + { + bounds = bounds.clipTo(clipRect); + } + bounds.offset(x - sprite.x, y - sprite.y); + + sprite.clipRect = rect.clipTo(bounds); + + bounds.put(); + } + + /** + * Helper function to draw sprites with the correct cameras and scroll factor. + */ + function drawSprite(sprite:FlxSprite):Void + { + if (sprite != null && sprite.visible) + { + sprite.scrollFactor.copyFrom(scrollFactor); + sprite._cameras = _cameras; + sprite.draw(); + } + } + + /** + * Returns the specified text filtered using `forceCase` and `filterMode`. + * @param newText The string to filter. + * @param selection Whether or not this string is meant to be added at the selection or if we're + * replacing the entire text. + */ + function filterText(newText:String, selection:Bool = false):String + { + if (forceCase == UPPER_CASE) + { + newText = newText.toUpperCase(); + } + else if (forceCase == LOWER_CASE) + { + newText = newText.toLowerCase(); + } + + if (filterMode != NONE) + { + var pattern = switch (filterMode) + { + case ALPHABET: + ~/[^a-zA-Z]*/g; + case NUMERIC: + ~/[^0-9]*/g; + case ALPHANUMERIC: + ~/[^a-zA-Z0-9]*/g; + case REG(reg): + reg; + case CHARS(chars): + // In a character set, only \, - and ] need to be escaped + chars = chars.replace('\\', "\\\\").replace('-', "\\-").replace(']', "\\]"); + new EReg("[^" + chars + "]*", "g"); + default: + throw "Unknown filterMode (" + filterMode + ")"; + } + if (pattern != null) + newText = pattern.replace(newText, ""); + } + + return newText; + } + + /** + * Returns the X offset of the selection cursor based on the current alignment. + * + * Used for positioning the cursor when there isn't any text at the current line. + */ + function getCaretOffsetX():Float + { + return switch (alignment) + { + case CENTER: (width / 2); + case RIGHT: width - GUTTER; + default: GUTTER; + } + } + + /** + * Gets the character index at a specific point on the text field. + * + * If the point is over a line but not over a character inside it, it will return + * the last character in the line. If no line is found at the point, the length + * of the text is returned. + */ + function getCharAtPosition(x:Float, y:Float):Int + { + if (x < GUTTER) + x = GUTTER; + + if (y > textField.textHeight) + y = textField.textHeight; + if (y < GUTTER) + y = GUTTER; + + for (line in 0...textField.numLines) + { + var lineY = GUTTER + getLineY(line); + var lineOffset = textField.getLineOffset(line); + var lineHeight = textField.getLineMetrics(line).height; + if (y >= lineY && y <= lineY + lineHeight) + { + // check for every character in the line + var lineLength = textField.getLineLength(line); + var lineEndIndex = lineOffset + lineLength; + for (char in 0...lineLength) + { + var boundaries = getCharBoundaries(lineOffset + char); + // reached end of line, return this character + if (boundaries == null) + return lineOffset + char; + if (x <= boundaries.right) + { + if (x <= boundaries.x + (boundaries.width / 2)) + { + return lineOffset + char; + } + else + { + return (lineOffset + char < lineEndIndex) ? lineOffset + char + 1 : lineEndIndex; + } + } + } + + // a character wasn't found, return the last character of the line + return lineEndIndex; + } + } + + return text.length; + } + + /** + * Gets the boundaries of the character at the specified index in the text field. + * + * This handles `textField.getCharBoundaries()` not being able to return boundaries + * of a character that isn't currently visible on Flash. + */ + function getCharBoundaries(char:Int):Rectangle + { + #if flash + // On Flash, `getCharBoundaries()` always returns null if the character is before + // the current vertical scroll. Let's just set the scroll directly at the line + // and change it back later + var cacheScrollV = scrollV; + var lineIndex = getLineIndexOfChar(char); + // Change the internal text field's property instead to not cause a loop due to `_regen` + // always being set back to true + textField.scrollV = lineIndex + 1; + var prevRegen = _regen; + #end + + var boundaries = textField.getCharBoundaries(char); + if (boundaries == null) + { + #if flash + textField.scrollV = cacheScrollV; + _regen = prevRegen; + #end + return null; + } + + #if flash + textField.scrollV = cacheScrollV; + _regen = prevRegen; + // Set the Y to the correct position + boundaries.y = GUTTER + getLineY(lineIndex); + #end + + return boundaries; + } + + /** + * Gets the index of the character horizontally closest to `charIndex` at the + * specified line. + */ + function getCharIndexOnDifferentLine(charIndex:Int, lineIndex:Int):Int + { + if (charIndex < 0 || charIndex > text.length) + return -1; + if (lineIndex < 0 || lineIndex > textField.numLines - 1) + return -1; + + var x = 0.0; + var charBoundaries = getCharBoundaries(charIndex - 1); + if (charBoundaries != null) + { + x = charBoundaries.right; + } + else + { + x = GUTTER; + } + + var y = GUTTER + getLineY(lineIndex) + textField.getLineMetrics(lineIndex).height / 2; + + return getCharAtPosition(x, y); + } + + /** + * Gets the line index of the specified character. + * + * This handles `textField.getLineIndexOfChar()` not returning a valid index for the + * text's length on Flash. + */ + function getLineIndexOfChar(char:Int):Int + { + // On Flash, if the character is equal to the end of the text, it returns -1 as the line. + // We have to fix it manually. + return (char == text.length) ? textField.numLines - 1 : textField.getLineIndexOfChar(char); + } + + /** + * Gets the Y position of the specified line in the text field. + * + * **NOTE:** This does not include the vertical gutter on top of the text field. + */ + function getLineY(line:Int):Float + { + var scrollY = 0.0; + for (i in 0...line) + { + scrollY += textField.getLineMetrics(i).height; + } + return scrollY; + } + + /** + * Calculates the bounds of the text field on the stage, which is used for setting the + * text input rect for the Lime window. + * @param camera The camera to use to get the bounds of the text field. + */ + function getLimeBounds(camera:FlxCamera):lime.math.Rectangle + { + if (camera == null) + camera = FlxG.camera; + + var rect = getScreenBounds(camera); + + // transform bounds inside camera & stage + rect.x = (rect.x * camera.totalScaleX) - (0.5 * camera.width * (camera.scaleX - camera.initialZoom) * FlxG.scaleMode.scale.x) + FlxG.game.x; + rect.y = (rect.y * camera.totalScaleY) - (0.5 * camera.height * (camera.scaleY - camera.initialZoom) * FlxG.scaleMode.scale.y) + FlxG.game.y; + rect.width *= camera.totalScaleX; + rect.height *= camera.totalScaleY; + + #if openfl_dpi_aware + var scale = FlxG.stage.window.scale; + if (scale != 1.0) + { + rect.x /= scale; + rect.y /= scale; + rect.width /= scale; + rect.height /= scale; + } + #end + + return new lime.math.Rectangle(rect.x, rect.y, rect.width, rect.height); + } + + /** + * Gets the Y offset of the current vertical scroll based on `scrollV`. + */ + function getScrollVOffset():Float + { + return getLineY(scrollV - 1); + } + + /** + * Checks if the line the selection cursor is at is currently visible. + */ + function isCaretLineVisible():Bool + { + // `getLineIndexOfChar()` will return -1 if text is empty, but we still want the caret to show up + if (text.length == 0) + return true; + + var line = getLineIndexOfChar(_caretIndex); + return line >= scrollV - 1 && line <= bottomScrollV - 1; + } + + /** + * Dispatches an action to move the selection cursor. + * @param type The type of action to dispatch. + * @param shiftKey Whether or not the shift key is currently pressed. + */ + function moveCursor(type:MoveCursorAction, shiftKey:Bool):Void + { + switch (type) + { + case LEFT: + if (_caretIndex > 0) + { + _caretIndex--; + } + + if (!shiftKey) + { + _selectionIndex = _caretIndex; + } + setSelection(_selectionIndex, _caretIndex); + restartCaretTimer(); + case RIGHT: + if (_caretIndex < text.length) + { + _caretIndex++; + } + + if (!shiftKey) + { + _selectionIndex = _caretIndex; + } + setSelection(_selectionIndex, _caretIndex); + restartCaretTimer(); + case UP: + var lineIndex = getLineIndexOfChar(_caretIndex); + if (lineIndex > 0) + { + _caretIndex = getCharIndexOnDifferentLine(_caretIndex, lineIndex - 1); + } + + if (!shiftKey) + { + _selectionIndex = _caretIndex; + } + setSelection(_selectionIndex, _caretIndex); + restartCaretTimer(); + case DOWN: + var lineIndex = getLineIndexOfChar(_caretIndex); + if (lineIndex < textField.numLines - 1) + { + _caretIndex = getCharIndexOnDifferentLine(_caretIndex, lineIndex + 1); + } + + if (!shiftKey) + { + _selectionIndex = _caretIndex; + } + setSelection(_selectionIndex, _caretIndex); + restartCaretTimer(); + case TOP: + _caretIndex = 0; + + if (!shiftKey) + { + _selectionIndex = _caretIndex; + } + setSelection(_selectionIndex, _caretIndex); + restartCaretTimer(); + case BOTTOM: + _caretIndex = text.length; + + if (!shiftKey) + { + _selectionIndex = _caretIndex; + } + setSelection(_selectionIndex, _caretIndex); + restartCaretTimer(); + case LINE_LEFT: + _caretIndex = textField.getLineOffset(getLineIndexOfChar(_caretIndex)); + + if (!shiftKey) + { + _selectionIndex = _caretIndex; + } + setSelection(_selectionIndex, _caretIndex); + restartCaretTimer(); + case LINE_RIGHT: + var lineIndex = getLineIndexOfChar(_caretIndex); + if (lineIndex < textField.numLines - 1) + { + _caretIndex = textField.getLineOffset(lineIndex + 1) - 1; + } + else + { + _caretIndex = text.length; + } + + if (!shiftKey) + { + _selectionIndex = _caretIndex; + } + setSelection(_selectionIndex, _caretIndex); + restartCaretTimer(); + case WORD_LEFT: + if (_caretIndex > 0) + { + _caretIndex--; + while (_caretIndex > 0 && DELIMITERS.contains(text.charAt(_caretIndex))) + { + _caretIndex--; + } + while (_caretIndex > 0 && !DELIMITERS.contains(text.charAt(_caretIndex - 1))) + { + _caretIndex--; + } + } + + if (!shiftKey) + { + _selectionIndex = _caretIndex; + } + setSelection(_selectionIndex, _caretIndex); + restartCaretTimer(); + case WORD_RIGHT: + while (_caretIndex < text.length && !DELIMITERS.contains(text.charAt(_caretIndex))) + { + _caretIndex++; + } + while (_caretIndex < text.length && DELIMITERS.contains(text.charAt(_caretIndex))) + { + _caretIndex++; + } + + if (!shiftKey) + { + _selectionIndex = _caretIndex; + } + setSelection(_selectionIndex, _caretIndex); + restartCaretTimer(); + } + } + + /** + * Regenerates the background sprites if they're enabled. + */ + function regenBackground():Void + { + if (!background) + return; + + _regenBackground = false; + + if (fieldBorderThickness > 0) + { + _fieldBorderSprite.makeGraphic(Std.int(fieldWidth) + (fieldBorderThickness * 2), Std.int(fieldHeight) + (fieldBorderThickness * 2), + fieldBorderColor); + _fieldBorderSprite.visible = true; + } + else + { + _fieldBorderSprite.visible = false; + } + + if (backgroundColor.alpha > 0) + { + _backgroundSprite.makeGraphic(Std.int(fieldWidth), Std.int(fieldHeight), backgroundColor); + _backgroundSprite.visible = true; + } + else + { + _backgroundSprite.visible = false; + } + + updateBackgroundPosition(); + } + + /** + * Replaces the text at the specified range with `newText`, or just inserts it if + * `beginIndex` and `endIndex` are the same. + */ + function replaceText(beginIndex:Int, endIndex:Int, newText:String):Void + { + if (endIndex < beginIndex || beginIndex < 0 || endIndex > text.length || newText == null) + return; + + text = text.substring(0, beginIndex) + newText + text.substring(endIndex); + + _selectionIndex = _caretIndex = beginIndex + newText.length; + setSelection(_selectionIndex, _caretIndex); + restartCaretTimer(); + } + + /** + * Runs the specified typing command. + */ + function runCommand(cmd:TypingCommand):Void + { + switch (cmd) + { + case NEW_LINE: + if (editable && multiline) + { + addText("\n"); + } + else + { + restartCaretTimer(); + } + onEnter.dispatch(text); + case DELETE_LEFT: + if (!editable) + return; + + if (_selectionIndex == _caretIndex && _caretIndex > 0) + { + _selectionIndex = _caretIndex - 1; + } + + if (_selectionIndex != _caretIndex) + { + replaceSelectedText(""); + _selectionIndex = _caretIndex; + onTextChange.dispatch(text, BACKSPACE_ACTION); + } + else + { + restartCaretTimer(); + } + case DELETE_RIGHT: + if (!editable) + return; + + if (_selectionIndex == _caretIndex && _caretIndex < text.length) + { + _selectionIndex = _caretIndex + 1; + } + + if (_selectionIndex != _caretIndex) + { + replaceSelectedText(""); + _selectionIndex = _caretIndex; + onTextChange.dispatch(text, DELETE_ACTION); + } + else + { + restartCaretTimer(); + } + case COPY: + if (_caretIndex != _selectionIndex && !passwordMode) + { + Clipboard.text = text.substring(_caretIndex, _selectionIndex); + } + case CUT: + if (editable && _caretIndex != _selectionIndex && !passwordMode) + { + Clipboard.text = text.substring(_caretIndex, _selectionIndex); + + replaceSelectedText(""); + } + case PASTE: + if (editable && Clipboard.text != null) + { + addText(Clipboard.text); + } + case SELECT_ALL: + _selectionIndex = 0; + _caretIndex = text.length; + setSelection(_selectionIndex, _caretIndex); + } + } + + /** + * Starts the timer for the caret to flash. + * + * Call this right after `stopCaretTimer()` to show the caret immediately. + */ + function restartCaretTimer():Void + { + _caretTimer = 0; + } + + /** + * Updates the position of the background sprites, if they're enabled. + */ + function updateBackgroundPosition():Void + { + if (!background) + return; + + _fieldBorderSprite.setPosition(x - fieldBorderThickness, y - fieldBorderThickness); + _backgroundSprite.setPosition(x, y); + clipSprite(_fieldBorderSprite); + clipSprite(_backgroundSprite); + } + + /** + * Updates the position of the selection cursor. + */ + function updateCaretPosition():Void + { + if (textField == null || _caret == null) + return; + + if (text.length == 0) + { + _caret.setPosition(x + getCaretOffsetX(), y + GUTTER); + } + else + { + var boundaries = getCharBoundaries(_caretIndex - 1); + if (boundaries != null) + { + _caret.setPosition(x + boundaries.right - scrollH, y + boundaries.y - getScrollVOffset()); + } + else + { + boundaries = getCharBoundaries(_caretIndex); + if (boundaries != null) + { + _caret.setPosition(x + boundaries.x - scrollH, y + boundaries.y - getScrollVOffset()); + } + else // end of line + { + _caret.setPosition(x + getCaretOffsetX(), y + GUTTER + getLineY(getLineIndexOfChar(_caretIndex)) - getScrollVOffset()); + } + } + } + + clipSprite(_caret); + } + + /** + * Updates the size of the selection cursor. + */ + function updateCaretSize():Void + { + if (_caret == null) + return; + _regenCaretSize = false; + + var lineHeight = height - (GUTTER * 2); + if (text.length > 0) + { + lineHeight = textField.getLineMetrics(0).height; + } + + _caret.makeGraphic(caretWidth, Std.int(lineHeight)); + clipSprite(_caret); + } + + #if flash + /** + * Used in Flash to automatically update the horizontal scroll after setting the selection. + */ + function updateScrollH():Void + { + if (textField.textWidth <= width - (GUTTER * 2)) + { + scrollH = 0; + return; + } + + var tempScrollH = scrollH; + if (_caretIndex == 0 || textField.getLineOffset(getLineIndexOfChar(_caretIndex)) == _caretIndex) + { + tempScrollH = 0; + } + else + { + var caret:Rectangle = null; + if (_caretIndex < text.length) + { + caret = getCharBoundaries(_caretIndex); + } + if (caret == null) + { + caret = getCharBoundaries(_caretIndex - 1); + caret.x += caret.width; + } + + while (caret.x < tempScrollH && tempScrollH > 0) + { + tempScrollH -= 24; + } + while (caret.x > tempScrollH + width - (GUTTER * 2)) + { + tempScrollH += 24; + } + } + + if (tempScrollH < 0) + { + scrollH = 0; + } + else if (tempScrollH > maxScrollH) + { + scrollH = maxScrollH; + } + else + { + scrollH = tempScrollH; + } + } + #end + + /** + * Updates the selection with the current `_selectionIndex` and `_caretIndex`. + * @param keepScroll Whether or not to keep the current horizontal and vertical scroll. + */ + function updateSelection(keepScroll:Bool = false):Void + { + var cacheScrollH = scrollH; + var cacheScrollV = scrollV; + + textField.setSelection(_selectionIndex, _caretIndex); + _regen = true; + + if (keepScroll) + { + scrollH = cacheScrollH; + scrollV = cacheScrollV; + } + else + { + #if flash + // Horizontal scroll is not automatically set on Flash + updateScrollH(); + #end + + if (scrollH != cacheScrollH || scrollV != cacheScrollV) + { + onScrollChange.dispatch(scrollH, scrollV); + } + } + } + + /** + * Updates the selection boxes according to the current selection. + */ + function updateSelectionBoxes():Void + { + if (textField == null || _selectionBoxes == null) + return; + + var visibleLines = bottomScrollV - scrollV + 1; + while (_selectionBoxes.length > visibleLines) + { + var box = _selectionBoxes.pop(); + if (box != null) + box.destroy(); + } + + if (_caretIndex == _selectionIndex) + { + for (box in _selectionBoxes) + { + if (box != null) + box.visible = false; + } + + return; + } + + var beginLine = getLineIndexOfChar(selectionBeginIndex); + var endLine = getLineIndexOfChar(selectionEndIndex); + + var beginV = scrollV - 1; + var scrollVOffset = getScrollVOffset(); + + for (line in beginV...bottomScrollV) + { + var i = line - beginV; + var box = _selectionBoxes[i]; + if (line >= beginLine && line <= endLine) + { + var lineStartIndex = textField.getLineOffset(line); + var lineEndIndex = lineStartIndex + textField.getLineLength(line); + + var startIndex = FlxMath.maxInt(lineStartIndex, selectionBeginIndex); + var endIndex = FlxMath.minInt(lineEndIndex, selectionEndIndex); + + var startBoundaries = getCharBoundaries(startIndex); + var endBoundaries = getCharBoundaries(endIndex - 1); + if (endBoundaries == null && endIndex > startIndex) // end of line, try getting the previous character + { + endBoundaries = getCharBoundaries(endIndex - 2); + } + + // If word wrapping is enabled, the start boundary might actually be at the end of + // the previous line, which causes some visual bugs. Let's check to make sure the + // boundaries are in the same line + if (startBoundaries != null && endBoundaries != null && FlxMath.equal(startBoundaries.y, endBoundaries.y)) + { + if (box == null) + { + box = _selectionBoxes[i] = new FlxSprite(); + box.color = selectionColor; + } + + var boxRect = FlxRect.get(startBoundaries.x - scrollH, startBoundaries.y - scrollVOffset, + endBoundaries.right - startBoundaries.x, + startBoundaries.height); + boxRect.clipTo(FlxRect.weak(0, 0, width, height)); // clip the selection box inside the text sprite + + box.setPosition(x + boxRect.x, y + boxRect.y); + box.makeGraphic(Std.int(boxRect.width), Std.int(boxRect.height)); + clipSprite(box); + box.visible = true; + + boxRect.put(); + } + else if (box != null) + { + box.visible = false; + } + } + else if (box != null) + { + box.visible = false; + } + } + } + + /** + * Updates both the selection cursor and the selection boxes. + */ + function updateSelectionSprites():Void + { + updateCaretPosition(); + updateSelectionBoxes(); + } + + /** + * Updates all of the sprites' positions. + */ + function updateSpritePositions():Void + { + updateBackgroundPosition(); + updateCaretPosition(); + updateSelectionBoxes(); + } + + #if FLX_POINTER_INPUT + /** + * Checks for mouse input on the text field. + * @return Whether or not mouse overlap was detected. + */ + function updateMouseInput(elapsed:Float):Bool + { + var overlap = false; + #if FLX_MOUSE + if (_mouseDown) + { + updatePointerDrag(FlxG.mouse, elapsed); + + if (FlxG.mouse.justMoved) + { + updatePointerMove(FlxG.mouse); + } + + if (FlxG.mouse.released) + { + updatePointerRelease(FlxG.mouse); + _mouseDown = false; + } + } + else if (FlxG.mouse.justReleased) + { + _lastPressTime = 0; + } + + if (checkPointerOverlap(FlxG.mouse)) + { + overlap = true; + if (FlxG.mouse.justPressed && selectable) + { + _mouseDown = true; + updatePointerPress(FlxG.mouse); + } + if (FlxG.mouse.wheel != 0 && mouseWheelEnabled) + { + var cacheScrollV = scrollV; + scrollV = FlxMath.minInt(scrollV - FlxG.mouse.wheel, maxScrollV); + if (scrollV != cacheScrollV) + { + onScrollChange.dispatch(scrollH, scrollV); + } + } + } + else if (FlxG.mouse.justPressed && !_justGainedFocus) + { + endFocus(); + } + #end + return overlap; + } + + /** + * Checks for touch input on the text field. + * @return Whether or not touch overlap was detected. + */ + function updateTouchInput(elapsed:Float):Bool + { + var overlap = false; + #if FLX_TOUCH + if (_currentTouch != null) + { + updatePointerDrag(_currentTouch, elapsed); + + if (_lastTouchX != _currentTouch.x || _lastTouchY != _currentTouch.y) + { + updatePointerMove(_currentTouch); + _lastTouchX = _currentTouch.x; + _lastTouchY = _currentTouch.y; + } + + if (_currentTouch.released) + { + updatePointerRelease(_currentTouch); + _currentTouch = null; + _lastTouchY = _lastTouchX = null; + } + } + + var pressedElsewhere = false; + for (touch in FlxG.touches.list) + { + if (checkPointerOverlap(touch)) + { + overlap = true; + if (touch.justPressed && selectable) + { + _currentTouch = touch; + _lastTouchX = touch.x; + _lastTouchY = touch.y; + updatePointerPress(touch); + } + break; + } + else if (touch.justPressed) + { + pressedElsewhere = true; + _lastPressTime = 0; + } + } + if (pressedElsewhere && _currentTouch == null && !_justGainedFocus) + { + endFocus(); + } + #end + return overlap; + } + + /** + * Checks if the pointer is overlapping the text field. This will also set + * `_pointerCamera` accordingly if it detects overlap. + */ + function checkPointerOverlap(pointer:FlxPointer):Bool + { + var overlap = false; + var pointerPos = FlxPoint.get(); + for (camera in getCameras()) + { + pointer.getWorldPosition(camera, pointerPos); + if (overlapsPoint(pointerPos, true, camera)) + { + if (_pointerCamera == null) + _pointerCamera = camera; + overlap = true; + break; + } + } + + pointerPos.put(); + return overlap; + } + + /** + * Called when a pointer presses on this text field. + */ + function updatePointerPress(pointer:FlxPointer):Void + { + startFocus(); + + var relativePos = getRelativePosition(pointer); + _caretIndex = getCharAtPosition(relativePos.x + scrollH, relativePos.y + getScrollVOffset()); + _selectionIndex = _caretIndex; + updateSelection(true); + restartCaretTimer(); + + relativePos.put(); + } + + /** + * Updates the text field's dragging while a pointer has pressed down on it. + */ + function updatePointerDrag(pointer:FlxPointer, elapsed:Float):Void + { + var relativePos = getRelativePosition(pointer); + var cacheScrollH = scrollH; + var cacheScrollV = scrollV; + + if (relativePos.x > width - 1) + { + scrollH += Std.int(Math.max(Math.min((relativePos.x - width) * .1, 10), 1)); + } + else if (relativePos.x < 1) + { + scrollH -= Std.int(Math.max(Math.min(relativePos.x * -.1, 10), 1)); + } + + _scrollVCounter += elapsed; + + if (_scrollVCounter > 0.1) + { + if (relativePos.y > height - 2) + { + scrollV = Std.int(Math.min(scrollV + Math.max(Math.min((relativePos.y - height) * .03, 5), 1), maxScrollV)); + } + else if (relativePos.y < 2) + { + scrollV -= Std.int(Math.max(Math.min(relativePos.y * -.03, 5), 1)); + } + _scrollVCounter = 0; + } + + if (scrollH != cacheScrollH || scrollV != cacheScrollV) + { + onScrollChange.dispatch(scrollH, scrollV); + } + } + + /** + * Called when a pointer moves while its pressed down on the text field. + */ + function updatePointerMove(pointer:FlxPointer):Void + { + if (_selectionIndex < 0) + return; + + var relativePos = getRelativePosition(pointer); + + var char = getCharAtPosition(relativePos.x + scrollH, relativePos.y + getScrollVOffset()); + if (char != _caretIndex) + { + _caretIndex = char; + updateSelection(true); + restartCaretTimer(); + } + + relativePos.put(); + } + + /** + * Called when a pointer is released after pressing down on the text field. + */ + function updatePointerRelease(pointer:FlxPointer):Void + { + if (!hasFocus) + return; + + + if (hasFocus) + { + restartCaretTimer(); + } + + _pointerCamera = null; + var currentTime = FlxG.game.ticks; + if (currentTime - _lastPressTime < 500) + { + updatePointerDoublePress(pointer); + _lastPressTime = 0; + } + else + { + _lastPressTime = currentTime; + } + } + + /** + * Called when a pointer double-presses the text field. + */ + function updatePointerDoublePress(pointer:FlxPointer):Void + { + var rightPos = text.length; + if (text.length > 0 && _caretIndex >= 0 && rightPos >= _caretIndex) + { + var leftPos = -1; + var startPos = FlxMath.maxInt(_caretIndex, 1); + + for (c in DELIMITERS) + { + var pos = text.lastIndexOf(c, startPos - 1); + if (pos > leftPos) + leftPos = pos + 1; + + pos = text.indexOf(c, startPos); + if (pos < rightPos && pos != -1) + rightPos = pos; + } + + if (leftPos != rightPos) + { + setSelection(leftPos, rightPos); + } + } + } + + /** + * Returns the position of the pointer relative to the text field. + */ + function getRelativePosition(pointer:FlxPointer):FlxPoint + { + var pointerPos = pointer.getWorldPosition(_pointerCamera, FlxPoint.get()); + getScreenPosition(_point, _pointerCamera); + var result = FlxPoint.get((pointerPos.x - _pointerCamera.scroll.x) - _point.x, (pointerPos.y - _pointerCamera.scroll.y) - _point.y); + pointerPos.put(); + return result; + } + #end + + override function set_bold(value:Bool):Bool + { + if (bold != value) + { + super.set_bold(value); + _regenCaretSize = _regenBackground = true; + } + + return value; + } + override function set_clipRect(value:FlxRect):FlxRect + { + super.set_clipRect(value); + + clipSprite(_backgroundSprite); + clipSprite(_fieldBorderSprite); + clipSprite(_caret); + for (box in _selectionBoxes) + clipSprite(box); + + return value; + } + + override function set_color(value:FlxColor):FlxColor + { + if (color != value) + { + super.set_color(value); + caretColor = value; + } + + return value; + } + override function set_fieldHeight(value:Float):Float + { + if (fieldHeight != value) + { + super.set_fieldHeight(value); + _regenBackground = true; + } + + return value; + } + + override function set_fieldWidth(value:Float):Float + { + if (fieldWidth != value) + { + super.set_fieldWidth(value); + _regenBackground = true; + } + + return value; + } + + override function set_font(value:String):String + { + if (font != value) + { + super.set_font(value); + _regenCaretSize = _regenBackground = true; + } + + return value; + } + + override function set_italic(value:Bool):Bool + { + if (italic != value) + { + super.set_italic(value); + _regenCaretSize = _regenBackground = true; + } + + return value; + } + + override function set_size(value:Int):Int + { + if (size != value) + { + super.set_size(value); + _regenCaretSize = _regenBackground = true; + } + + return value; + } + + override function set_systemFont(value:String):String + { + if (systemFont != value) + { + super.set_systemFont(value); + _regenCaretSize = _regenBackground = true; + } + + return value; + } + + override function set_text(value:String):String + { + if (text != value) + { + super.set_text(value); + + if (textField != null) + { + if (hasFocus) + { + if (text.length < _selectionIndex) + { + _selectionIndex = text.length; + } + if (text.length < _caretIndex) + { + _caretIndex = text.length; + } + } + else + { + _selectionIndex = 0; + _caretIndex = 0; + } + + setSelection(_selectionIndex, _caretIndex); + if (hasFocus) + { + restartCaretTimer(); + } + } + if (autoSize || _autoHeight) + { + _regenBackground = true; + } + } + + return value; + } + + override function set_x(value:Float) + { + if (x != value) + { + super.set_x(value); + updateSpritePositions(); + } + + return value; + } + + override function set_y(value:Float) + { + if (y != value) + { + super.set_y(value); + updateSpritePositions(); + } + + return value; + } + + function set_background(value:Bool):Bool + { + if (background != value) + { + background = value; + + if (background) + { + if (_backgroundSprite == null) + _backgroundSprite = new FlxSprite(); + if (_fieldBorderSprite == null) + _fieldBorderSprite = new FlxSprite(); + + _regenBackground = true; + } + else + { + _backgroundSprite = FlxDestroyUtil.destroy(_backgroundSprite); + _fieldBorderSprite = FlxDestroyUtil.destroy(_fieldBorderSprite); + } + } + + return value; + } + + function set_backgroundColor(value:FlxColor):FlxColor + { + if (backgroundColor != value) + { + backgroundColor = value; + _regenBackground = true; + } + + return value; + } + + inline function get_bottomScrollV():Int + { + return textField.bottomScrollV; + } + + function set_caretColor(value:FlxColor):FlxColor + { + if (caretColor != value) + { + caretColor = value; + _caret.color = caretColor; + } + + return value; + } + + inline function get_caretIndex():Int + { + return _caretIndex; + } + + function set_caretIndex(value:Int):Int + { + if (value < 0) + value = 0; + if (value > text.length) + value = text.length; + if (_caretIndex != value) + { + _caretIndex = value; + setSelection(_caretIndex, _caretIndex); + restartCaretTimer(); + } + + return value; + } + + function set_caretWidth(value:Int):Int + { + if (value < 1) + value = 1; + if (caretWidth != value) + { + caretWidth = value; + _regenCaretSize = true; + } + + return value; + } + + function set_fieldBorderColor(value:FlxColor):FlxColor + { + if (fieldBorderColor != value) + { + fieldBorderColor = value; + _regenBackground = true; + } + + return value; + } + + function set_fieldBorderThickness(value:Int):Int + { + if (value < 0) + value = 0; + if (fieldBorderThickness != value) + { + fieldBorderThickness = value; + _regenBackground = true; + } + + return value; + } + + function set_filterMode(value:FlxInputTextFilterMode):FlxInputTextFilterMode + { + if (filterMode != value) + { + filterMode = value; + text = filterText(text); + } + + return value; + } + + function set_forceCase(value:FlxInputTextCase):FlxInputTextCase + { + if (forceCase != value) + { + forceCase = value; + text = filterText(text); + } + + return value; + } + + inline function get_maxChars():Int + { + return textField.maxChars; + } + + function set_maxChars(value:Int):Int + { + if (textField.maxChars != value) + { + textField.maxChars = value; + _regen = true; + } + + return value; + } + + inline function get_maxScrollH():Int + { + return textField.maxScrollH; + } + + inline function get_maxScrollV():Int + { + return textField.maxScrollV; + } + + inline function get_multiline():Bool + { + return textField.multiline; + } + + inline function set_multiline(value:Bool):Bool + { + if (textField.multiline != value) + { + textField.multiline = value; + } + + return value; + } + + inline function get_passwordMode():Bool + { + return textField.displayAsPassword; + } + + function set_passwordMode(value:Bool):Bool + { + if (textField.displayAsPassword != value) + { + textField.displayAsPassword = value; + _regen = true; + } + return value; + } + + inline function get_scrollH():Int + { + return textField.scrollH; + } + + function set_scrollH(value:Int):Int + { + if (textField.scrollH != value) + { + textField.scrollH = value; + _regen = true; + } + return value; + } + + inline function get_scrollV():Int + { + return textField.scrollV; + } + + function set_scrollV(value:Int):Int + { + if (textField.scrollV != value || textField.scrollV == 0) + { + textField.scrollV = value; + _regen = true; + } + return value; + } + + function set_selectedTextColor(value:FlxColor):FlxColor + { + if (selectedTextColor != value) + { + selectedTextColor = value; + _selectionFormat.color = selectedTextColor; + _regen = true; + } + + return value; + } + + function get_selectionBeginIndex():Int + { + return FlxMath.minInt(_caretIndex, _selectionIndex); + } + + function set_selectionColor(value:FlxColor):FlxColor + { + if (selectionColor != value) + { + selectionColor = value; + for (box in _selectionBoxes) + { + if (box != null) + box.color = selectionColor; + } + } + + return value; + } + + function get_selectionEndIndex():Int + { + return FlxMath.maxInt(_caretIndex, _selectionIndex); + } + + function set_useSelectedTextFormat(value:Bool):Bool + { + if (useSelectedTextFormat != value) + { + useSelectedTextFormat = value; + _regen = true; + } + + return value; + } +} + +enum abstract FlxInputTextChange(String) from String to String +{ + /** + * Dispatched whenever new text is added by the user. + */ + var INPUT_ACTION = "input"; + /** + * Dispatched whenever text to the left is removed by the user (pressing + * backspace). + */ + var BACKSPACE_ACTION = "backspace"; + /** + * Dispatched whenever text to the right is removed by the user (pressing + * delete). + */ + var DELETE_ACTION = "delete"; +} + +enum abstract FlxInputTextCase(Int) from Int to Int +{ + /** + * Allows both lowercase and uppercase letters. + */ + var ALL_CASES = 0; + /** + * Changes all text to be uppercase. + */ + var UPPER_CASE = 1; + /** + * Changes all text to be lowercase. + */ + var LOWER_CASE = 2; +} + +enum FlxInputTextFilterMode +{ + /** + * Does not filter the text at all. + */ + NONE; + /** + * Only allows letters (a-z & A-Z) to be added to the text. + */ + ALPHABET; + /** + * Only allows numbers (0-9) to be added to the text. + */ + NUMERIC; + /** + * Only allows letters (a-z & A-Z) and numbers (0-9) to be added to the text. + */ + ALPHANUMERIC; + /** + * Uses a regular expression to filter the text. Characters that are matched + * will be removed. + */ + REG(reg:EReg); + + /** + * Only allows the characters present in the string to be added to the text. + */ + CHARS(chars:String); +} \ No newline at end of file diff --git a/flixel/text/FlxInputTextManager.hx b/flixel/text/FlxInputTextManager.hx new file mode 100644 index 0000000000..f941292366 --- /dev/null +++ b/flixel/text/FlxInputTextManager.hx @@ -0,0 +1,424 @@ +package flixel.text; + +import flixel.util.FlxSignal; +import lime.ui.KeyCode; +import lime.ui.KeyModifier; +import openfl.events.Event; +import openfl.events.TextEvent; + +/** + * A manager for tracking and dispatching events for input text objects. + * Normally accessed via the static `FlxInputText.globalManager` rather than being created separately. + */ +class FlxInputTextManager extends FlxBasic +{ + /** + * The input text object that's currently in focus, or `null` if there isn't any. + */ + public var focus(default, null):IFlxInputText; + + /** + * Returns whether or not there's currently an editable input text in focus. + */ + public var isTyping(get, never):Bool; + + /** + * + */ + public final onTypingAction = new FlxTypedSignal<(action:TypingAction)->Void>(); + + /** + * Contains all of the currently registered input text objects. + */ + final _registeredInputTexts = new Array(); + + /** + * Whether we should use mac modifer keys or not. Behavior in linux is currently unknown + */ + final _mac:Bool = false; + + public function new () + { + #if mac + _mac = true; + #elseif (js && html5) + final userAgent = js.Browser.navigator.userAgent.toUpperCase(); + final platform = js.Browser.navigator.platform.toUpperCase(); + _mac = userAgent.indexOf("APPLEWEBKIT") != -1 || platform.indexOf("MAC") != -1; + #end + + super(); + } + + /** + * Clean up memory. + */ + override public function destroy():Void + { + super.destroy(); + + focus = null; + _registeredInputTexts.resize(0); + removeEvents(); + } + + function addEvents() + { + + FlxG.stage.addEventListener(TextEvent.TEXT_INPUT, onTextInput); + // Higher priority is needed here because FlxKeyboard will cancel + // the event for key codes in `preventDefaultKeys`. + FlxG.stage.window.onKeyDown.add(onKeyDown, false, 1000); + #if flash + FlxG.stage.addEventListener(Event.COPY, onCopy); + FlxG.stage.addEventListener(Event.CUT, onCut); + FlxG.stage.addEventListener(Event.PASTE, onPaste); + FlxG.stage.addEventListener(Event.SELECT_ALL, onSelectAll); + FlxG.stage.window.onKeyUp.add(onKeyUp, false, 1000); + #end + } + + function removeEvents() + { + FlxG.stage.removeEventListener(TextEvent.TEXT_INPUT, onTextInput); + FlxG.stage.window.onKeyDown.remove(onKeyDown); + #if flash + FlxG.stage.removeEventListener(Event.COPY, onCopy); + FlxG.stage.removeEventListener(Event.CUT, onCut); + FlxG.stage.removeEventListener(Event.PASTE, onPaste); + FlxG.stage.removeEventListener(Event.SELECT_ALL, onSelectAll); + FlxG.stage.window.onKeyUp.remove(onKeyUp); + #end + } + + /** + * Registers an input text object, and initiates the event listeners if it's + * the first one to be added. + */ + public function registerInputText(input:IFlxInputText):Void + { + if (!_registeredInputTexts.contains(input)) + { + _registeredInputTexts.push(input); + + if (!FlxG.stage.window.onKeyDown.has(onKeyDown)) + { + addEvents(); + } + } + } + + /** + * Unregisters an input text object, and removes the event listeners if there + * aren't any more left. + */ + public function unregisterInputText(input:IFlxInputText):Void + { + if (_registeredInputTexts.contains(input)) + { + _registeredInputTexts.remove(input); + + if (_registeredInputTexts.length == 0 && FlxG.stage.window.onKeyDown.has(onKeyDown)) + { + removeEvents(); + } + } + } + + public function setFocus(value:IFlxInputText) + { + if (focus != value) + { + if (focus != null) + { + focus.endFocus(); + } + + focus = value; + + if (focus != null) + { + focus.startFocus(); + } + + FlxG.stage.window.textInputEnabled = (focus != null); + } + } + + /** + * Called when a `TEXT_INPUT` event is received. + */ + function onTextInput(event:TextEvent):Void + { + // Adding new lines is handled inside FlxInputText + if (event.text.length == 1 && event.text.charCodeAt(0) == KeyCode.RETURN) + return; + + if (focus != null) + { + dispatchTypingAction(ADD_TEXT(event.text)); + } + } + + function dispatchTypingAction(action:TypingAction) + { + focus.dispatchTypingAction(action); + onTypingAction.dispatch(action); + } + + /** + * Called when an `onKeyDown` event is recieved. + */ + function onKeyDown(key:KeyCode, modifier:KeyModifier):Void + { + if (focus == null) + return; + + #if flash + // COPY, CUT, PASTE and SELECT_ALL events will only be dispatched if the stage has a focus. + // Let's set one manually (just the stage itself) + FlxG.stage.focus = FlxG.stage; + #end + + // Modifier used for commands like cut, copy and paste + final commandPressed = _mac ? modifier.metaKey : modifier.ctrlKey; + + // Modifier used to move one word over + final wordModPressed = modifier.altKey; + + // Modifier used to move one line over + final lineModPressed = commandPressed; + + switch (key) + { + case RETURN, NUMPAD_ENTER: + dispatchTypingAction(COMMAND(NEW_LINE)); + case BACKSPACE: + dispatchTypingAction(COMMAND(DELETE_LEFT)); + case DELETE: + dispatchTypingAction(COMMAND(DELETE_RIGHT)); + case LEFT if (lineModPressed): + dispatchTypingAction(MOVE_CURSOR(LINE_LEFT, modifier.shiftKey)); + case LEFT if (wordModPressed): + dispatchTypingAction(MOVE_CURSOR(WORD_LEFT, modifier.shiftKey)); + case LEFT: + dispatchTypingAction(MOVE_CURSOR(LEFT, modifier.shiftKey)); + case RIGHT if (lineModPressed): + dispatchTypingAction(MOVE_CURSOR(LINE_RIGHT, modifier.shiftKey)); + case RIGHT if (wordModPressed): + dispatchTypingAction(MOVE_CURSOR(WORD_RIGHT, modifier.shiftKey)); + case RIGHT: + dispatchTypingAction(MOVE_CURSOR(RIGHT, modifier.shiftKey)); + case UP if (_mac && commandPressed): + dispatchTypingAction(MOVE_CURSOR(TOP, modifier.shiftKey)); + case UP: + dispatchTypingAction(MOVE_CURSOR(UP, modifier.shiftKey)); + case DOWN if (_mac && commandPressed): + dispatchTypingAction(MOVE_CURSOR(BOTTOM, modifier.shiftKey)); + case DOWN: + dispatchTypingAction(MOVE_CURSOR(DOWN, modifier.shiftKey)); + case HOME if (!_mac && commandPressed): + dispatchTypingAction(MOVE_CURSOR(TOP, modifier.shiftKey)); + case HOME: + dispatchTypingAction(MOVE_CURSOR(LINE_LEFT, modifier.shiftKey)); + case END if (!_mac && commandPressed): + dispatchTypingAction(MOVE_CURSOR(BOTTOM, modifier.shiftKey)); + case END: + dispatchTypingAction(MOVE_CURSOR(LINE_RIGHT, modifier.shiftKey)); + case C if (commandPressed): + dispatchTypingAction(COMMAND(COPY)); + case X if (commandPressed): + dispatchTypingAction(COMMAND(CUT)); + #if !js + case V if (commandPressed): + dispatchTypingAction(COMMAND(PASTE)); + #end + case A if (commandPressed): + dispatchTypingAction(COMMAND(SELECT_ALL)); + default: + } + + #if (html5 && FLX_KEYBOARD) + // On HTML5, the SPACE key gets added to `FlxG.keys.preventDefaultKeys` by default, which also + // stops it from dispatching a text input event. We need to call `onTextInput()` manually + if (key == SPACE && FlxG.keys.preventDefaultKeys != null && FlxG.keys.preventDefaultKeys.contains(SPACE)) + { + onTextInput(new TextEvent(TextEvent.TEXT_INPUT, false, false, " ")); + } + #end + } + + #if flash + /** + * Called when an `onKeyUp` event is recieved. This is used to reset the stage's focus + * back to null. + */ + function onKeyUp(key:KeyCode, modifier:KeyModifier):Void + { + if (FlxG.stage.focus == FlxG.stage) + { + FlxG.stage.focus = null; + } + } + + /** + * Called when a `COPY` event is received. + */ + function onCopy(e:Event):Void + { + if (focus != null) + { + dispatchTypingAction(COMMAND(COPY)); + } + } + + /** + * Called when a `CUT` event is received. + */ + function onCut(e:Event):Void + { + if (focus != null) + { + dispatchTypingAction(COMMAND(CUT)); + } + } + + /** + * Called when a `PASTE` event is received. + */ + function onPaste(e:Event):Void + { + if (focus != null) + { + dispatchTypingAction(COMMAND(PASTE)); + } + } + + /** + * Called when a `SELECT_ALL` event is received. + */ + function onSelectAll(e:Event):Void + { + if (focus != null) + { + dispatchTypingAction(COMMAND(SELECT_ALL)); + } + } + #end + + function get_isTyping():Bool + { + return focus != null && focus.editable; + } +} + +interface IFlxInputText +{ + var editable:Bool; + function startFocus():Void; + function endFocus():Void; + function dispatchTypingAction(action:TypingAction):Void; +} + +enum TypingAction +{ + ADD_TEXT(text:String); + MOVE_CURSOR(type:MoveCursorAction, shiftKey:Bool); + COMMAND(cmd:TypingCommand); +} + +enum MoveCursorAction +{ + /** + * Moves the cursor one character to the left. + */ + LEFT; + + /** + * Moves the cursor one character to the right. + */ + RIGHT; + + /** + * Moves the cursor up to the previous line. + */ + UP; + + /** + * Moves the cursor down to the next line. + */ + DOWN; + + /** + * Moves the cursor to the beginning of the text. + */ + TOP; + + /** + * Moves the cursor to the end of the text. + */ + BOTTOM; + + /** + * Moves the cursor to the beginning of the current line. + */ + LINE_LEFT; + + /** + * Moves the cursor to the end of the current line. + */ + LINE_RIGHT; + + /** + * Moves the cursor to the beginning of the previous word, or the + * start of the text if there aren't any more words. + */ + WORD_LEFT; + + /** + * Moves the cursor to the beginning of the next word, or the end + * of the text if there aren't any more words. + */ + WORD_RIGHT; +} + +enum TypingCommand +{ + /** + * Enters a new line into the text. + */ + NEW_LINE; + + /** + * Deletes the character to the left of the cursor, or the selection if + * there's already one. + */ + DELETE_LEFT; + + /** + * Deletes the character to the right of the cursor, or the selection if + * there's already one. + */ + DELETE_RIGHT; + + /** + * Copies the current selection into the clipboard. + */ + COPY; + + /** + * Copies the current selection into the clipboard and then removes it + * from the text field. + */ + CUT; + + /** + * Pastes the clipboard's text into the field. + */ + PASTE; + + /** + * Selects all of the text in the field. + */ + SELECT_ALL; +} \ No newline at end of file From a6478fd712a5a82e4439368b03101f241ee2bb7b Mon Sep 17 00:00:00 2001 From: ACrazyTown <47027981+ACrazyTown@users.noreply.github.com> Date: Tue, 13 Aug 2024 19:25:11 +0200 Subject: [PATCH 27/99] Fix logo image link (#3230) --- .github/README_TR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/README_TR.md b/.github/README_TR.md index 4fe42ec841..b90a7a2e33 100644 --- a/.github/README_TR.md +++ b/.github/README_TR.md @@ -1,4 +1,4 @@ -[![](https://raw.github.com/HaxeFlixel/haxeflixel.com/master/src/files/images/flixel-logos/HaxeFlixel.png)](http://haxeflixel.com/) +[![](https://raw.githubusercontent.com/HaxeFlixel/haxeflixel.com/master/content/_static/images/flixel-logos/HaxeFlixel.png)](http://haxeflixel.com/) [flixel](https://github.com/HaxeFlixel/flixel) | [eklentiler](https://github.com/HaxeFlixel/flixel-addons) | [ui](https://github.com/HaxeFlixel/flixel-ui) | [demolar](https://github.com/HaxeFlixel/flixel-demos) | [araçlar](https://github.com/HaxeFlixel/flixel-tools) | [şablonlar](https://github.com/HaxeFlixel/flixel-templates) | [dökümanlar](https://github.com/HaxeFlixel/flixel-docs) | [haxeflixel.com](https://github.com/HaxeFlixel/haxeflixel.com) | [english](https://github.com/HaxeFlixel/flixel/blob/dev/README.md) From a52272da075a58025c5dfb207bfca76f005ab499 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Tue, 13 Aug 2024 16:09:24 -0500 Subject: [PATCH 28/99] fix crash in getWorldPos (#3231) --- flixel/input/FlxPointer.hx | 2 +- tests/unit/src/flixel/input/FlxPointerTest.hx | 44 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/flixel/input/FlxPointer.hx b/flixel/input/FlxPointer.hx index 3613cf5874..efe7578a6a 100644 --- a/flixel/input/FlxPointer.hx +++ b/flixel/input/FlxPointer.hx @@ -74,7 +74,7 @@ class FlxPointer if (camera == null) camera = FlxG.camera; - getViewPosition(camera, result); + result = getViewPosition(camera, result); result.addPoint(camera.scroll); return result; } diff --git a/tests/unit/src/flixel/input/FlxPointerTest.hx b/tests/unit/src/flixel/input/FlxPointerTest.hx index d6d04a4d32..81aed0c418 100644 --- a/tests/unit/src/flixel/input/FlxPointerTest.hx +++ b/tests/unit/src/flixel/input/FlxPointerTest.hx @@ -69,4 +69,48 @@ class FlxPointerTest Assert.areEqual(150, pointer.x); Assert.areEqual(124, pointer.y); } + + @Test + function testNullResult() + { + try + { + final result = pointer.getPosition(); + Assert.areEqual(0, result.x); + } + catch(e) + { + Assert.fail('Exception thrown from "getPosition", message: "${e.message}"'); + } + + try + { + final result = pointer.getWorldPosition(); + Assert.areEqual(0, result.x); + } + catch(e) + { + Assert.fail('Exception thrown from "getWorldPosition", message: "${e.message}"'); + } + + try + { + final result = pointer.getViewPosition(); + Assert.areEqual(0, result.x); + } + catch(e) + { + Assert.fail('Exception thrown from "getViewPosition", message: "${e.message}"'); + } + + try + { + final result = pointer.getGamePosition(); + Assert.areEqual(0, result.x); + } + catch(e) + { + Assert.fail('Exception thrown from "getGamePosition", message: "${e.message}"'); + } + } } From 9954eb5f0befef71757d4caf229d525a659befe9 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 14 Aug 2024 15:28:44 -0400 Subject: [PATCH 29/99] fix console completion selection on HTML5 (#3225) * fix completion selection on HTML revert formatting * remove trailing whitespace * Update flixel/system/debug/console/Console.hx --------- Co-authored-by: George Kurelic --- flixel/system/debug/completion/CompletionList.hx | 4 +--- flixel/system/debug/console/Console.hx | 4 ++++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/flixel/system/debug/completion/CompletionList.hx b/flixel/system/debug/completion/CompletionList.hx index 6afa57c2ac..2406f10dbf 100644 --- a/flixel/system/debug/completion/CompletionList.hx +++ b/flixel/system/debug/completion/CompletionList.hx @@ -37,8 +37,6 @@ class CompletionList extends Sprite createPopupEntries(capacity); createScrollBar(); updateSelectedItem(); - - FlxG.stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); } public function show(x:Float, items:Array) @@ -82,7 +80,7 @@ class CompletionList extends Sprite addChild(scrollBar); } - function onKeyDown(e:KeyboardEvent) + public function onKeyDown(e:KeyboardEvent) { if (!visible) return; diff --git a/flixel/system/debug/console/Console.hx b/flixel/system/debug/console/Console.hx index ec567331de..638e543b84 100644 --- a/flixel/system/debug/console/Console.hx +++ b/flixel/system/debug/console/Console.hx @@ -196,7 +196,11 @@ class Console extends Window function onKeyDown(e:KeyboardEvent) { if (completionList.visible) + { + // Fixes issue with listening for key down events - https://github.com/HaxeFlixel/flixel/pull/3225 + completionList.onKeyDown(e); return; + } switch (e.keyCode) { From efc0b00255e2f4009b48870de2bedcdbb6e7e5eb Mon Sep 17 00:00:00 2001 From: Davide <7047501+davidetan@users.noreply.github.com> Date: Wed, 14 Aug 2024 22:14:07 +0200 Subject: [PATCH 30/99] Fix flxstrip color-not reset causing not rendering for batches sharing the same shader. (#3220) --- flixel/graphics/tile/FlxDrawTrianglesItem.hx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/flixel/graphics/tile/FlxDrawTrianglesItem.hx b/flixel/graphics/tile/FlxDrawTrianglesItem.hx index 4447294f87..c1af4b6438 100644 --- a/flixel/graphics/tile/FlxDrawTrianglesItem.hx +++ b/flixel/graphics/tile/FlxDrawTrianglesItem.hx @@ -70,6 +70,11 @@ class FlxDrawTrianglesItem extends FlxDrawBaseItem shader.colorMultiplier.value = colorMultipliers; shader.colorOffset.value = colorOffsets; } + else + { + shader.colorMultiplier.value = null; + shader.colorOffset.value = null; + } setParameterValue(shader.hasTransform, true); setParameterValue(shader.hasColorTransform, colored || hasColorOffsets); @@ -175,6 +180,7 @@ class FlxDrawTrianglesItem extends FlxDrawBaseItem i += 2; } + var indicesLength:Int = indices.length; if (!cameraBounds.overlaps(bounds)) { this.vertices.splice(this.vertices.length - verticesLength, verticesLength); @@ -187,7 +193,6 @@ class FlxDrawTrianglesItem extends FlxDrawBaseItem this.uvtData[prevUVTDataLength + i] = uvtData[i]; } - var indicesLength:Int = indices.length; for (i in 0...indicesLength) { this.indices[prevIndicesLength + i] = indices[i] + prevNumberOfVertices; @@ -211,11 +216,9 @@ class FlxDrawTrianglesItem extends FlxDrawBaseItem cameraBounds.putWeak(); #if !flash - for (_ in 0...numTriangles) + for (_ in 0...indicesLength) { alphas.push(transform != null ? transform.alphaMultiplier : 1.0); - alphas.push(transform != null ? transform.alphaMultiplier : 1.0); - alphas.push(transform != null ? transform.alphaMultiplier : 1.0); } if (colored || hasColorOffsets) @@ -226,7 +229,7 @@ class FlxDrawTrianglesItem extends FlxDrawBaseItem if (colorOffsets == null) colorOffsets = []; - for (_ in 0...(numTriangles * 3)) + for (_ in 0...indicesLength) { if(transform != null) { From 7acac91369fc6027a30f960c0f146c46cd491e0d Mon Sep 17 00:00:00 2001 From: It'z Miles <95124554+Itz-Miles@users.noreply.github.com> Date: Thu, 15 Aug 2024 08:12:09 -0600 Subject: [PATCH 31/99] update flxbutton label position on status change (#3232) --- flixel/ui/FlxButton.hx | 1 + 1 file changed, 1 insertion(+) diff --git a/flixel/ui/FlxButton.hx b/flixel/ui/FlxButton.hx index 6b9722ef50..4407d88398 100644 --- a/flixel/ui/FlxButton.hx +++ b/flixel/ui/FlxButton.hx @@ -615,6 +615,7 @@ class FlxTypedButton extends FlxSprite implements IFlxInput { status = value; updateLabelAlpha(); + updateLabelPosition(); return status; } From a5479aa8d4b366a30323dcefbaf4a5f67754f05f Mon Sep 17 00:00:00 2001 From: It'z Miles <95124554+Itz-Miles@users.noreply.github.com> Date: Sun, 18 Aug 2024 08:36:29 -0600 Subject: [PATCH 32/99] fix `FlxButtonEvent` documentation typo (#3237) --- flixel/ui/FlxButton.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flixel/ui/FlxButton.hx b/flixel/ui/FlxButton.hx index 4407d88398..8c404a7319 100644 --- a/flixel/ui/FlxButton.hx +++ b/flixel/ui/FlxButton.hx @@ -667,7 +667,7 @@ class FlxTypedButton extends FlxSprite implements IFlxInput private class FlxButtonEvent implements IFlxDestroyable { /** - * The callback function to call when this even fires. + * The callback function to call when this event fires. */ public var callback:Void->Void; @@ -679,7 +679,7 @@ private class FlxButtonEvent implements IFlxDestroyable #end /** - * @param Callback The callback function to call when this even fires. + * @param Callback The callback function to call when this event fires. * @param sound The sound to play when this event fires. */ public function new(?Callback:Void->Void, ?sound:FlxSound) From 3f0ddaeb5515cfb321c72f52717b123aa8d6643a Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Tue, 20 Aug 2024 11:09:37 -0500 Subject: [PATCH 33/99] FlxTextBorderStyle: Add SHADOW_CUSTOM, always draw full outline (#3236) * add SHADOW_CUSTOM border style, dep shadowOffset * set image size/offset to fit border * swap case order * rename SHADOW_CUSTOM to SHADOW_XY * fix shadowOffset clipping the graphic * add _graphicOffset * doc * use max shadow for iterations * add SHADOW_XY to FlxBitmapText --- flixel/text/FlxBitmapText.hx | 73 +++++++---- flixel/text/FlxText.hx | 245 ++++++++++++++++++++++++++--------- 2 files changed, 234 insertions(+), 84 deletions(-) diff --git a/flixel/text/FlxBitmapText.hx b/flixel/text/FlxBitmapText.hx index 6fcec9169a..4d0ec1551b 100644 --- a/flixel/text/FlxBitmapText.hx +++ b/flixel/text/FlxBitmapText.hx @@ -152,12 +152,18 @@ class FlxBitmapText extends FlxSprite * NOTE: If the borderSize is 1, borderQuality of 0 or 1 will have the exact same effect (and performance). */ public var borderQuality(default, set):Float = 0; - + + /** + * Internal handler for deprecated `shadowOffset` field + */ + var _shadowOffset:FlxPoint = FlxPoint.get(1, 1); + /** * Offset that is applied to the shadow border style, if active. - * x and y are multiplied by borderSize. Default is (1, 1), or lower-right corner. + * `x` and `y` are multiplied by `borderSize`. Default is `(1, 1)`, or lower-right corner. */ - public var shadowOffset(default, null):FlxPoint; + @:deprecated("shadowOffset is deprecated, use setBorderStyle(SHADOW_XY(offsetX, offsetY)), instead") // 5.9.0 + public var shadowOffset(get, never):FlxPoint; /** * Specifies whether the text should have a background. It is recommended to use a @@ -220,8 +226,6 @@ class FlxBitmapText extends FlxSprite this.font = (font == null) ? FlxBitmapFont.getDefaultFont() : font; - shadowOffset = FlxPoint.get(1, 1); - if (FlxG.renderBlit) { pixels = new BitmapData(1, 1, true, FlxColor.TRANSPARENT); @@ -247,7 +251,7 @@ class FlxBitmapText extends FlxSprite _lines = null; _linesWidth = null; - shadowOffset = FlxDestroyUtil.put(shadowOffset); + _shadowOffset = FlxDestroyUtil.put(_shadowOffset); textBitmap = FlxDestroyUtil.dispose(textBitmap); _colorParams = null; @@ -1293,27 +1297,19 @@ class FlxBitmapText extends FlxSprite var delta:Int = Std.int(borderSize / iterations); - var iterationsX:Int = 1; - var iterationsY:Int = 1; - var deltaX:Int = 1; - var deltaY:Int = 1; - - if (borderStyle == FlxTextBorderStyle.SHADOW) - { - iterationsX = Math.round(Math.abs(shadowOffset.x) * borderQuality); - iterationsX = (iterationsX <= 0) ? 1 : iterationsX; - - iterationsY = Math.round(Math.abs(shadowOffset.y) * borderQuality); - iterationsY = (iterationsY <= 0) ? 1 : iterationsY; - - deltaX = Math.round(shadowOffset.x / iterationsX); - deltaY = Math.round(shadowOffset.y / iterationsY); - } - // render border switch (borderStyle) { - case SHADOW: + case SHADOW if (_shadowOffset.x != 1 || _shadowOffset.y != 1): + var iterationsX = Math.round(Math.abs(_shadowOffset.x) * borderQuality); + iterationsX = (iterationsX <= 0) ? 1 : iterationsX; + + var iterationsY = Math.round(Math.abs(_shadowOffset.y) * borderQuality); + iterationsY = (iterationsY <= 0) ? 1 : iterationsY; + + final deltaX = Math.round(_shadowOffset.x / iterationsX); + final deltaY = Math.round(_shadowOffset.y / iterationsY); + for (iterY in 0...iterationsY) { for (iterX in 0...iterationsX) @@ -1321,6 +1317,26 @@ class FlxBitmapText extends FlxSprite drawText(deltaX * (iterX + 1), deltaY * (iterY + 1), isFront, bitmap, useTiles); } } + + case SHADOW: + final iterations = borderQuality < 1 ? 1 : Std.int(Math.abs(borderSize) * borderQuality); + final delta = borderSize / iterations; + var i = iterations + 1; + while (i-- > 1) + { + drawText(Std.int(delta * i), Std.int(delta * i), isFront, bitmap, useTiles); + } + + case SHADOW_XY(shadowX, shadowY): + // Size is max of both, so (4, 4) has 4 iterations, just like SHADOW + final size = Math.max(shadowX, shadowY); + final iterations = borderQuality < 1 ? 1 : Std.int(size * borderQuality); + var i = iterations + 1; + while (i-- > 1) + { + drawText(Std.int(shadowX / iterations * i), Std.int(shadowY / iterations * i), isFront, bitmap, useTiles); + } + case OUTLINE: // Render an outline around the text // (do 8 offset draw calls) @@ -1482,7 +1498,7 @@ class FlxBitmapText extends FlxSprite borderQuality = quality; if (borderStyle == FlxTextBorderStyle.SHADOW) { - shadowOffset.set(borderSize, borderSize); + _shadowOffset.set(borderSize, borderSize); } pendingTextBitmapChange = true; } @@ -1742,7 +1758,12 @@ class FlxBitmapText extends FlxSprite checkPendingChanges(true); return super.get_height(); } - + + inline function get_shadowOffset() + { + return _shadowOffset; + } + /** * Checks if the specified code is one of the Unicode Combining Diacritical Marks * @param Code The charactercode we want to check diff --git a/flixel/text/FlxText.hx b/flixel/text/FlxText.hx index 0c643a152a..3378887100 100644 --- a/flixel/text/FlxText.hx +++ b/flixel/text/FlxText.hx @@ -160,13 +160,24 @@ class FlxText extends FlxSprite public var autoSize(get, set):Bool; var _autoHeight:Bool = true; - + + /** + * Internal handler for deprecated `shadowOffset` field + */ + var _shadowOffset:FlxPoint = FlxPoint.get(1, 1); + /** * Offset that is applied to the shadow border style, if active. * `x` and `y` are multiplied by `borderSize`. Default is `(1, 1)`, or lower-right corner. */ - public var shadowOffset(default, null):FlxPoint; - + @:deprecated("shadowOffset is deprecated, use setBorderStyle(SHADOW_XY(offsetX, offsetY)), instead") // 5.9.0 + public var shadowOffset(get, never):FlxPoint; + + /** + * Used to offset the graphic to account for the border + */ + var _graphicOffset:FlxPoint = FlxPoint.get(0, 0); + var _defaultFormat:TextFormat; var _formatAdjusted:TextFormat; var _formatRanges:Array = []; @@ -239,8 +250,6 @@ class FlxText extends FlxSprite moves = false; drawFrame(); - - shadowOffset = FlxPoint.get(1, 1); } /** @@ -252,7 +261,8 @@ class FlxText extends FlxSprite _font = null; _defaultFormat = null; _formatAdjusted = null; - shadowOffset = FlxDestroyUtil.put(shadowOffset); + _shadowOffset = FlxDestroyUtil.put(_shadowOffset); + _graphicOffset = FlxDestroyUtil.put(_graphicOffset); super.destroy(); } @@ -841,6 +851,11 @@ class FlxText extends FlxSprite regenGraphic(); return super.get_height(); } + + inline function get_shadowOffset() + { + return _shadowOffset; + } override function updateColorTransform():Void { @@ -865,33 +880,47 @@ class FlxText extends FlxSprite { if (textField == null || !_regen) return; - - var oldWidth:Int = 0; - var oldHeight:Int = VERTICAL_GUTTER; - - if (graphic != null) + + final oldWidth:Int = graphic != null ? graphic.width : 0; + final oldHeight:Int = graphic != null ? graphic.height : VERTICAL_GUTTER; + + final newWidthFloat:Float = textField.width; + final newHeightFloat:Float = _autoHeight ? textField.textHeight + VERTICAL_GUTTER : textField.height; + + var borderWidth:Float = 0; + var borderHeight:Float = 0; + switch(borderStyle) { - oldWidth = graphic.width; - oldHeight = graphic.height; + case SHADOW if (_shadowOffset.x != 1 || _shadowOffset.y != 1): + borderWidth += Math.abs(_shadowOffset.x); + borderHeight += Math.abs(_shadowOffset.y); + + case SHADOW: // With the default shadowOffset value + borderWidth += Math.abs(borderSize); + borderHeight += Math.abs(borderSize); + + case SHADOW_XY(offsetX, offsetY): + borderWidth += Math.abs(offsetX); + borderHeight += Math.abs(offsetY); + + case OUTLINE_FAST | OUTLINE: + borderWidth += Math.abs(borderSize) * 2; + borderHeight += Math.abs(borderSize) * 2; + + case NONE: } - - var newWidth:Int = Math.ceil(textField.width); - var textfieldHeight = _autoHeight ? textField.textHeight : textField.height; - var vertGutter = _autoHeight ? VERTICAL_GUTTER : 0; - // Account for gutter - var newHeight:Int = Math.ceil(textfieldHeight) + vertGutter; - + + final newWidth:Int = Math.ceil(newWidthFloat + borderWidth); + final newHeight:Int = Math.ceil(newHeightFloat + borderHeight); + // prevent text height from shrinking on flash if text == "" - if (textField.textHeight == 0) - { - newHeight = oldHeight; - } - - if (oldWidth != newWidth || oldHeight != newHeight) + if (textField.textHeight != 0 && (oldWidth != newWidth || oldHeight != newHeight)) { // Need to generate a new buffer to store the text graphic - var key:String = FlxG.bitmap.getUniqueKey("text"); + final key:String = FlxG.bitmap.getUniqueKey("text"); makeGraphic(newWidth, newHeight, FlxColor.TRANSPARENT, false, key); + width = Math.ceil(newWidthFloat); + height = Math.ceil(newHeightFloat); #if FLX_TRACK_GRAPHICS graphic.trackingInfo = 'text($ID, $text)'; @@ -1002,6 +1031,45 @@ class FlxText extends FlxSprite regenGraphic(); super.draw(); } + + override function drawSimple(camera:FlxCamera):Void + { + // same as super but checks _graphicOffset + getScreenPosition(_point, camera).subtractPoint(offset).subtractPoint(_graphicOffset); + if (isPixelPerfectRender(camera)) + _point.floor(); + + _point.copyToFlash(_flashPoint); + camera.copyPixels(_frame, framePixels, _flashRect, _flashPoint, colorTransform, blend, antialiasing); + } + + override function drawComplex(camera:FlxCamera):Void + { + _frame.prepareMatrix(_matrix, ANGLE_0, checkFlipX(), checkFlipY()); + _matrix.translate(-origin.x, -origin.y); + _matrix.scale(scale.x, scale.y); + + if (bakedRotationAngle <= 0) + { + updateTrig(); + + if (angle != 0) + _matrix.rotateWithTrig(_cosAngle, _sinAngle); + } + + // same as super but checks _graphicOffset + getScreenPosition(_point, camera).subtractPoint(offset).subtractPoint(_graphicOffset); + _point.add(origin.x, origin.y); + _matrix.translate(_point.x, _point.y); + + if (isPixelPerfectRender(camera)) + { + _matrix.tx = Math.floor(_matrix.tx); + _matrix.ty = Math.floor(_matrix.ty); + } + + camera.drawPixels(_frame, framePixels, _matrix, colorTransform, blend, antialiasing, shader); + } /** * Internal function to update the current animation frame. @@ -1019,38 +1087,93 @@ class FlxText extends FlxSprite regenGraphic(); super.calcFrame(RunOnCpp); } - + function applyBorderStyle():Void { - var iterations:Int = Std.int(borderSize * borderQuality); - if (iterations <= 0) + // offset entire image to fit the border + switch(borderStyle) { - iterations = 1; + case SHADOW if (_shadowOffset.x != 1 || _shadowOffset.y != 1): + _graphicOffset.x = _shadowOffset.x > 0 ? _shadowOffset.x : 0; + _graphicOffset.y = _shadowOffset.y > 0 ? _shadowOffset.y : 0; + + case SHADOW: // With the default shadowOffset value + if (borderSize < 0) + _graphicOffset.set(-borderSize, -borderSize); + + case SHADOW_XY(offsetX, offsetY): + _graphicOffset.x = offsetX < 0 ? -offsetX : 0; + _graphicOffset.y = offsetY < 0 ? -offsetY : 0; + + case OUTLINE_FAST | OUTLINE if (borderSize < 0): + _graphicOffset.set(-borderSize, -borderSize); + + case NONE | OUTLINE_FAST | OUTLINE: + _graphicOffset.set(0, 0); } - var delta:Float = borderSize / iterations; - + _matrix.translate(_graphicOffset.x, _graphicOffset.y); + switch (borderStyle) { - case SHADOW: - // Render a shadow beneath the text - // (do one lower-right offset draw call) + case SHADOW if (_shadowOffset.x != 1 || _shadowOffset.y != 1): + // Render a shadow beneath the text using the shadowOffset property applyFormats(_formatAdjusted, true); - + + var iterations = borderQuality < 1 ? 1 : Std.int(Math.abs(borderSize) * borderQuality); + final delta = borderSize / iterations; for (i in 0...iterations) { copyTextWithOffset(delta, delta); } - - _matrix.translate(-shadowOffset.x * borderSize, -shadowOffset.y * borderSize); - + + _matrix.translate(-_shadowOffset.x * borderSize, -_shadowOffset.y * borderSize); + + case SHADOW: // With the default shadowOffset value + // Render a shadow beneath the text + applyFormats(_formatAdjusted, true); + + final originX = _matrix.tx; + final originY = _matrix.ty; + + final iterations = borderQuality < 1 ? 1 : Std.int(Math.abs(borderSize) * borderQuality); + var i = iterations + 1; + while (i-- > 1) + { + copyTextWithOffset(borderSize / iterations * i, borderSize / iterations * i); + // reset to origin + _matrix.tx = originX; + _matrix.ty = originY; + } + + case SHADOW_XY(shadowX, shadowY): + // Render a shadow beneath the text with the specified offset + applyFormats(_formatAdjusted, true); + + final originX = _matrix.tx; + final originY = _matrix.ty; + + // Size is max of both, so (4, 4) has 4 iterations, just like SHADOW + final size = Math.max(shadowX, shadowY); + final iterations = borderQuality < 1 ? 1 : Std.int(size * borderQuality); + var i = iterations + 1; + while (i-- > 1) + { + copyTextWithOffset(shadowX / iterations * i, shadowY / iterations * i); + // reset to origin + _matrix.tx = originX; + _matrix.ty = originY; + } + case OUTLINE: // Render an outline around the text // (do 8 offset draw calls) applyFormats(_formatAdjusted, true); - - var curDelta:Float = delta; - for (i in 0...iterations) + + final iterations = FlxMath.maxInt(1, Std.int(borderSize * borderQuality)); + var i = iterations + 1; + while (i-- > 1) { + final curDelta = borderSize / iterations * i; copyTextWithOffset(-curDelta, -curDelta); // upper-left copyTextWithOffset(curDelta, 0); // upper-middle copyTextWithOffset(curDelta, 0); // upper-right @@ -1059,29 +1182,29 @@ class FlxText extends FlxSprite copyTextWithOffset(-curDelta, 0); // lower-middle copyTextWithOffset(-curDelta, 0); // lower-left copyTextWithOffset(0, -curDelta); // lower-left - + _matrix.translate(curDelta, 0); // return to center - curDelta += delta; } - + case OUTLINE_FAST: // Render an outline around the text // (do 4 diagonal offset draw calls) // (this method might not work with certain narrow fonts) applyFormats(_formatAdjusted, true); - - var curDelta:Float = delta; - for (i in 0...iterations) + + final iterations = FlxMath.maxInt(1, Std.int(borderSize * borderQuality)); + var i = iterations + 1; + while (i-- > 1) { + final curDelta = borderSize / iterations * i; copyTextWithOffset(-curDelta, -curDelta); // upper-left copyTextWithOffset(curDelta * 2, 0); // upper-right copyTextWithOffset(0, curDelta * 2); // lower-right copyTextWithOffset(-curDelta * 2, 0); // lower-left - + _matrix.translate(curDelta, -curDelta); // return to center - curDelta += delta; } - + case NONE: } } @@ -1237,20 +1360,26 @@ class FlxTextFormatMarkerPair enum FlxTextBorderStyle { NONE; - + /** - * A simple shadow to the lower-right. - * Use `FlxText.shadowOffset` for custom placement. + * A simple shadow to the lower-right */ SHADOW; - + + /** + * A shadow that allows custom placement + * **Note:** Ignores borderSize + */ + SHADOW_XY(offsetX:Float, offsetY:Float); + /** * Outline on all 8 sides */ OUTLINE; - + /** - * Outline, optimized using only 4 draw calls (might not work for narrow and/or 1-pixel fonts) + * Outline, optimized using only 4 draw calls + * **Note:** Might not work for narrow and/or 1-pixel fonts */ OUTLINE_FAST; } From 089ff95023ac61e26c5af124e9f6e9d340531309 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Wed, 21 Aug 2024 09:14:44 -0500 Subject: [PATCH 34/99] add callback(data) to logstyle, replace callbackFunction() (#3239) --- flixel/system/debug/log/LogStyle.hx | 33 ++++++++++++++++---------- flixel/system/frontEnds/LogFrontEnd.hx | 10 +++++--- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/flixel/system/debug/log/LogStyle.hx b/flixel/system/debug/log/LogStyle.hx index 99d0efcb18..b3c2671e31 100644 --- a/flixel/system/debug/log/LogStyle.hx +++ b/flixel/system/debug/log/LogStyle.hx @@ -38,7 +38,13 @@ class LogStyle /** * A callback function that is called when this LogStyle is used */ + @:deprecated("callbackFunction is deprecated, use callback, instead") public var callbackFunction:()->Void; + + /** + * A callback function that is called when this LogStyle is used + */ + public var callback:(data:Any)->Void; /** * Whether an exception is thrown when this LogStyle is used. @@ -50,19 +56,21 @@ class LogStyle /** * Create a new LogStyle to be used in conjunction with `FlxG.log.advanced()` * - * @param prefix A prefix which is always attached to the start of the logged data - * @param color The text color - * @param size The text size - * @param bold Whether the text is bold or not - * @param italic Whether the text is italic or not - * @param underlined Whether the text is underlined or not - * @param errorSound A sound to be played when this LogStyle is used - * @param openConsole Whether the console should be forced to open when this LogStyle is used - * @param callback A callback function that is called when this LogStyle is used - * @param throwError Whether an error is thrown when this LogStyle is used + * @param prefix A prefix which is always attached to the start of the logged data + * @param color The text color + * @param size The text size + * @param bold Whether the text is bold or not + * @param italic Whether the text is italic or not + * @param underlined Whether the text is underlined or not + * @param errorSound A sound to be played when this LogStyle is used + * @param openConsole Whether the console should be forced to open when this LogStyle is used + * @param callbackFunction A callback function that is called when this LogStyle is used + * @param callback A callback function that is called when this LogStyle is used + * @param throwError Whether an error is thrown when this LogStyle is used */ + @:haxe.warning("-WDeprecated") public function new(prefix = "", color = "FFFFFF", size = 12, bold = false, italic = false, underlined = false, - ?errorSound:String, openConsole = false, ?callback:()->Void, throwException = false) + ?errorSound:String, openConsole = false, ?callbackFunction:()->Void, ?callback:(Any)->Void, throwException = false) { this.prefix = prefix; this.color = color; @@ -72,7 +80,8 @@ class LogStyle this.underlined = underlined; this.errorSound = errorSound; this.openConsole = openConsole; - this.callbackFunction = callback; + this.callbackFunction = callbackFunction; + this.callback = callback; this.throwException = throwException; } diff --git a/flixel/system/frontEnds/LogFrontEnd.hx b/flixel/system/frontEnds/LogFrontEnd.hx index 05765bb39b..b355c7ceb3 100644 --- a/flixel/system/frontEnds/LogFrontEnd.hx +++ b/flixel/system/frontEnds/LogFrontEnd.hx @@ -44,7 +44,8 @@ class LogFrontEnd * @param style The LogStyle to use, for example LogStyle.WARNING. You can also create your own by importing the LogStyle class. * @param fireOnce Whether you only want to log the Data in case it hasn't been added already */ - public function advanced(data:Dynamic, ?style:LogStyle, fireOnce = false):Void + @:haxe.warning("-WDeprecated") + public function advanced(data:Any, ?style:LogStyle, fireOnce = false):Void { if (style == null) style = LogStyle.NORMAL; @@ -74,6 +75,9 @@ class LogFrontEnd if (style.callbackFunction != null) style.callbackFunction(); + + if (style.callback != null) + style.callback(data); } #end @@ -109,9 +113,9 @@ class LogFrontEnd * @param data The data that has been traced * @param info Information about the position at which trace() was called */ - function processTraceData(data:Dynamic, ?info:PosInfos):Void + function processTraceData(data:Any, ?info:PosInfos):Void { - var paramArray:Array = [data]; + var paramArray:Array = [data]; if (info.customParams != null) { From 0573fe3865bc4770778cbba3afde5dde6a328e5f Mon Sep 17 00:00:00 2001 From: DigiEggz Date: Wed, 21 Aug 2024 10:47:43 -0400 Subject: [PATCH 35/99] Prevent crash in FlxInputText when switching states (#3243) Prevents null textField access in FlxInputText when switching between states. Resolves #3242. --- flixel/text/FlxInputText.hx | 1 + 1 file changed, 1 insertion(+) diff --git a/flixel/text/FlxInputText.hx b/flixel/text/FlxInputText.hx index 86180d4dd7..cdea3319fc 100644 --- a/flixel/text/FlxInputText.hx +++ b/flixel/text/FlxInputText.hx @@ -482,6 +482,7 @@ class FlxInputText extends FlxText implements IFlxInputText */ override function destroy():Void { + endFocus(); manager.unregisterInputText(this); FlxDestroyUtil.destroy(onEnter); From fc01c6e66dd97b9be04c6ec268245dd08d3a58d4 Mon Sep 17 00:00:00 2001 From: George FunBook Date: Wed, 21 Aug 2024 11:58:25 -0500 Subject: [PATCH 36/99] Update Changelog --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fd860069f..174ce41eed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ 5.9.0 (TBD) ------------------------------ #### New features: +- `FlxInputText`: Add improved input text to core flixel (flixel-ui's implementation will be deprecated) ([#3219](https://github.com/HaxeFlixel/flixel/pull/3219)) - `FlxReplay`: Add `getDuration` ([#3135](https://github.com/HaxeFlixel/flixel/pull/3135)) - `InputFrontEnd`: ([#3134](https://github.com/HaxeFlixel/flixel/pull/3134)) - Add `addInput` and `addUniqueType` to replace `add` @@ -13,6 +14,12 @@ - Replacement fields: `startAt`, `direction`, `loopType`, `target`, `currentIndex`, `nextIndex`, `current` and `next` - `FlxGraphic`: Add `trackingInfo` to help debugging graphics ([#3183](https://github.com/HaxeFlixel/flixel/pull/3183)) - `FlxFlicker`: Add `pause` and `resume` ([#3179](https://github.com/HaxeFlixel/flixel/pull/3179)) +- `FlxRect`: Add `clipTo` and fix `intersection` bug ([#3190](https://github.com/HaxeFlixel/flixel/pull/3190)) +- `FlxPointer`: Add `getGamePosition`, `gameX/Y`, `getViewPosition`, and `viewX/Y`, to replace "screen" fields ([#3210](https://github.com/HaxeFlixel/flixel/pull/3210)) +- `FlxAnimationController`: Add `onLoop`, `onFrameChange` and `onFinish`, to replace `callback` and `finishCallback` ([#3205](https://github.com/HaxeFlixel/flixel/pull/3205)) ([#3216](https://github.com/HaxeFlixel/flixel/pull/3216)) +- `FlxStrip`: Add support for blendmodes ([3213](https://github.com/HaxeFlixel/flixel/pull/3213)) +- `FlxTextBorderStyle`: Add SHADOW_XY, prevent border clipping ([3236](https://github.com/HaxeFlixel/flixel/pull/3236)) +- `LogStyle`: add `callback` to replace `callbackFunction` ([3239](https://github.com/HaxeFlixel/flixel/pull/3239)) #### Changes and improvements: - `FlxKey`: Add `NONE` to `fromStringMap` and `toStringMap` ([#3119](https://github.com/HaxeFlixel/flixel/pull/3119)) @@ -42,11 +49,17 @@ - `FlxBGSprite`: Prevent draw call when transparent ([#3173](https://github.com/HaxeFlixel/flixel/pull/3173)) - `FlxArrayUtil`: Deprecate `resize`, use `array.setLength` ([#3094](https://github.com/HaxeFlixel/flixel/pull/3094)) - Debugging: Check alpha when point-selecting sprites ([#3184](https://github.com/HaxeFlixel/flixel/pull/3184)) +- `FlxBitmapText`: Ignore border outline when computing field size ([#3193](https://github.com/HaxeFlixel/flixel/pull/3193)) +- `FlxDebugger`: Improve console code completion ([#3222](https://github.com/HaxeFlixel/flixel/pull/3222)) #### Bugfixes: - `FlxFlickerTween`: Fix "Unsupported recursive type" error on hl ([#3170](https://github.com/HaxeFlixel/flixel/pull/3170)) - `FlxBGSprite`: Fix draw size when scale is not `1.0` ([#3142](https://github.com/HaxeFlixel/flixel/pull/3142)) - `FlxGraphic`: Prevent null ref in `getFramesCollections` with destroyed graphics ([#3180](https://github.com/HaxeFlixel/flixel/pull/3180)) +- `FlxText`: Handle null align on HL ([#3196](https://github.com/HaxeFlixel/flixel/pull/3196)) +- `FlxCamera`: Fix blending issue ([#3217](https://github.com/HaxeFlixel/flixel/pull/3217)) ([#3255](https://github.com/HaxeFlixel/flixel/pull/3255)) +- `FlxStrip`: Fix `color` preventing other strips from drawing ([#3220](https://github.com/HaxeFlixel/flixel/pull/3220)) +- `FlxButton`: Fix `label` position when moves is false ([#3232](https://github.com/HaxeFlixel/flixel/pull/3232)) 5.8.0 (April 19, 2024) ------------------------------ From 51ecb444dbc57424719af9c6850e135b805f9da7 Mon Sep 17 00:00:00 2001 From: Flainn Date: Sat, 24 Aug 2024 09:25:20 -0400 Subject: [PATCH 37/99] Fix mouse wheel scrolling not working (#3244) --- flixel/text/FlxInputText.hx | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/flixel/text/FlxInputText.hx b/flixel/text/FlxInputText.hx index cdea3319fc..79e2369978 100644 --- a/flixel/text/FlxInputText.hx +++ b/flixel/text/FlxInputText.hx @@ -507,8 +507,8 @@ class FlxInputText extends FlxText implements IFlxInputText override function applyFormats(formatAdjusted:TextFormat, useBorderColor:Bool = false):Void { - // scroll variables will be reset when `textField.setTextFormat()` is called, - // cache the current ones first + // Scroll variables will be reset when `textField.setTextFormat()` is called, + // cache the current ones first. var cacheScrollH = scrollH; var cacheScrollV = scrollV; @@ -517,9 +517,15 @@ class FlxInputText extends FlxText implements IFlxInputText if (!useBorderColor && useSelectedTextFormat && selectionEndIndex > selectionBeginIndex) textField.setTextFormat(_selectionFormat, selectionBeginIndex, selectionEndIndex); - // set the scroll back to how it was - scrollH = cacheScrollH; - scrollV = cacheScrollV; + // Set the scroll back to how it was. + // This changes the internal text field's scroll instead to make sure that + // `__updateLayout()` gets called even if the scroll hasn't changed. + // If it doesn't get called here, it will be called when the text field + // is being drawn to this sprite's graphic, which will reset the scroll + // to the current selection, effectively making scrolling with the mouse + // wheel not work. + textField.scrollH = cacheScrollH; + textField.scrollV = cacheScrollV; } override function regenGraphic():Void From a1dfd995dae8bf2862f606c2fce6083b9a99dc33 Mon Sep 17 00:00:00 2001 From: Ne_Eo Date: Mon, 26 Aug 2024 20:13:55 +0200 Subject: [PATCH 38/99] Remove Matrix Math from default shader (#3227) --- flixel/graphics/tile/FlxGraphicsShader.hx | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/flixel/graphics/tile/FlxGraphicsShader.hx b/flixel/graphics/tile/FlxGraphicsShader.hx index 080608368e..e433b45a86 100644 --- a/flixel/graphics/tile/FlxGraphicsShader.hx +++ b/flixel/graphics/tile/FlxGraphicsShader.hx @@ -6,18 +6,18 @@ class FlxGraphicsShader extends GraphicsShader { @:glVertexSource(" #pragma header - + attribute float alpha; attribute vec4 colorMultiplier; attribute vec4 colorOffset; uniform bool hasColorTransform; - + void main(void) { #pragma body - + openfl_Alphav = openfl_Alpha * alpha; - + if (hasColorTransform) { openfl_ColorOffsetv = colorOffset / 255.0; @@ -48,13 +48,7 @@ class FlxGraphicsShader extends GraphicsShader color = vec4(color.rgb / color.a, color.a); - mat4 colorMultiplier = mat4(0); - colorMultiplier[0][0] = openfl_ColorMultiplierv.x; - colorMultiplier[1][1] = openfl_ColorMultiplierv.y; - colorMultiplier[2][2] = openfl_ColorMultiplierv.z; - colorMultiplier[3][3] = openfl_ColorMultiplierv.w; - - color = clamp(openfl_ColorOffsetv + (color * colorMultiplier), 0.0, 1.0); + color = clamp(openfl_ColorOffsetv + (color * openfl_ColorMultiplierv), 0.0, 1.0); if (color.a > 0.0) { @@ -65,7 +59,7 @@ class FlxGraphicsShader extends GraphicsShader ") @:glFragmentSource(" #pragma header - + void main(void) { gl_FragColor = flixel_texture2D(bitmap, openfl_TextureCoordv); From 440957701b11e983bfd1d5f2599b2b7eb86939b8 Mon Sep 17 00:00:00 2001 From: DetectiveBaldi <86160807+DetectiveBaldi@users.noreply.github.com> Date: Mon, 26 Aug 2024 14:19:45 -0400 Subject: [PATCH 39/99] Add support for custom border sizes to `FlxBar` (#3234) * Update FlxBar.hx * Update some documentation * Update FlxBar.hx * Update FlxBar.hx * Update FlxBar.hx --- flixel/ui/FlxBar.hx | 80 +++++++++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 35 deletions(-) diff --git a/flixel/ui/FlxBar.hx b/flixel/ui/FlxBar.hx index 04b5a99a61..11997a8c72 100644 --- a/flixel/ui/FlxBar.hx +++ b/flixel/ui/FlxBar.hx @@ -158,7 +158,7 @@ class FlxBar extends FlxSprite * @param variable The variable of the object that is used to determine the bar position. For example if the parent was an FlxSprite this could be "health" to track the health value * @param min The minimum value. I.e. for a progress bar this would be zero (nothing loaded yet) * @param max The maximum value the bar can reach. I.e. for a progress bar this would typically be 100. - * @param showBorder Include a 1px border around the bar? (if true it adds +2 to width and height to accommodate it) + * @param showBorder Should the bar be outlined with a solid border? */ public function new(x:Float = 0, y:Float = 0, ?direction:FlxBarFillDirection, width:Int = 100, height:Int = 10, ?parentRef:Dynamic, variable:String = "", min:Float = 0, max:Float = 100, showBorder:Bool = false) @@ -324,37 +324,39 @@ class FlxBar extends FlxSprite } /** - * Creates a solid-colour filled health bar in the given colours, with optional 1px thick border. + * Creates a solid-colour filled health bar in the given colours, with optional border. * All colour values are in 0xAARRGGBB format, so if you want a slightly transparent health bar give it lower AA values. * * @param empty The color of the bar when empty in 0xAARRGGBB format (the background colour) * @param fill The color of the bar when full in 0xAARRGGBB format (the foreground colour) - * @param showBorder Should the bar be outlined with a 1px solid border? + * @param showBorder Should the bar be outlined with a solid border? * @param border The border colour in 0xAARRGGBB format + * @param borderSize The size of the border, in pixels. * @return This FlxBar object with generated images for front and background. */ - public function createFilledBar(empty:FlxColor, fill:FlxColor, showBorder:Bool = false, border:FlxColor = FlxColor.WHITE):FlxBar + public function createFilledBar(empty:FlxColor, fill:FlxColor, showBorder:Bool = false, border:FlxColor = FlxColor.WHITE, borderSize:Int = 1):FlxBar { - createColoredEmptyBar(empty, showBorder, border); - createColoredFilledBar(fill, showBorder, border); + createColoredEmptyBar(empty, showBorder, border, borderSize); + createColoredFilledBar(fill, showBorder, border, borderSize); return this; } /** - * Creates a solid-colour filled background for health bar in the given colour, with optional 1px thick border. + * Creates a solid-colour filled background for health bar in the given colour, with optional border. * * @param empty The color of the bar when empty in 0xAARRGGBB format (the background colour) - * @param showBorder Should the bar be outlined with a 1px solid border? + * @param showBorder Should the bar be outlined with a solid border? * @param border The border colour in 0xAARRGGBB format + * @param borderSize The size of the border, in pixels. * @return This FlxBar object with generated image for rendering health bar background. */ - public function createColoredEmptyBar(empty:FlxColor, showBorder:Bool = false, border:FlxColor = FlxColor.WHITE):FlxBar + public function createColoredEmptyBar(empty:FlxColor, showBorder:Bool = false, border:FlxColor = FlxColor.WHITE, borderSize:Int = 1):FlxBar { if (FlxG.renderTile) { var emptyKey:String = "empty: " + barWidth + "x" + barHeight + ":" + empty.toHexString(); if (showBorder) - emptyKey += ",border: " + border.toHexString(); + emptyKey += ",border: " + border.toHexString() + "borderSize: " + borderSize; if (!FlxG.bitmap.checkCache(emptyKey)) { @@ -363,7 +365,7 @@ class FlxBar extends FlxSprite if (showBorder) { emptyBar = new BitmapData(barWidth, barHeight, true, border); - emptyBar.fillRect(new Rectangle(1, 1, barWidth - 2, barHeight - 2), empty); + emptyBar.fillRect(new Rectangle(borderSize, borderSize, barWidth - borderSize * 2, barHeight - borderSize * 2), empty); } else { @@ -380,7 +382,7 @@ class FlxBar extends FlxSprite if (showBorder) { _emptyBar = new BitmapData(barWidth, barHeight, true, border); - _emptyBar.fillRect(new Rectangle(1, 1, barWidth - 2, barHeight - 2), empty); + _emptyBar.fillRect(new Rectangle(borderSize, borderSize, barWidth - borderSize * 2, barHeight - borderSize * 2), empty); } else { @@ -395,19 +397,20 @@ class FlxBar extends FlxSprite } /** - * Creates a solid-colour filled foreground for health bar in the given colour, with optional 1px thick border. + * Creates a solid-colour filled foreground for health bar in the given colour, with optional border. * @param fill The color of the bar when full in 0xAARRGGBB format (the foreground colour) - * @param showBorder Should the bar be outlined with a 1px solid border? + * @param showBorder Should the bar be outlined with a solid border? * @param border The border colour in 0xAARRGGBB format + * @param borderSize The size of the border, in pixels. * @return This FlxBar object with generated image for rendering actual values. */ - public function createColoredFilledBar(fill:FlxColor, showBorder:Bool = false, border:FlxColor = FlxColor.WHITE):FlxBar + public function createColoredFilledBar(fill:FlxColor, showBorder:Bool = false, border:FlxColor = FlxColor.WHITE, borderSize:Int = 1):FlxBar { if (FlxG.renderTile) { var filledKey:String = "filled: " + barWidth + "x" + barHeight + ":" + fill.toHexString(); if (showBorder) - filledKey += ",border: " + border.toHexString(); + filledKey += ",border: " + border.toHexString() + "borderSize: " + borderSize; if (!FlxG.bitmap.checkCache(filledKey)) { @@ -416,7 +419,7 @@ class FlxBar extends FlxSprite if (showBorder) { filledBar = new BitmapData(barWidth, barHeight, true, border); - filledBar.fillRect(new Rectangle(1, 1, barWidth - 2, barHeight - 2), fill); + filledBar.fillRect(new Rectangle(borderSize, borderSize, barWidth - borderSize * 2, barHeight - borderSize * 2), fill); } else { @@ -433,7 +436,7 @@ class FlxBar extends FlxSprite if (showBorder) { _filledBar = new BitmapData(barWidth, barHeight, true, border); - _filledBar.fillRect(new Rectangle(1, 1, barWidth - 2, barHeight - 2), fill); + _filledBar.fillRect(new Rectangle(borderSize, borderSize, barWidth - borderSize * 2, barHeight - borderSize * 2), fill); } else { @@ -447,37 +450,39 @@ class FlxBar extends FlxSprite } /** - * Creates a gradient filled health bar using the given colour ranges, with optional 1px thick border. + * Creates a gradient filled health bar using the given colour ranges, with optional border. * All colour values are in 0xAARRGGBB format, so if you want a slightly transparent health bar give it lower AA values. * * @param empty Array of colour values used to create the gradient of the health bar when empty, each colour must be in 0xAARRGGBB format (the background colour) * @param fill Array of colour values used to create the gradient of the health bar when full, each colour must be in 0xAARRGGBB format (the foreground colour) * @param chunkSize If you want a more old-skool looking chunky gradient, increase this value! * @param rotation Angle of the gradient in degrees. 90 = top to bottom, 180 = left to right. Any angle is valid - * @param showBorder Should the bar be outlined with a 1px solid border? + * @param showBorder Should the bar be outlined with a solid border? * @param border The border colour in 0xAARRGGBB format + * @param borderSize The size of the border, in pixels. * @return This FlxBar object with generated images for front and background. */ public function createGradientBar(empty:Array, fill:Array, chunkSize:Int = 1, rotation:Int = 180, showBorder:Bool = false, - border:FlxColor = FlxColor.WHITE):FlxBar + border:FlxColor = FlxColor.WHITE, borderSize:Int = 1):FlxBar { - createGradientEmptyBar(empty, chunkSize, rotation, showBorder, border); - createGradientFilledBar(fill, chunkSize, rotation, showBorder, border); + createGradientEmptyBar(empty, chunkSize, rotation, showBorder, border, borderSize); + createGradientFilledBar(fill, chunkSize, rotation, showBorder, border, borderSize); return this; } /** - * Creates a gradient filled background for health bar using the given colour range, with optional 1px thick border. + * Creates a gradient filled background for health bar using the given colour range, with optional border. * * @param empty Array of colour values used to create the gradient of the health bar when empty, each colour must be in 0xAARRGGBB format (the background colour) * @param chunkSize If you want a more old-skool looking chunky gradient, increase this value! * @param rotation Angle of the gradient in degrees. 90 = top to bottom, 180 = left to right. Any angle is valid - * @param showBorder Should the bar be outlined with a 1px solid border? + * @param showBorder Should the bar be outlined with a solid border? * @param border The border colour in 0xAARRGGBB format + * @param borderSize The size of the border, in pixels. * @return This FlxBar object with generated image for background rendering. */ public function createGradientEmptyBar(empty:Array, chunkSize:Int = 1, rotation:Int = 180, showBorder:Bool = false, - border:FlxColor = FlxColor.WHITE):FlxBar + border:FlxColor = FlxColor.WHITE, borderSize:Int = 1):FlxBar { if (FlxG.renderTile) { @@ -490,7 +495,7 @@ class FlxBar extends FlxSprite if (showBorder) { - emptyKey += ",border: " + border.toHexString(); + emptyKey += ",border: " + border.toHexString() + "borderSize: " + borderSize; } if (!FlxG.bitmap.checkCache(emptyKey)) @@ -500,7 +505,8 @@ class FlxBar extends FlxSprite if (showBorder) { emptyBar = new BitmapData(barWidth, barHeight, true, border); - FlxGradient.overlayGradientOnBitmapData(emptyBar, barWidth - 2, barHeight - 2, empty, 1, 1, chunkSize, rotation); + FlxGradient.overlayGradientOnBitmapData(emptyBar, barWidth - borderSize * 2, barHeight - borderSize * 2, empty, borderSize, borderSize, + chunkSize, rotation); } else { @@ -517,7 +523,8 @@ class FlxBar extends FlxSprite if (showBorder) { _emptyBar = new BitmapData(barWidth, barHeight, true, border); - FlxGradient.overlayGradientOnBitmapData(_emptyBar, barWidth - 2, barHeight - 2, empty, 1, 1, chunkSize, rotation); + FlxGradient.overlayGradientOnBitmapData(_emptyBar, barWidth - borderSize * 2, barHeight - borderSize * 2, empty, borderSize, borderSize, + chunkSize, rotation); } else { @@ -532,17 +539,18 @@ class FlxBar extends FlxSprite } /** - * Creates a gradient filled foreground for health bar using the given colour range, with optional 1px thick border. + * Creates a gradient filled foreground for health bar using the given colour range, with optional border. * * @param fill Array of colour values used to create the gradient of the health bar when full, each colour must be in 0xAARRGGBB format (the foreground colour) * @param chunkSize If you want a more old-skool looking chunky gradient, increase this value! * @param rotation Angle of the gradient in degrees. 90 = top to bottom, 180 = left to right. Any angle is valid - * @param showBorder Should the bar be outlined with a 1px solid border? + * @param showBorder Should the bar be outlined with a solid border? * @param border The border colour in 0xAARRGGBB format + * @param borderSize The size of the border, in pixels. * @return This FlxBar object with generated image for rendering actual values. */ public function createGradientFilledBar(fill:Array, chunkSize:Int = 1, rotation:Int = 180, showBorder:Bool = false, - border:FlxColor = FlxColor.WHITE):FlxBar + border:FlxColor = FlxColor.WHITE, borderSize:Int = 1):FlxBar { if (FlxG.renderTile) { @@ -555,7 +563,7 @@ class FlxBar extends FlxSprite if (showBorder) { - filledKey += ",border: " + border.toHexString(); + filledKey += ",border: " + border.toHexString() + "borderSize: " + borderSize; } if (!FlxG.bitmap.checkCache(filledKey)) @@ -565,7 +573,8 @@ class FlxBar extends FlxSprite if (showBorder) { filledBar = new BitmapData(barWidth, barHeight, true, border); - FlxGradient.overlayGradientOnBitmapData(filledBar, barWidth - 2, barHeight - 2, fill, 1, 1, chunkSize, rotation); + FlxGradient.overlayGradientOnBitmapData(filledBar, barWidth - borderSize * 2, barHeight - borderSize * 2, fill, borderSize, borderSize, + chunkSize, rotation); } else { @@ -582,7 +591,8 @@ class FlxBar extends FlxSprite if (showBorder) { _filledBar = new BitmapData(barWidth, barHeight, true, border); - FlxGradient.overlayGradientOnBitmapData(_filledBar, barWidth - 2, barHeight - 2, fill, 1, 1, chunkSize, rotation); + FlxGradient.overlayGradientOnBitmapData(_filledBar, barWidth - borderSize * 2, barHeight - borderSize * 2, fill, borderSize, borderSize, + chunkSize, rotation); } else { From 32d4c35d29399edeb4f1da29232de1fb3faf6a52 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 3 Sep 2024 13:17:30 -0400 Subject: [PATCH 40/99] fix for html5 arrow keys not working on the console (#3247) --- flixel/system/debug/console/Console.hx | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/flixel/system/debug/console/Console.hx b/flixel/system/debug/console/Console.hx index 638e543b84..0a01140ed8 100644 --- a/flixel/system/debug/console/Console.hx +++ b/flixel/system/debug/console/Console.hx @@ -218,6 +218,24 @@ class Console extends Window if (!history.isEmpty) setText(history.getPreviousCommand()); + #if html5 + // FlxKeyboard.preventDefaultKeys adds "preventDefault" on HTML5 + // so it ends up not fully propegating our inputs to the stage/event listeners + // we do this small work around so we don't need to mess around with lime/openfl events + // todo: support the modifier keys + case Keyboard.RIGHT: + if (FlxG.keys.preventDefaultKeys.contains(Keyboard.RIGHT)) + { + @:privateAccess + input.window_onKeyDown(RIGHT, 0); + } + case Keyboard.LEFT: + if (FlxG.keys.preventDefaultKeys.contains(Keyboard.LEFT)) + { + @:privateAccess + input.window_onKeyDown(LEFT, 0); + } + #end case Keyboard.DOWN: if (!history.isEmpty) setText(history.getNextCommand()); From f2b090d6c608471e730b051c8ee22b8b378964b1 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 9 Sep 2024 13:00:28 -0400 Subject: [PATCH 41/99] logarithmic volume control for SoundTray --- flixel/FlxObject.hx | 150 +++++++++++------------ flixel/system/frontEnds/SoundFrontEnd.hx | 32 +++-- flixel/system/ui/FlxSoundTray.hx | 2 +- 3 files changed, 101 insertions(+), 83 deletions(-) diff --git a/flixel/FlxObject.hx b/flixel/FlxObject.hx index 3acd654348..1fa9f792b9 100644 --- a/flixel/FlxObject.hx +++ b/flixel/FlxObject.hx @@ -18,7 +18,7 @@ import flixel.util.FlxStringUtil; * At their core `FlxObjects` are just boxes with positions that can move and collide with other * objects. Most games utilize `FlxObject's` features through [FlxSprite](https://api.haxeflixel.com/flixel/FlxSprite.html), * which extends `FlxObject` directly and adds graphical capabilities. - * + * * ## Motion * Whenever `update` is called, objects with `move` set to true will update their positions based * on the following properties: @@ -30,17 +30,17 @@ import flixel.util.FlxStringUtil; * - `angle`: The orientation, in degrees, of this `object`. Does not affect collision, mainly * used for `FlxSprite` graphics. * - `angularVelocity`: The rotational speed of the object in degrees per second. - * + * * ## Overlaps * If you're only checking an overlap between two objects you can use `player.overlaps(door)` * or `player.overlaps(spikeGroup)`. You can check if two objects or groups of object overlap * with [FlxG.overlap](https://api.haxeflixel.com/flixel/FlxG.html#overlap). - * + * * Example: * ```haxe * if (FlxG.overlap(playerGroup, spikeGroup)) trace("overlap!"); * ``` - * + * * You can also specify a callback to handle which specific objects collided: * ```haxe * FlxG.overlap(playerGroup, medKitGroup @@ -51,11 +51,11 @@ import flixel.util.FlxStringUtil; * } * ); * ``` - * + * * Additional resources: * - [Snippets - Simple Overlap](https://snippets.haxeflixel.com/overlap/simple-overlap/) * - [Snippets - Overlap Callbacks](https://snippets.haxeflixel.com/overlap/overlap-callbacks/) - * + * * ## Collision * `FlxG.collide` is similar to `FlxG.overlap` except it resolves the overlap by separating their * positions before calling the callback. Typically collide is called on an update loop like so: @@ -65,7 +65,7 @@ import flixel.util.FlxStringUtil; * This takes the player's and crate's momentum and previous and current position in consideration * when resolving overlaps between them. Like `overlap` collide will return true if any objects * were overlapping, and you can specify a callback. - * + * * Additional resources: * - [Snippets - 1 to 1 Collision](https://snippets.haxeflixel.com/collision/1-to-1-collision/) * - [Demos - FlxCollisions](https://haxeflixel.com/demos/FlxCollisions/) @@ -92,7 +92,7 @@ class FlxObject extends FlxBasic * @since 5.6.0 */ public static var defaultMoves:Bool = true; - + static function allowCollisionDrag(type:CollisionDragType, object1:FlxObject, object2:FlxObject):Bool { return object2.active && object2.moves && switch (type) @@ -103,15 +103,15 @@ class FlxObject extends FlxBasic case HEAVIER: object2.immovable || object2.mass > object1.mass; } } - + /** * Internal elper that determines whether either object is a tilemap, determines * which tiles are overlapping and calls the appropriate separator - * - * - * + * + * + * * @param func The process you wish to call with both objects, or between tiles, - * + * * @param isCollision Does nothing, if both objects are immovable * @return The result of whichever separator was used * @since 5.9.0 @@ -123,7 +123,7 @@ class FlxObject extends FlxBasic // two immovable objects cannot collide if (isCollision && object1.immovable && object2.immovable) return false; - + // If one of the objects is a tilemap, just pass it off. if (object1.flixelType == TILEMAP) { @@ -147,14 +147,14 @@ class FlxObject extends FlxBasic } return tilemap.overlapsWithCallback(object1, recurseProcess, false, position); } - + return func(object1, object2); } - + /** * Separates 2 overlapping objects. If an object is a tilemap, * it will separate it from any tiles that overlap it. - * + * * @return Whether the objects were overlapping and were separated */ public static function separate(object1:FlxObject, object2:FlxObject):Bool @@ -162,7 +162,7 @@ class FlxObject extends FlxBasic final separatedX = separateX(object1, object2); final separatedY = separateY(object1, object2); return separatedX || separatedY; - + /* * Note: can't do the following, FlxTilemapExt works better when you separate all * tiles in the x and then all tiles the y, rather than iterating all overlapping @@ -177,29 +177,29 @@ class FlxObject extends FlxBasic // } // return processCheckTilemap(object1, object2, helper); } - + /** * Separates 2 overlapping objects along the X-axis. if an object is a tilemap, * it will separate it from any tiles that overlap it. - * + * * @return Whether the objects were overlapping and were separated along the X-axis */ public static function separateX(object1:FlxObject, object2:FlxObject):Bool { return processCheckTilemap(object1, object2, separateXHelper); } - + /** * Separates 2 overlapping objects along the Y-axis. if an object is a tilemap, * it will separate it from any tiles that overlap it. - * + * * @return Whether the objects were overlapping and were separated along the Y-axis */ public static function separateY(object1:FlxObject, object2:FlxObject):Bool { return processCheckTilemap(object1, object2, separateYHelper); } - + /** * Same as `separateX` but assumes both are not immovable and not tilemaps */ @@ -213,7 +213,7 @@ class FlxObject extends FlxBasic final delta2 = object2.x - object2.last.x; final vel1 = object1.velocity.x; final vel2 = object2.velocity.x; - + if (!object1.immovable && !object2.immovable) { #if FLX_4_LEGACY_COLLISION @@ -221,7 +221,7 @@ class FlxObject extends FlxBasic #else object1.x -= overlap * 0.5; object2.x += overlap * 0.5; - + final mass1 = object1.mass; final mass2 = object2.mass; final momentum = mass1 * vel1 + mass2 * vel2; @@ -239,19 +239,19 @@ class FlxObject extends FlxBasic object2.x += overlap; object2.velocity.x = vel1 - vel2 * object2.elasticity; } - + // use collisionDrag properties to determine whether one object if (allowCollisionDrag(object1.collisionYDrag, object1, object2) && delta1 > delta2) object1.y += object2.y - object2.last.y; else if (allowCollisionDrag(object2.collisionYDrag, object2, object1) && delta2 > delta1) object2.y += object1.y - object1.last.y; - + return true; } - + return false; } - + /** * Same as `separateY` but assumes both are not immovable and not tilemaps */ @@ -265,7 +265,7 @@ class FlxObject extends FlxBasic final delta2 = object2.y - object2.last.y; final vel1 = object1.velocity.y; final vel2 = object2.velocity.y; - + if (!object1.immovable && !object2.immovable) { #if FLX_4_LEGACY_COLLISION @@ -273,7 +273,7 @@ class FlxObject extends FlxBasic #else object1.y -= overlap / 2; object2.y += overlap / 2; - + final mass1 = object1.mass; final mass2 = object2.mass; final momentum = mass1 * vel1 + mass2 * vel2; @@ -293,19 +293,19 @@ class FlxObject extends FlxBasic object2.y += overlap; object2.velocity.y = vel1 - vel2 * object2.elasticity; } - + // use collisionDrag properties to determine whether one object if (allowCollisionDrag(object1.collisionXDrag, object1, object2) && delta1 > delta2) object1.x += object2.x - object2.last.x; else if (allowCollisionDrag(object2.collisionXDrag, object2, object1) && delta2 > delta1) object2.x += object1.x - object1.last.x; - + return true; } - + return false; } - + /** * The separateX that existed before HaxeFlixel 5.0, preserved for anyone who * needs to use it in an old project. Does not preserve momentum, avoid if possible @@ -318,7 +318,7 @@ class FlxObject extends FlxBasic final mass2 = object2.mass; object1.x = object1.x - (overlap * 0.5); object2.x += overlap * 0.5; - + var newVel1 = Math.sqrt((vel2 * vel2 * mass2) / mass1) * ((vel2 > 0) ? 1 : -1); var newVel2 = Math.sqrt((vel1 * vel1 * mass1) / mass2) * ((vel1 > 0) ? 1 : -1); final average = (newVel1 + newVel2) * 0.5; @@ -327,7 +327,7 @@ class FlxObject extends FlxBasic object1.velocity.x = average + (newVel1 * object1.elasticity); object2.velocity.x = average + (newVel2 * object2.elasticity); } - + /** * The separateY that existed before HaxeFlixel 5.0, preserved for anyone who * needs to use it in an old project. Does not preserve momentum, avoid if possible @@ -340,7 +340,7 @@ class FlxObject extends FlxBasic final mass2 = object2.mass; object1.y = object1.y - (overlap * 0.5); object2.y += overlap * 0.5; - + var newVel1 = Math.sqrt((vel2 * vel2 * mass2) / mass1) * ((vel2 > 0) ? 1 : -1); var newVel2 = Math.sqrt((vel1 * vel1 * mass1) / mass2) * ((vel1 > 0) ? 1 : -1); final average = (newVel1 + newVel2) * 0.5; @@ -349,11 +349,11 @@ class FlxObject extends FlxBasic object1.velocity.y = average + (newVel1 * object1.elasticity); object2.velocity.y = average + (newVel2 * object2.elasticity); } - + /** * Checks two objects for overlaps and sets their touching flags, accordingly. * If either object may be a tilemap, this will check the object against individual tiles - * + * * @return Whether the objects in fact touched */ public static function updateTouchingFlags(object1:FlxObject, object2:FlxObject):Bool @@ -366,24 +366,24 @@ class FlxObject extends FlxBasic } return processCheckTilemap(object1, object2, helper, false); } - + /** * Checks two objects for overlaps in the X-axis and sets their touching flags, accordingly. * If either object may be a tilemap, this will check the object against individual tiles - * + * * @return Whether the objects are overlapping in the X-axis */ public static function updateTouchingFlagsX(object1:FlxObject, object2:FlxObject):Bool { return processCheckTilemap(object1, object2, updateTouchingFlagsXHelper, false); } - + static function updateTouchingFlagsXHelper(object1:FlxObject, object2:FlxObject):Bool { // Since we are not separating, always return any amount of overlap => false as last parameter return computeOverlapX(object1, object2, false) != 0; } - + /** * Checks two objects for overlaps in the Y-axis and sets their touching flags, accordingly. * If either object may be a tilemap, this will check the object against individual tiles @@ -394,13 +394,13 @@ class FlxObject extends FlxBasic { return processCheckTilemap(object1, object2, updateTouchingFlagsYHelper, false); } - + static function updateTouchingFlagsYHelper(object1:FlxObject, object2:FlxObject):Bool { // Since we are not separating, always return any amount of overlap => false as last parameter return computeOverlapY(object1, object2, false) != 0; } - + /** * Internal function that computes overlap among two objects on the X axis. It also updates the `touching` variable. * `checkMaxOverlap` is used to determine whether we want to exclude (therefore check) overlaps which are @@ -421,16 +421,16 @@ class FlxObject extends FlxBasic final rect1 = FlxRect.get(object1.x - (delta1 > 0 ? delta1 : 0), object1.last.y, object1.width + delta1Abs, object1.height); final rect2 = FlxRect.get(object2.x - (delta2 > 0 ? delta2 : 0), object2.last.y, object2.width + delta2Abs, object2.height); - + if (rect1.overlaps(rect2)) { final maxOverlap:Float = checkMaxOverlap ? (delta1Abs + delta2Abs + SEPARATE_BIAS) : 0; - + inline function canCollide(obj:FlxObject, dir:FlxDirectionFlags) { return obj.allowCollisions.has(dir); } - + // If they do overlap (and can), figure out by how much and flip the corresponding flags if (delta1 > delta2) { @@ -463,14 +463,14 @@ class FlxObject extends FlxBasic } } } - + rect1.put(); rect2.put(); } - + return overlap; } - + /** * Internal function that computes overlap among two objects on the Y axis. It also updates the `touching` variable. * `checkMaxOverlap` is used to determine whether we want to exclude (therefore check) overlaps which are @@ -488,19 +488,19 @@ class FlxObject extends FlxBasic // Check if the Y hulls actually overlap final delta1Abs:Float = (delta1 > 0) ? delta1 : -delta1; final delta2Abs:Float = (delta2 > 0) ? delta2 : -delta2; - + final rect1 = FlxRect.get(object1.last.x, object1.y - (delta1 > 0 ? delta1 : 0), object1.width, object1.height + delta1Abs); final rect2 = FlxRect.get(object2.last.x, object2.y - (delta2 > 0 ? delta2 : 0), object2.width, object2.height + delta2Abs); if (rect1.overlaps(rect2)) { final maxOverlap:Float = checkMaxOverlap ? (delta1Abs + delta2Abs + SEPARATE_BIAS) : 0; - + inline function canCollide(obj:FlxObject, dir:FlxDirectionFlags) { return obj.allowCollisions.has(dir); } - + // If they did overlap (and can), figure out by how much and flip the corresponding flags if (delta1 > delta2) { @@ -533,14 +533,14 @@ class FlxObject extends FlxBasic } } } - + rect1.put(); rect2.put(); } - + return overlap; } - + /** * X position of the upper left corner of this object in world space. */ @@ -920,7 +920,7 @@ class FlxObject extends FlxBasic if (camera == null) camera = getDefaultCamera(); - + var objectScreenPos:FlxPoint = object.getScreenPosition(null, camera); getScreenPosition(_point, camera); return (objectScreenPos.x + object.width > _point.x) @@ -979,7 +979,7 @@ class FlxObject extends FlxBasic if (camera == null) camera = getDefaultCamera(); - + var objectScreenPos:FlxPoint = object.getScreenPosition(null, camera); getScreenPosition(_point, camera); return (objectScreenPos.x + object.width > _point.x) @@ -1011,7 +1011,7 @@ class FlxObject extends FlxBasic if (camera == null) camera = getDefaultCamera(); - + final xPos:Float = point.x - camera.scroll.x; final yPos:Float = point.y - camera.scroll.y; getScreenPosition(_point, camera); @@ -1054,7 +1054,7 @@ class FlxObject extends FlxBasic /** * Returns the world position of this object. - * + * * @param result Optional arg for the returning point. * @return The world position of this object. */ @@ -1062,7 +1062,7 @@ class FlxObject extends FlxBasic { if (result == null) result = FlxPoint.get(); - + return result.set(x, y); } @@ -1172,7 +1172,7 @@ class FlxObject extends FlxBasic /** * Centers this `FlxObject` on the screen, either by the x axis, y axis, or both. * - * @param axes On what axes to center the object (e.g. `X`, `Y`, `XY`) - default is both. + * @param axes On what axes to center the object (e.g. `X`, `Y`, `XY`) - default is both. * @return This FlxObject for chaining */ public inline function screenCenter(axes:FlxAxes = XY):FlxObject @@ -1216,13 +1216,13 @@ class FlxObject extends FlxBasic { if (ignoreDrawDebug) return; - + final drawPath = path != null && !path.ignoreDrawDebug; - + for (camera in getCamerasLegacy()) { drawDebugOnCamera(camera); - + if (drawPath) { path.drawDebugOnCamera(camera); @@ -1253,22 +1253,22 @@ class FlxObject extends FlxBasic final color = getDebugBoundingBoxColor(allowCollisions); drawDebugBoundingBoxColor(gfx, rect, color); } - + function getDebugBoundingBoxColor(allowCollisions:Int) { if (debugBoundingBoxColor != null) return debugBoundingBoxColor; - + if (allowCollisions == FlxDirectionFlags.NONE) return debugBoundingBoxColorNotSolid; - + if (allowCollisions == FlxDirectionFlags.ANY) return debugBoundingBoxColorSolid; - + return debugBoundingBoxColorPartial; - + } - + function drawDebugBoundingBoxColor(gfx:Graphics, rect:FlxRect, color:FlxColor) { // fill static graphics object with square shape @@ -1311,7 +1311,7 @@ class FlxObject extends FlxBasic return _rect; } - + /** * Calculates the smallest globally aligned bounding box that encompasses this * object's width and height, at its current rotation. @@ -1325,7 +1325,7 @@ class FlxObject extends FlxBasic { if (newRect == null) newRect = FlxRect.get(); - + newRect.set(x, y, width, height); return newRect.getRotatedBounds(angle, null, newRect); } diff --git a/flixel/system/frontEnds/SoundFrontEnd.hx b/flixel/system/frontEnds/SoundFrontEnd.hx index 9784d759bb..7bdf47da04 100644 --- a/flixel/system/frontEnds/SoundFrontEnd.hx +++ b/flixel/system/frontEnds/SoundFrontEnd.hx @@ -70,14 +70,14 @@ class SoundFrontEnd * volumeUp-, volumeDown- or muteKeys is pressed. */ public var soundTrayEnabled:Bool = true; - + #if FLX_SOUND_TRAY /** * The sound tray display container. * A getter for `FlxG.game.soundTray`. */ public var soundTray(get, never):FlxSoundTray; - + inline function get_soundTray() { return FlxG.game.soundTray; @@ -116,7 +116,7 @@ class SoundFrontEnd { if (group == null) group = defaultMusicGroup; - + if (music == null) { music = new FlxSound(); @@ -125,7 +125,7 @@ class SoundFrontEnd { music.stop(); } - + music.loadEmbedded(embeddedMusic, looped); music.volume = volume; music.persist = true; @@ -193,13 +193,13 @@ class SoundFrontEnd { if (group == null) group = defaultSoundGroup; - + sound.volume = volume; group.add(sound); - + if (autoPlay) sound.play(); - + return sound; } @@ -357,10 +357,28 @@ class SoundFrontEnd public function changeVolume(Amount:Float):Void { muted = false; + volume = logToLinear(volume); volume += Amount; + volume = linearToLog(volume); showSoundTray(Amount > 0); } + public function linearToLog(x:Float, minValue:Float = 0.001):Float { + // Ensure x is between 0 and 1 + x = Math.max(0, Math.min(1, x)); + + // Convert linear scale to logarithmic + return Math.exp(Math.log(minValue) * (1 - x)); + } + + public function logToLinear(x:Float, minValue:Float = 0.001):Float { + // Ensure x is between minValue and 1 + x = Math.max(minValue, Math.min(1, x)); + + // Convert logarithmic scale to linear + return 1 - (Math.log(x) / Math.log(minValue)); + } + /** * Shows the sound tray if it is enabled. * @param up Whether or not the volume is increasing. diff --git a/flixel/system/ui/FlxSoundTray.hx b/flixel/system/ui/FlxSoundTray.hx index a5492bca4d..62869efc85 100644 --- a/flixel/system/ui/FlxSoundTray.hx +++ b/flixel/system/ui/FlxSoundTray.hx @@ -157,7 +157,7 @@ class FlxSoundTray extends Sprite y = 0; visible = true; active = true; - var globalVolume:Int = Math.round(FlxG.sound.volume * 10); + var globalVolume:Int = Math.round(FlxG.sound.logToLinear(FlxG.sound.volume) * 10); if (FlxG.sound.muted) { From 6bc06aa2c54cbaea7bae29fe88c2a862ff5b5e44 Mon Sep 17 00:00:00 2001 From: DetectiveBaldi <86160807+DetectiveBaldi@users.noreply.github.com> Date: Thu, 19 Sep 2024 15:04:39 -0400 Subject: [PATCH 42/99] 1 line patch? (#3254) --- flixel/system/frontEnds/CameraFrontEnd.hx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/flixel/system/frontEnds/CameraFrontEnd.hx b/flixel/system/frontEnds/CameraFrontEnd.hx index 2ae337d044..a343747f49 100644 --- a/flixel/system/frontEnds/CameraFrontEnd.hx +++ b/flixel/system/frontEnds/CameraFrontEnd.hx @@ -143,6 +143,8 @@ class CameraFrontEnd */ public function reset(?NewCamera:FlxCamera):Void { + FlxG.camera = null; + while (list.length > 0) remove(list[0]); From 4b054883be168d488157457b7041876ab0aff2c2 Mon Sep 17 00:00:00 2001 From: Mihai Alexandru <77043862+MAJigsaw77@users.noreply.github.com> Date: Thu, 19 Sep 2024 20:07:44 +0000 Subject: [PATCH 43/99] Fixed a small issue with android config on lime 8.2.0. (#3253) * Update include.xml * Using `≥` isn't supported? --- include.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include.xml b/include.xml index d0c2a32b00..e1cb529dbf 100644 --- a/include.xml +++ b/include.xml @@ -47,9 +47,9 @@ -
+
- +
From a7b8d9cddcba9232b0945e3b10d61171cbbcaea5 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 24 Sep 2024 14:20:10 -0400 Subject: [PATCH 44/99] Resize the debug watch window whenever something gets added / removed (#3251) * Resize the watch window whenever something gets added / removed * reposition window after it resizes, incase we are out of bounds * fix CI * remove reposition * add reposition back --------- Co-authored-by: George FunBook --- flixel/system/debug/watch/Watch.hx | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/flixel/system/debug/watch/Watch.hx b/flixel/system/debug/watch/Watch.hx index ff50592790..a2a0811095 100644 --- a/flixel/system/debug/watch/Watch.hx +++ b/flixel/system/debug/watch/Watch.hx @@ -30,7 +30,7 @@ class Watch extends Window entriesContainer.y = entriesContainerOffset.y; addChild(entriesContainer); - FlxG.signals.preStateSwitch.add(removeAll); + FlxG.signals.preStateSwitch.add(clear); } public function add(displayName:String, data:WatchEntryData):Void @@ -87,7 +87,7 @@ class Watch extends Window var entry = new WatchEntry(displayName, data, removeEntry); entries.push(entry); entriesContainer.addChild(entry); - resetEntries(); + updateSize(); } public function remove(displayName:String, data:WatchEntryData):Void @@ -102,19 +102,27 @@ class Watch extends Window entries.fastSplice(entry); entriesContainer.removeChild(entry); entry.destroy(); - resetEntries(); + updateSize(); } - public function removeAll():Void + /** + * internal method to remove all without calling updateSize + */ + function clear():Void { - for (i in 0...entries.length) + for (entry in entries) { - var entry = entries[i]; entriesContainer.removeChild(entry); entry.destroy(); } - entries.splice(0, entries.length); - resetEntries(); + + entries.resize(0); + } + + public function removeAll():Void + { + clear(); + updateSize(); } override public function update():Void @@ -125,9 +133,10 @@ class Watch extends Window override function updateSize():Void { + resetEntries(); minSize.setTo(getMaxMinWidth() + entriesContainerOffset.x, entriesContainer.height + entriesContainerOffset.y); super.updateSize(); - resetEntries(); + reposition(x, y); } function resetEntries():Void From 096a7df6b6ee483b171bd77367df5c2853cd6b83 Mon Sep 17 00:00:00 2001 From: Vortex <73261680+Vortex2Oblivion@users.noreply.github.com> Date: Thu, 26 Sep 2024 21:02:44 +0000 Subject: [PATCH 45/99] oxipng all assets (#3257) --- assets/images/debugger/buttons/arrowLeft.png | Bin 122 -> 101 bytes assets/images/debugger/buttons/bitmapLog.png | Bin 117 -> 96 bytes assets/images/debugger/buttons/close.png | Bin 163 -> 142 bytes assets/images/debugger/buttons/console.png | Bin 123 -> 102 bytes assets/images/debugger/buttons/eraser.png | Bin 125 -> 104 bytes .../images/debugger/buttons/interactive.png | Bin 151 -> 130 bytes assets/images/debugger/buttons/log.png | Bin 99 -> 75 bytes assets/images/debugger/buttons/maximize.png | Bin 120 -> 99 bytes assets/images/debugger/buttons/minimize.png | Bin 123 -> 102 bytes assets/images/debugger/buttons/mover.png | Bin 149 -> 128 bytes assets/images/debugger/buttons/pause.png | Bin 78 -> 75 bytes assets/images/debugger/buttons/pointer.png | Bin 115 -> 91 bytes assets/images/debugger/buttons/stats.png | Bin 105 -> 83 bytes assets/images/debugger/buttons/toggleSize.png | Bin 99 -> 78 bytes assets/images/debugger/buttons/transform.png | Bin 117 -> 93 bytes assets/images/debugger/buttons/watch.png | Bin 230 -> 209 bytes assets/images/debugger/cursorCross.png | Bin 103 -> 79 bytes .../debugger/cursors/transformRotate.png | Bin 128 -> 107 bytes .../debugger/cursors/transformScaleX.png | Bin 130 -> 109 bytes .../debugger/cursors/transformScaleXY.png | Bin 110 -> 87 bytes .../debugger/cursors/transformScaleY.png | Bin 113 -> 90 bytes assets/images/debugger/flixel.png | Bin 340 -> 319 bytes assets/images/logo/default.png | Bin 505 -> 484 bytes assets/images/logo/logo.png | Bin 1083 -> 1062 bytes assets/images/tile/autotiles_full.png | Bin 409 -> 407 bytes assets/images/ui/button.png | Bin 277 -> 222 bytes assets/images/ui/virtual-input.png | Bin 29353 -> 29332 bytes images/platforms.png | Bin 6735 -> 6714 bytes images/showcase.png | Bin 239688 -> 239667 bytes 29 files changed, 0 insertions(+), 0 deletions(-) diff --git a/assets/images/debugger/buttons/arrowLeft.png b/assets/images/debugger/buttons/arrowLeft.png index dd4f2b5d5dc4c04cc24a535ca13d480637bd5237..9db907b7426b7976871b3cffedd4bfb4b39cad2a 100644 GIT binary patch delta 7 OcmbO>_%)r1c48n{Iv*t)lRCECVQ9A{+ diff --git a/assets/images/debugger/buttons/bitmapLog.png b/assets/images/debugger/buttons/bitmapLog.png index 3772a3bf52a1b9b2d1ee654289edbf087aedf4c6..01b92ea131eb170052a19f15db416f5716f71ec0 100644 GIT binary patch delta 7 OcmXR-n4mJz(gpwvI|7gZ delta 26 fcmYc&ouDGbS>O>_%)r1c48n{Iv*t)lRI~>GP&Wmo diff --git a/assets/images/debugger/buttons/close.png b/assets/images/debugger/buttons/close.png index 97435a31fcd5071f7047b69d53fdfd6fee7704f2..ee3f129222e6bb1dce3ca9ea7ed7dc12e8f49d23 100644 GIT binary patch delta 9 QcmZ3?*vB|QWuj#k01u-B8~^|S delta 28 hcmeBUT+BE@MToP&BeIx*fuRh98U3o&I3_CQ0svvy28sXx diff --git a/assets/images/debugger/buttons/console.png b/assets/images/debugger/buttons/console.png index c01b4820c792823d80a47094c2a45182be708c15..886391def9358da206e47d9fd0d3a12758ea0d84 100644 GIT binary patch delta 7 Ocmb3q delta 26 fcmYeRo}ePcS>O>_%)r1c48n{Iv*t)lRCEOZQEvse diff --git a/assets/images/debugger/buttons/eraser.png b/assets/images/debugger/buttons/eraser.png index 3afeb609e14cfd87087adb468cc36a304b62ca77..c1a66b2090f5ccd51c97972c3f240b3cc7db652f 100644 GIT binary patch delta 7 Ocmb=;n4mJz(ggqus{*J1 delta 26 fcmd0(ouDGbS>O>_%)r1c1j3A$?$-U8sOSy=Tnh)5 diff --git a/assets/images/debugger/buttons/interactive.png b/assets/images/debugger/buttons/interactive.png index 07c0e2153ffa404ca65164f66990eb61d9473d3c..d5be49d4f073dad73a23de19fee113eb18639ff5 100644 GIT binary patch delta 9 QcmbQv*u*$NWuj#q01npz_y7O^ delta 28 hcmZo-oX$8wMToP&BeIx*fm;ZK886+f`!i875ddQ(2j&0( diff --git a/assets/images/debugger/buttons/log.png b/assets/images/debugger/buttons/log.png index 22c7e58cc468c08196d39ad67b0e10660c6eeb4b..23c84b11a9cb1ea323735444b8e6a54b623d52b5 100644 GIT binary patch delta 55 zcmYfHo*-$&!oa}5ymbFsASLAK;uunKEBOHPzr_p_P8bC9GL)yd?hgMX=MR)+@O1Ta JS?83{1OU&Y5n2EM delta 79 zcmeZHo*?PP#=yX^a!t7!km4-xh%9Dc;1&j9Muu5)B!GgVo-U3d6}OTVxc?kyPRL?g ecyh5CGsB(y?o!De`73}57(8A5T-G@yGywqlwH3Mm diff --git a/assets/images/debugger/buttons/maximize.png b/assets/images/debugger/buttons/maximize.png index a7a091d1654a4708f5bcbb315b4c5967f2b0278e..efea3b550f5484850398c23a6c5a07c5c100dc82 100644 GIT binary patch delta 7 OcmbO>_%)r1<2EvSf)oL6Q6`cTACk6)q diff --git a/assets/images/debugger/buttons/minimize.png b/assets/images/debugger/buttons/minimize.png index 6be4754d3d6ce19eb23689c7c1a5b923bceea2fe..76db33fa59e3e1ab41ce3dbbdf4777555ce7a2e5 100644 GIT binary patch delta 7 Ocmb3q delta 26 ecmYeRo}ePcS>O>_%)r1<2EvSf)oL6Q6b*#=yX^a!t7!kP`KDaSW-rmHeZhO=1E=+np7U6xT^G2-d`HnEm?XZlD4N MPgg&ebxsLQ03CP}`v3p{ diff --git a/assets/images/debugger/buttons/pointer.png b/assets/images/debugger/buttons/pointer.png index 1443e67b913f4cecd50d3ef13015e2d5c2a3fd91..1f6da7ec0d8c143dedbc5c0e121fc56f941f341c 100644 GIT binary patch delta 71 zcmXSpo*?PO!oa}5ymbFsAf@E#;uunKEBOHDKV`->hay4`|7Zzi_AKF)VDIMhQYoks aWbpauxqbWm^*ey789ZJ6T-G@yGywobLl`>% delta 95 zcmazpo*)^;#=yX^a!t7!km4-xh%9Dc;1&X5#!GkW{s0A4JzX3_DsCk!Nd7s_*b(Nl u<)lI3tC>7W!dDvf9H;OyFK&Etf|+5l%H&+TuZev?4Gf;HelF{r5}E){h#wUI diff --git a/assets/images/debugger/buttons/stats.png b/assets/images/debugger/buttons/stats.png index 5c4a7173e073e4d9aaf873a11f1da475eb14b5c9..843b4899056d31017bb565010159c96a4cb56594 100644 GIT binary patch delta 63 zcmc}{o*-$(!oa}5ymbFsASLDL;uunKD|rFWA9kichd3BFwJQ32YAxI)$8bO2d9UO2 SD-(dK7(8A5T-G@yGywpUKNbN1 delta 85 zcmWH}oFEy%#=yX^a!t7!km4-xh%9Dc;1&j9Muu5)B!Gg_o-U3d6}OTlEI!C{X$1DH jZ1~qD*z_gbM~i{MiK)FZ-t*d8pfUzeS3j3^P6O>_%)r1<2EvSf)oL6Q6?Fkp;|0h7 diff --git a/assets/images/debugger/buttons/transform.png b/assets/images/debugger/buttons/transform.png index a81710440c8a5628b049d50086f757d6f09ad3d8..0fb049a1a44103d7f3a6fa870b4319347fe604f8 100644 GIT binary patch delta 73 zcmXSoognGL!oa}5ymbFsAf@8z;uunKE7^hl|3QXh4h$^@yRv)|HRhKcDwu5;^GRO& cz(Og8c+TXxN1V@C0o5~jy85}Sb4q9e0D;FD8UO$Q delta 97 zcmazoogf**#=yX^a!t7!km4-xh%9Dc;1&X5#!GkW{s0BlJzX3_DsCmGC@}nEW?aQE xkzt`UyMn7>*Pnpko`=y*3qQ_hahP6IaiV$akM`SSr1Gg{;GcwGYBQa5N0|0612KoR1 diff --git a/assets/images/debugger/cursorCross.png b/assets/images/debugger/cursorCross.png index 21275c359bc318d55ff283ebae5c268aa11904f7..a9a743d8cc7f6b9b6186610b498c4ffd70882b22 100644 GIT binary patch delta 59 zcmYfIpCD<*!oa}5ymbFsASLGM;uunKE7_sp|9`=pSzP~*bFm#zWmuP?dELnVhYnB$ NgQu&X%Q~loCIC8e6Vd;o09@7vw*UYD diff --git a/assets/images/debugger/cursors/transformScaleX.png b/assets/images/debugger/cursors/transformScaleX.png index 8422ad04f25b33d1baa8507af005cee4b157fb73..c1490b315f23864634549986d757c7e5903dad1a 100644 GIT binary patch delta 8 PcmZo-%$=Yz(b5wD40{5& delta 27 gcmd08Vw|8N#981GSB~c|Zud$Ma!C|NI VS=Lid2Z1UXJYD@<);T3K0RTeA65ap+ delta 90 zcmWH~n;;p=#=yYPYjl1ukm4-xh%5%uejv=a@vOWtkfGq|;uunKEBQx1n?wQQB9Vz} o1f*vxEa*>qRW)VF2UbRg-wNq7yAQ090;*;3boFyt=akR{0EDa@HUIzs diff --git a/assets/images/debugger/cursors/transformScaleY.png b/assets/images/debugger/cursors/transformScaleY.png index 05a8d5c1ffb1196515c687636a69d6f6bc536db2..7826244114530449292055bb498635a32ca16f54 100644 GIT binary patch delta 70 zcmXSnnjq=O!oa|wZq056q!c|}978H@B{wwwcVI|VY+1k%%MmQGaITW0lbB-5#|(A` Y4GH^$lGhHV0TnZNy85}Sb4q9e0Gv(~O#lD@ delta 93 zcmazloFEy&#=yYPYjl1ukm4-xh%5%uejv=a@vOWtkfH49;uunKE7^hl|H1}F`5*mk rAGDMf%-C?1dA-2G2A%nnQ%xBZMd}-Q??{^fl{0v{`njxgN@xNA-WMEM diff --git a/assets/images/debugger/flixel.png b/assets/images/debugger/flixel.png index 7a5fafd825b2b7f75009b58e4ca3f939e81b1eae..8d3764299cfad8278c93a4be4740ac125899ed5c 100644 GIT binary patch delta 10 Rcmcb@w4Z5$@W@fk$L90|U1Z2s2)~TlZ(9q8uXtdhiH9 diff --git a/assets/images/logo/default.png b/assets/images/logo/default.png index e0376d6b217b72d8d8a4e9ef01e11b9e9c366541..7a684e86dfc927a4cea8d6cb6fce58d1563bf767 100644 GIT binary patch delta 10 Rcmey#{DgUe@W@fk$L90|Vb75M~tB@M_qoc$g6Yha(7e diff --git a/assets/images/logo/logo.png b/assets/images/logo/logo.png index e6a78d18cfc17f80442599e9288879cf9f91c728..03b6adde02caf3c329c99b1bf63aae3c5acbbd85 100644 GIT binary patch delta 10 RcmdnZv5aGa@W@fk$L90|U1(2s1Lwnj^7Mk(C7iYFY*> diff --git a/assets/images/tile/autotiles_full.png b/assets/images/tile/autotiles_full.png index e2f24583213a64c04ba3248ab662d4b9e1404e59..f1886f6f02cb8e65e84f447be59ff64074b27eeb 100644 GIT binary patch delta 375 zcmV--0f_#Y1D6AkDSvXARR90~*z2M?TsbuJ!j}L500MMUPE-F50uLQc0003vNkl6BitX+IH{_sG24S&Ug zWLj(A6?z-0a38SeWqk%;?(sI*^|C$-lnQ+TDy)OdqY9u*(0>7_tvw#s$1iZJiKlwj z1f`(~Ds+J$dJ&)tu7Gm{EM{GpFc)AB1ZLKSu|N?BT)^r;02BeAW)^V)9t7sZyO{-! z1suHrvCq*P5c^E9PGQI8p&H*09yGYMu;cPjJ^Oy}8ctn!z3g8B=Lj(A7rHP9!Uq@# zuL-(X9S9$=I&i?G4f+lU1q6J+8}uCzd4P5s8Fz?v?tKhVVRHc+p-w#o#6Jl_oqGz< zZleb?q0T)8NQWo50?rtqZ@v`n0zZJi1=$1zDcl9g-GXESOKt=49=r_rcN3lj`~l8X Vde2S+F&h8?002ovPDHLkV1kXfo6rCN delta 377 zcmV-<0fzpU1DOMmDS!X}|JduII$Sw&nN$}Hv$g;L00DGTPE!u2UiD!B00BEmL_t(| z+U=DwY6DRWL`ClSN#*z+Ig(POw=sJPm$^WCHw(*T97Z67ys+)Eg6A*KdPw<=wdX2pR{e?bQc7Gb<|1!_P^G?ud>K~e5 z9x=i5qCil!3g`(O0s9CzyI+I{DZmp5ocD#>8JGov6fgy4f?2>mnNo>>0s>EEzx*g{ z3)s8^if@~DK=Ew>rlq{`(A1;xLxTwtLM60WHIie{`gp=$eet^7zp?N>B= zmfm(;c#zunS_DYgJi#6VjsX4VtIA%$Hz~WIonVHl>;+Zc1^oox?uLFJtOqnZ;bp)d Xll2S~|K>@z00000NkvXXu0mjfQ{k>M diff --git a/assets/images/ui/button.png b/assets/images/ui/button.png index 3a39af50692eb3795175a4dc4a216f3b379f5d65..0df1ba2b6f396d37e954a811f75e1aa3b8b93068 100644 GIT binary patch delta 205 zcmbQrbdPa@WIYQ51A~f$l^T#*>gnPbQgQ3;O-J4a0|A$dUqhq6Ht>0TXk^l}cz7yN zLB&^!r^Ks%e`EO_&&QRY-adUB<#RiJ(WXgttfNv2C7NXLgQ|ndf66`CAN(5DoJhb0!6vo#a(}q@#F^VTvZu#SEUVelF{r5}E)Z C1W#1} delta 260 zcmcb|IF)IFWIZzj1H;bqO!I*hV{wqX6T`Z5GB1G~tpJ}8S0D`p=gys5v}jRDNr|KYjXi;J|_Q_V(Yue_y_QdFj%n3l}bAPCC8|sFbfH$S;@ys0abVy>5#DW$Ha$ z977^n-(HXAYB1n&xwvH6zPta+mez)ZKWM#VRnEw6@5Odj=IoivEYt4T7=5p`prwVPcnZ)O~8uFW~c_ciZSqiVo{1JfRKF7-`3pl7DKVP1Jf zBBzK(fr@~Ae8#OQ>z~He9bn}Wv0(YJ-FGKr&4LZ7m+ta4f_&uZ>gTe~DWM4fO9ypo diff --git a/assets/images/ui/virtual-input.png b/assets/images/ui/virtual-input.png index b0fe0ef6d7e784124f8a9b7c275298086d9f7d79..916236b5c609acc2ed95448c51ac1ab3dc0e8d92 100644 GIT binary patch delta 12 TcmZ4alyS;a#tF(BEeeYOCkq9M delta 32 lcmbR8lyT)##tF*844efXk;M!Qe1}1p@p%4W@fk$L90|Va?5N4dJ%_qH4QBn#3hyVxJ diff --git a/images/showcase.png b/images/showcase.png index b0ff5e5dc38ed50726a667ac22f591c6e794e194..8f2bc6360fdef3c58c81f71118216fbb34b51350 100644 GIT binary patch delta 21 dcmX?cfp7B#z6nZ==B?(8t>#Qy&6x#P003i62gLvY delta 42 vcmdmdf$zixz6nYq3=EtF9+AZi4BWyX%*Zfnjzptkt0H5oBGXnyW}y`T`gjVO From eb842489f541ced88084ea6c491699272e7a3a8a Mon Sep 17 00:00:00 2001 From: Flainn Date: Fri, 27 Sep 2024 11:28:50 -0400 Subject: [PATCH 46/99] Fix FlxTextInput field border not being clipped correctly (#3259) --- flixel/text/FlxInputText.hx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/flixel/text/FlxInputText.hx b/flixel/text/FlxInputText.hx index 79e2369978..0c24efe218 100644 --- a/flixel/text/FlxInputText.hx +++ b/flixel/text/FlxInputText.hx @@ -615,7 +615,7 @@ class FlxInputText extends FlxText implements IFlxInputText * Clips the sprite inside the bounds of the text field, taking * `clipRect` into account. */ - function clipSprite(sprite:FlxSprite) + function clipSprite(sprite:FlxSprite, border:Bool = false) { if (sprite == null) return; @@ -625,7 +625,8 @@ class FlxInputText extends FlxText implements IFlxInputText rect = FlxRect.get(); rect.set(0, 0, sprite.width, sprite.height); - var bounds = FlxRect.get(0, 0, width, height); + var bounds = border ? FlxRect.get(-fieldBorderThickness, -fieldBorderThickness, width + (fieldBorderThickness * 2), + height + (fieldBorderThickness * 2)) : FlxRect.get(0, 0, width, height); if (clipRect != null) { bounds = bounds.clipTo(clipRect); @@ -1201,7 +1202,7 @@ class FlxInputText extends FlxText implements IFlxInputText _fieldBorderSprite.setPosition(x - fieldBorderThickness, y - fieldBorderThickness); _backgroundSprite.setPosition(x, y); - clipSprite(_fieldBorderSprite); + clipSprite(_fieldBorderSprite, true); clipSprite(_backgroundSprite); } @@ -1747,7 +1748,7 @@ class FlxInputText extends FlxText implements IFlxInputText super.set_clipRect(value); clipSprite(_backgroundSprite); - clipSprite(_fieldBorderSprite); + clipSprite(_fieldBorderSprite, true); clipSprite(_caret); for (box in _selectionBoxes) clipSprite(box); From 38d5323c9dc6056b78fe5e3d1a5e4d092634e01a Mon Sep 17 00:00:00 2001 From: Mihai Alexandru <77043862+MAJigsaw77@users.noreply.github.com> Date: Tue, 1 Oct 2024 16:01:16 +0000 Subject: [PATCH 47/99] Attach `DEACTIVATE`/`ACTIVATE` events to `stage.nativeWindow`. (#3260) * Update FlxGame.hx * Fix for `flash` and `html5`. * Fix compatibility with `openfl` `9.2.2`. --- flixel/FlxGame.hx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/flixel/FlxGame.hx b/flixel/FlxGame.hx index ef686a0e09..3dd97089d1 100644 --- a/flixel/FlxGame.hx +++ b/flixel/FlxGame.hx @@ -358,6 +358,9 @@ class FlxGame extends Sprite #if (desktop && openfl <= "4.0.0") stage.addEventListener(FocusEvent.FOCUS_OUT, onFocusLost); stage.addEventListener(FocusEvent.FOCUS_IN, onFocus); + #elseif (sys && openfl >= "9.3.0") + stage.nativeWindow.addEventListener(Event.DEACTIVATE, onFocusLost); + stage.nativeWindow.addEventListener(Event.ACTIVATE, onFocus); #else stage.addEventListener(Event.DEACTIVATE, onFocusLost); stage.addEventListener(Event.ACTIVATE, onFocus); @@ -918,4 +921,4 @@ private class FlxIntroSplash extends FlxSplash FlxG.game._gameJustStarted = true; super.startOutro(onOutroComplete); } -} \ No newline at end of file +} From b6358753a0f7e124786c5c38b0a6a64d8bd8be0a Mon Sep 17 00:00:00 2001 From: Vortex <73261680+Vortex2Oblivion@users.noreply.github.com> Date: Sun, 6 Oct 2024 16:32:02 +0000 Subject: [PATCH 48/99] Replace comments mentioning Std.is with Std.isOfType (#3263) * Update OneOfTwo.hx * Update OneOfThree.hx * Update OneOfFour.hx * Update ConsoleUtil.hx --- flixel/system/debug/console/ConsoleUtil.hx | 2 +- flixel/util/typeLimit/OneOfFour.hx | 2 +- flixel/util/typeLimit/OneOfThree.hx | 2 +- flixel/util/typeLimit/OneOfTwo.hx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/flixel/system/debug/console/ConsoleUtil.hx b/flixel/system/debug/console/ConsoleUtil.hx index d52d5241ad..ae78b304ff 100644 --- a/flixel/system/debug/console/ConsoleUtil.hx +++ b/flixel/system/debug/console/ConsoleUtil.hx @@ -120,7 +120,7 @@ class ConsoleUtil else if (Reflect.isObject(Object)) // get instance fields fields = Type.getInstanceFields(Type.getClass(Object)); - // on Flash, enums are classes, so Std.is(_, Enum) fails + // on Flash, enums are classes, so Std.isOfType(_, Enum) fails fields.remove("__constructs__"); var filteredFields = []; diff --git a/flixel/util/typeLimit/OneOfFour.hx b/flixel/util/typeLimit/OneOfFour.hx index bac25d240b..ad92714037 100644 --- a/flixel/util/typeLimit/OneOfFour.hx +++ b/flixel/util/typeLimit/OneOfFour.hx @@ -3,7 +3,7 @@ package flixel.util.typeLimit; /** * Useful to limit a Dynamic function argument's type to the specified * type parameters. This does NOT make the use of Dynamic type-safe in - * any way (the underlying type is still Dynamic and Std.is() checks + + * any way (the underlying type is still Dynamic and Std.isOfType() checks + * casts are necessary). */ abstract OneOfFour(Dynamic) from T1 from T2 from T3 from T4 to T1 to T2 to T3 to T4 {} diff --git a/flixel/util/typeLimit/OneOfThree.hx b/flixel/util/typeLimit/OneOfThree.hx index e51307f062..a055a3bfda 100644 --- a/flixel/util/typeLimit/OneOfThree.hx +++ b/flixel/util/typeLimit/OneOfThree.hx @@ -3,7 +3,7 @@ package flixel.util.typeLimit; /** * Useful to limit a Dynamic function argument's type to the specified * type parameters. This does NOT make the use of Dynamic type-safe in - * any way (the underlying type is still Dynamic and Std.is() checks + + * any way (the underlying type is still Dynamic and Std.isOfType() checks + * casts are necessary). */ abstract OneOfThree(Dynamic) from T1 from T2 from T3 to T1 to T2 to T3 {} diff --git a/flixel/util/typeLimit/OneOfTwo.hx b/flixel/util/typeLimit/OneOfTwo.hx index 5eff2d3f27..0ffebc9bd4 100644 --- a/flixel/util/typeLimit/OneOfTwo.hx +++ b/flixel/util/typeLimit/OneOfTwo.hx @@ -3,7 +3,7 @@ package flixel.util.typeLimit; /** * Useful to limit a Dynamic function argument's type to the specified * type parameters. This does NOT make the use of Dynamic type-safe in - * any way (the underlying type is still Dynamic and Std.is() checks + + * any way (the underlying type is still Dynamic and Std.isOfType() checks + * casts are necessary). */ abstract OneOfTwo(Dynamic) from T1 from T2 to T1 to T2 {} From ddb6a5f7efd1d25a2b4836383472eb2cc7c8f331 Mon Sep 17 00:00:00 2001 From: xMediKat <58391871+Temmiekat@users.noreply.github.com> Date: Sun, 13 Oct 2024 19:50:31 -0400 Subject: [PATCH 49/99] fixing spelling mistake (#3264) anebled should be enabled --- flixel/util/FlxAxes.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flixel/util/FlxAxes.hx b/flixel/util/FlxAxes.hx index 356d12ef8b..f05c2d2ae6 100644 --- a/flixel/util/FlxAxes.hx +++ b/flixel/util/FlxAxes.hx @@ -8,12 +8,12 @@ enum abstract FlxAxes(Int) var NONE = 0x00; /** - * Whether the horizontal axis is anebled + * Whether the horizontal axis is enabled */ public var x(get, never):Bool; /** - * Whether the vertical axis is anebled + * Whether the vertical axis is enabled */ public var y(get, never):Bool; From f5087ea69e42750893ac4ec29dc4367714ab815b Mon Sep 17 00:00:00 2001 From: ACrazyTown <47027981+ACrazyTown@users.noreply.github.com> Date: Thu, 17 Oct 2024 05:38:37 +0200 Subject: [PATCH 50/99] Use System.totalMemoryNumber in debugger (#3266) --- flixel/system/debug/stats/Stats.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flixel/system/debug/stats/Stats.hx b/flixel/system/debug/stats/Stats.hx index 02f971be20..a60de0f0bc 100644 --- a/flixel/system/debug/stats/Stats.hx +++ b/flixel/system/debug/stats/Stats.hx @@ -333,7 +333,7 @@ class Stats extends Window */ public inline function currentMem():Float { - return (System.totalMemory / 1024) / 1000; + return (#if (openfl >= "9.4.0") System.totalMemoryNumber #else System.totalMemory #end / 1024) / 1000; } /** From ffa691cb2d2d81de35b900a4411e4062ac84ab58 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 18 Oct 2024 16:47:23 -0400 Subject: [PATCH 51/99] Implement error handling for save data unserialization. --- flixel/util/FlxSave.hx | 60 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 8 deletions(-) diff --git a/flixel/util/FlxSave.hx b/flixel/util/FlxSave.hx index f2164833ac..c04faa7b4f 100644 --- a/flixel/util/FlxSave.hx +++ b/flixel/util/FlxSave.hx @@ -167,6 +167,17 @@ class FlxSave implements IFlxDestroyable _sharedObject = FlxSharedObject.getLocal(name, path); status = BOUND(name, path); } + catch (s:FlxSaveStatus) { + this.status = s; + switch (this.status) { + case EMPTY: + return false; + case ERROR(_): + return false; + case BOUND(_, _): + return true; + } + } catch (e:Error) { FlxG.log.error('Error:${e.message} name:"$name", path:"$path".'); @@ -459,11 +470,14 @@ private class FlxSharedObject extends SharedObject try { final unserializer = new haxe.Unserializer(encodedData); - final resolver = { resolveEnum: Type.resolveEnum, resolveClass: SharedObject.__resolveClass }; + final resolver = { resolveEnum: FlxSharedObject.resolveEnum, resolveClass: FlxSharedObject.resolveClass }; unserializer.setResolver(cast resolver); sharedObject.data = unserializer.unserialize(); } - catch (e:Dynamic) {} + catch (e:Dynamic) { + trace('Error loading shared object "' + name + '" from local path "' + localPath + '"'); + throw FlxSaveStatus.ERROR("There was a problem parsing the save data."); + } } all.set(id, sharedObject); @@ -471,7 +485,37 @@ private class FlxSharedObject extends SharedObject return all.get(id); } - + + static function resolveEnum(name:String):Enum { + try + { + return Type.resolveEnum(name); + } + catch (e) + { + FlxG.log.error('Found invalid enum type ${name} in save data, indicates partial save corruption.'); + throw e; + } + } + + static function resolveClass(name:String):Class { + if (name == 'Dynamic') + { + FlxG.log.warn('Found invalid class type ${name} in save data, indicates partial save corruption.'); + return null; + } + + try + { + return SharedObject.__resolveClass(name); + } + catch (e) + { + FlxG.log.error('Found invalid class type ${name} in save data, indicates partial save corruption.'); + throw e; + } + } + #if (js && html5) static function getData(name:String, ?localPath:String) { @@ -622,7 +666,7 @@ private class FlxSharedObject extends SharedObject if (!sys.FileSystem.exists(directory)) SharedObject.__mkdir(directory); - + var output = sys.io.File.write(path, false); output.writeString(encodedData); output.close(); @@ -631,18 +675,18 @@ private class FlxSharedObject extends SharedObject { return SharedObjectFlushStatus.PENDING; } - + return SharedObjectFlushStatus.FLUSHED; } - + override function clear() { data = {}; - + try { var path = getPath(__localPath, __name); - + if (sys.FileSystem.exists(path)) sys.FileSystem.deleteFile(path); } From 65bd4b867ddc913fdc470604fb4da5e7269435ae Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Wed, 30 Oct 2024 14:20:25 -0400 Subject: [PATCH 52/99] FlxGamepadInputID: Add ACCEPT/CANCEL buttons (#3276) * add ACCEPT/CANCEL * fix non-switch controllers --- flixel/input/gamepad/FlxGamepadInputID.hx | 16 +++++++++++-- .../gamepad/lists/FlxGamepadButtonList.hx | 23 +++++++++++++++++++ .../gamepad/mappings/FlxGamepadMapping.hx | 9 +++++++- .../input/gamepad/mappings/LogitechMapping.hx | 2 +- flixel/input/gamepad/mappings/MFiMapping.hx | 2 +- .../mappings/MayflashWiiRemoteMapping.hx | 15 ++++++------ flixel/input/gamepad/mappings/OUYAMapping.hx | 2 +- flixel/input/gamepad/mappings/PS4Mapping.hx | 2 +- .../input/gamepad/mappings/PSVitaMapping.hx | 2 +- .../mappings/SwitchJoyconLeftMapping.hx | 4 +++- .../mappings/SwitchJoyconRightMapping.hx | 4 +++- .../gamepad/mappings/SwitchProMapping.hx | 4 +++- .../gamepad/mappings/WiiRemoteMapping.hx | 17 +++++++------- .../input/gamepad/mappings/XInputMapping.hx | 2 +- 14 files changed, 75 insertions(+), 29 deletions(-) diff --git a/flixel/input/gamepad/FlxGamepadInputID.hx b/flixel/input/gamepad/FlxGamepadInputID.hx index 3d3e15fa7d..78f09a8649 100644 --- a/flixel/input/gamepad/FlxGamepadInputID.hx +++ b/flixel/input/gamepad/FlxGamepadInputID.hx @@ -35,7 +35,7 @@ enum abstract FlxGamepadInputID(Int) from Int to Int /**right digital "bumper"*/ var RIGHT_SHOULDER = 5; - /**also known as "select", the leftmost center button*/ + /**also known as "select", the left-most center button*/ var BACK = 6; /**the rightmost center button*/ @@ -127,7 +127,19 @@ enum abstract FlxGamepadInputID(Int) from Int to Int /**left analog stick as a dpad, pushed left**/ var RIGHT_STICK_DIGITAL_LEFT = 41; - + + /** + * Mapped to The bottom face button on most controllers, and the + * right face button on Nintendo Switch controllers + **/ + var ACCEPT = 42; + + /** + * Mapped to The bottom face button on most controllers, and the + * right face button on Nintendo Switch controllers + **/ + var CANCEL = 43; + @:from public static inline function fromString(s:String) { diff --git a/flixel/input/gamepad/lists/FlxGamepadButtonList.hx b/flixel/input/gamepad/lists/FlxGamepadButtonList.hx index ca741f1a41..f681041569 100644 --- a/flixel/input/gamepad/lists/FlxGamepadButtonList.hx +++ b/flixel/input/gamepad/lists/FlxGamepadButtonList.hx @@ -39,6 +39,10 @@ class FlxGamepadButtonList extends FlxBaseGamepadList inline function get_RIGHT_SHOULDER() return check(FlxGamepadInputID.RIGHT_SHOULDER); + /** + * Also known as "select", the left-most center button. + * Not to be confused with `CANCEL`, which is a face button (usually B) + */ public var BACK(get, never):Bool; inline function get_BACK() @@ -210,6 +214,25 @@ class FlxGamepadButtonList extends FlxBaseGamepadList inline function get_RIGHT_STICK_DIGITAL_LEFT() return check(FlxGamepadInputID.RIGHT_STICK_DIGITAL_LEFT); + + /** + * Mapped to The bottom face button on most controllers, and the + * right face button on Nintendo Switch controllers + **/ + public var ACCEPT(get, never):Bool; + + inline function get_ACCEPT() + return check(FlxGamepadInputID.ACCEPT); + + /** + * Mapped to The right face button on most controllers, and the + * bottom face button on Nintendo Switch controllers. + * Not to be confused with `BACK` which is the XInput "select" button + **/ + public var CANCEL(get, never):Bool; + + inline function get_CANCEL() + return check(FlxGamepadInputID.CANCEL); public function new(status:FlxInputState, gamepad:FlxGamepad) { diff --git a/flixel/input/gamepad/mappings/FlxGamepadMapping.hx b/flixel/input/gamepad/mappings/FlxGamepadMapping.hx index 86fa919a77..d7e54b0a25 100644 --- a/flixel/input/gamepad/mappings/FlxGamepadMapping.hx +++ b/flixel/input/gamepad/mappings/FlxGamepadMapping.hx @@ -65,7 +65,12 @@ class FlxGamepadMapping */ public function getRawID(ID:FlxGamepadInputID):Int { - return -1; + return switch ID + { + case ACCEPT: getRawID(A); + case CANCEL: getRawID(B); + default: -1; + } } /** @@ -139,6 +144,8 @@ class FlxGamepadMapping case RIGHT_STICK_DIGITAL_DOWN: "rs-down"; case RIGHT_STICK_DIGITAL_LEFT: "rs-left"; case RIGHT_STICK_DIGITAL_RIGHT: "rs-right"; + case ACCEPT: getInputLabel(cast getRawID(id)); + case CANCEL: getInputLabel(cast getRawID(id)); #if FLX_JOYSTICK_API case LEFT_TRIGGER_FAKE: "l2"; case RIGHT_TRIGGER_FAKE: "r2"; diff --git a/flixel/input/gamepad/mappings/LogitechMapping.hx b/flixel/input/gamepad/mappings/LogitechMapping.hx index 921ccdec2d..c717842dbb 100644 --- a/flixel/input/gamepad/mappings/LogitechMapping.hx +++ b/flixel/input/gamepad/mappings/LogitechMapping.hx @@ -85,7 +85,7 @@ class LogitechMapping extends FlxGamepadMapping case LEFT_TRIGGER_FAKE: LogitechID.SEVEN; case RIGHT_TRIGGER_FAKE: LogitechID.EIGHT; #end - default: -1; + default: super.getRawID(ID); } } diff --git a/flixel/input/gamepad/mappings/MFiMapping.hx b/flixel/input/gamepad/mappings/MFiMapping.hx index 5498338f57..2e77478ab0 100644 --- a/flixel/input/gamepad/mappings/MFiMapping.hx +++ b/flixel/input/gamepad/mappings/MFiMapping.hx @@ -75,7 +75,7 @@ class MFiMapping extends FlxGamepadMapping case LEFT_TRIGGER_FAKE: MFiID.LEFT_TRIGGER; case RIGHT_TRIGGER_FAKE: MFiID.RIGHT_TRIGGER; #end - default: -1; + default: super.getRawID(ID); } } diff --git a/flixel/input/gamepad/mappings/MayflashWiiRemoteMapping.hx b/flixel/input/gamepad/mappings/MayflashWiiRemoteMapping.hx index ac7dc77cdd..8f5a08a27f 100644 --- a/flixel/input/gamepad/mappings/MayflashWiiRemoteMapping.hx +++ b/flixel/input/gamepad/mappings/MayflashWiiRemoteMapping.hx @@ -80,12 +80,11 @@ class MayflashWiiRemoteMapping extends FlxGamepadMapping case MayflashWiiRemoteID.NUNCHUK_DPAD_DOWN: DPAD_DOWN; case MayflashWiiRemoteID.NUNCHUK_DPAD_LEFT: DPAD_LEFT; case MayflashWiiRemoteID.NUNCHUK_DPAD_RIGHT: DPAD_RIGHT; - default: - if (rawID == MayflashWiiRemoteID.LEFT_ANALOG_STICK.rawUp) LEFT_STICK_DIGITAL_UP; - if (rawID == MayflashWiiRemoteID.LEFT_ANALOG_STICK.rawDown) LEFT_STICK_DIGITAL_DOWN; - if (rawID == MayflashWiiRemoteID.LEFT_ANALOG_STICK.rawLeft) LEFT_STICK_DIGITAL_LEFT; - if (rawID == MayflashWiiRemoteID.LEFT_ANALOG_STICK.rawRight) LEFT_STICK_DIGITAL_RIGHT; - NONE; + case id if (id == MayflashWiiRemoteID.LEFT_ANALOG_STICK.rawUp): LEFT_STICK_DIGITAL_UP; + case id if (id == MayflashWiiRemoteID.LEFT_ANALOG_STICK.rawDown): LEFT_STICK_DIGITAL_DOWN; + case id if (id == MayflashWiiRemoteID.LEFT_ANALOG_STICK.rawLeft): LEFT_STICK_DIGITAL_LEFT; + case id if (id == MayflashWiiRemoteID.LEFT_ANALOG_STICK.rawRight): LEFT_STICK_DIGITAL_RIGHT; + default: NONE; } } @@ -174,7 +173,7 @@ class MayflashWiiRemoteMapping extends FlxGamepadMapping case LEFT_STICK_DIGITAL_DOWN: MayflashWiiRemoteID.LEFT_ANALOG_STICK.rawDown; case LEFT_STICK_DIGITAL_LEFT: MayflashWiiRemoteID.LEFT_ANALOG_STICK.rawLeft; case LEFT_STICK_DIGITAL_RIGHT: MayflashWiiRemoteID.LEFT_ANALOG_STICK.rawRight; - default: -1; + default: super.getRawID(ID); } } @@ -193,7 +192,7 @@ class MayflashWiiRemoteMapping extends FlxGamepadMapping case BACK: MayflashWiiRemoteID.REMOTE_MINUS; case GUIDE: MayflashWiiRemoteID.REMOTE_HOME; case START: MayflashWiiRemoteID.REMOTE_PLUS; - default: -1; + default: super.getRawID(ID); } } diff --git a/flixel/input/gamepad/mappings/OUYAMapping.hx b/flixel/input/gamepad/mappings/OUYAMapping.hx index 372ba6a3f4..870debd8c9 100644 --- a/flixel/input/gamepad/mappings/OUYAMapping.hx +++ b/flixel/input/gamepad/mappings/OUYAMapping.hx @@ -77,7 +77,7 @@ class OUYAMapping extends FlxGamepadMapping case RIGHT_STICK_DIGITAL_DOWN: OUYAID.RIGHT_ANALOG_STICK.rawDown; case RIGHT_STICK_DIGITAL_LEFT: OUYAID.RIGHT_ANALOG_STICK.rawLeft; case RIGHT_STICK_DIGITAL_RIGHT: OUYAID.RIGHT_ANALOG_STICK.rawRight; - default: -1; + default: super.getRawID(ID); } } diff --git a/flixel/input/gamepad/mappings/PS4Mapping.hx b/flixel/input/gamepad/mappings/PS4Mapping.hx index f636298f73..5fc74bd85a 100644 --- a/flixel/input/gamepad/mappings/PS4Mapping.hx +++ b/flixel/input/gamepad/mappings/PS4Mapping.hx @@ -96,7 +96,7 @@ class PS4Mapping extends FlxGamepadMapping case LEFT_TRIGGER_FAKE: LEFT_TRIGGER_FAKE; case RIGHT_TRIGGER_FAKE: RIGHT_TRIGGER_FAKE; #end - default: -1; + default: super.getRawID(ID); } } diff --git a/flixel/input/gamepad/mappings/PSVitaMapping.hx b/flixel/input/gamepad/mappings/PSVitaMapping.hx index 8c19c80124..6b46e8e090 100644 --- a/flixel/input/gamepad/mappings/PSVitaMapping.hx +++ b/flixel/input/gamepad/mappings/PSVitaMapping.hx @@ -63,7 +63,7 @@ class PSVitaMapping extends FlxGamepadMapping case RIGHT_STICK_DIGITAL_DOWN: PSVitaID.RIGHT_ANALOG_STICK.rawDown; case RIGHT_STICK_DIGITAL_LEFT: PSVitaID.RIGHT_ANALOG_STICK.rawLeft; case RIGHT_STICK_DIGITAL_RIGHT: PSVitaID.RIGHT_ANALOG_STICK.rawRight; - default: -1; + default: super.getRawID(ID); } } diff --git a/flixel/input/gamepad/mappings/SwitchJoyconLeftMapping.hx b/flixel/input/gamepad/mappings/SwitchJoyconLeftMapping.hx index 07c16e52e3..699443e9ab 100644 --- a/flixel/input/gamepad/mappings/SwitchJoyconLeftMapping.hx +++ b/flixel/input/gamepad/mappings/SwitchJoyconLeftMapping.hx @@ -70,7 +70,9 @@ class SwitchJoyconLeftMapping extends FlxGamepadMapping case LEFT_TRIGGER_FAKE: LEFT_TRIGGER_FAKE; case RIGHT_TRIGGER_FAKE: RIGHT_TRIGGER_FAKE; #end - default: -1; + case ACCEPT: SwitchJoyconLeftID.RIGHT; + case CANCEL: SwitchJoyconLeftID.DOWN; + default: super.getRawID(id); } } diff --git a/flixel/input/gamepad/mappings/SwitchJoyconRightMapping.hx b/flixel/input/gamepad/mappings/SwitchJoyconRightMapping.hx index 6a7bdc51a6..05297f02e2 100644 --- a/flixel/input/gamepad/mappings/SwitchJoyconRightMapping.hx +++ b/flixel/input/gamepad/mappings/SwitchJoyconRightMapping.hx @@ -72,7 +72,9 @@ class SwitchJoyconRightMapping extends FlxGamepadMapping case LEFT_TRIGGER_FAKE: LEFT_TRIGGER_FAKE; case RIGHT_TRIGGER_FAKE: RIGHT_TRIGGER_FAKE; #end - default: -1; + case ACCEPT: SwitchJoyconRightID.A; + case CANCEL: SwitchJoyconRightID.B; + default: super.getRawID(ID); } } diff --git a/flixel/input/gamepad/mappings/SwitchProMapping.hx b/flixel/input/gamepad/mappings/SwitchProMapping.hx index 190e879090..1d9b7e4583 100644 --- a/flixel/input/gamepad/mappings/SwitchProMapping.hx +++ b/flixel/input/gamepad/mappings/SwitchProMapping.hx @@ -95,7 +95,9 @@ class SwitchProMapping extends FlxGamepadMapping case LEFT_TRIGGER_FAKE: LEFT_TRIGGER_FAKE; case RIGHT_TRIGGER_FAKE: RIGHT_TRIGGER_FAKE; #end - default: -1; + case ACCEPT: SwitchProID.A; + case CANCEL: SwitchProID.B; + default: super.getRawID(ID); } } diff --git a/flixel/input/gamepad/mappings/WiiRemoteMapping.hx b/flixel/input/gamepad/mappings/WiiRemoteMapping.hx index 4b7c2f04e5..41692228d7 100644 --- a/flixel/input/gamepad/mappings/WiiRemoteMapping.hx +++ b/flixel/input/gamepad/mappings/WiiRemoteMapping.hx @@ -80,12 +80,11 @@ class WiiRemoteMapping extends FlxGamepadMapping case WiiRemoteID.NUNCHUK_DPAD_DOWN: DPAD_DOWN; case WiiRemoteID.NUNCHUK_DPAD_LEFT: DPAD_LEFT; case WiiRemoteID.NUNCHUK_DPAD_RIGHT: DPAD_RIGHT; - default: - if (rawID == WiiRemoteID.LEFT_ANALOG_STICK.rawUp) LEFT_STICK_DIGITAL_UP; - if (rawID == WiiRemoteID.LEFT_ANALOG_STICK.rawDown) LEFT_STICK_DIGITAL_DOWN; - if (rawID == WiiRemoteID.LEFT_ANALOG_STICK.rawLeft) LEFT_STICK_DIGITAL_LEFT; - if (rawID == WiiRemoteID.LEFT_ANALOG_STICK.rawRight) LEFT_STICK_DIGITAL_RIGHT; - NONE; + case id if (id == WiiRemoteID.LEFT_ANALOG_STICK.rawUp): LEFT_STICK_DIGITAL_UP; + case id if (id == WiiRemoteID.LEFT_ANALOG_STICK.rawDown): LEFT_STICK_DIGITAL_DOWN; + case id if (id == WiiRemoteID.LEFT_ANALOG_STICK.rawLeft): LEFT_STICK_DIGITAL_LEFT; + case id if (id == WiiRemoteID.LEFT_ANALOG_STICK.rawRight): LEFT_STICK_DIGITAL_RIGHT; + default: super.getRawID(rawID); } } @@ -147,7 +146,7 @@ class WiiRemoteMapping extends FlxGamepadMapping case RIGHT_STICK_DIGITAL_DOWN: WiiRemoteID.RIGHT_ANALOG_STICK.rawDown; case RIGHT_STICK_DIGITAL_LEFT: WiiRemoteID.RIGHT_ANALOG_STICK.rawLeft; case RIGHT_STICK_DIGITAL_RIGHT: WiiRemoteID.RIGHT_ANALOG_STICK.rawRight; - default: -1; + default: super.getRawID(ID); } } @@ -174,7 +173,7 @@ class WiiRemoteMapping extends FlxGamepadMapping case LEFT_STICK_DIGITAL_DOWN: WiiRemoteID.LEFT_ANALOG_STICK.rawDown; case LEFT_STICK_DIGITAL_LEFT: WiiRemoteID.LEFT_ANALOG_STICK.rawLeft; case LEFT_STICK_DIGITAL_RIGHT: WiiRemoteID.LEFT_ANALOG_STICK.rawRight; - default: -1; + default: super.getRawID(ID); } } @@ -195,7 +194,7 @@ class WiiRemoteMapping extends FlxGamepadMapping case START: WiiRemoteID.REMOTE_PLUS; case TILT_PITCH: WiiRemoteID.REMOTE_TILT_PITCH; case TILT_ROLL: WiiRemoteID.REMOTE_TILT_ROLL; - default: -1; + default: super.getRawID(ID); } } diff --git a/flixel/input/gamepad/mappings/XInputMapping.hx b/flixel/input/gamepad/mappings/XInputMapping.hx index 4073dbe79b..1833a48dc3 100644 --- a/flixel/input/gamepad/mappings/XInputMapping.hx +++ b/flixel/input/gamepad/mappings/XInputMapping.hx @@ -93,7 +93,7 @@ class XInputMapping extends FlxGamepadMapping case RIGHT_STICK_DIGITAL_DOWN: XInputID.RIGHT_ANALOG_STICK.rawDown; case RIGHT_STICK_DIGITAL_LEFT: XInputID.RIGHT_ANALOG_STICK.rawLeft; case RIGHT_STICK_DIGITAL_RIGHT: XInputID.RIGHT_ANALOG_STICK.rawRight; - default: -1; + default: super.getRawID(ID); } } From 60b8e2da592197841552efce295ca7c37d7561b5 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Fri, 1 Nov 2024 11:09:46 -0400 Subject: [PATCH 53/99] Various FlxAction changes (#3277) * make FlxInputDeviceID an enum * prevent actions from resetting each check * cast trigger in super --- flixel/input/actions/FlxAction.hx | 40 +++++++++----------- flixel/input/actions/FlxActionInput.hx | 8 ++-- flixel/input/actions/FlxActionInputAnalog.hx | 12 +++--- 3 files changed, 27 insertions(+), 33 deletions(-) diff --git a/flixel/input/actions/FlxAction.hx b/flixel/input/actions/FlxAction.hx index 48237e9046..27e37d06a0 100644 --- a/flixel/input/actions/FlxAction.hx +++ b/flixel/input/actions/FlxAction.hx @@ -342,6 +342,7 @@ class FlxAction implements IFlxDestroyable var _y:Null = null; var _timestamp:Int = 0; + @:deprecated("_checked is deprecated, use triggered, instead") var _checked:Bool = false; /** @@ -435,40 +436,33 @@ class FlxAction implements IFlxDestroyable */ public function check():Bool { + if (_timestamp == FlxG.game.ticks) + return triggered; // run no more than once per frame + _x = null; _y = null; - - if (_timestamp == FlxG.game.ticks) - { - triggered = _checked; - return _checked; // run no more than once per frame - } - + _timestamp = FlxG.game.ticks; - _checked = false; - - var len = inputs != null ? inputs.length : 0; - for (i in 0...len) + triggered = false; + + var i = inputs != null ? inputs.length : 0; + while (i-- > 0) // Iterate backwards, since we may remove items { - var j = len - i - 1; - var input = inputs[j]; - + final input = inputs[i]; + if (input.destroyed) { - inputs.splice(j, 1); + inputs.remove(input); continue; } - + input.update(); - + if (input.check(this)) - { - _checked = true; - } + triggered = true; } - - triggered = _checked; - return _checked; + + return triggered; } /** diff --git a/flixel/input/actions/FlxActionInput.hx b/flixel/input/actions/FlxActionInput.hx index 0d8f6cffb8..c74f52792d 100644 --- a/flixel/input/actions/FlxActionInput.hx +++ b/flixel/input/actions/FlxActionInput.hx @@ -110,22 +110,22 @@ enum FlxInputDevice * Just a bucket for some handy sentinel values. * @since 4.6.0 */ -class FlxInputDeviceID +enum abstract FlxInputDeviceID(Int) from Int to Int { /** * Means "every connected device of the given type" (ie all gamepads, all steam controllers, etc) */ - public static inline var ALL:Int = -1; + var ALL = -1; /** * Means "the first connected device that has an active input" (ie a pressed button or moved analog stick/trigger/etc) */ - public static inline var FIRST_ACTIVE:Int = -2; + var FIRST_ACTIVE = -2; /** * Means "no device" */ - public static inline var NONE:Int = -3; + var NONE = -3; } /** diff --git a/flixel/input/actions/FlxActionInputAnalog.hx b/flixel/input/actions/FlxActionInputAnalog.hx index 58264d1bfb..1dff292005 100644 --- a/flixel/input/actions/FlxActionInputAnalog.hx +++ b/flixel/input/actions/FlxActionInputAnalog.hx @@ -97,7 +97,7 @@ class FlxActionInputAnalogMouseMotion extends FlxActionInputAnalog deadZone = DeadZone; invertX = InvertX; invertY = InvertY; - super(FlxInputDevice.MOUSE, -1, cast Trigger, Axis); + super(FlxInputDevice.MOUSE, -1, Trigger, Axis); } override public function update():Void @@ -144,7 +144,7 @@ class FlxActionInputAnalogMousePosition extends FlxActionInputAnalog */ public function new(Trigger:FlxAnalogState, Axis:FlxAnalogAxis = EITHER) { - super(FlxInputDevice.MOUSE, -1, cast Trigger, Axis); + super(FlxInputDevice.MOUSE, -1, Trigger, Axis); } override public function update():Void @@ -193,7 +193,7 @@ class FlxActionInputAnalogGamepad extends FlxActionInputAnalog */ public function new(InputID:FlxGamepadInputID, Trigger:FlxAnalogState, Axis:FlxAnalogAxis = EITHER, GamepadID:Int = FlxInputDeviceID.FIRST_ACTIVE) { - super(FlxInputDevice.GAMEPAD, InputID, cast Trigger, Axis, GamepadID); + super(FlxInputDevice.GAMEPAD, InputID, Trigger, Axis, GamepadID); } override public function update():Void @@ -265,7 +265,7 @@ class FlxActionInputAnalogSteam extends FlxActionInputAnalog @:allow(flixel.input.actions.FlxActionSet) function new(ActionHandle:Int, Trigger:FlxAnalogState, Axis:FlxAnalogAxis = EITHER, DeviceID:Int = FlxInputDeviceID.ALL) { - super(FlxInputDevice.STEAM_CONTROLLER, ActionHandle, cast Trigger, Axis, DeviceID); + super(FlxInputDevice.STEAM_CONTROLLER, ActionHandle, Trigger, Axis, DeviceID); #if FLX_NO_STEAM FlxG.log.warn("steamwrap library not installed; steam inputs will be ignored."); #end @@ -310,9 +310,9 @@ class FlxActionInputAnalog extends FlxActionInput static inline var A_X = true; static inline var A_Y = false; - function new(Device:FlxInputDevice, InputID:Int, Trigger:FlxInputState, Axis:FlxAnalogAxis = EITHER, DeviceID:Int = FlxInputDeviceID.FIRST_ACTIVE) + function new(Device:FlxInputDevice, InputID:Int, Trigger:FlxAnalogState, Axis:FlxAnalogAxis = EITHER, DeviceID:Int = FlxInputDeviceID.FIRST_ACTIVE) { - super(FlxInputType.ANALOG, Device, InputID, Trigger, DeviceID); + super(FlxInputType.ANALOG, Device, InputID, cast Trigger, DeviceID); axis = Axis; xMoved = new FlxInput(0); yMoved = new FlxInput(1); From 049e9edb219762a9f6221881448339ebab6eca9a Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Fri, 1 Nov 2024 12:03:42 -0400 Subject: [PATCH 54/99] FlxGamepadManager: Add FlxG.gamepads.acceptMode (#3280) * add ACCEPT/CANCEL * fix non-switch controllers * add FlxG.gamepad.acceptMode * rename ADAPTIVE to USE_MAPPING * fix getInputLabel on accept/cancel * use monomorph on FlxGamepadMappings add gamepad.getMappedInput * doc * fix code climate * fix flash * remove casts * clean up stick fields, reduce casts * fix code climate again * fix flash too * more codeclimate fixes * fix typo * more typo * add mapped input tools * d'oh * D'oh * add since --- flixel/input/gamepad/FlxGamepad.hx | 15 +- flixel/input/gamepad/FlxGamepadAnalogStick.hx | 53 +-- flixel/input/gamepad/FlxGamepadManager.hx | 32 +- flixel/input/gamepad/FlxGamepadMappedInput.hx | 57 ++++ flixel/input/gamepad/id/LogitechID.hx | 102 +++--- flixel/input/gamepad/id/MFiID.hx | 73 ++-- .../input/gamepad/id/MayflashWiiRemoteID.hx | 249 ++++++-------- flixel/input/gamepad/id/OUYAID.hx | 64 ++-- flixel/input/gamepad/id/PS4ID.hx | 252 +++++++------- flixel/input/gamepad/id/PSVitaID.hx | 58 ++-- flixel/input/gamepad/id/SwitchJoyconLeftID.hx | 74 ++-- .../input/gamepad/id/SwitchJoyconRightID.hx | 84 +++-- flixel/input/gamepad/id/SwitchProID.hx | 130 +++---- flixel/input/gamepad/id/WiiRemoteID.hx | 316 +++++++++--------- flixel/input/gamepad/id/XInputID.hx | 303 +++++++++-------- .../gamepad/mappings/FlxGamepadMapping.hx | 62 +++- .../input/gamepad/mappings/LogitechMapping.hx | 22 +- flixel/input/gamepad/mappings/MFiMapping.hx | 14 +- .../mappings/MayflashWiiRemoteMapping.hx | 28 +- flixel/input/gamepad/mappings/OUYAMapping.hx | 16 +- flixel/input/gamepad/mappings/PS4Mapping.hx | 14 +- .../input/gamepad/mappings/PSVitaMapping.hx | 16 +- .../mappings/SwitchJoyconLeftMapping.hx | 17 +- .../mappings/SwitchJoyconRightMapping.hx | 17 +- .../gamepad/mappings/SwitchProMapping.hx | 17 +- .../gamepad/mappings/WiiRemoteMapping.hx | 34 +- .../input/gamepad/mappings/XInputMapping.hx | 18 +- 27 files changed, 1206 insertions(+), 931 deletions(-) create mode 100644 flixel/input/gamepad/FlxGamepadMappedInput.hx diff --git a/flixel/input/gamepad/FlxGamepad.hx b/flixel/input/gamepad/FlxGamepad.hx index a6a0005265..a6dfdd2726 100644 --- a/flixel/input/gamepad/FlxGamepad.hx +++ b/flixel/input/gamepad/FlxGamepad.hx @@ -1,6 +1,7 @@ package flixel.input.gamepad; import flixel.input.FlxInput.FlxInputState; +import flixel.input.gamepad.FlxGamepadMappedInput; import flixel.input.gamepad.lists.FlxGamepadAnalogList; import flixel.input.gamepad.lists.FlxGamepadButtonList; import flixel.input.gamepad.lists.FlxGamepadMotionValueList; @@ -879,13 +880,25 @@ class FlxGamepad implements IFlxDestroyable return _deadZone = deadZone; } - /** + /** + * A string representing the label of the target input. For instance, on a PS4 gamepad + * `A` is "x", while Xbox is "a" and the Switch pro controller is "B" * @since 4.8.0 */ public inline function getInputLabel(id:FlxGamepadInputID) { return mapping.getInputLabel(id); } + + /** + * The value of the target gamepad input. For instance, on a PS4 gamepad `A` is `PS4(PS4ID.X)`, + * while Xbox is `X_INPUT(XInputID.A)` and the Switch pro controller is `SWITCH_PRO(SwitchProID.B)` + * @since 5.9.0 + */ + public function getMappedInput(id:FlxGamepadInputID):FlxGamepadMappedInput + { + return mapping.getMappedInput(id); + } public function toString():String { diff --git a/flixel/input/gamepad/FlxGamepadAnalogStick.hx b/flixel/input/gamepad/FlxGamepadAnalogStick.hx index e80481b27b..31aca85a6b 100644 --- a/flixel/input/gamepad/FlxGamepadAnalogStick.hx +++ b/flixel/input/gamepad/FlxGamepadAnalogStick.hx @@ -2,7 +2,9 @@ package flixel.input.gamepad; import flixel.util.FlxStringUtil; -class FlxGamepadAnalogStick +typedef FlxGamepadAnalogStick = FlxTypedGamepadAnalogStick; + +class FlxTypedGamepadAnalogStick { public var x(default, null):Int; public var y(default, null):Int; @@ -10,22 +12,22 @@ class FlxGamepadAnalogStick /** * a raw button input ID, for sending a digital event for "up" alongside the analog event */ - public var rawUp(default, null):Int = -1; + public var rawUp(default, null):TInputID = cast -1; /** * a raw button input ID, for sending a digital event for "down" alongside the analog event */ - public var rawDown(default, null):Int = -1; + public var rawDown(default, null):TInputID = cast -1; /** * a raw button input ID, for sending a digital event for "left" alongside the analog event */ - public var rawLeft(default, null):Int = -1; + public var rawLeft(default, null):TInputID = cast -1; /** * a raw button input ID, for sending a digital event for "right" alongside the analog event */ - public var rawRight(default, null):Int = -1; + public var rawRight(default, null):TInputID = cast -1; /** * the absolute value the dpad must be greater than before digital inputs are sent @@ -37,20 +39,31 @@ class FlxGamepadAnalogStick */ public var mode(default, null):FlxAnalogToDigitalMode = BOTH; - public function new(x:Int, y:Int, ?settings:FlxGamepadAnalogStickSettings) + public function new(x:Int, y:Int, ?settings:FlxGamepadAnalogStickSettings) { this.x = x; this.y = y; - if (settings == null) - return; - - mode = (settings.mode != null) ? settings.mode : BOTH; - rawUp = (settings.up != null) ? settings.up : -1; - rawDown = (settings.down != null) ? settings.down : -1; - rawLeft = (settings.left != null) ? settings.left : -1; - rawRight = (settings.right != null) ? settings.right : -1; - digitalThreshold = (settings.threshold != null) ? settings.threshold : 0.5; + if (settings != null) + { + if (settings.mode != null) + mode = settings.mode; + + if (settings.up != null) + rawUp = settings.up; + + if (settings.down != null) + rawDown = settings.down; + + if (settings.left != null) + rawLeft = settings.left; + + if (settings.right != null) + rawRight = settings.right; + + if (settings.threshold != null) + digitalThreshold = settings.threshold; + } } public function toString():String @@ -68,12 +81,12 @@ class FlxGamepadAnalogStick } } -typedef FlxGamepadAnalogStickSettings = +typedef FlxGamepadAnalogStickSettings = { - ?up:Int, - ?down:Int, - ?left:Int, - ?right:Int, + ?up:TInputID, + ?down:TInputID, + ?left:TInputID, + ?right:TInputID, ?threshold:Float, ?mode:FlxAnalogToDigitalMode } diff --git a/flixel/input/gamepad/FlxGamepadManager.hx b/flixel/input/gamepad/FlxGamepadManager.hx index 79d9b8d401..0477304e5c 100644 --- a/flixel/input/gamepad/FlxGamepadManager.hx +++ b/flixel/input/gamepad/FlxGamepadManager.hx @@ -50,7 +50,13 @@ class FlxGamepadManager implements IFlxInputManager * @since 4.6.0 */ public var deviceDisconnected(default, null):FlxTypedSignalVoid>; - + + /** + * Whether the bottom or right face button is ACCEPT + * @since 5.9.0 + */ + public var acceptMode:FlxGamepadAcceptMode = BOTTOM; + /** * Stores all gamepads - can have null entries, but index matches event.device */ @@ -595,3 +601,27 @@ class FlxGamepadManager implements IFlxInputManager return count; } } + +/** + * @since 5.9.0 + */ +enum FlxGamepadAcceptMode +{ + /** + * The bottom face button is `ACCEPT` and the right face button is `CANCEL`. + * This is common on western-style consoles, like XBox or American PS4/5 + */ + BOTTOM; + + /** + * The right face button is `ACCEPT` and the bottom face button is `CANCEL`. + * This is common in Japanese PS4/5 consoles, and Nintendo consoles + */ + RIGHT; + + /** + * Behaves like `BOTTOM` for nearly all gamepads, but `RIGHT` for specific mappings, + * namely Nintendo Switch gamepads + */ + USE_MAPPING; +} diff --git a/flixel/input/gamepad/FlxGamepadMappedInput.hx b/flixel/input/gamepad/FlxGamepadMappedInput.hx new file mode 100644 index 0000000000..d6005c444a --- /dev/null +++ b/flixel/input/gamepad/FlxGamepadMappedInput.hx @@ -0,0 +1,57 @@ +package flixel.input.gamepad; + +import flixel.input.gamepad.FlxGamepad; +import flixel.input.gamepad.id.LogitechID; +import flixel.input.gamepad.id.MayflashWiiRemoteID; +import flixel.input.gamepad.id.MFiID; +import flixel.input.gamepad.id.OUYAID; +import flixel.input.gamepad.id.PS4ID; +import flixel.input.gamepad.id.PSVitaID; +import flixel.input.gamepad.id.SwitchJoyconLeftID; +import flixel.input.gamepad.id.SwitchJoyconRightID; +import flixel.input.gamepad.id.SwitchProID; +import flixel.input.gamepad.id.WiiRemoteID; +import flixel.input.gamepad.id.XInputID; + +/** + * A list of every possible gamepad input from every known device + * @since 5.9.0 + */ +@:using(flixel.input.gamepad.FlxGamepadMappedInput.FlxGamepadMappedInputTools) +enum FlxGamepadMappedInput +{ + LOGITECH(id:LogitechID); + MAYFLASH_WII(id:MayflashWiiRemoteID); + MFI(id:MFiID); + OUYA(id:OUYAID); + PS4(id:PS4ID); + PS_VITA(id:PSVitaID); + SWITCH_JOYCON_LEFT(id:SwitchJoyconLeftID); + SWITCH_JOYCON_RIGHT(id:SwitchJoyconRightID); + SWITCH_PRO(id:SwitchProID); + WII(id:WiiRemoteID); + X_INPUT(id:XInputID); + UNKNOWN(id:FlxGamepadInputID); +} + +private class FlxGamepadMappedInputTools +{ + public static inline function toModel(input:FlxGamepadMappedInput):FlxGamepadModel + { + return switch input + { + case FlxGamepadMappedInput.OUYA(_): FlxGamepadModel.OUYA; + case FlxGamepadMappedInput.PS4(_): FlxGamepadModel.PS4; + case FlxGamepadMappedInput.PS_VITA(_): FlxGamepadModel.PSVITA; + case FlxGamepadMappedInput.LOGITECH(_): FlxGamepadModel.LOGITECH; + case FlxGamepadMappedInput.X_INPUT(_): FlxGamepadModel.XINPUT; + case FlxGamepadMappedInput.WII(_): FlxGamepadModel.WII_REMOTE; + case FlxGamepadMappedInput.MAYFLASH_WII(_): FlxGamepadModel.MAYFLASH_WII_REMOTE; + case FlxGamepadMappedInput.SWITCH_PRO(_): FlxGamepadModel.SWITCH_PRO; + case FlxGamepadMappedInput.SWITCH_JOYCON_LEFT(_): FlxGamepadModel.SWITCH_JOYCON_LEFT; + case FlxGamepadMappedInput.SWITCH_JOYCON_RIGHT(_): FlxGamepadModel.SWITCH_JOYCON_RIGHT; + case FlxGamepadMappedInput.MFI(_): FlxGamepadModel.MFI; + case FlxGamepadMappedInput.UNKNOWN(_): FlxGamepadModel.UNKNOWN; + } + } +} \ No newline at end of file diff --git a/flixel/input/gamepad/id/LogitechID.hx b/flixel/input/gamepad/id/LogitechID.hx index 6b33c0e5d8..3c0024e48c 100644 --- a/flixel/input/gamepad/id/LogitechID.hx +++ b/flixel/input/gamepad/id/LogitechID.hx @@ -5,63 +5,73 @@ import flixel.input.gamepad.FlxGamepadAnalogStick; /** * IDs for Logitech controllers (key codes based on Cordless Rumblepad 2) */ -class LogitechID +enum abstract LogitechID(Int) to Int { #if flash - public static inline var ONE:Int = 8; - public static inline var TWO:Int = 9; - public static inline var THREE:Int = 10; - public static inline var FOUR:Int = 11; - public static inline var FIVE:Int = 12; - public static inline var SIX:Int = 13; - public static inline var SEVEN:Int = 14; - public static inline var EIGHT:Int = 15; - public static inline var NINE:Int = 16; - public static inline var TEN:Int = 17; - public static inline var LEFT_STICK_CLICK:Int = 18; - public static inline var RIGHT_STICK_CLICK:Int = 19; + var ONE = 8; + var TWO = 9; + var THREE = 10; + var FOUR = 11; + var FIVE = 12; + var SIX = 13; + var SEVEN = 14; + var EIGHT = 15; + var NINE = 16; + var TEN = 17; + var LEFT_STICK_CLICK = 18; + var RIGHT_STICK_CLICK = 19; - public static inline var DPAD_UP:Int = 4; - public static inline var DPAD_DOWN:Int = 5; - public static inline var DPAD_LEFT:Int = 6; - public static inline var DPAD_RIGHT:Int = 7; + var DPAD_UP = 4; + var DPAD_DOWN = 5; + var DPAD_LEFT = 6; + var DPAD_RIGHT = 7; // TODO: Someone needs to look this up and define it! (NOTE: not all logitech controllers have this) - public static inline var LOGITECH:Int = -1; + var LOGITECH = -1; #else // native and html5 - public static inline var ONE:Int = 0; - public static inline var TWO:Int = 1; - public static inline var THREE:Int = 2; - public static inline var FOUR:Int = 3; - public static inline var FIVE:Int = 4; - public static inline var SIX:Int = 5; - public static inline var SEVEN:Int = 6; - public static inline var EIGHT:Int = 7; - public static inline var NINE:Int = 8; - public static inline var TEN:Int = 9; - public static inline var LEFT_STICK_CLICK:Int = 10; - public static inline var RIGHT_STICK_CLICK:Int = 11; + var ONE = 0; + var TWO = 1; + var THREE = 2; + var FOUR = 3; + var FIVE = 4; + var SIX = 5; + var SEVEN = 6; + var EIGHT = 7; + var NINE = 8; + var TEN = 9; + var LEFT_STICK_CLICK = 10; + var RIGHT_STICK_CLICK = 11; // "fake" IDs, we manually watch for hat axis changes and then send events using these otherwise unused joystick button codes - public static inline var DPAD_UP:Int = 16; - public static inline var DPAD_DOWN:Int = 17; - public static inline var DPAD_LEFT:Int = 18; - public static inline var DPAD_RIGHT:Int = 19; + var DPAD_UP = 16; + var DPAD_DOWN = 17; + var DPAD_LEFT = 18; + var DPAD_RIGHT = 19; // TODO: Someone needs to look this up and define it! (NOTE: not all logitech controllers have this) - public static inline var LOGITECH:Int = -5; + var LOGITECH = -5; #end - - public static var LEFT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(0, 1, { - up: 24, - down: 25, - left: 26, - right: 27 + + var LEFT_STICK_UP = 24; + var LEFT_STICK_DOWN = 25; + var LEFT_STICK_LEFT = 26; + var LEFT_STICK_RIGHT = 27; + + var RIGHT_STICK_UP = 28; + var RIGHT_STICK_DOWN = 29; + var RIGHT_STICK_LEFT = 30; + var RIGHT_STICK_RIGHT = 31; + + public static final LEFT_ANALOG_STICK = new FlxTypedGamepadAnalogStick(0, 1, { + up: LEFT_STICK_UP, + down: LEFT_STICK_DOWN, + left: LEFT_STICK_LEFT, + right: LEFT_STICK_RIGHT }); - public static var RIGHT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(2, 3, { - up: 28, - down: 29, - left: 30, - right: 31 + public static final RIGHT_ANALOG_STICK = new FlxTypedGamepadAnalogStick(2, 3, { + up: RIGHT_STICK_UP, + down: RIGHT_STICK_DOWN, + left: RIGHT_STICK_LEFT, + right: RIGHT_STICK_RIGHT }); } diff --git a/flixel/input/gamepad/id/MFiID.hx b/flixel/input/gamepad/id/MFiID.hx index 8b5e7be4f0..d144e07bcf 100644 --- a/flixel/input/gamepad/id/MFiID.hx +++ b/flixel/input/gamepad/id/MFiID.hx @@ -1,41 +1,52 @@ package flixel.input.gamepad.id; +import flixel.input.gamepad.FlxGamepadAnalogStick; + /** * IDs for MFi controllers */ -class MFiID +enum abstract MFiID(Int) to Int { - public static inline var A:Int = 6; - public static inline var B:Int = 7; - public static inline var X:Int = 8; - public static inline var Y:Int = 9; - public static inline var LB:Int = 15; - public static inline var RB:Int = 16; - public static inline var BACK:Int = 10; - public static inline var START:Int = 12; - public static inline var LEFT_STICK_CLICK:Int = 13; - public static inline var RIGHT_STICK_CLICK:Int = 14; - - public static inline var GUIDE:Int = 11; + var LEFT_TRIGGER = 4; + var RIGHT_TRIGGER = 5; + + var A = 6; + var B = 7; + var X = 8; + var Y = 9; + var LB = 15; + var RB = 16; + var BACK = 10; + var GUIDE = 11; + var START = 12; + var LEFT_STICK_CLICK = 13; + var RIGHT_STICK_CLICK = 14; + + var DPAD_UP = 17; + var DPAD_DOWN = 18; + var DPAD_LEFT = 19; + var DPAD_RIGHT = 20; - public static inline var DPAD_UP:Int = 17; - public static inline var DPAD_DOWN:Int = 18; - public static inline var DPAD_LEFT:Int = 19; - public static inline var DPAD_RIGHT:Int = 20; - - public static var LEFT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(0, 1, { - up: 21, - down: 22, - left: 23, - right: 24 + var LEFT_STICK_UP = 21; + var LEFT_STICK_DOWN = 22; + var LEFT_STICK_LEFT = 23; + var LEFT_STICK_RIGHT = 24; + + var RIGHT_STICK_UP = 25; + var RIGHT_STICK_DOWN = 26; + var RIGHT_STICK_LEFT = 27; + var RIGHT_STICK_RIGHT = 28; + + public static final LEFT_ANALOG_STICK = new FlxTypedGamepadAnalogStick(0, 1, { + up: LEFT_STICK_UP, + down: LEFT_STICK_DOWN, + left: LEFT_STICK_LEFT, + right: LEFT_STICK_RIGHT }); - public static var RIGHT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(2, 3, { - up: 25, - down: 26, - left: 27, - right: 28 + public static final RIGHT_ANALOG_STICK = new FlxTypedGamepadAnalogStick(2, 3, { + up: RIGHT_STICK_UP, + down: RIGHT_STICK_DOWN, + left: RIGHT_STICK_LEFT, + right: RIGHT_STICK_RIGHT }); - - public static inline var LEFT_TRIGGER:Int = 4; - public static inline var RIGHT_TRIGGER:Int = 5; } diff --git a/flixel/input/gamepad/id/MayflashWiiRemoteID.hx b/flixel/input/gamepad/id/MayflashWiiRemoteID.hx index 3e0bf57ca6..d36e5f067b 100644 --- a/flixel/input/gamepad/id/MayflashWiiRemoteID.hx +++ b/flixel/input/gamepad/id/MayflashWiiRemoteID.hx @@ -7,7 +7,7 @@ import flixel.input.gamepad.FlxGamepadAnalogStick; * * @author larsiusprime */ -class MayflashWiiRemoteID +enum abstract MayflashWiiRemoteID(Int) to Int { /** * Things to add: @@ -19,158 +19,141 @@ class MayflashWiiRemoteID */ #if FLX_JOYSTICK_API // Standard Wii Remote inputs: - public static inline var REMOTE_ONE:Int = 0; - public static inline var REMOTE_TWO:Int = 1; - public static inline var REMOTE_A:Int = 2; - public static inline var REMOTE_B:Int = 3; + var REMOTE_ONE = 0; + var REMOTE_TWO = 1; + var REMOTE_A = 2; + var REMOTE_B = 3; - public static inline var REMOTE_MINUS:Int = 4; - public static inline var REMOTE_PLUS:Int = 5; + var REMOTE_MINUS = 4; + var REMOTE_PLUS = 5; - public static inline var REMOTE_HOME:Int = 11; + var REMOTE_HOME = 11; // Nunchuk attachment: - public static inline var NUNCHUK_Z:Int = 6; - public static inline var NUNCHUK_C:Int = 7; + var NUNCHUK_Z = 6; + var NUNCHUK_C = 7; - public static inline var NUNCHUK_DPAD_DOWN:Int = 12; - public static inline var NUNCHUK_DPAD_UP:Int = 13; - public static inline var NUNCHUK_DPAD_LEFT:Int = 14; - public static inline var NUNCHUK_DPAD_RIGHT:Int = 15; + var NUNCHUK_DPAD_DOWN = 12; + var NUNCHUK_DPAD_UP = 13; + var NUNCHUK_DPAD_LEFT = 14; + var NUNCHUK_DPAD_RIGHT = 15; - public static inline var NUNCHUK_MINUS:Int = 4; - public static inline var NUNCHUK_PLUS:Int = 5; + var NUNCHUK_MINUS = 4; + var NUNCHUK_PLUS = 5; - public static inline var NUNCHUK_HOME:Int = 11; + var NUNCHUK_HOME = 11; - public static inline var NUNCHUK_ONE:Int = 0; - public static inline var NUNCHUK_TWO:Int = 1; - public static inline var NUNCHUK_A:Int = 2; - public static inline var NUNCHUK_B:Int = 3; + var NUNCHUK_ONE = 0; + var NUNCHUK_TWO = 1; + var NUNCHUK_A = 2; + var NUNCHUK_B = 3; // classic controller attachment: - public static inline var CLASSIC_Y:Int = 0; // Identical to WiiRemote 1 - public static inline var CLASSIC_X:Int = 1; // Identical to WiiRemote 2 - public static inline var CLASSIC_B:Int = 2; // Identical to WiiRemote A - public static inline var CLASSIC_A:Int = 3; // Identical to WiiRemote B + var CLASSIC_Y = 0; // Identical to WiiRemote 1 + var CLASSIC_X = 1; // Identical to WiiRemote 2 + var CLASSIC_B = 2; // Identical to WiiRemote A + var CLASSIC_A = 3; // Identical to WiiRemote B - public static inline var CLASSIC_L:Int = 4; // Identical to MINUS and PLUS - public static inline var CLASSIC_R:Int = 5; - public static inline var CLASSIC_ZL:Int = 6; // Identical to C and Z - public static inline var CLASSIC_ZR:Int = 7; + var CLASSIC_L = 4; // Identical to MINUS and PLUS + var CLASSIC_R = 5; + var CLASSIC_ZL = 6; // Identical to C and Z + var CLASSIC_ZR = 7; - public static inline var CLASSIC_SELECT:Int = 8; - public static inline var CLASSIC_START:Int = 9; + var CLASSIC_SELECT = 8; + var CLASSIC_START = 9; - public static inline var CLASSIC_HOME:Int = 11; + var CLASSIC_HOME = 11; - public static inline var CLASSIC_DPAD_DOWN:Int = 12; - public static inline var CLASSIC_DPAD_UP:Int = 13; - public static inline var CLASSIC_DPAD_LEFT:Int = 14; - public static inline var CLASSIC_DPAD_RIGHT:Int = 15; + var CLASSIC_DPAD_DOWN = 12; + var CLASSIC_DPAD_UP = 13; + var CLASSIC_DPAD_LEFT = 14; + var CLASSIC_DPAD_RIGHT = 15; - public static inline var CLASSIC_ONE:Int = -1; - public static inline var CLASSIC_TWO:Int = -1; - - // Axis indices - public static inline var NUNCHUK_POINTER_X:Int = 2; - public static inline var NUNCHUK_POINTER_Y:Int = 3; - - // Yes, the WiiRemote DPAD is treated as ANALOG for some reason...so we have to pass in some "fake" ID's to get simulated digital inputs - public static var REMOTE_DPAD(default, null) = new FlxGamepadAnalogStick(0, 1, { - up: REMOTE_DPAD_UP, - down: REMOTE_DPAD_DOWN, - left: REMOTE_DPAD_LEFT, - right: REMOTE_DPAD_RIGHT, - threshold: 0.5, - mode: ONLY_DIGITAL - }); - - public static var LEFT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(0, 1, { - up: 26, - down: 27, - left: 28, - right: 29 - }); // the nunchuk only has the "left" analog stick - public static var RIGHT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(2, 3, { - up: 30, - down: 31, - left: 32, - right: 33 - }); // the classic controller has both the "left" and "right" analog sticks - - // these aren't real axes, they're simulated when the right digital buttons are pushed - public static inline var LEFT_TRIGGER_FAKE:Int = 4; - public static inline var RIGHT_TRIGGER_FAKE:Int = 5; - - // "fake" IDs - public static inline var REMOTE_DPAD_UP:Int = 22; - public static inline var REMOTE_DPAD_DOWN:Int = 23; - public static inline var REMOTE_DPAD_LEFT:Int = 24; - public static inline var REMOTE_DPAD_RIGHT:Int = 25; + var CLASSIC_ONE = -1; + var CLASSIC_TWO = -1; #else // gamepad API // Standard Wii Remote inputs: - public static inline var REMOTE_ONE:Int = 8; - public static inline var REMOTE_TWO:Int = 9; - public static inline var REMOTE_A:Int = 10; - public static inline var REMOTE_B:Int = 11; + var REMOTE_ONE = 8; + var REMOTE_TWO = 9; + var REMOTE_A = 10; + var REMOTE_B = 11; - public static inline var REMOTE_MINUS:Int = 12; - public static inline var REMOTE_PLUS:Int = 13; + var REMOTE_MINUS = 12; + var REMOTE_PLUS = 13; - public static inline var REMOTE_HOME:Int = 19; + var REMOTE_HOME = 19; // Nunchuk attachment: - public static inline var NUNCHUK_Z:Int = 14; - public static inline var NUNCHUK_C:Int = 15; + var NUNCHUK_Z = 14; + var NUNCHUK_C = 15; - public static inline var NUNCHUK_DPAD_UP:Int = 4; - public static inline var NUNCHUK_DPAD_DOWN:Int = 5; - public static inline var NUNCHUK_DPAD_LEFT:Int = 6; - public static inline var NUNCHUK_DPAD_RIGHT:Int = 7; + var NUNCHUK_DPAD_UP = 4; + var NUNCHUK_DPAD_DOWN = 5; + var NUNCHUK_DPAD_LEFT = 6; + var NUNCHUK_DPAD_RIGHT = 7; - public static inline var NUNCHUK_MINUS:Int = 12; - public static inline var NUNCHUK_PLUS:Int = 13; + var NUNCHUK_MINUS = 12; + var NUNCHUK_PLUS = 13; - public static inline var NUNCHUK_HOME:Int = 19; + var NUNCHUK_HOME = 19; - public static inline var NUNCHUK_A:Int = 10; - public static inline var NUNCHUK_B:Int = 11; + var NUNCHUK_A = 10; + var NUNCHUK_B = 11; - public static inline var NUNCHUK_ONE:Int = 8; - public static inline var NUNCHUK_TWO:Int = 9; + var NUNCHUK_ONE = 8; + var NUNCHUK_TWO = 9; // classic controller attachment: - public static inline var CLASSIC_Y:Int = 8; - public static inline var CLASSIC_X:Int = 9; - public static inline var CLASSIC_B:Int = 10; - public static inline var CLASSIC_A:Int = 11; + var CLASSIC_Y = 8; + var CLASSIC_X = 9; + var CLASSIC_B = 10; + var CLASSIC_A = 11; - public static inline var CLASSIC_L:Int = 12; - public static inline var CLASSIC_R:Int = 13; - public static inline var CLASSIC_ZL:Int = 14; - public static inline var CLASSIC_ZR:Int = 15; + var CLASSIC_L = 12; + var CLASSIC_R = 13; + var CLASSIC_ZL = 14; + var CLASSIC_ZR = 15; - public static inline var CLASSIC_SELECT:Int = 16; - public static inline var CLASSIC_START:Int = 17; + var CLASSIC_SELECT = 16; + var CLASSIC_START = 17; - public static inline var CLASSIC_HOME:Int = 19; + var CLASSIC_HOME = 19; - public static inline var CLASSIC_ONE:Int = -1; - public static inline var CLASSIC_TWO:Int = -1; + var CLASSIC_ONE = -1; + var CLASSIC_TWO = -1; // (input "10" does not seem to be defined) - public static inline var CLASSIC_DPAD_UP:Int = 4; - public static inline var CLASSIC_DPAD_DOWN:Int = 5; - public static inline var CLASSIC_DPAD_LEFT:Int = 6; - public static inline var CLASSIC_DPAD_RIGHT:Int = 7; - + var CLASSIC_DPAD_UP = 4; + var CLASSIC_DPAD_DOWN = 5; + var CLASSIC_DPAD_LEFT = 6; + var CLASSIC_DPAD_RIGHT = 7; + #end // Axis indices - public static inline var NUNCHUK_POINTER_X:Int = 2; - public static inline var NUNCHUK_POINTER_Y:Int = 3; + var NUNCHUK_POINTER_X = 2; + var NUNCHUK_POINTER_Y = 3; + + var LEFT_STICK_UP = 26; + var LEFT_STICK_DOWN = 27; + var LEFT_STICK_LEFT = 28; + var LEFT_STICK_RIGHT = 29; + + var RIGHT_STICK_UP = 30; + var RIGHT_STICK_DOWN = 31; + var RIGHT_STICK_LEFT = 32; + var RIGHT_STICK_RIGHT = 33; + + // these aren't real axes, they're simulated when the right digital buttons are pushed + var LEFT_TRIGGER_FAKE = 4; + var RIGHT_TRIGGER_FAKE = 5; + // "fake" IDs + var REMOTE_DPAD_UP = 22; + var REMOTE_DPAD_DOWN = 23; + var REMOTE_DPAD_LEFT = 24; + var REMOTE_DPAD_RIGHT = 25; + // Yes, the WiiRemote DPAD is treated as ANALOG for some reason...so we have to pass in some "fake" ID's to get simulated digital inputs - public static var REMOTE_DPAD(default, null) = new FlxGamepadAnalogStick(0, 1, { + public static final REMOTE_DPAD = new FlxTypedGamepadAnalogStick(0, 1, { up: REMOTE_DPAD_UP, down: REMOTE_DPAD_DOWN, left: REMOTE_DPAD_LEFT, @@ -178,28 +161,18 @@ class MayflashWiiRemoteID threshold: 0.5, mode: ONLY_DIGITAL }); - - public static var LEFT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(0, 1, { - up: 26, - down: 27, - left: 28, - right: 29 + + public static final LEFT_ANALOG_STICK = new FlxTypedGamepadAnalogStick(0, 1, { + up: LEFT_STICK_UP, + down: LEFT_STICK_DOWN, + left: LEFT_STICK_LEFT, + right: LEFT_STICK_RIGHT }); // the nunchuk only has the "left" analog stick - public static var RIGHT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(2, 3, { - up: 26, - down: 27, - left: 28, - right: 29 + + public static final RIGHT_ANALOG_STICK = new FlxTypedGamepadAnalogStick(2, 3, { + up: RIGHT_STICK_UP, + down: RIGHT_STICK_DOWN, + left: RIGHT_STICK_LEFT, + right: RIGHT_STICK_RIGHT }); // the classic controller has both the "left" and "right" analog sticks - - // these aren't real axes, they're simulated when the right digital buttons are pushed - public static inline var LEFT_TRIGGER_FAKE:Int = 4; - public static inline var RIGHT_TRIGGER_FAKE:Int = 5; - - // "fake" IDs - public static inline var REMOTE_DPAD_UP:Int = 22; - public static inline var REMOTE_DPAD_DOWN:Int = 23; - public static inline var REMOTE_DPAD_LEFT:Int = 24; - public static inline var REMOTE_DPAD_RIGHT:Int = 25; - #end } diff --git a/flixel/input/gamepad/id/OUYAID.hx b/flixel/input/gamepad/id/OUYAID.hx index 9e21a462fa..50defda484 100644 --- a/flixel/input/gamepad/id/OUYAID.hx +++ b/flixel/input/gamepad/id/OUYAID.hx @@ -5,37 +5,47 @@ import flixel.input.gamepad.FlxGamepadAnalogStick; /** * IDs for OUYA controllers */ -class OUYAID +enum abstract OUYAID(Int) to Int { - public static inline var O:Int = 6; - public static inline var U:Int = 8; - public static inline var Y:Int = 9; - public static inline var A:Int = 7; - public static inline var LB:Int = 15; - public static inline var RB:Int = 16; - public static inline var LEFT_STICK_CLICK:Int = 13; - public static inline var RIGHT_STICK_CLICK:Int = 14; - public static inline var HOME:Int = 0x01000012; // Not sure if press HOME is taken in account on OUYA - public static inline var LEFT_TRIGGER:Int = 4; - public static inline var RIGHT_TRIGGER:Int = 5; + var O = 6; + var U = 8; + var Y = 9; + var A = 7; + var LB = 15; + var RB = 16; + var LEFT_STICK_CLICK = 13; + var RIGHT_STICK_CLICK = 14; + var HOME = 0x01000012; // Not sure if press HOME is taken in account on OUYA + var LEFT_TRIGGER = 4; + var RIGHT_TRIGGER = 5; // "fake" IDs, we manually watch for hat axis changes and then send events using these otherwise unused joystick button codes - public static inline var DPAD_LEFT:Int = 19; - public static inline var DPAD_RIGHT:Int = 20; - public static inline var DPAD_DOWN:Int = 18; - public static inline var DPAD_UP:Int = 17; - + var DPAD_LEFT = 19; + var DPAD_RIGHT = 20; + var DPAD_DOWN = 18; + var DPAD_UP = 17; + + var LEFT_STICK_UP = 23; + var LEFT_STICK_DOWN = 24; + var LEFT_STICK_LEFT = 25; + var LEFT_STICK_RIGHT = 26; + + var RIGHT_STICK_UP = 27; + var RIGHT_STICK_DOWN = 28; + var RIGHT_STICK_LEFT = 29; + var RIGHT_STICK_RIGHT = 30; + // If TRIGGER axis returns value > 0 then LT is being pressed, and if it's < 0 then RT is being pressed - public static var LEFT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(0, 1, { - up: 23, - down: 24, - left: 25, - right: 26 + public static final LEFT_ANALOG_STICK = new FlxTypedGamepadAnalogStick(0, 1, { + up: LEFT_STICK_UP, + down: LEFT_STICK_DOWN, + left: LEFT_STICK_LEFT, + right: LEFT_STICK_RIGHT }); - public static var RIGHT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(2, 3, { - up: 27, - down: 28, - left: 29, - right: 30 + public static final RIGHT_ANALOG_STICK = new FlxTypedGamepadAnalogStick(2, 3, { + up: RIGHT_STICK_UP, + down: RIGHT_STICK_DOWN, + left: RIGHT_STICK_LEFT, + right: RIGHT_STICK_RIGHT }); } diff --git a/flixel/input/gamepad/id/PS4ID.hx b/flixel/input/gamepad/id/PS4ID.hx index 1fd01e7505..ccbb77ec63 100644 --- a/flixel/input/gamepad/id/PS4ID.hx +++ b/flixel/input/gamepad/id/PS4ID.hx @@ -18,136 +18,156 @@ import flixel.input.gamepad.FlxGamepadAnalogStick; * MAC: the PS4 controller seemed to work perfectly without anything special installed, and was not detected in the 360Controller * control panel, so it might just work right out of the box! */ -class PS4ID +enum abstract PS4ID(Int) to Int { #if flash - public static inline var SQUARE:Int = 10; - public static inline var X:Int = 11; - public static inline var CIRCLE:Int = 12; - public static inline var TRIANGLE:Int = 13; - public static inline var L1:Int = 14; - public static inline var R1:Int = 15; - public static inline var L2:Int = 16; - public static inline var R2:Int = 17; - public static inline var SHARE:Int = 18; - public static inline var OPTIONS:Int = 19; - public static inline var LEFT_STICK_CLICK:Int = 20; - public static inline var RIGHT_STICK_CLICK:Int = 21; - public static inline var PS:Int = 22; - public static inline var TOUCHPAD_CLICK:Int = 23; - - public static var LEFT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(0, 1, { - up: 24, - down: 25, - left: 26, - right: 27 - }); - public static var RIGHT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(2, 5, { - up: 28, - down: 29, - left: 30, - right: 31 - }); - - public static inline var DPAD_UP:Int = 6; - public static inline var DPAD_DOWN:Int = 7; - public static inline var DPAD_LEFT:Int = 8; - public static inline var DPAD_RIGHT:Int = 9; + var SQUARE = 10; + var X = 11; + var CIRCLE = 12; + var TRIANGLE = 13; + var L1 = 14; + var R1 = 15; + var L2 = 16; + var R2 = 17; + var SHARE = 18; + var OPTIONS = 19; + var LEFT_STICK_CLICK = 20; + var RIGHT_STICK_CLICK = 21; + var PS = 22; + var TOUCHPAD_CLICK = 23; + + static inline final LEFT_X = 0; + static inline final LEFT_Y = 1; + static inline final RIGHT_X = 2; + static inline final RIGHT_Y = 5; + + var LEFT_STICK_UP = 24; + var LEFT_STICK_DOWN = 25; + var LEFT_STICK_LEFT = 26; + var LEFT_STICK_RIGHT = 27; + + var RIGHT_STICK_UP = 28; + var RIGHT_STICK_DOWN = 29; + var RIGHT_STICK_LEFT = 30; + var RIGHT_STICK_RIGHT = 31; + + var DPAD_UP = 6; + var DPAD_DOWN = 7; + var DPAD_LEFT = 8; + var DPAD_RIGHT = 9; #elseif FLX_GAMEINPUT_API // #if (html5 || windows || mac || linux) - public static inline var X:Int = 6; - public static inline var CIRCLE:Int = 7; - public static inline var SQUARE:Int = 8; - public static inline var TRIANGLE:Int = 9; - public static inline var PS:Int = 11; - public static inline var OPTIONS:Int = 12; - public static inline var LEFT_STICK_CLICK:Int = 13; - public static inline var RIGHT_STICK_CLICK:Int = 14; - public static inline var L1:Int = 15; - public static inline var R1:Int = 16; + var X = 6; + var CIRCLE = 7; + var SQUARE = 8; + var TRIANGLE = 9; + var PS = 11; + var OPTIONS = 12; + var LEFT_STICK_CLICK = 13; + var RIGHT_STICK_CLICK = 14; + var L1 = 15; + var R1 = 16; #if ps4 - public static inline var TOUCHPAD_CLICK:Int = 10; // On an actual PS4, share is reserved by the system, and the touchpad click can serve more or less as a replacement for the "back/select" button - - public static var LEFT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(0, 1, { - up: 32, - down: 33, - left: 34, - right: 35 - }); - public static var RIGHT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(2, 3, { - up: 36, - down: 37, - left: 38, - right: 39 - }); - - public static inline var SHARE:Int = 40; // Not accessible on an actual PS4, just setting it to a dummy value + var TOUCHPAD_CLICK = 10; // On an actual PS4, share is reserved by the system, and the touchpad click can serve more or less as a replacement for the "back/select" button + + static inline final LEFT_X = 0; + static inline final LEFT_Y = 1; + static inline final RIGHT_X = 2; + static inline final RIGHT_Y = 3; + + var LEFT_STICK_UP = 32; + var LEFT_STICK_DOWN = 33; + var LEFT_STICK_LEFT = 34; + var LEFT_STICK_RIGHT = 35; + + var RIGHT_STICK_UP = 36; + var RIGHT_STICK_DOWN = 37; + var RIGHT_STICK_LEFT = 38; + var RIGHT_STICK_RIGHT = 39; + + var SHARE = 40; // Not accessible on an actual PS4, just setting it to a dummy value #else - public static inline var SHARE:Int = 10; // This is only accessible when not using an actual Playstation 4, otherwise it's reserved by the system - - public static var LEFT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(0, 1, { - up: 22, - down: 23, - left: 24, - right: 25 - }); - public static var RIGHT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(2, 3, { - up: 26, - down: 27, - left: 28, - right: 29 - }); - - public static inline var TOUCHPAD_CLICK:Int = 30; // I don't believe this is normally accessible on PC, just setting it to a dummy value - + var SHARE = 10; // This is only accessible when not using an actual Playstation 4, otherwise it's reserved by the system + + static inline final LEFT_X = 0; + static inline final LEFT_Y = 1; + static inline final RIGHT_X = 2; + static inline final RIGHT_Y = 3; + + var LEFT_STICK_UP = 22; + var LEFT_STICK_DOWN = 23; + var LEFT_STICK_LEFT = 24; + var LEFT_STICK_RIGHT = 25; + + var RIGHT_STICK_UP = 26; + var RIGHT_STICK_DOWN = 27; + var RIGHT_STICK_LEFT = 28; + var RIGHT_STICK_RIGHT = 29; + + var TOUCHPAD_CLICK = 30; // I don't believe this is normally accessible on PC, just setting it to a dummy value #end - public static inline var L2:Int = 4; - public static inline var R2:Int = 5; + var L2 = 4; + var R2 = 5; - public static inline var DPAD_UP:Int = 17; - public static inline var DPAD_DOWN:Int = 18; - public static inline var DPAD_LEFT:Int = 19; - public static inline var DPAD_RIGHT:Int = 20; + var DPAD_UP = 17; + var DPAD_DOWN = 18; + var DPAD_LEFT = 19; + var DPAD_RIGHT = 20; // On linux the drivers we're testing with just make the PS4 controller look like an XInput device, // So strictly speaking these ID's will probably not be used, but the compiler needs something or // else it will not compile on Linux #else // "legacy" - public static inline var SQUARE:Int = 0; - public static inline var X:Int = 1; - public static inline var CIRCLE:Int = 2; - public static inline var TRIANGLE:Int = 3; - public static inline var L1:Int = 4; - public static inline var R1:Int = 5; - - public static inline var SHARE:Int = 8; - public static inline var OPTIONS:Int = 9; - public static inline var LEFT_STICK_CLICK:Int = 10; - public static inline var RIGHT_STICK_CLICK:Int = 11; - public static inline var PS:Int = 12; - public static inline var TOUCHPAD_CLICK:Int = 13; - - public static inline var L2:Int = 3; - public static inline var R2:Int = 4; - - public static var LEFT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(0, 1, { - up: 27, - down: 28, - left: 29, - right: 30 - }); - public static var RIGHT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(2, 5, { - up: 31, - down: 32, - left: 33, - right: 34 - }); - + var SQUARE = 0; + var X = 1; + var CIRCLE = 2; + var TRIANGLE = 3; + var L1 = 4; + var R1 = 5; + + var SHARE = 8; + var OPTIONS = 9; + var LEFT_STICK_CLICK = 10; + var RIGHT_STICK_CLICK = 11; + var PS = 12; + var TOUCHPAD_CLICK = 13; + + var L2 = 3; + var R2 = 4; + + static inline final LEFT_X = 0; + static inline final LEFT_Y = 1; + static inline final RIGHT_X = 2; + static inline final RIGHT_Y = 5; + + var LEFT_STICK_UP = 27; + var LEFT_STICK_DOWN = 28; + var LEFT_STICK_LEFT = 29; + var LEFT_STICK_RIGHT = 30; + + var RIGHT_STICK_UP = 31; + var RIGHT_STICK_DOWN = 32; + var RIGHT_STICK_LEFT = 33; + var RIGHT_STICK_RIGHT = 34; + // "fake" IDs, we manually watch for hat axis changes and then send events using these otherwise unused joystick button codes - public static inline var DPAD_LEFT:Int = 15; - public static inline var DPAD_RIGHT:Int = 16; - public static inline var DPAD_DOWN:Int = 17; - public static inline var DPAD_UP:Int = 18; + var DPAD_LEFT = 15; + var DPAD_RIGHT = 16; + var DPAD_DOWN = 17; + var DPAD_UP = 18; #end + + public static final LEFT_ANALOG_STICK = new FlxTypedGamepadAnalogStick(LEFT_X, LEFT_Y, { + up: LEFT_STICK_UP, + down: LEFT_STICK_DOWN, + left: LEFT_STICK_LEFT, + right: LEFT_STICK_RIGHT + }); + public static final RIGHT_ANALOG_STICK = new FlxTypedGamepadAnalogStick(RIGHT_X, RIGHT_Y, { + up: RIGHT_STICK_UP, + down: RIGHT_STICK_DOWN, + left: RIGHT_STICK_LEFT, + right: RIGHT_STICK_RIGHT + }); } diff --git a/flixel/input/gamepad/id/PSVitaID.hx b/flixel/input/gamepad/id/PSVitaID.hx index bdcdfbc8f0..8a28fb9f42 100644 --- a/flixel/input/gamepad/id/PSVitaID.hx +++ b/flixel/input/gamepad/id/PSVitaID.hx @@ -8,32 +8,42 @@ import flixel.input.gamepad.FlxGamepadAnalogStick; * * This will ONLY work with the gamepad API (available only in OpenFL "next", not "legacy") and will NOT work with the joystick API */ -class PSVitaID +enum abstract PSVitaID(Int) to Int { - public static inline var X:Int = 6; - public static inline var CIRCLE:Int = 7; - public static inline var SQUARE:Int = 8; - public static inline var TRIANGLE:Int = 9; - public static inline var SELECT:Int = 10; - public static inline var START:Int = 12; - public static inline var L:Int = 15; - public static inline var R:Int = 16; + var X = 6; + var CIRCLE = 7; + var SQUARE = 8; + var TRIANGLE = 9; + var SELECT = 10; + var START = 12; + var L = 15; + var R = 16; - public static inline var DPAD_UP:Int = 17; - public static inline var DPAD_DOWN:Int = 18; - public static inline var DPAD_LEFT:Int = 19; - public static inline var DPAD_RIGHT:Int = 20; - - public static var LEFT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(0, 1, { - up: 21, - down: 22, - left: 23, - right: 24 + var DPAD_UP = 17; + var DPAD_DOWN = 18; + var DPAD_LEFT = 19; + var DPAD_RIGHT = 20; + + var LEFT_STICK_UP = 21; + var LEFT_STICK_DOWN = 22; + var LEFT_STICK_LEFT = 23; + var LEFT_STICK_RIGHT = 24; + + var RIGHT_STICK_UP = 25; + var RIGHT_STICK_DOWN = 26; + var RIGHT_STICK_LEFT = 27; + var RIGHT_STICK_RIGHT = 28; + + public static final LEFT_ANALOG_STICK = new FlxTypedGamepadAnalogStick(0, 1, { + up: LEFT_STICK_UP, + down: LEFT_STICK_DOWN, + left: LEFT_STICK_LEFT, + right: LEFT_STICK_RIGHT }); - public static var RIGHT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(2, 3, { - up: 25, - down: 26, - left: 27, - right: 28 + public static final RIGHT_ANALOG_STICK = new FlxTypedGamepadAnalogStick(2, 3, { + up: RIGHT_STICK_UP, + down: RIGHT_STICK_DOWN, + left: RIGHT_STICK_LEFT, + right: RIGHT_STICK_RIGHT }); } diff --git a/flixel/input/gamepad/id/SwitchJoyconLeftID.hx b/flixel/input/gamepad/id/SwitchJoyconLeftID.hx index 9d35d7a461..99090a87e4 100644 --- a/flixel/input/gamepad/id/SwitchJoyconLeftID.hx +++ b/flixel/input/gamepad/id/SwitchJoyconLeftID.hx @@ -19,44 +19,48 @@ import flixel.input.gamepad.FlxGamepadAnalogStick; * * @since 4.8.0 */ -class SwitchJoyconLeftID +enum abstract SwitchJoyconLeftID(Int) to Int { #if flash - public static inline var UP:Int = 8; - public static inline var LEFT:Int = 9; - public static inline var DOWN:Int = 10; - public static inline var RIGHT:Int = 11; - public static inline var SL:Int = 12; - public static inline var SR:Int = 13; - public static inline var ZL:Int = 14; - public static inline var L:Int = 15; - public static inline var MINUS:Int = 17; - public static inline var CAPTURE:Int = 21; - public static inline var LEFT_STICK_CLICK:Int = 22; - public static var LEFT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(0, 1, { - up: 24, - down: 25, - left: 26, - right: 27 - }); + var UP = 8; + var LEFT = 9; + var DOWN = 10; + var RIGHT = 11; + var SL = 12; + var SR = 13; + var ZL = 14; + var L = 15; + var MINUS = 17; + var CAPTURE = 21; + var LEFT_STICK_CLICK = 22; + + var LEFT_STICK_UP = 24; + var LEFT_STICK_DOWN = 25; + var LEFT_STICK_LEFT = 26; + var LEFT_STICK_RIGHT = 27; #else - public static inline var ZL:Int = 4; - public static inline var DOWN:Int = 6; - public static inline var RIGHT:Int = 7; - public static inline var LEFT:Int = 8; - public static inline var UP:Int = 9; - public static inline var L:Int = 10; - public static inline var MINUS:Int = 12; - public static inline var LEFT_STICK_CLICK:Int = 13; - public static inline var SL:Int = 15; - public static inline var SR:Int = 16; - public static inline var CAPTURE:Int = 21; - public static var LEFT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(0, 1, { - up: 22, - down: 23, - left: 24, - right: 25 - }); + var ZL = 4; + var DOWN = 6; + var RIGHT = 7; + var LEFT = 8; + var UP = 9; + var L = 10; + var MINUS = 12; + var LEFT_STICK_CLICK = 13; + var SL = 15; + var SR = 16; + var CAPTURE = 21; + + var LEFT_STICK_UP = 22; + var LEFT_STICK_DOWN = 23; + var LEFT_STICK_LEFT = 24; + var LEFT_STICK_RIGHT = 25; #end + public static final LEFT_ANALOG_STICK = new FlxTypedGamepadAnalogStick(0, 1, { + up: LEFT_STICK_UP, + down: LEFT_STICK_DOWN, + left: LEFT_STICK_LEFT, + right: LEFT_STICK_RIGHT + }); } diff --git a/flixel/input/gamepad/id/SwitchJoyconRightID.hx b/flixel/input/gamepad/id/SwitchJoyconRightID.hx index b75d3df1c1..626e131d33 100644 --- a/flixel/input/gamepad/id/SwitchJoyconRightID.hx +++ b/flixel/input/gamepad/id/SwitchJoyconRightID.hx @@ -19,51 +19,49 @@ import flixel.input.gamepad.FlxGamepadAnalogStick; * * @since 4.8.0 */ -class SwitchJoyconRightID + +enum abstract SwitchJoyconRightID(Int) to Int { #if flash - public static inline var A:Int = 8; - public static inline var B:Int = 9; - public static inline var X:Int = 10; - public static inline var Y:Int = 11; - public static inline var SL:Int = 12; - public static inline var SR:Int = 13; - public static inline var ZR:Int = 15; - public static inline var R:Int = 16; - public static inline var PLUS:Int = 17; - public static inline var HOME:Int = 20; - public static inline var CAPTURE:Int = 21; - public static inline var LEFT_STICK_CLICK:Int = 22; - public static var LEFT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(0, 1, { - up: 24, - down: 25, - left: 26, - right: 27 - }); - public static var RIGHT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(2, 3, { - up: 28, - down: 29, - left: 30, - right: 31 - }); + var A = 8; + var B = 9; + var X = 10; + var Y = 11; + var SL = 12; + var SR = 13; + var ZR = 15; + var R = 16; + var PLUS = 17; + var HOME = 20; + var CAPTURE = 21; + var LEFT_STICK_CLICK = 22; + + var LEFT_STICK_UP = 24; + var LEFT_STICK_DOWN = 25; + var LEFT_STICK_LEFT = 26; + var LEFT_STICK_RIGHT = 27; #else - public static inline var ZR:Int = 5; - public static inline var A:Int = 6; - public static inline var X:Int = 7; - public static inline var B:Int = 8; - public static inline var Y:Int = 9; - public static inline var R:Int = 10; - public static inline var HOME:Int = 11; - public static inline var PLUS:Int = 12; - public static inline var LEFT_STICK_CLICK:Int = 13; - public static inline var SL:Int = 15; - public static inline var SR:Int = 16; - public static var LEFT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(0, 1, { - up: 22, - down: 23, - left: 24, - right: 25 - }); - #end + var ZR = 5; + var A = 6; + var X = 7; + var B = 8; + var Y = 9; + var R = 10; + var HOME = 11; + var PLUS = 12; + var LEFT_STICK_CLICK = 13; + var SL = 15; + var SR = 16; + var LEFT_STICK_UP = 22; + var LEFT_STICK_DOWN = 23; + var LEFT_STICK_LEFT = 24; + var LEFT_STICK_RIGHT = 25; + #end + public static final LEFT_ANALOG_STICK = new FlxTypedGamepadAnalogStick(0, 1, { + up: LEFT_STICK_UP, + down: LEFT_STICK_DOWN, + left: LEFT_STICK_LEFT, + right: LEFT_STICK_RIGHT + }); } diff --git a/flixel/input/gamepad/id/SwitchProID.hx b/flixel/input/gamepad/id/SwitchProID.hx index 845a0264e9..0d8d79a7fd 100644 --- a/flixel/input/gamepad/id/SwitchProID.hx +++ b/flixel/input/gamepad/id/SwitchProID.hx @@ -17,70 +17,80 @@ import flixel.input.gamepad.FlxGamepadAnalogStick; * * @since 4.8.0 */ -class SwitchProID +enum abstract SwitchProID(Int) to Int { #if flash - public static inline var DPAD_UP:Int = 4; - public static inline var DPAD_DOWN:Int = 5; - public static inline var DPAD_LEFT:Int = 6; - public static inline var DPAD_RIGHT:Int = 7; - public static inline var A:Int = 8; - public static inline var B:Int = 9; - public static inline var X:Int = 10; - public static inline var Y:Int = 11; - public static inline var L:Int = 12; - public static inline var R:Int = 13; - public static inline var ZL:Int = 14; - public static inline var ZR:Int = 15; - public static inline var MINUS:Int = 16; - public static inline var PLUS:Int = 17; - public static inline var HOME:Int = 20; - public static inline var CAPTURE:Int = 21; - public static inline var LEFT_STICK_CLICK:Int = 22; - public static inline var RIGHT_STICK_CLICK:Int = 23; - public static var LEFT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(0, 1, { - up: 24, - down: 25, - left: 26, - right: 27 - }); - public static var RIGHT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(2, 3, { - up: 28, - down: 29, - left: 30, - right: 31 - }); + var DPAD_UP = 4; + var DPAD_DOWN = 5; + var DPAD_LEFT = 6; + var DPAD_RIGHT = 7; + var A = 8; + var B = 9; + var X = 10; + var Y = 11; + var L = 12; + var R = 13; + var ZL = 14; + var ZR = 15; + var MINUS = 16; + var PLUS = 17; + var HOME = 20; + var CAPTURE = 21; + var LEFT_STICK_CLICK = 22; + var RIGHT_STICK_CLICK = 23; + + var LEFT_STICK_UP = 24; + var LEFT_STICK_DOWN = 25; + var LEFT_STICK_LEFT = 26; + var LEFT_STICK_RIGHT = 27; + + var RIGHT_STICK_UP = 28; + var RIGHT_STICK_DOWN = 29; + var RIGHT_STICK_LEFT = 30; + var RIGHT_STICK_RIGHT = 31; + #else - public static inline var ZL:Int = 4; - public static inline var ZR:Int = 5; - public static inline var B:Int = 6; - public static inline var A:Int = 7; - public static inline var Y:Int = 8; - public static inline var X:Int = 9; - public static inline var MINUS:Int = 10; - public static inline var HOME:Int = 11; - public static inline var PLUS:Int = 12; - public static inline var LEFT_STICK_CLICK:Int = 13; - public static inline var RIGHT_STICK_CLICK:Int = 14; - public static inline var L:Int = 15; - public static inline var R:Int = 16; - public static inline var DPAD_UP:Int = 17; - public static inline var DPAD_DOWN:Int = 18; - public static inline var DPAD_LEFT:Int = 19; - public static inline var DPAD_RIGHT:Int = 20; - public static inline var CAPTURE:Int = 21; - public static var LEFT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(0, 1, { - up: 22, - down: 23, - left: 24, - right: 25 + var ZL = 4; + var ZR = 5; + var B = 6; + var A = 7; + var Y = 8; + var X = 9; + var MINUS = 10; + var HOME = 11; + var PLUS = 12; + var LEFT_STICK_CLICK = 13; + var RIGHT_STICK_CLICK = 14; + var L = 15; + var R = 16; + var DPAD_UP = 17; + var DPAD_DOWN = 18; + var DPAD_LEFT = 19; + var DPAD_RIGHT = 20; + var CAPTURE = 21; + + var LEFT_STICK_UP = 22; + var LEFT_STICK_DOWN = 23; + var LEFT_STICK_LEFT = 24; + var LEFT_STICK_RIGHT = 25; + + var RIGHT_STICK_UP = 26; + var RIGHT_STICK_DOWN = 27; + var RIGHT_STICK_LEFT = 28; + var RIGHT_STICK_RIGHT = 29; + #end + + public static final LEFT_ANALOG_STICK = new FlxTypedGamepadAnalogStick(0, 1, { + up: LEFT_STICK_UP, + down: LEFT_STICK_DOWN, + left: LEFT_STICK_LEFT, + right: LEFT_STICK_RIGHT }); - public static var RIGHT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(2, 3, { - up: 26, - down: 27, - left: 28, - right: 29 + public static final RIGHT_ANALOG_STICK = new FlxTypedGamepadAnalogStick(2, 3, { + up: RIGHT_STICK_UP, + down: RIGHT_STICK_DOWN, + left: RIGHT_STICK_LEFT, + right: RIGHT_STICK_RIGHT }); - #end } diff --git a/flixel/input/gamepad/id/WiiRemoteID.hx b/flixel/input/gamepad/id/WiiRemoteID.hx index 50919516ab..1fc0421c78 100644 --- a/flixel/input/gamepad/id/WiiRemoteID.hx +++ b/flixel/input/gamepad/id/WiiRemoteID.hx @@ -11,7 +11,7 @@ import flixel.input.gamepad.FlxGamepadAnalogStick; * * @author larsiusprime */ -class WiiRemoteID +enum abstract WiiRemoteID(Int) to Int { /** * Things to add: @@ -23,154 +23,163 @@ class WiiRemoteID */ #if FLX_JOYSTICK_API // Standard Wii Remote inputs: - public static inline var REMOTE_ONE:Int = 0; - public static inline var REMOTE_TWO:Int = 1; - public static inline var REMOTE_A:Int = 2; - public static inline var REMOTE_B:Int = 3; - public static inline var REMOTE_PLUS:Int = 4; - public static inline var REMOTE_MINUS:Int = 5; - public static inline var REMOTE_HOME:Int = 6; + var REMOTE_ONE = 0; + var REMOTE_TWO = 1; + var REMOTE_A = 2; + var REMOTE_B = 3; + var REMOTE_PLUS = 4; + var REMOTE_MINUS = 5; + var REMOTE_HOME = 6; // Nunchuk attachment: - public static inline var NUNCHUK_A:Int = 0; - public static inline var NUNCHUK_B:Int = 1; - public static inline var NUNCHUK_C:Int = 2; - public static inline var NUNCHUK_Z:Int = 3; - public static inline var NUNCHUK_ONE:Int = 4; - public static inline var NUNCHUK_TWO:Int = 5; - public static inline var NUNCHUK_PLUS:Int = 6; - public static inline var NUNCHUK_MINUS:Int = 7; - public static inline var NUNCHUK_HOME:Int = 8; + var NUNCHUK_A = 0; + var NUNCHUK_B = 1; + var NUNCHUK_C = 2; + var NUNCHUK_Z = 3; + var NUNCHUK_ONE = 4; + var NUNCHUK_TWO = 5; + var NUNCHUK_PLUS = 6; + var NUNCHUK_MINUS = 7; + var NUNCHUK_HOME = 8; // classic controller attachment: - public static inline var CLASSIC_A:Int = 0; - public static inline var CLASSIC_B:Int = 1; - public static inline var CLASSIC_Y:Int = 2; - public static inline var CLASSIC_X:Int = 3; - public static inline var CLASSIC_L:Int = 4; - public static inline var CLASSIC_R:Int = 5; - public static inline var CLASSIC_ZL:Int = 6; - public static inline var CLASSIC_ZR:Int = 7; - public static inline var CLASSIC_START:Int = 8; - public static inline var CLASSIC_SELECT:Int = 9; - public static inline var CLASSIC_HOME:Int = 10; - public static inline var CLASSIC_ONE:Int = 11; - public static inline var CLASSIC_TWO:Int = 12; - - public static inline var REMOTE_TILT_PITCH:Int = 2; - public static inline var REMOTE_TILT_ROLL:Int = 3; - - public static inline var NUNCHUK_TILT_PITCH:Int = 3; - public static inline var NUNCHUK_TILT_ROLL:Int = 2; - - public static inline var REMOTE_NULL_AXIS:Int = 4; - public static inline var NUNCHUK_NULL_AXIS:Int = 4; - - // Yes, the WiiRemote DPAD is treated as ANALOG for some reason... - // so we have to pass in some "fake" ID's to get simulated digital inputs - public static var REMOTE_DPAD(default, null) = new FlxGamepadAnalogStick(0, 1, { - up: REMOTE_DPAD_UP, - down: REMOTE_DPAD_DOWN, - left: REMOTE_DPAD_LEFT, - right: REMOTE_DPAD_RIGHT, - threshold: 0.5, - mode: ONLY_DIGITAL - }); - - // the nunchuk only has the "left" analog stick - public static var LEFT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(0, 1, { - up: 32, - down: 33, - left: 34, - right: 35 - }); - // the classic controller has both the "left" and "right" analog sticks - public static var RIGHT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(2, 3, { - up: 36, - down: 37, - left: 38, - right: 39 - }); - + var CLASSIC_A = 0; + var CLASSIC_B = 1; + var CLASSIC_Y = 2; + var CLASSIC_X = 3; + var CLASSIC_L = 4; + var CLASSIC_R = 5; + var CLASSIC_ZL = 6; + var CLASSIC_ZR = 7; + var CLASSIC_START = 8; + var CLASSIC_SELECT = 9; + var CLASSIC_HOME = 10; + var CLASSIC_ONE = 11; + var CLASSIC_TWO = 12; + + var REMOTE_TILT_PITCH = 2; + var REMOTE_TILT_ROLL = 3; + + var NUNCHUK_TILT_PITCH = 3; + var NUNCHUK_TILT_ROLL = 2; + + var REMOTE_NULL_AXIS = 4; + var NUNCHUK_NULL_AXIS = 4; + + var LEFT_STICK_UP = 32; + var LEFT_STICK_DOWN = 33; + var LEFT_STICK_LEFT = 34; + var LEFT_STICK_RIGHT = 35; + + var RIGHT_STICK_UP = 36; + var RIGHT_STICK_DOWN = 37; + var RIGHT_STICK_LEFT = 38; + var RIGHT_STICK_RIGHT = 39; + // these aren't real axes, they're simulated when the right digital buttons are pushed - public static inline var LEFT_TRIGGER_FAKE:Int = 4; - public static inline var RIGHT_TRIGGER_FAKE:Int = 5; + var LEFT_TRIGGER_FAKE = 4; + var RIGHT_TRIGGER_FAKE = 5; // "fake" ID's - public static inline var REMOTE_DPAD_UP:Int = 14; - public static inline var REMOTE_DPAD_DOWN:Int = 15; - public static inline var REMOTE_DPAD_LEFT:Int = 16; - public static inline var REMOTE_DPAD_RIGHT:Int = 17; - - public static inline var REMOTE_DPAD_X:Int = 18; - public static inline var REMOTE_DPAD_Y:Int = 19; - - public static inline var CLASSIC_DPAD_DOWN:Int = 24; - public static inline var CLASSIC_DPAD_UP:Int = 25; - public static inline var CLASSIC_DPAD_LEFT:Int = 26; - public static inline var CLASSIC_DPAD_RIGHT:Int = 27; - - public static inline var NUNCHUK_DPAD_DOWN:Int = 28; - public static inline var NUNCHUK_DPAD_UP:Int = 29; - public static inline var NUNCHUK_DPAD_LEFT:Int = 30; - public static inline var NUNCHUK_DPAD_RIGHT:Int = 31; + var REMOTE_DPAD_UP = 14; + var REMOTE_DPAD_DOWN = 15; + var REMOTE_DPAD_LEFT = 16; + var REMOTE_DPAD_RIGHT = 17; + + var REMOTE_DPAD_X = 18; + var REMOTE_DPAD_Y = 19; + + var CLASSIC_DPAD_DOWN = 24; + var CLASSIC_DPAD_UP = 25; + var CLASSIC_DPAD_LEFT = 26; + var CLASSIC_DPAD_RIGHT = 27; + + var NUNCHUK_DPAD_DOWN = 28; + var NUNCHUK_DPAD_UP = 29; + var NUNCHUK_DPAD_LEFT = 30; + var NUNCHUK_DPAD_RIGHT = 31; #else // gamepad API // Standard Wii Remote inputs: - public static inline var REMOTE_ONE:Int = 9; - public static inline var REMOTE_TWO:Int = 10; - public static inline var REMOTE_A:Int = 11; - public static inline var REMOTE_B:Int = 12; - public static inline var REMOTE_PLUS:Int = 13; - public static inline var REMOTE_MINUS:Int = 14; - public static inline var REMOTE_HOME:Int = 15; + var REMOTE_ONE = 9; + var REMOTE_TWO = 10; + var REMOTE_A = 11; + var REMOTE_B = 12; + var REMOTE_PLUS = 13; + var REMOTE_MINUS = 14; + var REMOTE_HOME = 15; // Nunchuk attachment: - public static inline var NUNCHUK_A:Int = 9; - public static inline var NUNCHUK_B:Int = 10; - public static inline var NUNCHUK_C:Int = 11; - public static inline var NUNCHUK_Z:Int = 12; - public static inline var NUNCHUK_ONE:Int = 13; - public static inline var NUNCHUK_TWO:Int = 14; - public static inline var NUNCHUK_PLUS:Int = 15; - public static inline var NUNCHUK_MINUS:Int = 16; - public static inline var NUNCHUK_HOME:Int = 17; - - public static inline var NUNCHUK_DPAD_UP:Int = 5; - public static inline var NUNCHUK_DPAD_DOWN:Int = 6; - public static inline var NUNCHUK_DPAD_LEFT:Int = 7; - public static inline var NUNCHUK_DPAD_RIGHT:Int = 8; + var NUNCHUK_A = 9; + var NUNCHUK_B = 10; + var NUNCHUK_C = 11; + var NUNCHUK_Z = 12; + var NUNCHUK_ONE = 13; + var NUNCHUK_TWO = 14; + var NUNCHUK_PLUS = 15; + var NUNCHUK_MINUS = 16; + var NUNCHUK_HOME = 17; + + var NUNCHUK_DPAD_UP = 5; + var NUNCHUK_DPAD_DOWN = 6; + var NUNCHUK_DPAD_LEFT = 7; + var NUNCHUK_DPAD_RIGHT = 8; // classic controller attachment: - public static inline var CLASSIC_A:Int = 9; - public static inline var CLASSIC_B:Int = 10; - public static inline var CLASSIC_Y:Int = 11; - public static inline var CLASSIC_X:Int = 12; - public static inline var CLASSIC_L:Int = 13; - public static inline var CLASSIC_R:Int = 14; - public static inline var CLASSIC_ZL:Int = 15; - public static inline var CLASSIC_ZR:Int = 16; - public static inline var CLASSIC_START:Int = 17; - public static inline var CLASSIC_SELECT:Int = 18; - public static inline var CLASSIC_HOME:Int = 19; - public static inline var CLASSIC_ONE:Int = 20; - public static inline var CLASSIC_TWO:Int = 21; - - public static inline var CLASSIC_DPAD_UP:Int = 5; - public static inline var CLASSIC_DPAD_DOWN:Int = 6; - public static inline var CLASSIC_DPAD_LEFT:Int = 7; - public static inline var CLASSIC_DPAD_RIGHT:Int = 8; - - public static inline var REMOTE_TILT_PITCH:Int = 2; - public static inline var REMOTE_TILT_ROLL:Int = 3; - - public static inline var NUNCHUK_TILT_PITCH:Int = 3; - public static inline var NUNCHUK_TILT_ROLL:Int = 2; - - public static inline var REMOTE_NULL_AXIS:Int = 4; - public static inline var NUNCHUK_NULL_AXIS:Int = 4; - - // Yes, the WiiRemote DPAD is treated as ANALOG for some reason...so we have to pass in some "fake" ID's to get simulated digital inputs - public static var REMOTE_DPAD(default, null) = new FlxGamepadAnalogStick(0, 1, { + var CLASSIC_A = 9; + var CLASSIC_B = 10; + var CLASSIC_Y = 11; + var CLASSIC_X = 12; + var CLASSIC_L = 13; + var CLASSIC_R = 14; + var CLASSIC_ZL = 15; + var CLASSIC_ZR = 16; + var CLASSIC_START = 17; + var CLASSIC_SELECT = 18; + var CLASSIC_HOME = 19; + var CLASSIC_ONE = 20; + var CLASSIC_TWO = 21; + + var CLASSIC_DPAD_UP = 5; + var CLASSIC_DPAD_DOWN = 6; + var CLASSIC_DPAD_LEFT = 7; + var CLASSIC_DPAD_RIGHT = 8; + + var REMOTE_TILT_PITCH = 2; + var REMOTE_TILT_ROLL = 3; + + var NUNCHUK_TILT_PITCH = 3; + var NUNCHUK_TILT_ROLL = 2; + + var REMOTE_NULL_AXIS = 4; + var NUNCHUK_NULL_AXIS = 4; + + var LEFT_STICK_UP = 28; + var LEFT_STICK_DOWN = 29; + var LEFT_STICK_LEFT = 30; + var LEFT_STICK_RIGHT = 31; + + var RIGHT_STICK_UP = 32; + var RIGHT_STICK_DOWN = 33; + var RIGHT_STICK_LEFT = 34; + var RIGHT_STICK_RIGHT = 35; + + // these aren't real axes, they're simulated when the right digital buttons are pushed + var LEFT_TRIGGER_FAKE = 4; + var RIGHT_TRIGGER_FAKE = 5; + + // "fake" ID's + var REMOTE_DPAD_UP = 22; + var REMOTE_DPAD_DOWN = 23; + var REMOTE_DPAD_LEFT = 24; + var REMOTE_DPAD_RIGHT = 25; + + var REMOTE_DPAD_X = 26; + var REMOTE_DPAD_Y = 27; + #end + + // Yes, the WiiRemote DPAD is treated as ANALOG for some reason... + // so we have to pass in some "fake" ID's to get simulated digital inputs + public static final REMOTE_DPAD = new FlxTypedGamepadAnalogStick(0, 1, { up: REMOTE_DPAD_UP, down: REMOTE_DPAD_DOWN, left: REMOTE_DPAD_LEFT, @@ -178,38 +187,25 @@ class WiiRemoteID threshold: 0.5, mode: ONLY_DIGITAL }); - + /** * the nunchuk only has the "left" analog stick */ - public static var LEFT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(0, 1, { - up: 28, - down: 29, - left: 30, - right: 31 + public static final LEFT_ANALOG_STICK = new FlxTypedGamepadAnalogStick(0, 1, { + up: LEFT_STICK_UP, + down: LEFT_STICK_DOWN, + left: LEFT_STICK_LEFT, + right: LEFT_STICK_RIGHT }); /** * the classic controller has both the "left" and "right" analog sticks */ - public static var RIGHT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(2, 3, { - up: 32, - down: 33, - left: 34, - right: 35 + public static final RIGHT_ANALOG_STICK = new FlxTypedGamepadAnalogStick(2, 3, { + up: RIGHT_STICK_UP, + down: RIGHT_STICK_DOWN, + left: RIGHT_STICK_LEFT, + right: RIGHT_STICK_RIGHT }); - // these aren't real axes, they're simulated when the right digital buttons are pushed - public static inline var LEFT_TRIGGER_FAKE:Int = 4; - public static inline var RIGHT_TRIGGER_FAKE:Int = 5; - - // "fake" ID's - public static inline var REMOTE_DPAD_UP:Int = 22; - public static inline var REMOTE_DPAD_DOWN:Int = 23; - public static inline var REMOTE_DPAD_LEFT:Int = 24; - public static inline var REMOTE_DPAD_RIGHT:Int = 25; - - public static inline var REMOTE_DPAD_X:Int = 26; - public static inline var REMOTE_DPAD_Y:Int = 27; - #end } diff --git a/flixel/input/gamepad/id/XInputID.hx b/flixel/input/gamepad/id/XInputID.hx index c25e217aa4..17ad775258 100644 --- a/flixel/input/gamepad/id/XInputID.hx +++ b/flixel/input/gamepad/id/XInputID.hx @@ -20,161 +20,184 @@ import flixel.input.gamepad.FlxGamepadAnalogStick; * MAC: we assume the user is using the 360 Controller driver, specifically this one: * https://github.com/360Controller/360Controller/releases */ -class XInputID +enum abstract XInputID(Int) to Int { #if flash - public static inline var A:Int = 4; - public static inline var B:Int = 5; - public static inline var X:Int = 6; - public static inline var Y:Int = 7; - public static inline var LB:Int = 8; - public static inline var RB:Int = 9; - - public static inline var BACK:Int = 12; - public static inline var GUIDE:Int = -1; - public static inline var START:Int = 13; - - public static inline var LEFT_STICK_CLICK:Int = 14; - public static inline var RIGHT_STICK_CLICK:Int = 15; - - public static inline var DPAD_UP:Int = 16; - public static inline var DPAD_DOWN:Int = 17; - public static inline var DPAD_LEFT:Int = 18; - public static inline var DPAD_RIGHT:Int = 19; - - public static inline var LEFT_TRIGGER:Int = 10; - public static inline var RIGHT_TRIGGER:Int = 11; - - public static var LEFT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(0, 1, { - up: 20, - down: 21, - left: 22, - right: 23 - }); - public static var RIGHT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(2, 3, { - up: 24, - down: 25, - left: 26, - right: 27 - }); + var A = 4; + var B = 5; + var X = 6; + var Y = 7; + var LB = 8; + var RB = 9; + + var BACK = 12; + var GUIDE = -1; + var START = 13; + + var LEFT_STICK_CLICK = 14; + var RIGHT_STICK_CLICK = 15; + + var DPAD_UP = 16; + var DPAD_DOWN = 17; + var DPAD_LEFT = 18; + var DPAD_RIGHT = 19; + + var LEFT_TRIGGER = 10; + var RIGHT_TRIGGER = 11; + + + static final LEFT_X = 0; + static final LEFT_Y = 1; + static final RIGHT_X = 2; + static final RIGHT_Y = 3; + + var LEFT_STICK_UP = 20; + var LEFT_STICK_DOWN = 21; + var LEFT_STICK_LEFT = 22; + var LEFT_STICK_RIGHT = 23; + + var RIGHT_STICK_UP = 24; + var RIGHT_STICK_DOWN = 25; + var RIGHT_STICK_LEFT = 26; + var RIGHT_STICK_RIGHT = 27; #elseif FLX_GAMEINPUT_API - public static inline var A:Int = 6; - public static inline var B:Int = 7; - public static inline var X:Int = 8; - public static inline var Y:Int = 9; - - public static inline var BACK:Int = 10; - public static inline var GUIDE:Int = #if mac 11 #else - 1 #end; - public static inline var START:Int = 12; - - public static inline var LEFT_STICK_CLICK:Int = 13; - public static inline var RIGHT_STICK_CLICK:Int = 14; - - public static inline var LB:Int = 15; - public static inline var RB:Int = 16; - - public static inline var DPAD_UP:Int = 17; - public static inline var DPAD_DOWN:Int = 18; - public static inline var DPAD_LEFT:Int = 19; - public static inline var DPAD_RIGHT:Int = 20; - - public static var LEFT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(0, 1, { - up: 21, - down: 22, - left: 23, - right: 24 - }); - public static var RIGHT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(2, 3, { - up: 25, - down: 26, - left: 27, - right: 28 - }); - - public static inline var LEFT_TRIGGER:Int = 4; - public static inline var RIGHT_TRIGGER:Int = 5; + var A = 6; + var B = 7; + var X = 8; + var Y = 9; + + var BACK = 10; + var GUIDE = #if mac 11 #else - 1 #end; + var START = 12; + + var LEFT_STICK_CLICK = 13; + var RIGHT_STICK_CLICK = 14; + + var LB = 15; + var RB = 16; + + var DPAD_UP = 17; + var DPAD_DOWN = 18; + var DPAD_LEFT = 19; + var DPAD_RIGHT = 20; + + static inline final LEFT_X = 0; + static inline final LEFT_Y = 1; + static inline final RIGHT_X = 2; + static inline final RIGHT_Y = 3; + + var LEFT_STICK_UP = 21; + var LEFT_STICK_DOWN = 22; + var LEFT_STICK_LEFT = 23; + var LEFT_STICK_RIGHT = 24; + + var RIGHT_STICK_UP = 25; + var RIGHT_STICK_DOWN = 26; + var RIGHT_STICK_LEFT = 27; + var RIGHT_STICK_RIGHT = 28; + + var LEFT_TRIGGER = 4; + var RIGHT_TRIGGER = 5; #elseif FLX_JOYSTICK_API #if (windows || linux) - public static inline var A:Int = 0; - public static inline var B:Int = 1; - public static inline var X:Int = 2; - public static inline var Y:Int = 3; + var A = 0; + var B = 1; + var X = 2; + var Y = 3; - public static inline var LB:Int = 4; - public static inline var RB:Int = 5; + var LB = 4; + var RB = 5; - public static inline var BACK:Int = 6; - public static inline var START:Int = 7; + var BACK = 6; + var START = 7; #if linux - public static inline var LEFT_STICK_CLICK:Int = 9; - public static inline var RIGHT_STICK_CLICK:Int = 10; - public static inline var GUIDE:Int = 8; + var LEFT_STICK_CLICK = 9; + var RIGHT_STICK_CLICK = 10; + var GUIDE = 8; #elseif windows - public static inline var LEFT_STICK_CLICK:Int = 8; - public static inline var RIGHT_STICK_CLICK:Int = 9; - public static inline var GUIDE:Int = 10; + var LEFT_STICK_CLICK = 8; + var RIGHT_STICK_CLICK = 9; + var GUIDE = 10; #end // "fake" IDs, we manually watch for hat axis changes and then send events using // these otherwise unused joystick button codes - public static inline var DPAD_UP:Int = 11; - public static inline var DPAD_DOWN:Int = 12; - public static inline var DPAD_LEFT:Int = 13; - public static inline var DPAD_RIGHT:Int = 14; - - public static inline var LEFT_TRIGGER:Int = 2; - public static inline var RIGHT_TRIGGER:Int = 5; - - public static var LEFT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(0, 1, { - up: 21, - down: 22, - left: 23, - right: 24 - }); - public static var RIGHT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(3, 4, { - up: 25, - down: 26, - left: 27, - right: 28 - }); + var DPAD_UP = 11; + var DPAD_DOWN = 12; + var DPAD_LEFT = 13; + var DPAD_RIGHT = 14; + + var LEFT_TRIGGER = 2; + var RIGHT_TRIGGER = 5; + + static inline final LEFT_X = 0; + static inline final LEFT_Y = 1; + static inline final RIGHT_X = 3; + static inline final RIGHT_Y = 4; + + var LEFT_STICK_UP = 21; + var LEFT_STICK_DOWN = 22; + var LEFT_STICK_LEFT = 23; + var LEFT_STICK_RIGHT = 24; + + var RIGHT_STICK_UP = 25; + var RIGHT_STICK_DOWN = 26; + var RIGHT_STICK_LEFT = 27; + var RIGHT_STICK_RIGHT = 28; #else // mac - public static inline var A:Int = 0; - public static inline var B:Int = 1; - public static inline var X:Int = 2; - public static inline var Y:Int = 3; - - public static inline var LB:Int = 4; - public static inline var RB:Int = 5; - - public static inline var LEFT_STICK_CLICK:Int = 6; - public static inline var RIGHT_STICK_CLICK:Int = 7; - - public static inline var BACK:Int = 9; - public static inline var START:Int = 8; - - public static inline var GUIDE:Int = 10; - - public static inline var DPAD_UP:Int = 11; - public static inline var DPAD_DOWN:Int = 12; - public static inline var DPAD_LEFT:Int = 13; - public static inline var DPAD_RIGHT:Int = 14; - - public static inline var LEFT_TRIGGER:Int = 2; - public static inline var RIGHT_TRIGGER:Int = 5; - - public static var LEFT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(0, 1, { - up: 21, - down: 22, - left: 23, - right: 24 - }); - public static var RIGHT_ANALOG_STICK(default, null) = new FlxGamepadAnalogStick(3, 4, { - up: 25, - down: 26, - left: 27, - right: 28 - }); + var A = 0; + var B = 1; + var X = 2; + var Y = 3; + + var LB = 4; + var RB = 5; + + var LEFT_STICK_CLICK = 6; + var RIGHT_STICK_CLICK = 7; + + var BACK = 9; + var START = 8; + + var GUIDE = 10; + + var DPAD_UP = 11; + var DPAD_DOWN = 12; + var DPAD_LEFT = 13; + var DPAD_RIGHT = 14; + + var LEFT_TRIGGER = 2; + var RIGHT_TRIGGER = 5; + + static inline final LEFT_X = 0; + static inline final LEFT_Y = 1; + static inline final RIGHT_X = 3; + static inline final RIGHT_Y = 4; + + var LEFT_STICK_UP = 21; + var LEFT_STICK_DOWN = 22; + var LEFT_STICK_LEFT = 23; + var LEFT_STICK_RIGHT = 24; + + var RIGHT_STICK_UP = 25; + var RIGHT_STICK_DOWN = 26; + var RIGHT_STICK_LEFT = 27; + var RIGHT_STICK_RIGHT = 28; #end #end + + public static final LEFT_ANALOG_STICK = new FlxTypedGamepadAnalogStick(LEFT_X, LEFT_Y, { + up: LEFT_STICK_UP, + down: LEFT_STICK_DOWN, + left: LEFT_STICK_LEFT, + right: LEFT_STICK_RIGHT + }); + + public static var RIGHT_ANALOG_STICK = new FlxTypedGamepadAnalogStick(RIGHT_X, RIGHT_Y, { + up: RIGHT_STICK_UP, + down: RIGHT_STICK_DOWN, + left: RIGHT_STICK_LEFT, + right: RIGHT_STICK_RIGHT + }); } diff --git a/flixel/input/gamepad/mappings/FlxGamepadMapping.hx b/flixel/input/gamepad/mappings/FlxGamepadMapping.hx index d7e54b0a25..f33d69a98c 100644 --- a/flixel/input/gamepad/mappings/FlxGamepadMapping.hx +++ b/flixel/input/gamepad/mappings/FlxGamepadMapping.hx @@ -7,18 +7,26 @@ import flixel.input.gamepad.FlxGamepadInputID; import openfl.system.Capabilities; #end -class FlxGamepadMapping +typedef FlxGamepadMapping = FlxTypedGamepadMapping; + +class FlxTypedGamepadMapping { public var supportsMotion:Bool = false; public var supportsPointer:Bool = false; - public var leftStick:FlxGamepadAnalogStick; - public var rightStick:FlxGamepadAnalogStick; + public var leftStick:FlxTypedGamepadAnalogStick; + public var rightStick:FlxTypedGamepadAnalogStick; @:allow(flixel.input.gamepad.FlxGamepad) var attachment(default, set):FlxGamepadAttachment = NONE; var manufacturer:Manufacturer; + + /** + * Whether to treat `A` or `B` as `ACCEPT` or `CANCEL`, when `FlxG.gamepads.acceptMode` is `ADAPTIVE` + * @since 5.9.0 + */ + var bottomIsAccept:Bool = true; public function new(?attachment:FlxGamepadAttachment) { @@ -39,7 +47,7 @@ class FlxGamepadMapping function initValues():Void {} - public function getAnalogStick(ID:FlxGamepadInputID):FlxGamepadAnalogStick + public function getAnalogStick(ID:FlxGamepadInputID):FlxTypedGamepadAnalogStick { return switch (ID) { @@ -55,7 +63,7 @@ class FlxGamepadMapping /** * Given a raw hardware code, return the "universal" ID */ - public function getID(rawID:Int):FlxGamepadInputID + public function getID(rawID:TInputID):FlxGamepadInputID { return FlxGamepadInputID.NONE; } @@ -63,25 +71,44 @@ class FlxGamepadMapping /** * Given an ID, return the raw hardware code */ - public function getRawID(ID:FlxGamepadInputID):Int + public function getRawID(ID:FlxGamepadInputID):TInputID { return switch ID { - case ACCEPT: getRawID(A); - case CANCEL: getRawID(B); - default: -1; + case ACCEPT if (getGlobalBottomIsAccept()): getRawID(A); + case CANCEL if (getGlobalBottomIsAccept()): getRawID(B); + case ACCEPT: getRawID(B); + case CANCEL: getRawID(A); + default: cast -1;// TODO: Throw error + } + } + + function getGlobalBottomIsAccept() + { + #if FLX_GAMEPAD + if (FlxG.gamepads != null) + { + return switch FlxG.gamepads.acceptMode + { + case BOTTOM: true; + case RIGHT: false; + case USE_MAPPING: bottomIsAccept; + } } + #end + + return bottomIsAccept; } /** * Whether this axis needs to be flipped */ - public function isAxisFlipped(axisID:Int):Bool + public function isAxisFlipped(axisID:TInputID):Bool { return false; } - public function isAxisForMotion(ID:FlxGamepadInputID):Bool + public function isAxisForMotion(ID:TInputID):Bool { return false; } @@ -91,7 +118,7 @@ class FlxGamepadMapping * Given an axis index value like 0-6, figures out which input that * corresponds to and returns a "fake" ButtonID for that input */ - public function axisIndexToRawID(axisID:Int):Int + public function axisIndexToRawID(axisID:TInputID):Int { return -1; } @@ -107,6 +134,11 @@ class FlxGamepadMapping return this.attachment = attachment; } + public function getMappedInput(id:FlxGamepadInputID) + { + return FlxGamepadMappedInput.UNKNOWN(id); + } + public function getInputLabel(id:FlxGamepadInputID):Null { if (getRawID(id) == -1) @@ -144,8 +176,10 @@ class FlxGamepadMapping case RIGHT_STICK_DIGITAL_DOWN: "rs-down"; case RIGHT_STICK_DIGITAL_LEFT: "rs-left"; case RIGHT_STICK_DIGITAL_RIGHT: "rs-right"; - case ACCEPT: getInputLabel(cast getRawID(id)); - case CANCEL: getInputLabel(cast getRawID(id)); + case ACCEPT if (getGlobalBottomIsAccept()): getInputLabel(A); + case CANCEL if (getGlobalBottomIsAccept()): getInputLabel(B); + case ACCEPT: getInputLabel(B); + case CANCEL: getInputLabel(A); #if FLX_JOYSTICK_API case LEFT_TRIGGER_FAKE: "l2"; case RIGHT_TRIGGER_FAKE: "r2"; diff --git a/flixel/input/gamepad/mappings/LogitechMapping.hx b/flixel/input/gamepad/mappings/LogitechMapping.hx index c717842dbb..b7c309e52f 100644 --- a/flixel/input/gamepad/mappings/LogitechMapping.hx +++ b/flixel/input/gamepad/mappings/LogitechMapping.hx @@ -2,15 +2,16 @@ package flixel.input.gamepad.mappings; import flixel.input.gamepad.FlxGamepadInputID; import flixel.input.gamepad.id.LogitechID; +import flixel.input.gamepad.mappings.FlxGamepadMapping; -class LogitechMapping extends FlxGamepadMapping +class LogitechMapping extends FlxTypedGamepadMapping { #if FLX_JOYSTICK_API - static inline var LEFT_ANALOG_STICK_FAKE_X:Int = 20; - static inline var LEFT_ANALOG_STICK_FAKE_Y:Int = 21; + static inline var LEFT_ANALOG_STICK_FAKE_X = 20; + static inline var LEFT_ANALOG_STICK_FAKE_Y = 21; - static inline var RIGHT_ANALOG_STICK_FAKE_X:Int = 22; - static inline var RIGHT_ANALOG_STICK_FAKE_Y:Int = 23; + static inline var RIGHT_ANALOG_STICK_FAKE_X = 22; + static inline var RIGHT_ANALOG_STICK_FAKE_Y = 23; #end override function initValues():Void @@ -19,7 +20,7 @@ class LogitechMapping extends FlxGamepadMapping rightStick = LogitechID.RIGHT_ANALOG_STICK; } - override public function getID(rawID:Int):FlxGamepadInputID + override function getID(rawID:LogitechID):FlxGamepadInputID { return switch (rawID) { @@ -52,7 +53,7 @@ class LogitechMapping extends FlxGamepadMapping } } - override public function getRawID(ID:FlxGamepadInputID):Int + override function getRawID(ID:FlxGamepadInputID):LogitechID { return switch (ID) { @@ -89,6 +90,11 @@ class LogitechMapping extends FlxGamepadMapping } } + override function getMappedInput(id:FlxGamepadInputID) + { + return FlxGamepadMappedInput.LOGITECH(getRawID(id)); + } + override function getInputLabel(id:FlxGamepadInputID) { return switch (id) @@ -113,7 +119,7 @@ class LogitechMapping extends FlxGamepadMapping } #if FLX_JOYSTICK_API - override public function axisIndexToRawID(axisID:Int):Int + override function axisIndexToRawID(axisID:LogitechID):Int { return if (axisID == leftStick.x) LEFT_ANALOG_STICK_FAKE_X; else if (axisID == leftStick.y) LEFT_ANALOG_STICK_FAKE_Y; else if (axisID == rightStick.x) RIGHT_ANALOG_STICK_FAKE_X; diff --git a/flixel/input/gamepad/mappings/MFiMapping.hx b/flixel/input/gamepad/mappings/MFiMapping.hx index 2e77478ab0..5f8afb5f09 100644 --- a/flixel/input/gamepad/mappings/MFiMapping.hx +++ b/flixel/input/gamepad/mappings/MFiMapping.hx @@ -2,8 +2,9 @@ package flixel.input.gamepad.mappings; import flixel.input.gamepad.FlxGamepadInputID; import flixel.input.gamepad.id.MFiID; +import flixel.input.gamepad.mappings.FlxGamepadMapping; -class MFiMapping extends FlxGamepadMapping +class MFiMapping extends FlxTypedGamepadMapping { override function initValues():Void { @@ -11,7 +12,7 @@ class MFiMapping extends FlxGamepadMapping rightStick = MFiID.RIGHT_ANALOG_STICK; } - override public function getID(rawID:Int):FlxGamepadInputID + override function getID(rawID:MFiID):FlxGamepadInputID { return switch (rawID) { @@ -42,7 +43,7 @@ class MFiMapping extends FlxGamepadMapping } } - override public function getRawID(ID:FlxGamepadInputID):Int + override function getRawID(ID:FlxGamepadInputID):MFiID { return switch (ID) { @@ -79,8 +80,13 @@ class MFiMapping extends FlxGamepadMapping } } + override function getMappedInput(id:FlxGamepadInputID) + { + return FlxGamepadMappedInput.MFI(getRawID(id)); + } + #if FLX_JOYSTICK_API - override public function axisIndexToRawID(axisID:Int):Int + override function axisIndexToRawID(axisID:MFiID):Int { // the axis index values for this don't overlap with anything so we can just return the original values! return axisID; diff --git a/flixel/input/gamepad/mappings/MayflashWiiRemoteMapping.hx b/flixel/input/gamepad/mappings/MayflashWiiRemoteMapping.hx index 8f5a08a27f..bbe3b1f194 100644 --- a/flixel/input/gamepad/mappings/MayflashWiiRemoteMapping.hx +++ b/flixel/input/gamepad/mappings/MayflashWiiRemoteMapping.hx @@ -3,8 +3,9 @@ package flixel.input.gamepad.mappings; import flixel.input.gamepad.FlxGamepad.FlxGamepadAttachment; import flixel.input.gamepad.FlxGamepadInputID; import flixel.input.gamepad.id.MayflashWiiRemoteID; +import flixel.input.gamepad.mappings.FlxGamepadMapping; -class MayflashWiiRemoteMapping extends FlxGamepadMapping +class MayflashWiiRemoteMapping extends FlxTypedGamepadMapping { #if FLX_JOYSTICK_API static inline var REMOTE_DPAD_X:Int = 16; @@ -22,7 +23,7 @@ class MayflashWiiRemoteMapping extends FlxGamepadMapping supportsPointer = true; } - override public function getID(rawID:Int):FlxGamepadInputID + override function getID(rawID:MayflashWiiRemoteID):FlxGamepadInputID { return switch (attachment) { @@ -32,7 +33,7 @@ class MayflashWiiRemoteMapping extends FlxGamepadMapping } } - function getIDClassicController(rawID:Int):FlxGamepadInputID + function getIDClassicController(rawID:MayflashWiiRemoteID):FlxGamepadInputID { return switch (rawID) { @@ -63,7 +64,7 @@ class MayflashWiiRemoteMapping extends FlxGamepadMapping } } - function getIDNunchuk(rawID:Int):FlxGamepadInputID + function getIDNunchuk(rawID:MayflashWiiRemoteID):FlxGamepadInputID { return switch (rawID) { @@ -88,7 +89,7 @@ class MayflashWiiRemoteMapping extends FlxGamepadMapping } } - function getIDDefault(rawID:Int):FlxGamepadInputID + function getIDDefault(rawID:MayflashWiiRemoteID):FlxGamepadInputID { return switch (rawID) { @@ -107,7 +108,7 @@ class MayflashWiiRemoteMapping extends FlxGamepadMapping } } - override public function getRawID(ID:FlxGamepadInputID):Int + override function getRawID(ID:FlxGamepadInputID):MayflashWiiRemoteID { return switch (attachment) { @@ -117,7 +118,7 @@ class MayflashWiiRemoteMapping extends FlxGamepadMapping } } - function getRawClassicController(ID:FlxGamepadInputID):Int + function getRawClassicController(ID:FlxGamepadInputID):MayflashWiiRemoteID { return switch (ID) { @@ -150,7 +151,7 @@ class MayflashWiiRemoteMapping extends FlxGamepadMapping } } - function getRawNunchuk(ID:FlxGamepadInputID):Int + function getRawNunchuk(ID:FlxGamepadInputID):MayflashWiiRemoteID { return switch (ID) { @@ -177,7 +178,7 @@ class MayflashWiiRemoteMapping extends FlxGamepadMapping } } - function getRawDefault(ID:FlxGamepadInputID):Int + function getRawDefault(ID:FlxGamepadInputID):MayflashWiiRemoteID { return switch (ID) { @@ -197,7 +198,7 @@ class MayflashWiiRemoteMapping extends FlxGamepadMapping } #if FLX_JOYSTICK_API - override public function axisIndexToRawID(axisID:Int):Int + override function axisIndexToRawID(axisID:MayflashWiiRemoteID):Int { if (attachment == WII_NUNCHUCK || attachment == WII_CLASSIC_CONTROLLER) { @@ -222,7 +223,7 @@ class MayflashWiiRemoteMapping extends FlxGamepadMapping return axisID; } - override public function checkForFakeAxis(ID:FlxGamepadInputID):Int + override function checkForFakeAxis(ID:FlxGamepadInputID):Int { if (attachment == WII_NUNCHUCK) { @@ -257,6 +258,11 @@ class MayflashWiiRemoteMapping extends FlxGamepadMapping return super.set_attachment(attachment); } + override function getMappedInput(id:FlxGamepadInputID) + { + return FlxGamepadMappedInput.MAYFLASH_WII(getRawID(id)); + } + override function getInputLabel(id:FlxGamepadInputID) { var label = WiiRemoteMapping.getWiiInputLabel(id, attachment); diff --git a/flixel/input/gamepad/mappings/OUYAMapping.hx b/flixel/input/gamepad/mappings/OUYAMapping.hx index 870debd8c9..8af15095e3 100644 --- a/flixel/input/gamepad/mappings/OUYAMapping.hx +++ b/flixel/input/gamepad/mappings/OUYAMapping.hx @@ -2,8 +2,9 @@ package flixel.input.gamepad.mappings; import flixel.input.gamepad.FlxGamepadInputID; import flixel.input.gamepad.id.OUYAID; +import flixel.input.gamepad.mappings.FlxGamepadMapping; -class OUYAMapping extends FlxGamepadMapping +class OUYAMapping extends FlxTypedGamepadMapping { #if FLX_JOYSTICK_API static inline var LEFT_ANALOG_STICK_FAKE_X:Int = 19; @@ -19,7 +20,7 @@ class OUYAMapping extends FlxGamepadMapping rightStick = OUYAID.RIGHT_ANALOG_STICK; } - override public function getID(rawID:Int):FlxGamepadInputID + override function getID(rawID:OUYAID):FlxGamepadInputID { return switch (rawID) { @@ -50,7 +51,7 @@ class OUYAMapping extends FlxGamepadMapping } } - override public function getRawID(ID:FlxGamepadInputID):Int + override function getRawID(ID:FlxGamepadInputID):OUYAID { return switch (ID) { @@ -93,9 +94,14 @@ class OUYAMapping extends FlxGamepadMapping case _: super.getInputLabel(id); } } - + + override function getMappedInput(id:FlxGamepadInputID) + { + return FlxGamepadMappedInput.OUYA(getRawID(id)); + } + #if FLX_JOYSTICK_API - override public function axisIndexToRawID(axisID:Int):Int + override function axisIndexToRawID(axisID:OUYAID):Int { return if (axisID == leftStick.x) LEFT_ANALOG_STICK_FAKE_X; else if (axisID == leftStick.y) LEFT_ANALOG_STICK_FAKE_Y; else if (axisID == rightStick.x) RIGHT_ANALOG_STICK_FAKE_X; diff --git a/flixel/input/gamepad/mappings/PS4Mapping.hx b/flixel/input/gamepad/mappings/PS4Mapping.hx index 5fc74bd85a..6d62b24d29 100644 --- a/flixel/input/gamepad/mappings/PS4Mapping.hx +++ b/flixel/input/gamepad/mappings/PS4Mapping.hx @@ -2,8 +2,9 @@ package flixel.input.gamepad.mappings; import flixel.input.gamepad.FlxGamepadInputID; import flixel.input.gamepad.id.PS4ID; +import flixel.input.gamepad.mappings.FlxGamepadMapping; -class PS4Mapping extends FlxGamepadMapping +class PS4Mapping extends FlxTypedGamepadMapping { #if FLX_JOYSTICK_API static inline var LEFT_ANALOG_STICK_FAKE_X:Int = 21; @@ -24,7 +25,7 @@ class PS4Mapping extends FlxGamepadMapping supportsPointer = true; } - override public function getID(rawID:Int):FlxGamepadInputID + override function getID(rawID:PS4ID):FlxGamepadInputID { return switch (rawID) { @@ -59,7 +60,7 @@ class PS4Mapping extends FlxGamepadMapping } } - override public function getRawID(ID:FlxGamepadInputID):Int + override function getRawID(ID:FlxGamepadInputID):PS4ID { return switch (ID) { @@ -119,8 +120,13 @@ class PS4Mapping extends FlxGamepadMapping } } + override function getMappedInput(id:FlxGamepadInputID) + { + return FlxGamepadMappedInput.PS4(getRawID(id)); + } + #if FLX_JOYSTICK_API - override public function axisIndexToRawID(axisID:Int):Int + override function axisIndexToRawID(axisID:PS4ID):Int { // Analog stick and trigger values overlap with regular buttons so we remap to "fake" button ID's return if (axisID == leftStick.x) LEFT_ANALOG_STICK_FAKE_X; else if (axisID == leftStick.y) LEFT_ANALOG_STICK_FAKE_Y; else if (axisID == rightStick.x) diff --git a/flixel/input/gamepad/mappings/PSVitaMapping.hx b/flixel/input/gamepad/mappings/PSVitaMapping.hx index 6b46e8e090..9099d9e01b 100644 --- a/flixel/input/gamepad/mappings/PSVitaMapping.hx +++ b/flixel/input/gamepad/mappings/PSVitaMapping.hx @@ -2,8 +2,9 @@ package flixel.input.gamepad.mappings; import flixel.input.gamepad.FlxGamepadInputID; import flixel.input.gamepad.id.PSVitaID; +import flixel.input.gamepad.mappings.FlxGamepadMapping; -class PSVitaMapping extends FlxGamepadMapping +class PSVitaMapping extends FlxTypedGamepadMapping { override function initValues():Void { @@ -11,7 +12,7 @@ class PSVitaMapping extends FlxGamepadMapping rightStick = PSVitaID.RIGHT_ANALOG_STICK; } - override public function getID(rawID:Int):FlxGamepadInputID + override function getID(rawID:PSVitaID):FlxGamepadInputID { return switch (rawID) { @@ -39,7 +40,7 @@ class PSVitaMapping extends FlxGamepadMapping } } - override public function getRawID(ID:FlxGamepadInputID):Int + override function getRawID(ID:FlxGamepadInputID):PSVitaID { return switch (ID) { @@ -83,8 +84,13 @@ class PSVitaMapping extends FlxGamepadMapping case _: super.getInputLabel(id); } } - - override public function isAxisFlipped(axisID:Int):Bool + + override function getMappedInput(id:FlxGamepadInputID) + { + return FlxGamepadMappedInput.PS_VITA(getRawID(id)); + } + + override function isAxisFlipped(axisID:Int):Bool { return axisID == PSVitaID.LEFT_ANALOG_STICK.y || axisID == PSVitaID.RIGHT_ANALOG_STICK.y; } diff --git a/flixel/input/gamepad/mappings/SwitchJoyconLeftMapping.hx b/flixel/input/gamepad/mappings/SwitchJoyconLeftMapping.hx index 699443e9ab..ac18224acf 100644 --- a/flixel/input/gamepad/mappings/SwitchJoyconLeftMapping.hx +++ b/flixel/input/gamepad/mappings/SwitchJoyconLeftMapping.hx @@ -2,11 +2,12 @@ package flixel.input.gamepad.mappings; import flixel.input.gamepad.FlxGamepadInputID; import flixel.input.gamepad.id.SwitchJoyconLeftID; +import flixel.input.gamepad.mappings.FlxGamepadMapping; /** * @since 4.8.0 */ -class SwitchJoyconLeftMapping extends FlxGamepadMapping +class SwitchJoyconLeftMapping extends FlxTypedGamepadMapping { #if FLX_JOYSTICK_API static inline var LEFT_ANALOG_STICK_FAKE_X:Int = 32; @@ -24,9 +25,10 @@ class SwitchJoyconLeftMapping extends FlxGamepadMapping leftStick = SwitchJoyconLeftID.LEFT_ANALOG_STICK; supportsMotion = true; supportsPointer = false; + bottomIsAccept = false; } - override public function getID(rawID:Int):FlxGamepadInputID + override function getID(rawID:SwitchJoyconLeftID):FlxGamepadInputID { return switch (rawID) { @@ -48,7 +50,7 @@ class SwitchJoyconLeftMapping extends FlxGamepadMapping } } - override public function getRawID(id:FlxGamepadInputID):Int + override function getRawID(id:FlxGamepadInputID):SwitchJoyconLeftID { return switch (id) { @@ -70,8 +72,6 @@ class SwitchJoyconLeftMapping extends FlxGamepadMapping case LEFT_TRIGGER_FAKE: LEFT_TRIGGER_FAKE; case RIGHT_TRIGGER_FAKE: RIGHT_TRIGGER_FAKE; #end - case ACCEPT: SwitchJoyconLeftID.RIGHT; - case CANCEL: SwitchJoyconLeftID.DOWN; default: super.getRawID(id); } } @@ -93,8 +93,13 @@ class SwitchJoyconLeftMapping extends FlxGamepadMapping } } + override function getMappedInput(id:FlxGamepadInputID) + { + return FlxGamepadMappedInput.SWITCH_JOYCON_LEFT(getRawID(id)); + } + #if FLX_JOYSTICK_API - override public function axisIndexToRawID(axisID:Int):Int + override function axisIndexToRawID(axisID:SwitchJoyconLeftID):Int { // Analog stick and trigger values overlap with regular buttons so we remap to "fake" button ID's return if (axisID == leftStick.x) diff --git a/flixel/input/gamepad/mappings/SwitchJoyconRightMapping.hx b/flixel/input/gamepad/mappings/SwitchJoyconRightMapping.hx index 05297f02e2..983b0df955 100644 --- a/flixel/input/gamepad/mappings/SwitchJoyconRightMapping.hx +++ b/flixel/input/gamepad/mappings/SwitchJoyconRightMapping.hx @@ -2,11 +2,12 @@ package flixel.input.gamepad.mappings; import flixel.input.gamepad.FlxGamepadInputID; import flixel.input.gamepad.id.SwitchJoyconRightID; +import flixel.input.gamepad.mappings.FlxGamepadMapping; /** * @since 4.8.0 */ -class SwitchJoyconRightMapping extends FlxGamepadMapping +class SwitchJoyconRightMapping extends FlxTypedGamepadMapping { #if FLX_JOYSTICK_API static inline var LEFT_ANALOG_STICK_FAKE_X:Int = 32; @@ -24,9 +25,10 @@ class SwitchJoyconRightMapping extends FlxGamepadMapping leftStick = SwitchJoyconRightID.LEFT_ANALOG_STICK; supportsMotion = true; supportsPointer = false; + bottomIsAccept = false; } - override public function getID(rawID:Int):FlxGamepadInputID + override function getID(rawID:SwitchJoyconRightID):FlxGamepadInputID { return switch (rawID) { @@ -49,7 +51,7 @@ class SwitchJoyconRightMapping extends FlxGamepadMapping } } - override public function getRawID(ID:FlxGamepadInputID):Int + override function getRawID(ID:FlxGamepadInputID):SwitchJoyconRightID { return switch (ID) { @@ -72,8 +74,6 @@ class SwitchJoyconRightMapping extends FlxGamepadMapping case LEFT_TRIGGER_FAKE: LEFT_TRIGGER_FAKE; case RIGHT_TRIGGER_FAKE: RIGHT_TRIGGER_FAKE; #end - case ACCEPT: SwitchJoyconRightID.A; - case CANCEL: SwitchJoyconRightID.B; default: super.getRawID(ID); } } @@ -96,8 +96,13 @@ class SwitchJoyconRightMapping extends FlxGamepadMapping } } + override function getMappedInput(id:FlxGamepadInputID) + { + return FlxGamepadMappedInput.SWITCH_JOYCON_RIGHT(getRawID(id)); + } + #if FLX_JOYSTICK_API - override public function axisIndexToRawID(axisID:Int):Int + override function axisIndexToRawID(axisID:SwitchJoyconRightID):Int { // Analog stick and trigger values overlap with regular buttons so we remap to "fake" button ID's return if (axisID == leftStick.x) diff --git a/flixel/input/gamepad/mappings/SwitchProMapping.hx b/flixel/input/gamepad/mappings/SwitchProMapping.hx index 1d9b7e4583..3b948887c8 100644 --- a/flixel/input/gamepad/mappings/SwitchProMapping.hx +++ b/flixel/input/gamepad/mappings/SwitchProMapping.hx @@ -2,11 +2,12 @@ package flixel.input.gamepad.mappings; import flixel.input.gamepad.FlxGamepadInputID; import flixel.input.gamepad.id.SwitchProID; +import flixel.input.gamepad.mappings.FlxGamepadMapping; /** * @since 4.8.0 */ -class SwitchProMapping extends FlxGamepadMapping +class SwitchProMapping extends FlxTypedGamepadMapping { #if FLX_JOYSTICK_API static inline var LEFT_ANALOG_STICK_FAKE_X:Int = 32; @@ -25,9 +26,10 @@ class SwitchProMapping extends FlxGamepadMapping rightStick = SwitchProID.RIGHT_ANALOG_STICK; supportsMotion = true; supportsPointer = false; + bottomIsAccept = false; } - override public function getID(rawID:Int):FlxGamepadInputID + override function getID(rawID:SwitchProID):FlxGamepadInputID { return switch (rawID) { @@ -61,7 +63,7 @@ class SwitchProMapping extends FlxGamepadMapping } } - override public function getRawID(ID:FlxGamepadInputID):Int + override function getRawID(ID:FlxGamepadInputID):SwitchProID { return switch (ID) { @@ -95,8 +97,6 @@ class SwitchProMapping extends FlxGamepadMapping case LEFT_TRIGGER_FAKE: LEFT_TRIGGER_FAKE; case RIGHT_TRIGGER_FAKE: RIGHT_TRIGGER_FAKE; #end - case ACCEPT: SwitchProID.A; - case CANCEL: SwitchProID.B; default: super.getRawID(ID); } } @@ -121,8 +121,13 @@ class SwitchProMapping extends FlxGamepadMapping } } + override function getMappedInput(id:FlxGamepadInputID) + { + return FlxGamepadMappedInput.SWITCH_PRO(getRawID(id)); + } + #if FLX_JOYSTICK_API - override public function axisIndexToRawID(axisID:Int):Int + override function axisIndexToRawID(axisID:SwitchProID):Int { // Analog stick and trigger values overlap with regular buttons so we remap to "fake" button ID's return if (axisID == leftStick.x) diff --git a/flixel/input/gamepad/mappings/WiiRemoteMapping.hx b/flixel/input/gamepad/mappings/WiiRemoteMapping.hx index 41692228d7..72ddb896c8 100644 --- a/flixel/input/gamepad/mappings/WiiRemoteMapping.hx +++ b/flixel/input/gamepad/mappings/WiiRemoteMapping.hx @@ -3,8 +3,9 @@ package flixel.input.gamepad.mappings; import flixel.input.gamepad.FlxGamepad.FlxGamepadAttachment; import flixel.input.gamepad.FlxGamepadInputID; import flixel.input.gamepad.id.WiiRemoteID; +import flixel.input.gamepad.mappings.FlxGamepadMapping; -class WiiRemoteMapping extends FlxGamepadMapping +class WiiRemoteMapping extends FlxTypedGamepadMapping { #if FLX_JOYSTICK_API static inline var LEFT_ANALOG_STICK_FAKE_X:Int = 20; @@ -20,7 +21,7 @@ class WiiRemoteMapping extends FlxGamepadMapping supportsPointer = false; } - override public function getID(rawID:Int):FlxGamepadInputID + override function getID(rawID:WiiRemoteID):FlxGamepadInputID { return switch (attachment) { @@ -30,7 +31,7 @@ class WiiRemoteMapping extends FlxGamepadMapping } } - function getIDClassicController(rawID:Int):FlxGamepadInputID + function getIDClassicController(rawID:WiiRemoteID):FlxGamepadInputID { return switch (rawID) { @@ -63,7 +64,7 @@ class WiiRemoteMapping extends FlxGamepadMapping } } - function getIDNunchuk(rawID:Int):FlxGamepadInputID + function getIDNunchuk(rawID:WiiRemoteID):FlxGamepadInputID { return switch (rawID) { @@ -84,11 +85,11 @@ class WiiRemoteMapping extends FlxGamepadMapping case id if (id == WiiRemoteID.LEFT_ANALOG_STICK.rawDown): LEFT_STICK_DIGITAL_DOWN; case id if (id == WiiRemoteID.LEFT_ANALOG_STICK.rawLeft): LEFT_STICK_DIGITAL_LEFT; case id if (id == WiiRemoteID.LEFT_ANALOG_STICK.rawRight): LEFT_STICK_DIGITAL_RIGHT; - default: super.getRawID(rawID); + default: super.getID(rawID); } } - function getIDDefault(rawID:Int):FlxGamepadInputID + function getIDDefault(rawID:WiiRemoteID):FlxGamepadInputID { return switch (rawID) { @@ -107,7 +108,7 @@ class WiiRemoteMapping extends FlxGamepadMapping } } - override public function getRawID(ID:FlxGamepadInputID):Int + override function getRawID(ID:FlxGamepadInputID):WiiRemoteID { return switch (attachment) { @@ -117,7 +118,7 @@ class WiiRemoteMapping extends FlxGamepadMapping } } - function getRawClassicController(ID:FlxGamepadInputID):Int + function getRawClassicController(ID:FlxGamepadInputID):WiiRemoteID { return switch (ID) { @@ -150,7 +151,7 @@ class WiiRemoteMapping extends FlxGamepadMapping } } - function getRawNunchuk(ID:FlxGamepadInputID):Int + function getRawNunchuk(ID:FlxGamepadInputID):WiiRemoteID { return switch (ID) { @@ -177,7 +178,7 @@ class WiiRemoteMapping extends FlxGamepadMapping } } - function getRawDefault(ID:FlxGamepadInputID):Int + function getRawDefault(ID:FlxGamepadInputID):WiiRemoteID { return switch (ID) { @@ -198,7 +199,7 @@ class WiiRemoteMapping extends FlxGamepadMapping } } - override public function isAxisForMotion(ID:FlxGamepadInputID):Bool + override function isAxisForMotion(ID:WiiRemoteID):Bool { if (attachment == NONE) { @@ -213,14 +214,14 @@ class WiiRemoteMapping extends FlxGamepadMapping return false; } - override public function isAxisFlipped(axisID:Int):Bool + override function isAxisFlipped(axisID:WiiRemoteID):Bool { return axisID == WiiRemoteID.LEFT_TRIGGER_FAKE; } #if FLX_JOYSTICK_API // Analog stick and trigger values overlap with regular buttons so we remap to "fake" button ID's - override public function axisIndexToRawID(axisID:Int):Int + override function axisIndexToRawID(axisID:WiiRemoteID):Int { // return null for this unused access so it doesn't overlap a button input if (attachment == NONE && axisID == WiiRemoteID.REMOTE_NULL_AXIS) @@ -252,7 +253,7 @@ class WiiRemoteMapping extends FlxGamepadMapping return axisID; } - override public function checkForFakeAxis(ID:FlxGamepadInputID):Int + override function checkForFakeAxis(ID:FlxGamepadInputID):WiiRemoteID { if (attachment == WII_NUNCHUCK && ID == FlxGamepadInputID.LEFT_TRIGGER) return WiiRemoteID.NUNCHUK_Z; @@ -347,4 +348,9 @@ class WiiRemoteMapping extends FlxGamepadMapping default: null; } } + + override function getMappedInput(id:FlxGamepadInputID) + { + return FlxGamepadMappedInput.WII(getRawID(id)); + } } diff --git a/flixel/input/gamepad/mappings/XInputMapping.hx b/flixel/input/gamepad/mappings/XInputMapping.hx index 1833a48dc3..bfbd560c5c 100644 --- a/flixel/input/gamepad/mappings/XInputMapping.hx +++ b/flixel/input/gamepad/mappings/XInputMapping.hx @@ -2,8 +2,9 @@ package flixel.input.gamepad.mappings; import flixel.input.gamepad.FlxGamepadInputID; import flixel.input.gamepad.id.XInputID; +import flixel.input.gamepad.mappings.FlxGamepadMapping; -class XInputMapping extends FlxGamepadMapping +class XInputMapping extends FlxTypedGamepadMapping { #if FLX_JOYSTICK_API static inline var LEFT_ANALOG_STICK_FAKE_X:Int = 15; @@ -22,7 +23,7 @@ class XInputMapping extends FlxGamepadMapping rightStick = XInputID.RIGHT_ANALOG_STICK; } - override public function getID(rawID:Int):FlxGamepadInputID + override function getID(rawID:XInputID):FlxGamepadInputID { return switch (rawID) { @@ -60,7 +61,7 @@ class XInputMapping extends FlxGamepadMapping } } - override public function getRawID(ID:FlxGamepadInputID):Int + override function getRawID(ID:FlxGamepadInputID):XInputID { return switch (ID) { @@ -98,7 +99,7 @@ class XInputMapping extends FlxGamepadMapping } #if flash - override public function isAxisFlipped(axisID:Int):Bool + override function isAxisFlipped(axisID:XInputID):Bool { if (manufacturer == GooglePepper) return false; @@ -108,14 +109,19 @@ class XInputMapping extends FlxGamepadMapping #end #if xbox1 - override public function isAxisFlipped(axisID:Int):Bool + override function isAxisFlipped(axisID:XInputID):Bool { return axisID == XInputID.LEFT_ANALOG_STICK.y || axisID == XInputID.RIGHT_ANALOG_STICK.y; } #end + override function getMappedInput(id:FlxGamepadInputID) + { + return FlxGamepadMappedInput.X_INPUT(getRawID(id)); + } + #if FLX_JOYSTICK_API - override public function axisIndexToRawID(axisID:Int):Int + override function axisIndexToRawID(axisID:XInputID):Int { // Analog stick and trigger values overlap with regular buttons so we remap to "fake" button ID's return if (axisID == leftStick.x) LEFT_ANALOG_STICK_FAKE_X; else if (axisID == leftStick.y) LEFT_ANALOG_STICK_FAKE_Y; else if (axisID == rightStick.x) From b39f68d2a4b6aa7f9114a2ed7233d32454397711 Mon Sep 17 00:00:00 2001 From: ACrazyTown <47027981+ACrazyTown@users.noreply.github.com> Date: Mon, 4 Nov 2024 02:02:51 +0100 Subject: [PATCH 55/99] Stricter checks for FlxG.bitmap.maxTextureSize (#3279) * Stricter checks for FlxG.bitmap.maxTextureSize * Add FLX_OPENGL_AVAILABLE define * Adjust comment * FlxGraphic: warn if size exceeds max * fix unit tests --------- Co-authored-by: George FunBook --- flixel/graphics/FlxGraphic.hx | 9 +++++++++ flixel/system/frontEnds/BitmapFrontEnd.hx | 17 ++++++++++++----- flixel/system/macros/FlxDefines.hx | 7 +++++++ 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/flixel/graphics/FlxGraphic.hx b/flixel/graphics/FlxGraphic.hx index 18ff89f271..287da7dbd0 100644 --- a/flixel/graphics/FlxGraphic.hx +++ b/flixel/graphics/FlxGraphic.hx @@ -634,6 +634,15 @@ class FlxGraphic implements IFlxDestroyable bitmap = value; width = bitmap.width; height = bitmap.height; + + #if FLX_OPENGL_AVAILABLE + var max:Int = FlxG.bitmap.maxTextureSize; + if (max != -1) + { + if (width > max || height > max) + FlxG.log.warn('Graphic dimensions (${width}x${height}) exceed the maximum allowed size (${max}x${max}), which may cause rendering issues.'); + } + #end } return value; diff --git a/flixel/system/frontEnds/BitmapFrontEnd.hx b/flixel/system/frontEnds/BitmapFrontEnd.hx index a60557099e..fb66af7025 100644 --- a/flixel/system/frontEnds/BitmapFrontEnd.hx +++ b/flixel/system/frontEnds/BitmapFrontEnd.hx @@ -8,7 +8,7 @@ import flixel.math.FlxRect; import flixel.system.FlxAssets.FlxGraphicAsset; import flixel.util.FlxColor; import openfl.Assets; -#if !flash +#if FLX_OPENGL_AVAILABLE import lime.graphics.opengl.GL; #end @@ -19,9 +19,13 @@ import lime.graphics.opengl.GL; */ class BitmapFrontEnd { - #if !flash + #if FLX_OPENGL_AVAILABLE /** - * Gets max texture size for native targets + * Returns the maximum allowed width and height (in pixels) for a texture. + * This value is only available on hardware-accelerated targets that use OpenGL. + * On unsupported targets, the returned value will always be -1. + * + * @see https://opengl.gpuinfo.org/displaycapability.php?name=GL_MAX_TEXTURE_SIZE */ public var maxTextureSize(get, never):Int; #end @@ -391,10 +395,13 @@ class BitmapFrontEnd } } - #if !flash + #if FLX_OPENGL_AVAILABLE function get_maxTextureSize():Int { - return cast GL.getParameter(GL.MAX_TEXTURE_SIZE); + if (FlxG.stage.window.context.attributes.hardware) + return cast GL.getParameter(GL.MAX_TEXTURE_SIZE); + + return -1; } #end diff --git a/flixel/system/macros/FlxDefines.hx b/flixel/system/macros/FlxDefines.hx index 8dd13e2fe4..1ef3234f44 100644 --- a/flixel/system/macros/FlxDefines.hx +++ b/flixel/system/macros/FlxDefines.hx @@ -86,6 +86,7 @@ private enum HelperDefines FLX_HEALTH; FLX_NO_TRACK_POOLS; FLX_NO_TRACK_GRAPHICS; + FLX_OPENGL_AVAILABLE; } class FlxDefines @@ -251,6 +252,12 @@ class FlxDefines if (defined(FLX_DEBUG)) define(FLX_TRACK_GRAPHICS); + + #if (lime_opengl || lime_opengles || lime_webgl) + // FlxG.stage.window.context.attributes.hardware is not always defined during unit tests + if (defined(FLX_NO_UNIT_TEST)) + define(FLX_OPENGL_AVAILABLE); + #end defineInversion(FLX_TRACK_GRAPHICS, FLX_NO_TRACK_GRAPHICS); } From fa637c1c2fd161ae9c5fcc4a4963e1c8606e1e7d Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Fri, 8 Nov 2024 17:34:08 -0600 Subject: [PATCH 56/99] add coverage 3 (#3282) * add coverage 3 * remove no-debug * fix coverage 3 in html --- flixel/system/debug/console/Console.hx | 2 +- tests/coverage/Project.xml | 19 +++++++++++++++++++ tests/coverage/test.bat | 5 ++++- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/flixel/system/debug/console/Console.hx b/flixel/system/debug/console/Console.hx index 0a01140ed8..f179566d5d 100644 --- a/flixel/system/debug/console/Console.hx +++ b/flixel/system/debug/console/Console.hx @@ -218,7 +218,7 @@ class Console extends Window if (!history.isEmpty) setText(history.getPreviousCommand()); - #if html5 + #if (html5 && FLX_KEYBOARD) // FlxKeyboard.preventDefaultKeys adds "preventDefault" on HTML5 // so it ends up not fully propegating our inputs to the stage/event listeners // we do this small work around so we don't need to mess around with lime/openfl events diff --git a/tests/coverage/Project.xml b/tests/coverage/Project.xml index 8a7d118958..e53cc93d2e 100644 --- a/tests/coverage/Project.xml +++ b/tests/coverage/Project.xml @@ -59,4 +59,23 @@
+
+ + + + + + + + + + + + + + + + + +
diff --git a/tests/coverage/test.bat b/tests/coverage/test.bat index bfb2f0b581..1ad805c04c 100644 --- a/tests/coverage/test.bat +++ b/tests/coverage/test.bat @@ -1,8 +1,11 @@ haxelib run lime build flash -Dcoverage1 haxelib run lime build flash -Dcoverage2 +haxelib run lime build flash -Dcoverage3 haxelib run lime build html5 -Dcoverage1 haxelib run lime build html5 -Dcoverage2 +haxelib run lime build html5 -Dcoverage3 haxelib run lime build neko -Dcoverage1 -haxelib run lime build neko -Dcoverage2 \ No newline at end of file +haxelib run lime build neko -Dcoverage2 +haxelib run lime build neko -Dcoverage3 \ No newline at end of file From 4e4fbc294b7f095972cbcb526d696381786303bb Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Fri, 8 Nov 2024 23:03:49 -0600 Subject: [PATCH 57/99] checkstyle fixes (#3281) --- checkstyle.json | 3 +- flixel/tweens/motion/Motion.hx | 3 +- flixel/util/FlxDirectionFlags.hx | 3 +- .../graphics/frames/bmfont/BMFontTest.hx | 6 +- tests/unit/src/flixel/math/FlxPointTest.hx | 13 ++-- tests/unit/src/flixel/tile/FlxTilemapTest.hx | 76 +++++++++---------- tests/unit/src/flixel/util/FlxSignalTest.hx | 6 +- 7 files changed, 57 insertions(+), 53 deletions(-) diff --git a/checkstyle.json b/checkstyle.json index 60a10dcb3d..d350375773 100644 --- a/checkstyle.json +++ b/checkstyle.json @@ -19,7 +19,8 @@ "exclude": { "all": [ "TestSuite", - "/export/" + "/export/", + "tests/unit/bin/" ], "AvoidStarImport": [ "flixel.math.FlxRandomTest" diff --git a/flixel/tweens/motion/Motion.hx b/flixel/tweens/motion/Motion.hx index 76f95cd8b6..744c069aa7 100644 --- a/flixel/tweens/motion/Motion.hx +++ b/flixel/tweens/motion/Motion.hx @@ -55,7 +55,8 @@ class Motion extends FlxTween } } - override function isTweenOf(object:Dynamic, ?field:String):Bool { + override function isTweenOf(object:Dynamic, ?field:String):Bool + { return _object == object && (field == null || field == "x" || field == "y"); } diff --git a/flixel/util/FlxDirectionFlags.hx b/flixel/util/FlxDirectionFlags.hx index e3f6b546f5..dab579d34b 100644 --- a/flixel/util/FlxDirectionFlags.hx +++ b/flixel/util/FlxDirectionFlags.hx @@ -41,7 +41,8 @@ enum abstract FlxDirectionFlags(Int) from Int from FlxDirection to Int public var degrees(get, never):Float; function get_degrees():Float { - return switch (this) { + return switch (this) + { case RIGHT: 0; case DOWN: 90; case UP: -90; diff --git a/tests/unit/src/flixel/graphics/frames/bmfont/BMFontTest.hx b/tests/unit/src/flixel/graphics/frames/bmfont/BMFontTest.hx index a027f2b9ea..6d1f8dea4e 100644 --- a/tests/unit/src/flixel/graphics/frames/bmfont/BMFontTest.hx +++ b/tests/unit/src/flixel/graphics/frames/bmfont/BMFontTest.hx @@ -64,7 +64,7 @@ class BMFontTest extends FlxTest } // This assumes the incoming font has a specific configuration we are checking for - private function assertFont(font:BMFont) + function assertFont(font:BMFont) { // INFO Assert.areEqual("Arial Black", font.info.face); @@ -127,7 +127,7 @@ class BMFontTest extends FlxTest } } - private function assertCharMatches(expected:BMFontChar, actual:BMFontChar) + function assertCharMatches(expected:BMFontChar, actual:BMFontChar) { Assert.areEqual(expected.id, actual.id); Assert.areEqual(expected.x, actual.x); @@ -143,7 +143,7 @@ class BMFontTest extends FlxTest // Assert.areEqual(expected.letter, actual.letter); } - private function assertKerningMatches(expected:BMFontKerning, actual:BMFontKerning) + function assertKerningMatches(expected:BMFontKerning, actual:BMFontKerning) { Assert.areEqual(expected.first, actual.first); Assert.areEqual(expected.second, actual.second); diff --git a/tests/unit/src/flixel/math/FlxPointTest.hx b/tests/unit/src/flixel/math/FlxPointTest.hx index 984525fbac..b7dd865926 100644 --- a/tests/unit/src/flixel/math/FlxPointTest.hx +++ b/tests/unit/src/flixel/math/FlxPointTest.hx @@ -160,7 +160,8 @@ class FlxPointTest extends FlxTest } @Test - function testPivotDegrees() { + function testPivotDegrees() + { // Pivot around point in same quadrant point1.set(10, 10); point2.set(5, 5); @@ -183,10 +184,10 @@ class FlxPointTest extends FlxTest } function assertPointNearlyEquals(p:FlxPoint, x:Float, y:Float, tolerance:Float = .01, ?msg:String, ?info:PosInfos) - { - if (msg == null) - msg = 'Expected (x: $x | y: $y) but was $p'; + { + if (msg == null) + msg = 'Expected (x: $x | y: $y) but was $p'; - Assert.isTrue(Math.abs(x - p.x) <= tolerance && Math.abs(y -p.y) <= tolerance, msg, info); - } + Assert.isTrue(Math.abs(x - p.x) <= tolerance && Math.abs(y -p.y) <= tolerance, msg, info); + } } diff --git a/tests/unit/src/flixel/tile/FlxTilemapTest.hx b/tests/unit/src/flixel/tile/FlxTilemapTest.hx index 8642932480..c721c1554e 100644 --- a/tests/unit/src/flixel/tile/FlxTilemapTest.hx +++ b/tests/unit/src/flixel/tile/FlxTilemapTest.hx @@ -444,8 +444,8 @@ class FlxTilemapTest extends FlxTest tilemap.y += 20; tilemap.scale.set(2, 2); - final SIZE = 16; - final HALF = 8; + final size = 16; + final half = 8; Assert.areEqual(tilemap.getTileIndex(4), tilemap.getTileIndex(1, 1)); Assert.areEqual(1, tilemap.getTileIndex(4)); @@ -454,12 +454,12 @@ class FlxTilemapTest extends FlxTest Assert.areEqual(-1, tilemap.getMapIndex(1000, 1)); Assert.areEqual(-1, tilemap.getTileIndex(1000, 1)); - Assert.areEqual(8, tilemap.getMapIndexAt(10 + 2 * SIZE + HALF, 20 + 2 * SIZE + HALF)); - Assert.areEqual(0, tilemap.getTileIndexAt(10 + 2 * SIZE + HALF, 20 + 2 * SIZE + HALF)); - Assert.areEqual(-1, tilemap.getTileIndexAt(10 + 1000 * SIZE + HALF, 20 + 2 * SIZE + HALF)); + Assert.areEqual(8, tilemap.getMapIndexAt(10 + 2 * size + half, 20 + 2 * size + half)); + Assert.areEqual(0, tilemap.getTileIndexAt(10 + 2 * size + half, 20 + 2 * size + half)); + Assert.areEqual(-1, tilemap.getTileIndexAt(10 + 1000 * size + half, 20 + 2 * size + half)); Assert.areEqual(tilemap.getTileData(4), tilemap.getTileData(1, 1)); - Assert.areEqual(tilemap.getTileData(1, 1), tilemap.getTileDataAt(10 + 1 * SIZE + HALF, 20 + 1 * SIZE + HALF)); + Assert.areEqual(tilemap.getTileData(1, 1), tilemap.getTileDataAt(10 + 1 * size + half, 20 + 1 * size + half)); } function testGetColumnRowAt() @@ -494,25 +494,25 @@ class FlxTilemapTest extends FlxTest tilemap.y = 20; tilemap.scale.set(2, 2); - final SIZE = 16; - final HALF = 8; + final size = 16; + final half = 8; Assert.areEqual(0, tilemap.getColumnAt(tilemap.getColumnPos(0))); Assert.areEqual(1, tilemap.getColumnAt(tilemap.getColumnPos(1))); Assert.areEqual(2, tilemap.getColumnAt(tilemap.getColumnPos(2))); Assert.areEqual(3, tilemap.getColumnAt(tilemap.getColumnPos(3))); Assert.areEqual(1000, tilemap.getColumnAt(tilemap.getColumnPos(1000))); - Assert.areEqual(10 + 3 * SIZE, tilemap.getColumnPos(3)); - Assert.areEqual(10 + 3 * SIZE + HALF, tilemap.getColumnPos(3, true)); - Assert.areEqual(10 + 1000 * SIZE, tilemap.getColumnPos(1000)); + Assert.areEqual(10 + 3 * size, tilemap.getColumnPos(3)); + Assert.areEqual(10 + 3 * size + half, tilemap.getColumnPos(3, true)); + Assert.areEqual(10 + 1000 * size, tilemap.getColumnPos(1000)); Assert.areEqual(0, tilemap.getRowAt(tilemap.getRowPos(0))); Assert.areEqual(1, tilemap.getRowAt(tilemap.getRowPos(1))); Assert.areEqual(2, tilemap.getRowAt(tilemap.getRowPos(2))); Assert.areEqual(1000, tilemap.getRowAt(tilemap.getRowPos(1000))); - Assert.areEqual(20 + 2 * SIZE, tilemap.getRowPos(2)); - Assert.areEqual(20 + 2 * SIZE + HALF, tilemap.getRowPos(2, true)); - Assert.areEqual(20 + 1000 * SIZE, tilemap.getRowPos(1000)); + Assert.areEqual(20 + 2 * size, tilemap.getRowPos(2)); + Assert.areEqual(20 + 2 * size + half, tilemap.getRowPos(2, true)); + Assert.areEqual(20 + 1000 * size, tilemap.getRowPos(1000)); Assert.areEqual(null, tilemap.getTilePos(1000)); Assert.areEqual(null, tilemap.getTilePos(-1)); @@ -524,10 +524,10 @@ class FlxTilemapTest extends FlxTest Assert.areEqual(expectedY, actual.y, 'Point y [${actual.y}] was not equal to expected value [$expectedY]', infos); } - assertPosEqual(10 + -SIZE, 20 + -SIZE, tilemap.getTilePos(-1, -1)); - assertPosEqual(10 + SIZE, 20 + SIZE, tilemap.getTilePos(1, 1)); - assertPosEqual(10 + 1000 * SIZE, 20 + 1000 * SIZE, tilemap.getTilePos(1000, 1000)); - assertPosEqual(10 + 1000 * SIZE, 20 + 1000 * SIZE, tilemap.getTilePosAt(10 + 1000 * SIZE, 20 + 1000 * SIZE)); + assertPosEqual(10 + -size, 20 + -size, tilemap.getTilePos(-1, -1)); + assertPosEqual(10 + size, 20 + size, tilemap.getTilePos(1, 1)); + assertPosEqual(10 + 1000 * size, 20 + 1000 * size, tilemap.getTilePos(1000, 1000)); + assertPosEqual(10 + 1000 * size, 20 + 1000 * size, tilemap.getTilePosAt(10 + 1000 * size, 20 + 1000 * size)); } @Test @@ -543,7 +543,7 @@ class FlxTilemapTest extends FlxTest tilemap.y = 20; tilemap.scale.set(2, 2); - final SIZE = 16; + final size = 16; Assert.isTrue(tilemap.tileExists(4)); Assert.isTrue(tilemap.tileExists(1, 1)); @@ -552,10 +552,10 @@ class FlxTilemapTest extends FlxTest Assert.isFalse(tilemap.tileExists(1, 3)); Assert.isFalse(tilemap.tileExists(5, 5)); - Assert.isTrue(tilemap.tileExistsAt(10 + 1 * SIZE, 20 + 1 * SIZE)); - Assert.isFalse(tilemap.tileExistsAt(10 + 3 * SIZE, 20 + 1 * SIZE)); - Assert.isFalse(tilemap.tileExistsAt(10 + 1 * SIZE, 20 + 3 * SIZE)); - Assert.isFalse(tilemap.tileExistsAt(10 + 5 * SIZE, 20 + 5 * SIZE)); + Assert.isTrue(tilemap.tileExistsAt(10 + 1 * size, 20 + 1 * size)); + Assert.isFalse(tilemap.tileExistsAt(10 + 3 * size, 20 + 1 * size)); + Assert.isFalse(tilemap.tileExistsAt(10 + 1 * size, 20 + 3 * size)); + Assert.isFalse(tilemap.tileExistsAt(10 + 5 * size, 20 + 5 * size)); } @Test @@ -571,41 +571,41 @@ class FlxTilemapTest extends FlxTest tilemap.y = 20; tilemap.scale.set(2, 2); - final SIZE = 16; + final size = 16; Assert.isFalse(tilemap.columnExists(5)); Assert.isFalse(tilemap.rowExists(5)); Assert.isFalse(tilemap.tileExists(5, 5)); - Assert.isFalse(tilemap.columnExistsAt(10 + 5 * SIZE)); - Assert.isFalse(tilemap.rowExistsAt(20 + 5 * SIZE)); - Assert.isFalse(tilemap.tileExistsAt(10 + 5 * SIZE, 20 + 5 * SIZE)); + Assert.isFalse(tilemap.columnExistsAt(10 + 5 * size)); + Assert.isFalse(tilemap.rowExistsAt(20 + 5 * size)); + Assert.isFalse(tilemap.tileExistsAt(10 + 5 * size, 20 + 5 * size)); Assert.isFalse(tilemap.columnExists(4)); Assert.isFalse(tilemap.rowExists(4)); Assert.isFalse(tilemap.tileExists(4, 4)); - Assert.isFalse(tilemap.columnExistsAt(10 + 4 * SIZE)); - Assert.isFalse(tilemap.rowExistsAt(20 + 4 * SIZE)); + Assert.isFalse(tilemap.columnExistsAt(10 + 4 * size)); + Assert.isFalse(tilemap.rowExistsAt(20 + 4 * size)); Assert.isTrue(tilemap.columnExists(3)); Assert.isFalse(tilemap.rowExists(3)); Assert.isFalse(tilemap.tileExists(3, 3)); - Assert.isTrue(tilemap.columnExistsAt(10 + 3 * SIZE)); - Assert.isFalse(tilemap.rowExistsAt(20 + 3 * SIZE)); - Assert.isFalse(tilemap.tileExistsAt(10 + 3 * SIZE, 20 + 3 * SIZE)); + Assert.isTrue(tilemap.columnExistsAt(10 + 3 * size)); + Assert.isFalse(tilemap.rowExistsAt(20 + 3 * size)); + Assert.isFalse(tilemap.tileExistsAt(10 + 3 * size, 20 + 3 * size)); Assert.isTrue(tilemap.columnExists(2)); Assert.isTrue(tilemap.rowExists(2)); Assert.isTrue(tilemap.tileExists(2, 2)); - Assert.isTrue(tilemap.columnExistsAt(10 + 2 * SIZE)); - Assert.isTrue(tilemap.rowExistsAt(20 + 2 * SIZE)); - Assert.isTrue(tilemap.tileExistsAt(10 + 2 * SIZE, 20 + 2 * SIZE)); + Assert.isTrue(tilemap.columnExistsAt(10 + 2 * size)); + Assert.isTrue(tilemap.rowExistsAt(20 + 2 * size)); + Assert.isTrue(tilemap.tileExistsAt(10 + 2 * size, 20 + 2 * size)); Assert.isTrue(tilemap.columnExists(1)); Assert.isTrue(tilemap.rowExists(1)); Assert.isTrue(tilemap.tileExists(1, 1)); - Assert.isTrue(tilemap.columnExistsAt(10 + 1 * SIZE)); - Assert.isTrue(tilemap.rowExistsAt(20 + 1 * SIZE)); - Assert.isTrue(tilemap.tileExistsAt(10 + 1 * SIZE, 20 + 1 * SIZE)); + Assert.isTrue(tilemap.columnExistsAt(10 + 1 * size)); + Assert.isTrue(tilemap.rowExistsAt(20 + 1 * size)); + Assert.isTrue(tilemap.tileExistsAt(10 + 1 * size, 20 + 1 * size)); Assert.isTrue(tilemap.columnExists(0)); Assert.isTrue(tilemap.rowExists(0)); diff --git a/tests/unit/src/flixel/util/FlxSignalTest.hx b/tests/unit/src/flixel/util/FlxSignalTest.hx index 8205deba89..83c7aa9971 100644 --- a/tests/unit/src/flixel/util/FlxSignalTest.hx +++ b/tests/unit/src/flixel/util/FlxSignalTest.hx @@ -29,7 +29,7 @@ class FlxSignalTest extends FlxTest function callbackIncrementCounter() counter++; - function callbackIncrementCounter_Int(v:Int):Void + function callbackIncrementCounterInt(v:Int):Void counter++; function addAllEmptyCallbacks():Void @@ -162,11 +162,11 @@ class FlxSignalTest extends FlxTest } @Test - function testDispatchOnce_signal1():Void + function testDispatchOnceSignal1():Void { // see https://github.com/HaxeFoundation/hashlink/issues/578 - signal1.addOnce(callbackIncrementCounter_Int); + signal1.addOnce(callbackIncrementCounterInt); signal1.dispatch(42); signal1.dispatch(42); From e2c77730a892e21d9453e6c922d5c9c5b0699aa8 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Tue, 12 Nov 2024 08:32:22 -0600 Subject: [PATCH 58/99] FlxG.assets: A way to overwrite and customize the way HaxeFlixel fetches or produces assets from ids (#2982) * add FlxG.assets * remove redundant public keyword * rename "Warn" suffix to "AndLog" + fix doc * more doc * more doc * more doc * remove "AndLog" suffix, add "Unsafe" * add flag FLX_CUSTOM_ASSETS_DIRECTORY * rename to singular * d'oh * check for sys --- flixel/FlxG.hx | 7 + flixel/graphics/FlxGraphic.hx | 6 +- flixel/graphics/frames/FlxAtlasFrames.hx | 17 +- flixel/input/mouse/FlxMouse.hx | 2 +- flixel/sound/FlxSound.hx | 8 +- flixel/system/FlxAssets.hx | 103 ++-- flixel/system/FlxSplash.hx | 2 +- flixel/system/frontEnds/AssetFrontEnd.hx | 640 ++++++++++++++++++++++ flixel/system/frontEnds/BitmapFrontEnd.hx | 4 +- flixel/system/frontEnds/LogFrontEnd.hx | 2 +- flixel/system/frontEnds/SoundFrontEnd.hx | 10 +- flixel/system/macros/FlxDefines.hx | 38 ++ flixel/system/ui/FlxSoundTray.hx | 2 +- flixel/text/FlxText.hx | 7 +- flixel/tile/FlxBaseTilemap.hx | 5 +- flixel/util/FlxStringUtil.hx | 2 +- 16 files changed, 771 insertions(+), 84 deletions(-) create mode 100644 flixel/system/frontEnds/AssetFrontEnd.hx diff --git a/flixel/FlxG.hx b/flixel/FlxG.hx index a7dd006d2a..912532fdcb 100644 --- a/flixel/FlxG.hx +++ b/flixel/FlxG.hx @@ -6,6 +6,7 @@ import flixel.math.FlxRandom; import flixel.math.FlxRect; import flixel.system.FlxQuadTree; import flixel.system.FlxVersion; +import flixel.system.frontEnds.AssetFrontEnd; import flixel.system.frontEnds.BitmapFrontEnd; import flixel.system.frontEnds.BitmapLogFrontEnd; import flixel.system.frontEnds.CameraFrontEnd; @@ -335,6 +336,12 @@ class FlxG */ public static var signals(default, null):SignalFrontEnd = new SignalFrontEnd(); + /** + * Contains helper functions relating to retrieving assets + * @since 5.9.0 + */ + public static var assets(default, null):AssetFrontEnd = new AssetFrontEnd(); + /** * Resizes the game within the window by reapplying the current scale mode. */ diff --git a/flixel/graphics/FlxGraphic.hx b/flixel/graphics/FlxGraphic.hx index 287da7dbd0..35c40a3e2d 100644 --- a/flixel/graphics/FlxGraphic.hx +++ b/flixel/graphics/FlxGraphic.hx @@ -40,7 +40,7 @@ class FlxGraphic implements IFlxDestroyable if (!Cache) { - bitmap = FlxAssets.getBitmapData(Source); + bitmap = FlxG.assets.getBitmapData(Source); if (bitmap == null) return null; return createGraphic(bitmap, Key, Unique, Cache); @@ -51,7 +51,7 @@ class FlxGraphic implements IFlxDestroyable if (graphic != null) return graphic; - bitmap = FlxAssets.getBitmapData(Source); + bitmap = FlxG.assets.getBitmapData(Source); if (bitmap == null) return null; @@ -564,7 +564,7 @@ class FlxGraphic implements IFlxDestroyable if (assetsClass != null) newBitmap = FlxAssets.getBitmapFromClass(assetsClass); else if (assetsKey != null) - newBitmap = FlxAssets.getBitmapData(assetsKey); + newBitmap = FlxG.assets.getBitmapData(assetsKey); if (newBitmap != null) return FlxGraphic.getBitmap(newBitmap, unique); diff --git a/flixel/graphics/frames/FlxAtlasFrames.hx b/flixel/graphics/frames/FlxAtlasFrames.hx index b1f3245c74..161d3698d1 100644 --- a/flixel/graphics/frames/FlxAtlasFrames.hx +++ b/flixel/graphics/frames/FlxAtlasFrames.hx @@ -9,7 +9,6 @@ import flixel.math.FlxPoint; import flixel.math.FlxRect; import flixel.system.FlxAssets; import haxe.xml.Access; -import openfl.Assets; import openfl.geom.Rectangle; /** @@ -40,7 +39,7 @@ class FlxAtlasFrames extends FlxFramesCollection * * @param source The image source (can be `FlxGraphic`, `String`, or `BitmapData`). * @param description Contents of JSON file with atlas description. - * You can get it with `Assets.getText(path/to/description.json)`. + * You can get it with `FlxG.assets.getText(path/to/description.json)`. * Or you can just a pass path to the JSON file in the assets directory. * You can also directly pass in the parsed object. * @return Newly created `FlxAtlasFrames` collection. @@ -56,7 +55,7 @@ class FlxAtlasFrames extends FlxFramesCollection * * @param source The image source (can be `FlxGraphic`, `String`, or `BitmapData`). * @param description Contents of JSON file with atlas description. - * You can get it with `Assets.getText(path/to/description.json)`. + * You can get it with `FlxG.assets.getText(path/to/description.json)`. * Or you can just a pass path to the JSON file in the assets directory. * You can also directly pass in the parsed object. * @param useFrameDuration If true, any frame durations defined in the JSON will override the @@ -132,7 +131,7 @@ class FlxAtlasFrames extends FlxFramesCollection * * @param source The image source (can be `FlxGraphic`, `String` or `BitmapData`). * @param description Contents of the file with atlas description. - * You can get it with `Assets.getText(path/to/description/file)`. + * You can get it with `FlxG.assets.getText(path/to/description/file)`. * Or you can just pass path to the description file in the assets directory. * @return Newly created `FlxAtlasFrames` collection. */ @@ -152,8 +151,8 @@ class FlxAtlasFrames extends FlxFramesCollection frames = new FlxAtlasFrames(graphic); - if (Assets.exists(description)) - description = Assets.getText(description); + if (FlxG.assets.exists(description)) + description = FlxG.assets.getTextUnsafe(description); var pack:String = StringTools.trim(description); var lines:Array = pack.split("\n"); @@ -358,7 +357,7 @@ class FlxAtlasFrames extends FlxFramesCollection * * @param Source The image source (can be `FlxGraphic`, `String` or `BitmapData`). * @param Description Contents of the file with atlas description. - * You can get it with `Assets.getText(path/to/description/file)`. + * You can get it with `FlxG.assets.getText(path/to/description/file)`. * Or you can just pass a path to the description file in the assets directory. * @return Newly created `FlxAtlasFrames` collection. */ @@ -378,8 +377,8 @@ class FlxAtlasFrames extends FlxFramesCollection frames = new FlxAtlasFrames(graphic); - if (Assets.exists(Description)) - Description = Assets.getText(Description); + if (FlxG.assets.exists(Description)) + Description = FlxG.assets.getTextUnsafe(Description); var pack = StringTools.trim(Description); var lines:Array = pack.split("\n"); diff --git a/flixel/input/mouse/FlxMouse.hx b/flixel/input/mouse/FlxMouse.hx index 65f1c984b4..9b191291fb 100644 --- a/flixel/input/mouse/FlxMouse.hx +++ b/flixel/input/mouse/FlxMouse.hx @@ -285,7 +285,7 @@ class FlxMouse extends FlxPointer implements IFlxInputManager } else if ((Graphic is String)) { - cursor = new Bitmap(FlxAssets.getBitmapData(Graphic)); + cursor = new Bitmap(FlxG.assets.getBitmapData(Graphic, false)); } else { diff --git a/flixel/sound/FlxSound.hx b/flixel/sound/FlxSound.hx index 950c389e88..e087968790 100644 --- a/flixel/sound/FlxSound.hx +++ b/flixel/sound/FlxSound.hx @@ -7,7 +7,6 @@ import flixel.math.FlxPoint; import flixel.system.FlxAssets.FlxSoundAsset; import flixel.tweens.FlxTween; import flixel.util.FlxStringUtil; -import openfl.Assets; import openfl.events.Event; import openfl.events.IEventDispatcher; import openfl.media.Sound; @@ -17,9 +16,6 @@ import openfl.net.URLRequest; #if flash11 import openfl.utils.ByteArray; #end -#if (openfl >= "8.0.0") -import openfl.utils.AssetType; -#end /** * This is the universal flixel sound object, used for streaming, music, and sound effects. @@ -365,8 +361,8 @@ class FlxSound extends FlxBasic } else if ((EmbeddedSound is String)) { - if (Assets.exists(EmbeddedSound, AssetType.SOUND) || Assets.exists(EmbeddedSound, AssetType.MUSIC)) - _sound = Assets.getSound(EmbeddedSound); + if (FlxG.assets.exists(EmbeddedSound, SOUND)) + _sound = FlxG.assets.getSoundUnsafe(EmbeddedSound); else FlxG.log.error('Could not find a Sound asset with an ID of \'$EmbeddedSound\'.'); } diff --git a/flixel/system/FlxAssets.hx b/flixel/system/FlxAssets.hx index 503dee6459..1ab20ca686 100644 --- a/flixel/system/FlxAssets.hx +++ b/flixel/system/FlxAssets.hx @@ -2,9 +2,6 @@ package flixel.system; import haxe.macro.Expr; #if !macro -import openfl.display.BitmapData; -import openfl.display.Graphics; -import openfl.media.Sound; import flixel.FlxG; import flixel.graphics.FlxGraphic; import flixel.graphics.atlas.AseAtlas; @@ -12,6 +9,7 @@ import flixel.graphics.atlas.TexturePackerAtlas; import flixel.graphics.frames.FlxAtlasFrames; import flixel.graphics.frames.FlxFrame; import flixel.graphics.frames.FlxFramesCollection; +import flixel.system.frontEnds.AssetFrontEnd; import flixel.graphics.frames.bmfont.BMFont; import flixel.util.typeLimit.OneOfFour; import flixel.util.typeLimit.OneOfThree; @@ -19,7 +17,9 @@ import flixel.util.typeLimit.OneOfTwo; import haxe.io.Bytes; import haxe.Json; import haxe.xml.Access; -import openfl.Assets; +import openfl.display.BitmapData; +import openfl.display.Graphics; +import openfl.media.Sound; import openfl.utils.ByteArray; using StringTools; @@ -66,7 +66,7 @@ abstract FlxXmlAsset(OneOfTwo) from Xml from String if ((this is String)) { final str:String = cast this; - if (Assets.exists(str)) + if (FlxG.assets.exists(str)) return fromPath(str); return fromXmlString(str); @@ -77,12 +77,12 @@ abstract FlxXmlAsset(OneOfTwo) from Xml from String static inline function fromPath(path:String):Xml { - return fromXmlString(Assets.getText(path)); + return FlxG.assets.getXmlUnsafe(path); } static inline function fromXmlString(data:String):Xml { - return Xml.parse(data); + return FlxG.assets.parseXml(data); } } @@ -93,7 +93,7 @@ abstract FlxJsonAsset(OneOfTwo) from T from String if ((this is String)) { final str:String = cast this; - if (Assets.exists(str)) + if (FlxG.assets.exists(str)) return fromPath(str); return fromDataString(str); @@ -104,12 +104,12 @@ abstract FlxJsonAsset(OneOfTwo) from T from String static inline function fromPath(path:String):T { - return fromDataString(Assets.getText(path)); + return cast FlxG.assets.getJsonUnsafe(path); } static inline function fromDataString(data:String):T { - return cast Json.parse(data); + return cast FlxG.assets.parseJson(data); } } @@ -272,20 +272,22 @@ class FlxAssets graph.lineTo(100, 100); graph.endFill(); } - + + /** + * Gets an instance of a bitmap, logs when the asset is not found. + * @param id The ID or asset path for the bitmap + * @return A new BitmapData object + **/ public static inline function getBitmapData(id:String):BitmapData { - if (Assets.exists(id)) - return Assets.getBitmapData(id, true); - FlxG.log.error('Could not find a BitmapData asset with ID \'$id\'.'); - return null; + return FlxG.assets.getBitmapData(id); } /** * Generates BitmapData from specified class. Less typing. * - * @param source BitmapData class to generate BitmapData object from. - * @return Newly instantiated BitmapData object. + * @param source BitmapData class to generate BitmapData object from. + * @return Newly instantiated BitmapData object. */ public static inline function getBitmapFromClass(source:Class):BitmapData { @@ -299,22 +301,22 @@ class FlxAssets * 3) if the input is String, then it will get BitmapData from openfl.Assets; * 4) it will return null in any other case. * - * @param Graphic input data to get BitmapData object for. - * @return BitmapData for specified Dynamic object. + * @param graphic input data to get BitmapData object for. + * @return BitmapData for specified Dynamic object. */ - public static function resolveBitmapData(Graphic:FlxGraphicSource):BitmapData + public static function resolveBitmapData(graphic:FlxGraphicSource):BitmapData { - if ((Graphic is BitmapData)) + if ((graphic is BitmapData)) { - return cast Graphic; + return cast graphic; } - else if ((Graphic is Class)) + else if ((graphic is Class)) { - return FlxAssets.getBitmapFromClass(cast Graphic); + return getBitmapFromClass(cast graphic); } - else if ((Graphic is String)) + else if ((graphic is String)) { - return FlxAssets.getBitmapData(Graphic); + return FlxG.assets.getBitmapData(graphic); } return null; @@ -327,30 +329,28 @@ class FlxAssets * 3) if the input is String, then it will return it; * 4) it will return null in any other case. * - * @param Graphic input data to get string key for. - * @param Key optional key string. - * @return Key String for specified Graphic object. + * @param graphic input data to get string key for. + * @param key optional key string. + * @return Key String for specified Graphic object. */ - public static function resolveKey(Graphic:FlxGraphicSource, ?Key:String):String + public static function resolveKey(graphic:FlxGraphicSource, ?key:String):String { - if (Key != null) - { - return Key; - } - - if ((Graphic is BitmapData)) + if (key != null) + return key; + + if ((graphic is BitmapData)) { - return Key; + return key; } - else if ((Graphic is Class)) + else if ((graphic is Class)) { - return FlxG.bitmap.getKeyForClass(cast Graphic); + return FlxG.bitmap.getKeyForClass(cast graphic); } - else if ((Graphic is String)) + else if ((graphic is String)) { - return Graphic; + return graphic; } - + return null; } @@ -361,12 +361,27 @@ class FlxAssets * @param id The asset id of the local sound file. * @return The sound file. */ - public static function getSound(id:String):Sound + @:deprecated("FlxAssets.getSound is deprecated, use getSoundAddExtension, instead") + public static inline function getSound(id:String):Sound + { + return getSoundAddExtension(id); + } + + /** + * Loads an OpenFL sound asset from the given asset id. If an extension not provided the + * `defaultSoundExtension` is used (defaults to "ogg" on non-flash targets). + * + * @param id The asset id of the local sound file. + * @return The sound file. + * + * @since 5.9.0 + */ + public static function getSoundAddExtension(id:String, useCache = true):Sound { if (!id.endsWith(".mp3") && !id.endsWith(".ogg") && !id.endsWith(".wav")) id += "." + defaultSoundExtension; - return Assets.getSound(id); + return FlxG.assets.getSoundUnsafe(id, useCache); } public static function getVirtualInputFrames():FlxAtlasFrames diff --git a/flixel/system/FlxSplash.hx b/flixel/system/FlxSplash.hx index 3becdcc3fb..10092194a4 100644 --- a/flixel/system/FlxSplash.hx +++ b/flixel/system/FlxSplash.hx @@ -87,7 +87,7 @@ class FlxSplash extends FlxState #if FLX_SOUND_SYSTEM if (!muted) { - FlxG.sound.load(FlxAssets.getSound("flixel/sounds/flixel")).play(); + FlxG.sound.load(FlxAssets.getSoundAddExtension("flixel/sounds/flixel")).play(); } #end } diff --git a/flixel/system/frontEnds/AssetFrontEnd.hx b/flixel/system/frontEnds/AssetFrontEnd.hx new file mode 100644 index 0000000000..00f1f68e5e --- /dev/null +++ b/flixel/system/frontEnds/AssetFrontEnd.hx @@ -0,0 +1,640 @@ +package flixel.system.frontEnds; + +import flixel.FlxG; +import flixel.system.FlxAssets; +import flixel.system.debug.log.LogStyle; +import haxe.io.Bytes; +import haxe.io.Path; +import haxe.Json; +import haxe.xml.Access; +import openfl.display.BitmapData; +import openfl.media.Sound; +import openfl.utils.Assets; +import openfl.utils.AssetType; +import openfl.utils.AssetCache; +import openfl.utils.Future; +import openfl.text.Font; + +using StringTools; + +/** + * Accessed via `FlxG.assets`. The main interface for the asset system. By default, OpenFl's + * Asset system is used, which uses relative path strings to retrive assets, though you can completely + * avoid Openfl's asset system by setting custom methods to the following dynamic fields: `getAssetUnsafe`, + * `loadAsset`, `exists`, `isLocal` and `list`. + * + * ## Common Uses + * The initial reason for making customizable asset system + * was to allow for "hot-reloading", or testing new assets in your game without recompiling, with + * each change. Say, if you would like a debug feature where you load assets from source assets, + * rather than the assets copied over to your export folder, you could overwrite this system to do + * just that. + * + * Other potential uses for this are modding, bypassing the manifest and loading resources from + * a remote location. + * + * ### Quick Setup for "Hot-Reloading" + * To simplify the process mentioned above, the `FLX_CUSTOM_ASSETS_DIRECTORY` flag was created. + * By adding `-DFLX_CUSTOM_ASSETS_DIRECTORY="../../../assets"` to your lime build command + * it will automatically grab assets from your project root's assets folder rather than, the + * default "export/hl/bin/assets". This will only work with a single asset root folder with one + * asset library and will use the openfl asset system if the asset id starts with "flixel/" or + * tries to references a specific library using the format: "libName:asset/path/file.ext". + * + * @since 5.9.0 + */ +class AssetFrontEnd +{ + #if FLX_CUSTOM_ASSETS_DIRECTORY + /** + * The target directory + */ + final directory:String; + + /** + * The parent of the target directory, is prepended to any `id` passed in + */ + final parentDirectory:String; + + public function new () + { + final rawPath = '${haxe.macro.Compiler.getDefine("FLX_CUSTOM_ASSETS_DIRECTORY")}'; + // Remove final slash and accepts backslashes and removes redundancies + directory = Path.normalize(rawPath); + // Verify valid directory + if (sys.FileSystem.exists(directory) == false) + throw 'Invalid value:"$directory" of FLX_CUSTOM_ASSETS_DIRECTORY, expecting relative or absolute path'; + // remove final "/assets" since the id typically contains it + final split = sys.FileSystem.absolutePath(directory).split("/"); + split.pop(); + parentDirectory = split.join("/"); + } + + function getPath(id:String) + { + return Path.normalize('$parentDirectory/$id'); + } + + /** + * True for assets packaged with all HaxeFlixel build, and any non-default libraries + */ + function useOpenflAssets(id:String) + { + return id.startsWith("flixel/") || id.contains(':'); + } + #else + public function new () {} + #end + + /** + * Used by methods like `getAsset`, `getBitmapData`, `getText`, their "unsafe" counterparts and + * the like to get assets synchronously. Can be set to a custom function to avoid the existing + * asset system. Unlike its "safe" counterpart, there is no log on missing assets + * + * @param id The id of the asset, usually a path + * @param type The type of asset to look for, determines the type + * @param useCache Whether to allow use of the asset cache (if one exists) + * @return The asset, if found, otherwise `null` is returned + */ + public dynamic function getAssetUnsafe(id:String, type:FlxAssetType, useCache = true):Null + { + #if FLX_STANDARD_ASSETS_DIRECTORY + return getOpenflAssetUnsafe(id, type, useCache); + #else + + if (useOpenflAssets(id)) + return getOpenflAssetUnsafe(id, type, useCache); + // load from custom assets directory + final canUseCache = useCache && Assets.cache.enabled; + + final asset:Any = switch type + { + // No caching + case TEXT: + sys.io.File.getContent(getPath(id)); + case BINARY: + sys.io.File.getBytes(getPath(id)); + + // Check cache + case IMAGE if (canUseCache && Assets.cache.hasBitmapData(id)): + Assets.cache.getBitmapData(id); + case SOUND if (canUseCache && Assets.cache.hasSound(id)): + Assets.cache.getSound(id); + case FONT if (canUseCache && Assets.cache.hasFont(id)): + Assets.cache.getFont(id); + + // Get asset and set cache + case IMAGE: + final bitmap = BitmapData.fromFile(getPath(id)); + if (canUseCache) + Assets.cache.setBitmapData(id, bitmap); + bitmap; + case SOUND: + final sound = Sound.fromFile(getPath(id)); + if (canUseCache) + Assets.cache.setSound(id, sound); + sound; + case FONT: + final font = Font.fromFile(getPath(id)); + if (canUseCache) + Assets.cache.setFont(id, font); + font; + } + + return asset; + #end + } + + function getOpenflAssetUnsafe(id:String, type:FlxAssetType, useCache = true):Null + { + // Use openfl assets + return switch(type) + { + case TEXT: Assets.getText(id); + case BINARY: Assets.getBytes(id); + case IMAGE: Assets.getBitmapData(id, useCache); + case SOUND: Assets.getSound(id, useCache); + case FONT: Assets.getFont(id, useCache); + } + } + + /** + * Calls `getAssetUnsafe` if the asset exists, otherwise logs that the asset is missing, via `FlxG.log` + * + * @param id The id of the asset, usually a path + * @param type The type of asset to look for, determines the type + * @param useCache Whether to allow use of the asset cache (if one exists) + * @param logStyle How to log, if the asset is not found. Uses `LogStyle.ERROR` by default + */ + public function getAsset(id:String, type:FlxAssetType, useCache = true, ?logStyle:LogStyle):Null + { + inline function log(message:String) + { + if (logStyle == null) + logStyle = LogStyle.ERROR; + FlxG.log.advanced(message, logStyle); + } + + if (exists(id, type)) + { + if (isLocal(id, type)) + return getAssetUnsafe(id, type, useCache); + + log('$type asset "$id" exists, but only asynchronously'); + return null; + } + + log('Could not find a $type asset with ID \'$id\'.'); + return null; + } + + /** + * Used by methods like `loadBitmapData`, `loadText` and the like to get assets asynchronously. + * Can be set to a custom function to avoid the existing asset system. + * + * @param id The id of the asset, usually a path + * @param type The type of asset to look for, determines the type + * @param useCache Whether to allow use of the asset cache (if one exists) + */ + public dynamic function loadAsset(id:String, type:FlxAssetType, useCache = true):Future + { + #if FLX_STANDARD_ASSETS_DIRECTORY + return loadOpenflAsset(id, type, useCache); + #else + + if (useOpenflAssets(id)) + return loadOpenflAsset(id, type, useCache); + + // get the asset synchronously and wrap it in a future + return Future.withValue(getAsset(id, type, useCache)); + // TODO: html? + #end + } + + function loadOpenflAsset(id:String, type:FlxAssetType, useCache = true):Future + { + return switch(type) + { + case TEXT: Assets.loadText(id); + case BINARY: Assets.loadBytes(id); + case IMAGE: Assets.loadBitmapData(id, useCache); + case SOUND: Assets.loadSound(id, useCache); + case FONT: Assets.loadFont(id, useCache); + } + } + + /** + * Whether a specific asset ID and type exists. + * Can be set to a custom function to avoid the existing asset system. + * + * @param id The ID or asset path for the asset + * @param type The asset type to match, or null to match any type + */ + public dynamic function exists(id:String, ?type:FlxAssetType) + { + #if FLX_STANDARD_ASSETS_DIRECTORY + return Assets.exists(id, type.toOpenFlType()); + #else + if (useOpenflAssets(id)) + return Assets.exists(id, type.toOpenFlType()); + // Can't verify contents match expected type without + return sys.FileSystem.exists(getPath(id)); + #end + } + + /** + * Returns whether an asset is "local", and therefore can be loaded synchronously, or with the + * `getAsset` method, otherwise the `loadAsset` method should be used. + * Can be set to a custom function to avoid the existing asset system. + * + * @param id The ID or asset path for the asset + * @param type The asset type to match, or null to match any type + * @param useCache Whether to allow use of the asset cache (if one exists) + * @return Whether the asset is local + */ + public dynamic function isLocal(id:String, ?type:FlxAssetType, useCache = true) + { + #if FLX_STANDARD_ASSETS_DIRECTORY + return Assets.isLocal(id, type.toOpenFlType(), useCache); + #else + + if (useOpenflAssets(id)) + Assets.isLocal(id, type.toOpenFlType(), useCache); + + return true; + #end + } + + /** + * Returns a list of all assets (by type). + * Can be set to a custom function to avoid the existing asset system. + * + * @param type The asset type to match, or null to match any type + * @return An array of asset ID values + */ + public dynamic function list(?type:FlxAssetType) + { + #if FLX_STANDARD_ASSETS_DIRECTORY + return Assets.list(type.toOpenFlType()); + #else + // list all files in the directory, recursively + final list = []; + function addFiles(directory:String, prefix = "") + { + for (path in sys.FileSystem.readDirectory(directory)) + { + if (sys.FileSystem.isDirectory('$directory/$path')) + addFiles('$directory/$path',path + '/'); + else + list.push(prefix + path); + } + } + final prefix = Path.withoutDirectory(directory) + "/"; + addFiles(directory, prefix); + return list; + #end + } + + /** + * Gets an instance of a bitmap. Unlike its "safe" counterpart, there is no log on missing assets + * + * @param id The ID or asset path for the bitmap + * @param useCache Whether to allow use of the asset cache (if one exists) + * @return A new BitmapData object + */ + public inline function getBitmapDataUnsafe(id:String, useCache = false):BitmapData + { + return cast getAssetUnsafe(id, IMAGE, useCache); + } + + /** + * Gets an instance of a bitmap, logs when the asset is not found + * + * @param id The ID or asset path for the bitmap + * @param useCache Whether to allow use of the asset cache (if one exists) + * @return A new BitmapData object + */ + public inline function getBitmapData(id:String, useCache = false, ?logStyle:LogStyle):BitmapData + { + return cast getAsset(id, IMAGE, useCache, logStyle); + } + + /** + * Gets an instance of a sound. Unlike its "safe" counterpart, there is no log on missing assets + * + * @param id The ID or asset path for the sound + * @param useCache Whether to allow use of the asset cache (if one exists) + * @return A new `Sound` object Note: Dos not return a `FlxSound` + */ + public inline function getSoundUnsafe(id:String, useCache = true):Sound + { + return cast getAssetUnsafe(id, SOUND, useCache); + } + + /** + * Gets an instance of a sound, logs when the asset is not found + * + * @param id The ID or asset path for the sound + * @param useCache Whether to allow use of the asset cache (if one exists) + * @param logStyle How to log, if the asset is not found. Uses `LogStyle.ERROR` by default + * @return A new `Sound` object Note: Dos not return a `FlxSound` + */ + public inline function getSound(id:String, useCache = true, ?logStyle:LogStyle):Sound + { + return cast getAsset(id, SOUND, useCache, logStyle); + } + + /** + * Gets the contents of a text-based asset. Unlike its "safe" counterpart, there is no log + * on missing assets + * + * **Note:** The default asset system does not cache text assets + * + * @param id The ID or asset path for the asset + * @param useCache Whether to allow use of the asset cache (if one exists) + */ + public inline function getTextUnsafe(id:String, useCache = true):String + { + return cast getAssetUnsafe(id, TEXT, useCache); + } + + /** + * Gets the contents of a text-based asset, logs when the asset is not found + * + * **Note:** The default asset system does not cache text assets + * + * @param id The ID or asset path for the asset + * @param useCache Whether to allow use of the asset cache (if one exists) + * @param logStyle How to log, if the asset is not found. Uses `LogStyle.ERROR` by default + */ + public inline function getText(id:String, useCache = true, ?logStyle:LogStyle):String + { + return cast getAsset(id, TEXT, useCache, logStyle); + } + + /** + * Parses the contents of a xml-based asset into an `Xml` object. + * Unlike its "safe" counterpart, there is no log on missing assets + * + * **Note:** The default asset system does not cache xml assets + * + * @param id The ID or asset path for the asset + * @param useCache Whether to allow use of the asset cache (if one exists) + */ + public inline function getXmlUnsafe(id:String, useCache = true) + { + final text = getTextUnsafe(id, useCache); + return text != null ? parseXml(text) : null; + } + + /** + * Parses the contents of a xml-based asset into an `Xml` object, logs when the asset is not found + * + * **Note:** The default asset system does not cache xml assets + * + * @param id The ID or asset path for the asset + * @param useCache Whether to allow use of the asset cache (if one exists) + * @param logStyle How to log, if the asset is not found. Uses `LogStyle.ERROR` by default + */ + public inline function getXml(id:String, useCache = true, ?logStyle:LogStyle) + { + final text = getText(id, useCache, logStyle); + return text != null ? parseXml(text) : null; + } + + /** + * Gets the contents of a xml-based asset. + * Unlike its "safe" counterpart, there is no log on missing assets + * + * **Note:** The default asset system does not cache json assets + * + * @param id The ID or asset path for the asset + * @param useCache Whether to allow use of the asset cache (if one exists) + */ + public inline function getJsonUnsafe(id:String, useCache = true) + { + final text = getTextUnsafe(id, useCache); + return text != null ? parseJson(text) : null; + } + + /** + * Gets the contents of a xml-based asset, logs when the asset is not found + * + * **Note:** The default asset system does not cache json assets + * + * @param id The ID or asset path for the asset + * @param useCache Whether to allow use of the asset cache (if one exists) + * @param logStyle How to log, if the asset is not found. Uses `LogStyle.ERROR` by default + */ + public inline function getJson(id:String, useCache = true, ?logStyle:LogStyle) + { + final text = getText(id, useCache, logStyle); + return text != null ? parseJson(text) : null; + } + + /** + * Gets the contents of a binary asset. + * Unlike its "safe" counterpart, there is no log on missing assets + * + * **Note:** The default asset system does not cache binary assets + * + * @param id The ID or asset path for the asset + * @param useCache Whether to allow use of the asset cache (if one exists) + */ + public inline function getBytesUnsafe(id:String, useCache = true):Bytes + { + return cast getAssetUnsafe(id, BINARY, useCache); + } + + /** + * Gets the contents of a binary asset, logs when the asset is not found + * + * **Note:** The default asset system does not cache binary assets + * + * @param id The ID or asset path for the asset + * @param useCache Whether to allow use of the asset cache (if one exists) + * @param logStyle How to log, if the asset is not found. Uses `LogStyle.ERROR` by default + */ + public inline function getBytes(id:String, useCache = true, ?logStyle:LogStyle):Bytes + { + return cast getAsset(id, BINARY, useCache); + } + + /** + * Gets the contents of a font asset. + * Unlike its "safe" counterpart, there is no log on missing assets + * + * @param id The ID or asset path for the asset + * @param useCache Whether to allow use of the asset cache + */ + public inline function getFontUnsafe(id:String, useCache = true):Font + { + return cast getAssetUnsafe(id, FONT, useCache); + } + + /** + * Gets the contents of a font asset, logs when the asset is not found + * + * @param id The ID or asset path for the asset + * @param useCache Whether to allow use of the asset cache (if one exists) + * @param logStyle How to log, if the asset is not found. Uses `LogStyle.ERROR` by default + */ + public inline function getFont(id:String, useCache = true, ?logStyle:LogStyle):Font + { + return cast getAsset(id, FONT, useCache, logStyle); + } + + /** + * Loads an bitmap asset asynchronously + * + * @param id The ID or asset path for the asset + * @param useCache Whether to allow use of the asset cache (if one exists) + * @return Returns a `Future` which allows listeners to be added via methods like `onComplete` + */ + public inline function loadBitmapData(id:String, useCache = false):Future + { + return cast loadAsset(id, IMAGE, useCache); + } + + /** + * Loads a sound asset asynchronously + * + * @param id The ID or asset path for the asset + * @param useCache Whether to allow use of the asset cache (if one exists) + * @return Returns a `Future` which allows listeners to be added via methods like `onComplete` + */ + public inline function loadSound(id:String, useCache = true):Future + { + return cast loadAsset(id, SOUND, useCache); + } + + /** + * Loads a text asset asynchronously + * + * **Note:** The default asset system does not cache text assets + * + * @param id The ID or asset path for the asset + * @param useCache Whether to allow use of the asset cache (if one exists) + * @return Returns a `Future` which allows listeners to be added via methods like `onComplete` + */ + public inline function loadText(id:String, useCache = true):Future + { + return cast loadAsset(id, TEXT, useCache); + } + + /** + * Loads a text asset asynchronously + * + * **Note:** The default asset system does not cache xml assets + * + * @param id The ID or asset path for the asset + * @param useCache Whether to allow use of the asset cache (if one exists) + * @return Returns a `Future` which allows listeners to be added via methods like `onComplete` + */ + public inline function loadXml(id:String, useCache = true):Future + { + return wrapFuture(loadText(id, useCache), parseXml); + } + + /** + * Loads a text asset asynchronously + * + * **Note:** The default asset system does not cache json assets + * + * @param id The ID or asset path for the asset + * @param useCache Whether to allow use of the asset cache (if one exists) + * @return Returns a `Future` which allows listeners to be added via methods like `onComplete` + */ + public inline function loadJson(id:String, useCache = true):Future + { + return wrapFuture(loadText(id, useCache), parseJson); + } + + /** + * Loads a binary asset asynchronously + * + * **Note:** The default asset system does not cache binary assets + * + * @param id The ID or asset path for the asset + * @param useCache Whether to allow use of the asset cache (if one exists) + * @return Returns a `Future` which allows listeners to be added via methods like `onComplete` + */ + public inline function loadBytes(id:String, useCache = true):Future + { + return cast loadAsset(id, BINARY, useCache); + } + + /** + * Loads a font asset asynchronously + * + * @param id The ID or asset path for the asset + * @param useCache Whether to allow use of the asset cache (if one exists) + * @return Returns a `Future` which allows listeners to be added via methods like `onComplete` + */ + public inline function loadFont(id:String, useCache = true):Future + { + return cast loadAsset(id, FONT, useCache); + } + + /** + * Parses a json string, creates and returns a struct + */ + public inline function parseJson(jsonText:String) + { + return Json.parse(jsonText); + } + + /** + * Parses an xml string, creates and returns an Xml object + */ + public inline function parseXml(xmlText:String) + { + return Xml.parse(xmlText); + } + + inline function wrapFuture(future:Future, converter:(T1)->T2):Future + { + final promise = new lime.app.Promise(); + + future.onComplete((data)->promise.complete(converter(data))); + future.onError((error)->promise.error(error)); + future.onProgress((progress, total)->promise.progress(progress, total)); + + return promise.future; + } +} + +/** + * The AssetType enum lists the core set of available + * asset types from the OpenFL command-line tools. + * @since 5.9.0 + */ +enum abstract FlxAssetType(String) +{ + /** Binary assets (data that is not readable as text) */ + var BINARY = "binary"; + + /** Font assets, such as *.ttf or *.otf files */ + var FONT = "font"; + + /** Image assets, such as *.png or *.jpg files */ + var IMAGE ="image"; + + /** Audio assets, such as *.ogg or *.wav files */ + var SOUND = "sound"; + + /** Text assets */ + var TEXT = "text"; + + public function toOpenFlType() + { + return switch((cast this:FlxAssetType)) + { + case BINARY: AssetType.BINARY; + case FONT: AssetType.FONT; + case IMAGE: AssetType.IMAGE; + case SOUND: AssetType.SOUND; + case TEXT: AssetType.TEXT; + } + } +} diff --git a/flixel/system/frontEnds/BitmapFrontEnd.hx b/flixel/system/frontEnds/BitmapFrontEnd.hx index fb66af7025..4076756083 100644 --- a/flixel/system/frontEnds/BitmapFrontEnd.hx +++ b/flixel/system/frontEnds/BitmapFrontEnd.hx @@ -5,7 +5,7 @@ import flixel.graphics.FlxGraphic; import flixel.graphics.frames.FlxFrame; import flixel.math.FlxPoint; import flixel.math.FlxRect; -import flixel.system.FlxAssets.FlxGraphicAsset; +import flixel.system.FlxAssets; import flixel.util.FlxColor; import openfl.Assets; #if FLX_OPENGL_AVAILABLE @@ -216,7 +216,7 @@ class BitmapFrontEnd /** * Creates string key for further caching. * - * @param systemKey The first string key to use as a base for a new key. It's usually a key from openfl.Assets ("assets/image.png"). + * @param systemKey The first string key to use as a base for a new key. It's usually an asset key ("assets/image.png"). * @param userKey The second string key to use as a base for a new key. It's usually a key provided by the user * @param unique Whether generated key should be unique or not. * @return Created key. diff --git a/flixel/system/frontEnds/LogFrontEnd.hx b/flixel/system/frontEnds/LogFrontEnd.hx index b355c7ceb3..a93f27df74 100644 --- a/flixel/system/frontEnds/LogFrontEnd.hx +++ b/flixel/system/frontEnds/LogFrontEnd.hx @@ -64,7 +64,7 @@ class LogFrontEnd #if (FLX_SOUND_SYSTEM && !FLX_UNIT_TEST) if (style.errorSound != null) { - final sound = FlxAssets.getSound(style.errorSound); + final sound = FlxAssets.getSoundAddExtension(style.errorSound); if (sound != null) FlxG.sound.load(sound).play(); } diff --git a/flixel/system/frontEnds/SoundFrontEnd.hx b/flixel/system/frontEnds/SoundFrontEnd.hx index 9784d759bb..3a40e9ddc5 100644 --- a/flixel/system/frontEnds/SoundFrontEnd.hx +++ b/flixel/system/frontEnds/SoundFrontEnd.hx @@ -11,11 +11,7 @@ import flixel.system.FlxAssets; import flixel.system.ui.FlxSoundTray; import flixel.text.FlxInputText; import flixel.util.FlxSignal; -import openfl.Assets; import openfl.media.Sound; -#if (openfl >= "8.0.0") -import openfl.utils.AssetType; -#end /** * Accessed via `FlxG.sound`. @@ -213,8 +209,8 @@ class SoundFrontEnd public inline function cache(embeddedSound:String):Sound { // load the sound into the OpenFL assets cache - if (Assets.exists(embeddedSound, AssetType.SOUND) || Assets.exists(embeddedSound, AssetType.MUSIC)) - return Assets.getSound(embeddedSound, true); + if (FlxG.assets.exists(embeddedSound, SOUND)) + return FlxG.assets.getSoundUnsafe(embeddedSound, true); FlxG.log.error('Could not find a Sound asset with an ID of \'$embeddedSound\'.'); return null; } @@ -225,7 +221,7 @@ class SoundFrontEnd */ public function cacheAll():Void { - for (id in Assets.list(AssetType.SOUND)) + for (id in FlxG.assets.list(SOUND)) { cache(id); } diff --git a/flixel/system/macros/FlxDefines.hx b/flixel/system/macros/FlxDefines.hx index 1ef3234f44..882bb6aaf5 100644 --- a/flixel/system/macros/FlxDefines.hx +++ b/flixel/system/macros/FlxDefines.hx @@ -3,6 +3,7 @@ package flixel.system.macros; import haxe.macro.Compiler; import haxe.macro.Context; import haxe.macro.Expr.Position; +import haxe.io.Path; #if (flixel_addons >= "3.2.2") import flixel.addons.system.macros.FlxAddonDefines; #end @@ -43,6 +44,14 @@ private enum UserDefines FLX_TRACK_POOLS; /** Adds `creationInfo` to FlxGraphic instances, automatically defined with FLX_DEBUG */ FLX_TRACK_GRAPHICS; + /** + * Loads from the specified relative or absolute directory. Unlike other boolean flags, + * this flag should contain a string value. + * + * **Note:** When using assets entirely from outside the build directory, it is wise to disable + * any `` tags in your project.xml, to reduce your total memory + */ + FLX_CUSTOM_ASSETS_DIRECTORY; } /** @@ -87,6 +96,8 @@ private enum HelperDefines FLX_NO_TRACK_POOLS; FLX_NO_TRACK_GRAPHICS; FLX_OPENGL_AVAILABLE; + /** Defined to `1`(or `true`) if `FLX_CUSTOM_ASSETS_DIRECTORY` is not defined */ + FLX_STANDARD_ASSETS_DIRECTORY; } class FlxDefines @@ -260,6 +271,28 @@ class FlxDefines #end defineInversion(FLX_TRACK_GRAPHICS, FLX_NO_TRACK_GRAPHICS); + + if (defined(FLX_CUSTOM_ASSETS_DIRECTORY)) + { + if (!defined("sys")) + { + abort('FLX_CUSTOM_ASSETS_DIRECTORY is only available on sys targets', (macro null).pos); + } + else + { + // Todo: check sys targets + final rawDirectory = Path.normalize(definedValue(FLX_CUSTOM_ASSETS_DIRECTORY)); + final directory = Path.normalize(rawDirectory); + if (!sys.FileSystem.isDirectory(directory) || directory == "1") + { + final absPath = sys.FileSystem.absolutePath(directory); + abort('FLX_CUSTOM_ASSETS_DIRECTORY must be a path to a directory, got "$rawDirectory"' + + '\nabsolute path: $absPath', (macro null).pos); + } + } + } + else // define boolean inversion + define(FLX_STANDARD_ASSETS_DIRECTORY); } static function defineInversion(userDefine:UserDefines, invertedDefine:HelperDefines) @@ -287,6 +320,11 @@ class FlxDefines abort(errorMessage, (macro null).pos); } + static inline function definedValue(define:Dynamic):String + { + return Context.definedValue(Std.string(define)); + } + static inline function defined(define:Dynamic) { return Context.defined(Std.string(define)); diff --git a/flixel/system/ui/FlxSoundTray.hx b/flixel/system/ui/FlxSoundTray.hx index a5492bca4d..e04212ad84 100644 --- a/flixel/system/ui/FlxSoundTray.hx +++ b/flixel/system/ui/FlxSoundTray.hx @@ -148,7 +148,7 @@ class FlxSoundTray extends Sprite { if (!silent) { - var sound = FlxAssets.getSound(up ? volumeUpSound : volumeDownSound); + var sound = FlxAssets.getSoundAddExtension(up ? volumeUpSound : volumeDownSound); if (sound != null) FlxG.sound.load(sound).play(); } diff --git a/flixel/text/FlxText.hx b/flixel/text/FlxText.hx index 3378887100..f7228b9ce1 100644 --- a/flixel/text/FlxText.hx +++ b/flixel/text/FlxText.hx @@ -26,9 +26,6 @@ using flixel.util.FlxStringUtil; #if flash import openfl.geom.Rectangle; #end -#if (openfl >= "8.0.0") -import openfl.utils.AssetType; -#end // TODO: think about filters and text @@ -693,9 +690,9 @@ class FlxText extends FlxSprite if (Font != null) { var newFontName:String = Font; - if (Assets.exists(Font, AssetType.FONT)) + if (FlxG.assets.exists(Font, FONT)) { - newFontName = Assets.getFont(Font).fontName; + newFontName = FlxG.assets.getFontUnsafe(Font).fontName; } _defaultFormat.font = newFontName; diff --git a/flixel/tile/FlxBaseTilemap.hx b/flixel/tile/FlxBaseTilemap.hx index 590095422c..f60d6eeb08 100644 --- a/flixel/tile/FlxBaseTilemap.hx +++ b/flixel/tile/FlxBaseTilemap.hx @@ -11,7 +11,6 @@ import flixel.util.FlxCollision; import flixel.util.FlxColor; import flixel.util.FlxDirectionFlags; import flixel.util.FlxStringUtil; -import openfl.Assets; import openfl.display.BitmapData; using StringTools; @@ -390,9 +389,9 @@ class FlxBaseTilemap extends FlxObject startingIndex = 0, drawIndex = 1, collideIndex = 1) { // path to map data file? - if (Assets.exists(mapData)) + if (FlxG.assets.exists(mapData)) { - mapData = Assets.getText(mapData); + mapData = FlxG.assets.getTextUnsafe(mapData); } // Figure out the map dimensions based on the data string diff --git a/flixel/util/FlxStringUtil.hx b/flixel/util/FlxStringUtil.hx index 13ef02ecf7..92bef9c222 100644 --- a/flixel/util/FlxStringUtil.hx +++ b/flixel/util/FlxStringUtil.hx @@ -568,7 +568,7 @@ class FlxStringUtil if ((ImageFile is String)) { - tempBitmapData = FlxAssets.getBitmapData(ImageFile); + tempBitmapData = FlxG.assets.getBitmapData(ImageFile); } else { From ed5300078914bf12705bd04e51b052d399bbefaa Mon Sep 17 00:00:00 2001 From: ACrazyTown <47027981+ACrazyTown@users.noreply.github.com> Date: Wed, 13 Nov 2024 18:46:49 +0100 Subject: [PATCH 59/99] Fix some documentation in AssetFrontEnd (#3283) * Fix some docs in AssetFrontEnd * more fixes --- flixel/system/frontEnds/AssetFrontEnd.hx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/flixel/system/frontEnds/AssetFrontEnd.hx b/flixel/system/frontEnds/AssetFrontEnd.hx index 00f1f68e5e..382d27762a 100644 --- a/flixel/system/frontEnds/AssetFrontEnd.hx +++ b/flixel/system/frontEnds/AssetFrontEnd.hx @@ -373,7 +373,7 @@ class AssetFrontEnd } /** - * Parses the contents of a xml-based asset into an `Xml` object. + * Parses the contents of an xml-based asset into an `Xml` object. * Unlike its "safe" counterpart, there is no log on missing assets * * **Note:** The default asset system does not cache xml assets @@ -388,7 +388,7 @@ class AssetFrontEnd } /** - * Parses the contents of a xml-based asset into an `Xml` object, logs when the asset is not found + * Parses the contents of an xml-based asset into an `Xml` object, logs when the asset is not found * * **Note:** The default asset system does not cache xml assets * @@ -403,7 +403,7 @@ class AssetFrontEnd } /** - * Gets the contents of a xml-based asset. + * Gets the contents of a json-based asset. * Unlike its "safe" counterpart, there is no log on missing assets * * **Note:** The default asset system does not cache json assets @@ -418,7 +418,7 @@ class AssetFrontEnd } /** - * Gets the contents of a xml-based asset, logs when the asset is not found + * Gets the contents of a json-based asset, logs when the asset is not found * * **Note:** The default asset system does not cache json assets * @@ -485,7 +485,7 @@ class AssetFrontEnd } /** - * Loads an bitmap asset asynchronously + * Loads a bitmap asset asynchronously * * @param id The ID or asset path for the asset * @param useCache Whether to allow use of the asset cache (if one exists) @@ -523,7 +523,7 @@ class AssetFrontEnd } /** - * Loads a text asset asynchronously + * Loads an xml asset asynchronously * * **Note:** The default asset system does not cache xml assets * @@ -537,7 +537,7 @@ class AssetFrontEnd } /** - * Loads a text asset asynchronously + * Loads a json asset asynchronously * * **Note:** The default asset system does not cache json assets * @@ -585,7 +585,7 @@ class AssetFrontEnd } /** - * Parses an xml string, creates and returns an Xml object + * Parses an xml string, creates and returns an `Xml` object */ public inline function parseXml(xmlText:String) { From e0e481ca9c147ddaf3c18dd0e560d0bfc038790b Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 18 Nov 2024 20:48:58 -0500 Subject: [PATCH 60/99] fix: 0 volume properly is muted with log volume --- flixel/system/frontEnds/SoundFrontEnd.hx | 32 +++++++++++++++--------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/flixel/system/frontEnds/SoundFrontEnd.hx b/flixel/system/frontEnds/SoundFrontEnd.hx index 7bdf47da04..cbc0e08c09 100644 --- a/flixel/system/frontEnds/SoundFrontEnd.hx +++ b/flixel/system/frontEnds/SoundFrontEnd.hx @@ -363,21 +363,29 @@ class SoundFrontEnd showSoundTray(Amount > 0); } - public function linearToLog(x:Float, minValue:Float = 0.001):Float { - // Ensure x is between 0 and 1 - x = Math.max(0, Math.min(1, x)); + public function linearToLog(x:Float, minValue:Float = 0.001):Float + { + // If linear volume is 0, return 0 + if (x <= 0) return 0; + + // Ensure x is between 0 and 1 + x = Math.min(1, x); + + // Convert linear scale to logarithmic + return Math.exp(Math.log(minValue) * (1 - x)); + } - // Convert linear scale to logarithmic - return Math.exp(Math.log(minValue) * (1 - x)); - } + public function logToLinear(x:Float, minValue:Float = 0.001):Float + { + // If logarithmic volume is 0, return 0 + if (x <= 0) return 0; - public function logToLinear(x:Float, minValue:Float = 0.001):Float { - // Ensure x is between minValue and 1 - x = Math.max(minValue, Math.min(1, x)); + // Ensure x is between minValue and 1 + x = Math.min(1, x); - // Convert logarithmic scale to linear - return 1 - (Math.log(x) / Math.log(minValue)); - } + // Convert logarithmic scale to linear + return 1 - (Math.log(Math.max(x, minValue)) / Math.log(minValue)); + } /** * Shows the sound tray if it is enabled. From 9bea6004e04ae6f2055304a6e31c6dcfcaea58d9 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sun, 24 Nov 2024 13:02:26 -0500 Subject: [PATCH 61/99] add lime and openfl to haxelib.json dependencies (#3289) --- haxelib.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/haxelib.json b/haxelib.json index a5ddb35510..a3d45e9f22 100644 --- a/haxelib.json +++ b/haxelib.json @@ -7,5 +7,8 @@ "version": "5.9.0", "releasenote": "TBD", "contributors": ["haxeflixel", "Gama11", "GeoKureli"], - "dependencies": {} + "dependencies": { + "lime": "", + "openfl": "" + } } From 72192767fc953d05c50dad8203d2720a6c7314b9 Mon Sep 17 00:00:00 2001 From: T5mpler <57325909+T5mpler@users.noreply.github.com> Date: Sun, 24 Nov 2024 17:12:46 -0500 Subject: [PATCH 62/99] Add "insert" function to the CameraFrontEnd like in FlxGroups (#3290) * Add insert function to CameraFrontEnd * What the Fuck * apply suggestions * D'oh! --------- Co-authored-by: George Kurelic --- flixel/system/frontEnds/CameraFrontEnd.hx | 36 +++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/flixel/system/frontEnds/CameraFrontEnd.hx b/flixel/system/frontEnds/CameraFrontEnd.hx index 82c026014b..3342a40d20 100644 --- a/flixel/system/frontEnds/CameraFrontEnd.hx +++ b/flixel/system/frontEnds/CameraFrontEnd.hx @@ -74,6 +74,42 @@ class CameraFrontEnd cameraAdded.dispatch(NewCamera); return NewCamera; } + + /** + * Inserts a new camera object to the game. + * + * - If `position` is negative, `list.length + position` is used + * - If `position` exceeds `list.length`, the camera is added to the end. + * + * @param newCamera The camera you want to add. + * @param position The position in the list where you want to insert the camera + * @param defaultDrawTarget Whether to add the camera to the list of default draw targets. If false, + * `FlxBasics` will not render to it unless you add it to their `cameras` list. + * @return This FlxCamera instance. + */ + public function insert(newCamera:T, position:Int, defaultDrawTarget = true):T + { + // negative numbers are relative to the length (match Array.insert's behavior) + if (position < 0) + position += list.length; + + // invalid ranges are added (match Array.insert's behavior) + if (position >= list.length) + return add(newCamera); + + final childIndex = FlxG.game.getChildIndex(list[position].flashSprite); + FlxG.game.addChildAt(newCamera.flashSprite, childIndex); + + list.insert(position, newCamera); + if (defaultDrawTarget) + defaults.push(newCamera); + + for (i in position...list.length) + list[i].ID = i; + + cameraAdded.dispatch(newCamera); + return newCamera; + } /** * Remove a camera from the game. From df19e4b619c736c5e8b95b7c02c2f6a47d731971 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Mon, 25 Nov 2024 10:13:15 -0500 Subject: [PATCH 63/99] FlxSave: Allow custom handling of parsing errors (#3286) * add new LOAD_ERROR state * add backupParser arg to bind * fix flash CI * don't set data on failures * fix typo * use backup parsed data rather than copying fields * doc * fix flash CI --- flixel/util/FlxSave.hx | 158 ++++++++++++++++++++++++++++++++--------- 1 file changed, 126 insertions(+), 32 deletions(-) diff --git a/flixel/util/FlxSave.hx b/flixel/util/FlxSave.hx index f2164833ac..629e9f3e2e 100644 --- a/flixel/util/FlxSave.hx +++ b/flixel/util/FlxSave.hx @@ -1,6 +1,7 @@ package flixel.util; import flixel.util.FlxDestroyUtil.IFlxDestroyable; +import haxe.Exception; import openfl.errors.Error; import openfl.net.SharedObject; import openfl.net.SharedObjectFlushStatus; @@ -98,6 +99,19 @@ class FlxSave implements IFlxDestroyable return newStr; } + /** + * The default class resolver of a FlxSave, handles certain Flixel and Openfl classes + */ + public static inline function resolveFlixelClasses(name:String) + { + #if flash + return Type.resolveClass(name); + #else + @:privateAccess + return SharedObject.__resolveClass(name); + #end + } + /** * Allows you to directly access the data container in the local shared object. */ @@ -146,15 +160,18 @@ class FlxSave implements IFlxDestroyable /** * Automatically creates or reconnects to locally saved data. * - * @param name The name of the save (should be the same each time to access old data). - * May not contain spaces or any of the following characters: - * `~ % & \ ; : " ' , < > ? #` - * @param path The full or partial path to the file that created the shared object. - * Mainly used to differentiate from other FlxSaves. If you do not specify - * this parameter, the company name specified in your Project.xml is used. + * @param name The name of the save (should be the same each time to access old data). + * May not contain spaces or any of the following characters: + * `~ % & \ ; : " ' , < > ? #` + * @param path The full or partial path to the file that created the shared object. + * Mainly used to differentiate from other FlxSaves. If you do not specify + * this parameter, the company name specified in your Project.xml is used. + * @param backupParser If there is an error parsing the raw save data, this will be called as + * a backup. if null is returned, the save will stay in an error state. + * **Note:** This arg is never used when targeting flash * @return Whether or not you successfully connected to the save data. */ - public function bind(name:String, ?path:String):Bool + public function bind(name:String, ?path:String, ?backupParser:(String, Exception)->Null):Bool { destroy(); @@ -164,8 +181,35 @@ class FlxSave implements IFlxDestroyable try { - _sharedObject = FlxSharedObject.getLocal(name, path); - status = BOUND(name, path); + switch FlxSharedObject.getLocal(name, path) + { + case SUCCESS(sharedObject): + _sharedObject = sharedObject; + data = _sharedObject.data; + status = BOUND(name, path); + return true; + #if !flash + case FAILURE(PARSING(rawData, exception), sharedObject) if (backupParser != null): + // Use the provided backup parser + final parsedData = backupParser(rawData, exception); + if (parsedData == null) + { + status = LOAD_ERROR(PARSING(rawData, exception)); + return false; + } + + _sharedObject = sharedObject; + data = parsedData; + @:privateAccess + sharedObject.data = parsedData; + status = BOUND(name, path); + return true; + #end + case FAILURE(type, sharedObject): + _sharedObject = sharedObject; + status = LOAD_ERROR(type); + return false; + } } catch (e:Error) { @@ -173,8 +217,6 @@ class FlxSave implements IFlxDestroyable destroy(); return false; } - data = _sharedObject.data; - return true; } /** @@ -275,12 +317,12 @@ class FlxSave implements IFlxDestroyable { status = ERROR("There was an problem flushing the save data."); } - + checkStatus(); - + return isBound; } - + /** * Erases everything stored in the local shared object. * Data is immediately erased and the object is saved that way, @@ -292,7 +334,7 @@ class FlxSave implements IFlxDestroyable { if (!checkStatus()) return false; - + _sharedObject.clear(); data = {}; return true; @@ -307,12 +349,22 @@ class FlxSave implements IFlxDestroyable { switch (status) { + case BOUND(name, path): + return true; case EMPTY: - FlxG.log.warn("You must call FlxSave.bind() before you can read or write data."); + FlxG.log.warn("You must call save.bind() before you can read or write data."); case ERROR(msg): FlxG.log.error(msg); - default: - return true; + case LOAD_ERROR(IO(e)): + FlxG.log.error('IO ERROR: ${e.message}'); + case LOAD_ERROR(INVALID_NAME(name, reason)): + FlxG.log.error('Invalid name:"$name", ${reason == null ? "" : reason}.'); + case LOAD_ERROR(INVALID_PATH(path, reason)): + FlxG.log.error('Invalid path:"$path", ${reason == null ? "" : reason}.'); + case LOAD_ERROR(PARSING(rawData, e)): + FlxG.log.error('Error parsing "$rawData", ${e.message}.'); + case found: + throw 'Unexpected status: $found'; } return false; } @@ -376,9 +428,18 @@ private class FlxSharedObject extends SharedObject { #if (flash || android || ios) /** Use SharedObject as usual */ - public static inline function getLocal(name:String, ?localPath:String):SharedObject + public static inline function getLocal(name:String, ?localPath:String):LoadResult { - return SharedObject.getLocal(name, localPath); + try + { + final obj = SharedObject.getLocal(name, localPath); + return SUCCESS(obj); + } + catch (e) + { + // We can't detect parsing or naming errors in flash, just use IO for everything + return FAILURE(IO(e)); + } } public static inline function exists(name:String, ?path:String) @@ -421,10 +482,10 @@ private class FlxSharedObject extends SharedObject return path; } - public static function getLocal(name:String, ?localPath:String):SharedObject + public static function getLocal(name:String, ?localPath:String):LoadResult { if (name == null || name == "") - throw new Error('Error: Invalid name:"$name".'); + return FAILURE(INVALID_NAME(name)); if (localPath == null) localPath = ""; @@ -437,14 +498,17 @@ private class FlxSharedObject extends SharedObject { var encodedData = null; + if (~/(?:^|\/)\.\.\//.match(localPath)) + return FAILURE(INVALID_PATH(localPath, "../ not allowed in localPath")); + try { - if (~/(?:^|\/)\.\.\//.match(localPath)) - throw new Error("../ not allowed in localPath"); - encodedData = getData(name, localPath); } - catch (e:Dynamic) {} + catch (e) + { + return FAILURE(IO(e)); + } if (localPath == "") localPath = getDefaultLocalPath(); @@ -459,17 +523,21 @@ private class FlxSharedObject extends SharedObject try { final unserializer = new haxe.Unserializer(encodedData); - final resolver = { resolveEnum: Type.resolveEnum, resolveClass: SharedObject.__resolveClass }; + final resolver = { resolveEnum: Type.resolveEnum, resolveClass: FlxSave.resolveFlixelClasses }; unserializer.setResolver(cast resolver); sharedObject.data = unserializer.unserialize(); } - catch (e:Dynamic) {} + catch (e) + { + all.set(id, sharedObject); + return FAILURE(PARSING(encodedData, e), sharedObject); + } } all.set(id, sharedObject); } - return all.get(id); + return SUCCESS(all.get(id)); } #if (js && html5) @@ -652,20 +720,46 @@ private class FlxSharedObject extends SharedObject #end } +enum LoadResult +{ + SUCCESS(obj:SharedObject); + FAILURE(type:LoadFailureType, ?obj:SharedObject); +} + +enum LoadFailureType +{ + /** Malformed name string */ + INVALID_NAME(name:String, ?message:String); + + /** Malformed path string */ + INVALID_PATH(path:String, ?message:String); + + /** An error while retrieving the data */ + IO(exception:Exception); + + /** An error while parsing the data */ + PARSING(rawData:String, exception:Exception); +} + enum FlxSaveStatus { /** * The initial state, call bind() in order to use. */ EMPTY; - + /** * The save is set up correctly. */ BOUND(name:String, ?path:String); - + /** - * There was an issue. + * There was an issue during `flush` */ ERROR(msg:String); + + /** + * There was an issue while loading + */ + LOAD_ERROR(type:LoadFailureType); } From 2cca263d06746f4ac87d9ac3e962c0934c1c46b2 Mon Sep 17 00:00:00 2001 From: George FunBook Date: Mon, 25 Nov 2024 10:32:58 -0600 Subject: [PATCH 64/99] Update Changelog --- CHANGELOG.md | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 174ce41eed..62b03bfe59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,9 +17,16 @@ - `FlxRect`: Add `clipTo` and fix `intersection` bug ([#3190](https://github.com/HaxeFlixel/flixel/pull/3190)) - `FlxPointer`: Add `getGamePosition`, `gameX/Y`, `getViewPosition`, and `viewX/Y`, to replace "screen" fields ([#3210](https://github.com/HaxeFlixel/flixel/pull/3210)) - `FlxAnimationController`: Add `onLoop`, `onFrameChange` and `onFinish`, to replace `callback` and `finishCallback` ([#3205](https://github.com/HaxeFlixel/flixel/pull/3205)) ([#3216](https://github.com/HaxeFlixel/flixel/pull/3216)) -- `FlxStrip`: Add support for blendmodes ([3213](https://github.com/HaxeFlixel/flixel/pull/3213)) -- `FlxTextBorderStyle`: Add SHADOW_XY, prevent border clipping ([3236](https://github.com/HaxeFlixel/flixel/pull/3236)) -- `LogStyle`: add `callback` to replace `callbackFunction` ([3239](https://github.com/HaxeFlixel/flixel/pull/3239)) +- `FlxStrip`: Add support for blendmodes ([#3213](https://github.com/HaxeFlixel/flixel/pull/3213)) +- `FlxTextBorderStyle`: Add SHADOW_XY, prevent border clipping ([#3236](https://github.com/HaxeFlixel/flixel/pull/3236)) +- `LogStyle`: Add `callback` to replace `callbackFunction` ([#3239](https://github.com/HaxeFlixel/flixel/pull/3239)) +- `FlxBar`: Add custom border sizes ([#3234](https://github.com/HaxeFlixel/flixel/pull/3234)) +- Gamepads: Add `acceptMode` and "mapped inputs" ([#3276](https://github.com/HaxeFlixel/flixel/pull/3276)) ([#3280](https://github.com/HaxeFlixel/flixel/pull/3280)) + - Add `ACCEPT` and `CANCEL` input IDs that conditionally map to either `A` or `B` depending on `FlxG.gamepads.acceptMode` + - Add `gamepad.getMappedInput` to get an anum value of every possible gamepad input from various devices, i.e. `PS4(PS4ID.X)` +- `FlxG.assets`: A way to overwrite and customize the way HaxeFlixel fetches or produces assets from ids ([#2982](https://github.com/HaxeFlixel/flixel/pull/2982)) +- `FlxG.cameras`: Add `insert` method ([#3290](https://github.com/HaxeFlixel/flixel/pull/3290)) +- `FlxSave`: Allow custom handling of parsing errors ([#3286](https://github.com/HaxeFlixel/flixel/pull/3286)) #### Changes and improvements: - `FlxKey`: Add `NONE` to `fromStringMap` and `toStringMap` ([#3119](https://github.com/HaxeFlixel/flixel/pull/3119)) @@ -51,6 +58,12 @@ - Debugging: Check alpha when point-selecting sprites ([#3184](https://github.com/HaxeFlixel/flixel/pull/3184)) - `FlxBitmapText`: Ignore border outline when computing field size ([#3193](https://github.com/HaxeFlixel/flixel/pull/3193)) - `FlxDebugger`: Improve console code completion ([#3222](https://github.com/HaxeFlixel/flixel/pull/3222)) +- `FlxGraphicsShader`: Optimize color math ([#3227](https://github.com/HaxeFlixel/flixel/pull/3227)) +- Improve android config on lime 8.2.0 ([#3253](https://github.com/HaxeFlixel/flixel/pull/3253)) +- Debug Watch: Resize the watch window when watchers are added or removed ([#3251](https://github.com/HaxeFlixel/flixel/pull/3251)) +- Reduce memory of Flixel's embedded assets via oxipng ([#3257](https://github.com/HaxeFlixel/flixel/pull/3257)) +- Debug Stats: Improve accuracy of "Total Memory" in OpenFL 9.4.0 ([#3266](https://github.com/HaxeFlixel/flixel/pull/3266)) +- `FlxGraphic`: Improve checks for max texture size ([#3279](https://github.com/HaxeFlixel/flixel/pull/3279)) #### Bugfixes: - `FlxFlickerTween`: Fix "Unsupported recursive type" error on hl ([#3170](https://github.com/HaxeFlixel/flixel/pull/3170)) @@ -60,6 +73,9 @@ - `FlxCamera`: Fix blending issue ([#3217](https://github.com/HaxeFlixel/flixel/pull/3217)) ([#3255](https://github.com/HaxeFlixel/flixel/pull/3255)) - `FlxStrip`: Fix `color` preventing other strips from drawing ([#3220](https://github.com/HaxeFlixel/flixel/pull/3220)) - `FlxButton`: Fix `label` position when moves is false ([#3232](https://github.com/HaxeFlixel/flixel/pull/3232)) +- Debug Console: Fix arrow keys ([#3247](https://github.com/HaxeFlixel/flixel/pull/3247)) +- `FlxGame`: Fix `ACTIVATE` and `DEACTIVATE` event dispatches ([#3260](https://github.com/HaxeFlixel/flixel/pull/3260)) +- `FlxAction`: Fix bug where multiple `check` calls wipe analog fields ([#3277](https://github.com/HaxeFlixel/flixel/pull/3277)) 5.8.0 (April 19, 2024) ------------------------------ From fb408f1a6bd437ad92a252f794b876bd277f5a8b Mon Sep 17 00:00:00 2001 From: ACrazyTown <47027981+ACrazyTown@users.noreply.github.com> Date: Thu, 28 Nov 2024 22:59:48 +0100 Subject: [PATCH 65/99] Check if maxTextureSize >0 rather than !=-1 (#3295) --- flixel/graphics/FlxGraphic.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flixel/graphics/FlxGraphic.hx b/flixel/graphics/FlxGraphic.hx index 35c40a3e2d..0414ea16b9 100644 --- a/flixel/graphics/FlxGraphic.hx +++ b/flixel/graphics/FlxGraphic.hx @@ -637,7 +637,7 @@ class FlxGraphic implements IFlxDestroyable #if FLX_OPENGL_AVAILABLE var max:Int = FlxG.bitmap.maxTextureSize; - if (max != -1) + if (max > 0) { if (width > max || height > max) FlxG.log.warn('Graphic dimensions (${width}x${height}) exceed the maximum allowed size (${max}x${max}), which may cause rendering issues.'); From bf753a1527f58edcd1330aa6c0617a6c775f9a9b Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Thu, 28 Nov 2024 22:06:36 -0500 Subject: [PATCH 66/99] fix custom asset path, add _abs (#3296) --- flixel/system/frontEnds/AssetFrontEnd.hx | 7 +++---- flixel/system/macros/FlxDefines.hx | 11 +++++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/flixel/system/frontEnds/AssetFrontEnd.hx b/flixel/system/frontEnds/AssetFrontEnd.hx index 382d27762a..4baa8d4d48 100644 --- a/flixel/system/frontEnds/AssetFrontEnd.hx +++ b/flixel/system/frontEnds/AssetFrontEnd.hx @@ -59,13 +59,12 @@ class AssetFrontEnd public function new () { final rawPath = '${haxe.macro.Compiler.getDefine("FLX_CUSTOM_ASSETS_DIRECTORY")}'; - // Remove final slash and accepts backslashes and removes redundancies - directory = Path.normalize(rawPath); + directory = '${haxe.macro.Compiler.getDefine("FLX_CUSTOM_ASSETS_DIRECTORY_ABS")}'; // Verify valid directory if (sys.FileSystem.exists(directory) == false) - throw 'Invalid value:"$directory" of FLX_CUSTOM_ASSETS_DIRECTORY, expecting relative or absolute path'; + throw 'Error finding custom asset directory:"$directory" from given path: $rawPath'; // remove final "/assets" since the id typically contains it - final split = sys.FileSystem.absolutePath(directory).split("/"); + final split = directory.split("/"); split.pop(); parentDirectory = split.join("/"); } diff --git a/flixel/system/macros/FlxDefines.hx b/flixel/system/macros/FlxDefines.hx index 882bb6aaf5..c019da71ca 100644 --- a/flixel/system/macros/FlxDefines.hx +++ b/flixel/system/macros/FlxDefines.hx @@ -1,9 +1,9 @@ package flixel.system.macros; +import haxe.io.Path; import haxe.macro.Compiler; import haxe.macro.Context; import haxe.macro.Expr.Position; -import haxe.io.Path; #if (flixel_addons >= "3.2.2") import flixel.addons.system.macros.FlxAddonDefines; #end @@ -98,6 +98,8 @@ private enum HelperDefines FLX_OPENGL_AVAILABLE; /** Defined to `1`(or `true`) if `FLX_CUSTOM_ASSETS_DIRECTORY` is not defined */ FLX_STANDARD_ASSETS_DIRECTORY; + /** The normalized, absolute path of `FLX_CUSTOM_ASSETS_DIRECTORY`, used internally */ + FLX_CUSTOM_ASSETS_DIRECTORY_ABS; } class FlxDefines @@ -283,12 +285,13 @@ class FlxDefines // Todo: check sys targets final rawDirectory = Path.normalize(definedValue(FLX_CUSTOM_ASSETS_DIRECTORY)); final directory = Path.normalize(rawDirectory); + final absPath = sys.FileSystem.absolutePath(directory); if (!sys.FileSystem.isDirectory(directory) || directory == "1") { - final absPath = sys.FileSystem.absolutePath(directory); abort('FLX_CUSTOM_ASSETS_DIRECTORY must be a path to a directory, got "$rawDirectory"' + '\nabsolute path: $absPath', (macro null).pos); } + define(FLX_CUSTOM_ASSETS_DIRECTORY_ABS, absPath); } } else // define boolean inversion @@ -330,9 +333,9 @@ class FlxDefines return Context.defined(Std.string(define)); } - static inline function define(define:Dynamic) + static inline function define(define:Dynamic, ?value:String) { - Compiler.define(Std.string(define)); + Compiler.define(Std.string(define), value); } static function abort(message:String, pos:Position) From f9b7aed0da2b177f1138ca98911720ec41ac026f Mon Sep 17 00:00:00 2001 From: ACrazyTown <47027981+ACrazyTown@users.noreply.github.com> Date: Sun, 1 Dec 2024 17:08:09 +0100 Subject: [PATCH 67/99] Stop dispatching onFocus when debugger is not visible (#3271) --- flixel/system/frontEnds/DebuggerFrontEnd.hx | 2 -- 1 file changed, 2 deletions(-) diff --git a/flixel/system/frontEnds/DebuggerFrontEnd.hx b/flixel/system/frontEnds/DebuggerFrontEnd.hx index 3eaf720b4b..a7be301d39 100644 --- a/flixel/system/frontEnds/DebuggerFrontEnd.hx +++ b/flixel/system/frontEnds/DebuggerFrontEnd.hx @@ -173,8 +173,6 @@ class DebuggerFrontEnd if (!Value) { FlxG.stage.focus = null; - // setting focus to null will trigger a focus lost event, let's undo that - FlxG.game.onFocus(null); #if FLX_MOUSE FlxG.mouse.enabled = true; From c0cccb4aed38a92605adb4c0aa63bf21d0bfe4e4 Mon Sep 17 00:00:00 2001 From: George FunBook Date: Sun, 1 Dec 2024 10:42:49 -0600 Subject: [PATCH 68/99] add #3271 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62b03bfe59..80ccff8b74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,7 @@ - Reduce memory of Flixel's embedded assets via oxipng ([#3257](https://github.com/HaxeFlixel/flixel/pull/3257)) - Debug Stats: Improve accuracy of "Total Memory" in OpenFL 9.4.0 ([#3266](https://github.com/HaxeFlixel/flixel/pull/3266)) - `FlxGraphic`: Improve checks for max texture size ([#3279](https://github.com/HaxeFlixel/flixel/pull/3279)) +- Debugging: Stop dispatching onFocus event when closing debugger ([#3271](https://github.com/HaxeFlixel/flixel/pull/3271)) #### Bugfixes: - `FlxFlickerTween`: Fix "Unsupported recursive type" error on hl ([#3170](https://github.com/HaxeFlixel/flixel/pull/3170)) From fedc20640be77524cb33c36e54a0ef7285b77046 Mon Sep 17 00:00:00 2001 From: DetectiveBaldi <86160807+DetectiveBaldi@users.noreply.github.com> Date: Sun, 1 Dec 2024 20:26:15 -0500 Subject: [PATCH 69/99] remove events to avoid crashes (#3299) --- flixel/input/FlxKeyManager.hx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/flixel/input/FlxKeyManager.hx b/flixel/input/FlxKeyManager.hx index 73ccc2aa34..75d4e06e03 100644 --- a/flixel/input/FlxKeyManager.hx +++ b/flixel/input/FlxKeyManager.hx @@ -228,6 +228,9 @@ class FlxKeyManager implements IFlxInputManager */ public function destroy():Void { + FlxG.stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); + FlxG.stage.removeEventListener(KeyboardEvent.KEY_UP, onKeyUp); + _keyListArray = null; _keyListMap = null; } From b14d1e5687a7a50063f710b0a88da9bc828982f4 Mon Sep 17 00:00:00 2001 From: ACrazyTown <47027981+ACrazyTown@users.noreply.github.com> Date: Mon, 2 Dec 2024 18:17:46 +0100 Subject: [PATCH 70/99] oops (#3300) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9e5703a478..829256482e 100644 --- a/README.md +++ b/README.md @@ -32,4 +32,4 @@ Thanks to being built on top of [Haxe](https://haxe.org/) and [OpenFL](http://ww HaxeFlixel has its roots in the original [ActionScript 3 version of Flixel](https://github.com/AdamAtomic/flixel), created by [Adam “Atomic” Saltsman](http://www.adamatomic.com/). It was started by [Alexander Hohlov](https://github.com/beeblerox) in 2011, initially as a straightforward Haxe port of the AS3 codebase and Richard Davey's [Flixel Power Tools](http://www.photonstorm.com/flixel-power-tools). -Thanks to the efforts of the [core team](https://github.com/orgs/HaxeFlixel/people) as well as [over 100 contributors](https://github.com/HaxeFlixel/flixel/graphs/contributors), today's version of HaxeFlixel far surpasses the capabilities of the original. Not only has the core engine seen many substantial improvements and new features, there is also a far richer ecosystem with additional libaries and [over 80 demo projects](https://github.com/HaxeFlixel/flixel-demos) to learn from. +Thanks to the efforts of the [core team](https://github.com/orgs/HaxeFlixel/people) as well as [over 100 contributors](https://github.com/HaxeFlixel/flixel/graphs/contributors), today's version of HaxeFlixel far surpasses the capabilities of the original. Not only has the core engine seen many substantial improvements and new features, there is also a far richer ecosystem with additional libraries and [over 80 demo projects](https://github.com/HaxeFlixel/flixel-demos) to learn from. From e9e90dff8825eff7ff313da07e3d77a2dd80a694 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Tue, 3 Dec 2024 11:21:53 -0600 Subject: [PATCH 71/99] FlxDirectoinFlags: add up, down, left and right fields (#3303) --- flixel/util/FlxDirectionFlags.hx | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/flixel/util/FlxDirectionFlags.hx b/flixel/util/FlxDirectionFlags.hx index dab579d34b..5b13ec4fc6 100644 --- a/flixel/util/FlxDirectionFlags.hx +++ b/flixel/util/FlxDirectionFlags.hx @@ -65,6 +65,23 @@ enum abstract FlxDirectionFlags(Int) from Int from FlxDirection to Int { return degrees * FlxAngle.TO_RAD; } + + /** Whether this has the `UP` flag **/ + public var up(get, never):Bool; + inline function get_up() return has(UP); + + /** Whether this has the `DOWN` flag **/ + public var down(get, never):Bool; + inline function get_down() return has(DOWN); + + /** Whether this has the `LEFT` flag **/ + public var left(get, never):Bool; + inline function get_left() return has(LEFT); + + /** Whether this has the `RIGHT` flag **/ + public var right(get, never):Bool; + inline function get_right() return has(RIGHT); + /** * Returns true if this contains **all** of the supplied flags. From b247edbfd871e3104718f95d25c5af0eff41bd56 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Fri, 6 Dec 2024 21:58:39 -0600 Subject: [PATCH 72/99] fix list (#3306) --- flixel/system/frontEnds/AssetFrontEnd.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flixel/system/frontEnds/AssetFrontEnd.hx b/flixel/system/frontEnds/AssetFrontEnd.hx index 4baa8d4d48..d233683759 100644 --- a/flixel/system/frontEnds/AssetFrontEnd.hx +++ b/flixel/system/frontEnds/AssetFrontEnd.hx @@ -283,7 +283,7 @@ class AssetFrontEnd for (path in sys.FileSystem.readDirectory(directory)) { if (sys.FileSystem.isDirectory('$directory/$path')) - addFiles('$directory/$path',path + '/'); + addFiles('$directory/$path', prefix + path + '/'); else list.push(prefix + path); } From 2f1e4466f0a17e7a6ab8846c8fc6394a016dacf5 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Mon, 9 Dec 2024 12:40:29 -0600 Subject: [PATCH 73/99] replace callback with onLog (#3307) * replace callback with onLog * update changelog --- CHANGELOG.md | 2 +- flixel/system/debug/log/LogStyle.hx | 9 +++++++-- flixel/system/frontEnds/LogFrontEnd.hx | 14 ++++++-------- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80ccff8b74..62b840a504 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,7 @@ - `FlxAnimationController`: Add `onLoop`, `onFrameChange` and `onFinish`, to replace `callback` and `finishCallback` ([#3205](https://github.com/HaxeFlixel/flixel/pull/3205)) ([#3216](https://github.com/HaxeFlixel/flixel/pull/3216)) - `FlxStrip`: Add support for blendmodes ([#3213](https://github.com/HaxeFlixel/flixel/pull/3213)) - `FlxTextBorderStyle`: Add SHADOW_XY, prevent border clipping ([#3236](https://github.com/HaxeFlixel/flixel/pull/3236)) -- `LogStyle`: Add `callback` to replace `callbackFunction` ([#3239](https://github.com/HaxeFlixel/flixel/pull/3239)) +- `LogStyle`: Add `onLog` signal to replace `callbackFunction` ([#3239](https://github.com/HaxeFlixel/flixel/pull/3239))([#3307](https://github.com/HaxeFlixel/flixel/pull/3307)) - `FlxBar`: Add custom border sizes ([#3234](https://github.com/HaxeFlixel/flixel/pull/3234)) - Gamepads: Add `acceptMode` and "mapped inputs" ([#3276](https://github.com/HaxeFlixel/flixel/pull/3276)) ([#3280](https://github.com/HaxeFlixel/flixel/pull/3280)) - Add `ACCEPT` and `CANCEL` input IDs that conditionally map to either `A` or `B` depending on `FlxG.gamepads.acceptMode` diff --git a/flixel/system/debug/log/LogStyle.hx b/flixel/system/debug/log/LogStyle.hx index b3c2671e31..cf0bee3829 100644 --- a/flixel/system/debug/log/LogStyle.hx +++ b/flixel/system/debug/log/LogStyle.hx @@ -1,5 +1,7 @@ package flixel.system.debug.log; +import flixel.util.FlxSignal; + using flixel.util.FlxStringUtil; /** @@ -43,8 +45,10 @@ class LogStyle /** * A callback function that is called when this LogStyle is used + * **Note:** Unlike the deprecated `callbackFunction`, this is called every time, + * even when logged with `once = true` and even in release mode. */ - public var callback:(data:Any)->Void; + public final onLog = new FlxTypedSignal<(data:Any)->Void>(); /** * Whether an exception is thrown when this LogStyle is used. @@ -81,7 +85,8 @@ class LogStyle this.errorSound = errorSound; this.openConsole = openConsole; this.callbackFunction = callbackFunction; - this.callback = callback; + if (callback != null) + onLog.add(callback); this.throwException = throwException; } diff --git a/flixel/system/frontEnds/LogFrontEnd.hx b/flixel/system/frontEnds/LogFrontEnd.hx index a93f27df74..ab74996886 100644 --- a/flixel/system/frontEnds/LogFrontEnd.hx +++ b/flixel/system/frontEnds/LogFrontEnd.hx @@ -50,16 +50,15 @@ class LogFrontEnd if (style == null) style = LogStyle.NORMAL; - if (!(data is Array)) - data = [data]; + final arrayData = (!(data is Array) ? [data] : cast data); #if FLX_DEBUG // Check null game since `FlxG.save.bind` may be called before `new FlxGame` if (FlxG.game == null || FlxG.game.debugger == null) { - _standardTraceFunction(data); + _standardTraceFunction(arrayData); } - else if (FlxG.game.debugger.log.add(data, style, fireOnce)) + else if (FlxG.game.debugger.log.add(arrayData, style, fireOnce)) { #if (FLX_SOUND_SYSTEM && !FLX_UNIT_TEST) if (style.errorSound != null) @@ -75,14 +74,13 @@ class LogFrontEnd if (style.callbackFunction != null) style.callbackFunction(); - - if (style.callback != null) - style.callback(data); } #end + style.onLog.dispatch(data); + if (style.throwException) - throw style.toLogString(data); + throw style.toLogString(arrayData); } /** From 34655345c0dd05353aee3d610d90a5b4cecae239 Mon Sep 17 00:00:00 2001 From: George FunBook Date: Tue, 10 Dec 2024 11:33:58 -0600 Subject: [PATCH 74/99] fix deprecation typo --- flixel/FlxCamera.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flixel/FlxCamera.hx b/flixel/FlxCamera.hx index be352e355d..6a29052544 100644 --- a/flixel/FlxCamera.hx +++ b/flixel/FlxCamera.hx @@ -1906,11 +1906,11 @@ class FlxCamera extends FlxBasic * and `viewHeight`. * * Notes: Deprecated, in 4.11.0 this was made public, but the wording is confusing. - * In flixel 6.0.0 this will be changed to use `viewX`, `viewY`, `viewWidth` and `viewHeight`, + * After flixel 6.0.0 this will be changed to use `viewX`, `viewY`, `viewWidth` and `viewHeight`, * meaning, this will return the world coordinates of the camera. * @since 4.11.0 */ - @deprecated("getViewMarginRect") + @:deprecated("getViewRect is deprecated, use getViewMarginRect") public function getViewRect(?rect:FlxRect) { if (rect == null) From 9294856b03848fa5b22f16093c0849de76811ec4 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Wed, 11 Dec 2024 10:02:32 -0600 Subject: [PATCH 75/99] add getSoundAddExt (#3311) --- flixel/system/frontEnds/AssetFrontEnd.hx | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/flixel/system/frontEnds/AssetFrontEnd.hx b/flixel/system/frontEnds/AssetFrontEnd.hx index d233683759..6c2d7cf3a9 100644 --- a/flixel/system/frontEnds/AssetFrontEnd.hx +++ b/flixel/system/frontEnds/AssetFrontEnd.hx @@ -343,6 +343,22 @@ class AssetFrontEnd return cast getAsset(id, SOUND, useCache, logStyle); } + /** + * Gets an instance of a sound, logs when the asset is not found + * + * @param id The ID or asset path for the sound + * @param useCache Whether to allow use of the asset cache (if one exists) + * @param logStyle How to log, if the asset is not found. Uses `LogStyle.ERROR` by default + * @return A new `Sound` object Note: Dos not return a `FlxSound` + */ + public inline function getSoundAddExt(id:String, useCache = true, ?logStyle:LogStyle):Sound + { + if (!id.endsWith(".mp3") && !id.endsWith(".ogg") && !id.endsWith(".wav")) + id += "." + #if flash "mp3" #else "ogg" #end; + + return getSound(id, useCache, logStyle); + } + /** * Gets the contents of a text-based asset. Unlike its "safe" counterpart, there is no log * on missing assets From cc8125716154662d7758abfb59c836580c9ea077 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Wed, 11 Dec 2024 10:05:12 -0600 Subject: [PATCH 76/99] use haxe 4.3.6 --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a51eda1410..82a56f8acf 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -12,7 +12,7 @@ jobs: build: strategy: matrix: - haxe-version: ["4.2.5", "4.3.4"] + haxe-version: ["4.2.5", "4.3.6"] target: [html5, hl, neko, flash, cpp] fail-fast: false runs-on: ubuntu-latest From 0fad3b04cf7e25f733d4eb2538cd63e6396b89ef Mon Sep 17 00:00:00 2001 From: LeonGamerPS4 <108237023+LeonGamerPS1@users.noreply.github.com> Date: Wed, 11 Dec 2024 19:18:44 +0100 Subject: [PATCH 77/99] Removed @param descriptions for non existent Arguments L115 (a little bit of outdated info remoced) (#3312) * Removed @param descriptions for non existent Arguments L115 * remove doc tabs, lowercase arg names --------- Co-authored-by: George Kurelic --- flixel/system/frontEnds/BitmapFrontEnd.hx | 24 ++++++++++------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/flixel/system/frontEnds/BitmapFrontEnd.hx b/flixel/system/frontEnds/BitmapFrontEnd.hx index 4076756083..fd6e85660a 100644 --- a/flixel/system/frontEnds/BitmapFrontEnd.hx +++ b/flixel/system/frontEnds/BitmapFrontEnd.hx @@ -139,28 +139,24 @@ class BitmapFrontEnd /** * Loads a bitmap from a file, clones it if necessary and caches it. - * @param Graphic Optional FlxGraphics object to create FlxGraphic from. - * @param Frames Optional FlxFramesCollection object to create FlxGraphic from. - * @param Bitmap Optional BitmapData object to create FlxGraphic from. - * @param BitmapClass Optional Class for BitmapData to create FlxGraphic from. - * @param Str Optional String key to use for FlxGraphic instantiation. - * @param Unique Ensures that the bitmap data uses a new slot in the cache. - * @param Key Force the cache to use a specific Key to index the bitmap. - * @return The FlxGraphic we just created. + * @param graphic Optional FlxGraphics object to create FlxGraphic from. + * @param unique Ensures that the bitmap data uses a new slot in the cache. + * @param key Force the cache to use a specific Key to index the bitmap. + * @return The FlxGraphic we just created. */ - public function add(Graphic:FlxGraphicAsset, Unique:Bool = false, ?Key:String):FlxGraphic + public function add(graphic:FlxGraphicAsset, unique = false, ?key:String):FlxGraphic { - if ((Graphic is FlxGraphic)) + if ((graphic is FlxGraphic)) { - return FlxGraphic.fromGraphic(cast Graphic, Unique, Key); + return FlxGraphic.fromGraphic(cast graphic, unique, key); } - else if ((Graphic is BitmapData)) + else if ((graphic is BitmapData)) { - return FlxGraphic.fromBitmapData(cast Graphic, Unique, Key); + return FlxGraphic.fromBitmapData(cast graphic, unique, key); } // String case - return FlxGraphic.fromAssetKey(Std.string(Graphic), Unique, Key); + return FlxGraphic.fromAssetKey(Std.string(graphic), unique, key); } /** From e4a994d23312b4a5a595c476115ea9c3a4b2355b Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Thu, 12 Dec 2024 07:09:22 -0600 Subject: [PATCH 78/99] Automatically append file extension to sound asset ids (#3314) * auto add sound extensions * allow FLX_SOUND_ADD_EXT to specify the extension * doc * d'oh * D'oh! * allow any file extension * rename to FLX_DEFAULT_SOUND_EXT --- flixel/sound/FlxSound.hx | 2 ++ flixel/system/frontEnds/AssetFrontEnd.hx | 44 +++++++++++++++++++++--- flixel/system/frontEnds/SoundFrontEnd.hx | 6 ++++ flixel/system/macros/FlxDefines.hx | 8 +++++ tests/coverage/Project.xml | 2 ++ 5 files changed, 57 insertions(+), 5 deletions(-) diff --git a/flixel/sound/FlxSound.hx b/flixel/sound/FlxSound.hx index e087968790..ff7f3e8213 100644 --- a/flixel/sound/FlxSound.hx +++ b/flixel/sound/FlxSound.hx @@ -337,6 +337,8 @@ class FlxSound extends FlxBasic /** * One of the main setup functions for sounds, this function loads a sound from an embedded MP3. * + * **Note:** If the `FLX_SOUND_ADD_EXT` flag is enabled, you may omit the file extension + * * @param EmbeddedSound An embedded Class object representing an MP3 file. * @param Looped Whether or not this sound should loop endlessly. * @param AutoDestroy Whether or not this FlxSound instance should be destroyed when the sound finishes playing. diff --git a/flixel/system/frontEnds/AssetFrontEnd.hx b/flixel/system/frontEnds/AssetFrontEnd.hx index 6c2d7cf3a9..a6eea14cc2 100644 --- a/flixel/system/frontEnds/AssetFrontEnd.hx +++ b/flixel/system/frontEnds/AssetFrontEnd.hx @@ -85,6 +85,12 @@ class AssetFrontEnd public function new () {} #end + #if (FLX_DEFAULT_SOUND_EXT == "1" || FLX_NO_DEFAULT_SOUND_EXT) + public final defaultSoundExtension:String = #if flash ".mp3" #else ".ogg" #end; + #else + public final defaultSoundExtension:String = '.${haxe.macro.Compiler.getDefine("FLX_DEFAULT_SOUND_EXT")}'; + #end + /** * Used by methods like `getAsset`, `getBitmapData`, `getText`, their "unsafe" counterparts and * the like to get assets synchronously. Can be set to a custom function to avoid the existing @@ -231,6 +237,12 @@ class AssetFrontEnd */ public dynamic function exists(id:String, ?type:FlxAssetType) { + #if FLX_DEFAULT_SOUND_EXT + // add file extension + if (type == SOUND) + id = addSoundExt(id); + #end + #if FLX_STANDARD_ASSETS_DIRECTORY return Assets.exists(id, type.toOpenFlType()); #else @@ -253,6 +265,12 @@ class AssetFrontEnd */ public dynamic function isLocal(id:String, ?type:FlxAssetType, useCache = true) { + #if FLX_DEFAULT_SOUND_EXT + // add file extension + if (type == SOUND) + id = addSoundExt(id); + #end + #if FLX_STANDARD_ASSETS_DIRECTORY return Assets.isLocal(id, type.toOpenFlType(), useCache); #else @@ -327,11 +345,13 @@ class AssetFrontEnd */ public inline function getSoundUnsafe(id:String, useCache = true):Sound { - return cast getAssetUnsafe(id, SOUND, useCache); + return cast getAssetUnsafe(addSoundExtIf(id), SOUND, useCache); } /** - * Gets an instance of a sound, logs when the asset is not found + * Gets an instance of a sound, logs when the asset is not found. + * + * **Note:** If the `FLX_DEFAULT_SOUND_EXT` flag is enabled, you may omit the file extension * * @param id The ID or asset path for the sound * @param useCache Whether to allow use of the asset cache (if one exists) @@ -340,7 +360,7 @@ class AssetFrontEnd */ public inline function getSound(id:String, useCache = true, ?logStyle:LogStyle):Sound { - return cast getAsset(id, SOUND, useCache, logStyle); + return cast getAsset(addSoundExtIf(id), SOUND, useCache, logStyle); } /** @@ -352,11 +372,25 @@ class AssetFrontEnd * @return A new `Sound` object Note: Dos not return a `FlxSound` */ public inline function getSoundAddExt(id:String, useCache = true, ?logStyle:LogStyle):Sound + { + return getSound(addSoundExt(id), useCache, logStyle); + } + + inline function addSoundExtIf(id:String) + { + #if FLX_DEFAULT_SOUND_EXT + return addSoundExt(id); + #else + return id; + #end + } + + inline function addSoundExt(id:String) { if (!id.endsWith(".mp3") && !id.endsWith(".ogg") && !id.endsWith(".wav")) - id += "." + #if flash "mp3" #else "ogg" #end; + return id + defaultSoundExtension; - return getSound(id, useCache, logStyle); + return id; } /** diff --git a/flixel/system/frontEnds/SoundFrontEnd.hx b/flixel/system/frontEnds/SoundFrontEnd.hx index 3a40e9ddc5..4ecae68745 100644 --- a/flixel/system/frontEnds/SoundFrontEnd.hx +++ b/flixel/system/frontEnds/SoundFrontEnd.hx @@ -103,6 +103,8 @@ class SoundFrontEnd /** * Set up and play a looping background soundtrack. * + * **Note:** If the `FLX_SOUND_ADD_EXT` flag is enabled, you may omit the file extension + * * @param embeddedMusic The sound file you want to loop in the background. * @param volume How loud the sound should be, from 0 to 1. * @param looped Whether to loop this music. @@ -132,6 +134,8 @@ class SoundFrontEnd /** * Creates a new FlxSound object. * + * **Note:** If the `FLX_SOUND_ADD_EXT` flag is enabled, you may omit the file extension + * * @param embeddedSound The embedded sound resource you want to play. To stream, use the optional URL parameter instead. * @param volume How loud to play it (0 to 1). * @param looped Whether to loop this sound. @@ -230,6 +234,8 @@ class SoundFrontEnd /** * Plays a sound from an embedded sound. Tries to recycle a cached sound first. * + * **Note:** If the `FLX_SOUND_ADD_EXT` flag is enabled, you may omit the file extension + * * @param embeddedSound The embedded sound resource you want to play. * @param volume How loud to play it (0 to 1). * @param looped Whether to loop this sound. diff --git a/flixel/system/macros/FlxDefines.hx b/flixel/system/macros/FlxDefines.hx index c019da71ca..4bf4815839 100644 --- a/flixel/system/macros/FlxDefines.hx +++ b/flixel/system/macros/FlxDefines.hx @@ -52,6 +52,12 @@ private enum UserDefines * any `` tags in your project.xml, to reduce your total memory */ FLX_CUSTOM_ASSETS_DIRECTORY; + /** + * Allows you to use sound paths with no extension, and the default sound type for that + * target will be used. If enabled it will use ogg on all targets except flash, which uses mp3. + * If this flag is set to any string, that is used for the file extension + */ + FLX_DEFAULT_SOUND_EXT; } /** @@ -100,6 +106,7 @@ private enum HelperDefines FLX_STANDARD_ASSETS_DIRECTORY; /** The normalized, absolute path of `FLX_CUSTOM_ASSETS_DIRECTORY`, used internally */ FLX_CUSTOM_ASSETS_DIRECTORY_ABS; + FLX_NO_DEFAULT_SOUND_EXT; } class FlxDefines @@ -200,6 +207,7 @@ class FlxDefines defineInversion(FLX_SWF_VERSION_TEST, FLX_NO_SWF_VERSION_TEST); defineInversion(FLX_NO_HEALTH, FLX_HEALTH); defineInversion(FLX_TRACK_POOLS, FLX_NO_TRACK_POOLS); + defineInversion(FLX_DEFAULT_SOUND_EXT, FLX_NO_DEFAULT_SOUND_EXT); // defineInversion(FLX_TRACK_GRAPHICS, FLX_NO_TRACK_GRAPHICS); // special case } diff --git a/tests/coverage/Project.xml b/tests/coverage/Project.xml index e53cc93d2e..46a00af3da 100644 --- a/tests/coverage/Project.xml +++ b/tests/coverage/Project.xml @@ -54,6 +54,7 @@ +
@@ -77,5 +78,6 @@ +
From 2927eadfb063dd49625d270d2b23f9804135f78a Mon Sep 17 00:00:00 2001 From: George FunBook Date: Thu, 12 Dec 2024 07:34:15 -0600 Subject: [PATCH 79/99] update changelog --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62b840a504..7a34c6c7b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,9 @@ - `FlxG.assets`: A way to overwrite and customize the way HaxeFlixel fetches or produces assets from ids ([#2982](https://github.com/HaxeFlixel/flixel/pull/2982)) - `FlxG.cameras`: Add `insert` method ([#3290](https://github.com/HaxeFlixel/flixel/pull/3290)) - `FlxSave`: Allow custom handling of parsing errors ([#3286](https://github.com/HaxeFlixel/flixel/pull/3286)) +- `FlxDirectionFlags`: Add `up`, `down`, `left` and `right` fields ([#3303](https://github.com/HaxeFlixel/flixel/pull/3303)) +- `FlxG.assets`: Add `getSoundAddExt` ([#3311](https://github.com/HaxeFlixel/flixel/pull/3311)) +- `FlxG.assets`: Add `-DFLX_DEFAULT_SOUND_EXT` to automatically append file extension to sound asset ids ([#3314](https://github.com/HaxeFlixel/flixel/pull/3314)) #### Changes and improvements: - `FlxKey`: Add `NONE` to `fromStringMap` and `toStringMap` ([#3119](https://github.com/HaxeFlixel/flixel/pull/3119)) @@ -63,7 +66,7 @@ - Debug Watch: Resize the watch window when watchers are added or removed ([#3251](https://github.com/HaxeFlixel/flixel/pull/3251)) - Reduce memory of Flixel's embedded assets via oxipng ([#3257](https://github.com/HaxeFlixel/flixel/pull/3257)) - Debug Stats: Improve accuracy of "Total Memory" in OpenFL 9.4.0 ([#3266](https://github.com/HaxeFlixel/flixel/pull/3266)) -- `FlxGraphic`: Improve checks for max texture size ([#3279](https://github.com/HaxeFlixel/flixel/pull/3279)) +- `FlxGraphic`: Improve checks for max texture size ([#3279](https://github.com/HaxeFlixel/flixel/pull/3279))([#3295](https://github.com/HaxeFlixel/flixel/pull/3295)) - Debugging: Stop dispatching onFocus event when closing debugger ([#3271](https://github.com/HaxeFlixel/flixel/pull/3271)) #### Bugfixes: @@ -77,6 +80,7 @@ - Debug Console: Fix arrow keys ([#3247](https://github.com/HaxeFlixel/flixel/pull/3247)) - `FlxGame`: Fix `ACTIVATE` and `DEACTIVATE` event dispatches ([#3260](https://github.com/HaxeFlixel/flixel/pull/3260)) - `FlxAction`: Fix bug where multiple `check` calls wipe analog fields ([#3277](https://github.com/HaxeFlixel/flixel/pull/3277)) +- `FlxKeyManager`: Remove events on destroy, preventing crashes ([#3299](https://github.com/HaxeFlixel/flixel/pull/3299)) 5.8.0 (April 19, 2024) ------------------------------ From 34343d172fea9ccb2422804e1c3592cc7e8a72d0 Mon Sep 17 00:00:00 2001 From: George FunBook Date: Thu, 12 Dec 2024 07:36:12 -0600 Subject: [PATCH 80/99] add date --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a34c6c7b5..3f5e3369fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -5.9.0 (TBD) +5.9.0 (December 12, 2024) ------------------------------ #### New features: - `FlxInputText`: Add improved input text to core flixel (flixel-ui's implementation will be deprecated) ([#3219](https://github.com/HaxeFlixel/flixel/pull/3219)) From 5c816d3c1ea2c565a9c89a79ee02c1548e135af1 Mon Sep 17 00:00:00 2001 From: George FunBook Date: Thu, 12 Dec 2024 09:41:20 -0600 Subject: [PATCH 81/99] add release notes --- haxelib.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/haxelib.json b/haxelib.json index a3d45e9f22..fb21ebebe9 100644 --- a/haxelib.json +++ b/haxelib.json @@ -5,7 +5,7 @@ "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.9.0", - "releasenote": "TBD", + "releasenote": "Added FlxInputText, FlxG.assets, FlxBasePath and more", "contributors": ["haxeflixel", "Gama11", "GeoKureli"], "dependencies": { "lime": "", From 58b4381a51d4f4b86e271f036b8fdf76a463b0de Mon Sep 17 00:00:00 2001 From: glintfish <85320064+glintfishGH@users.noreply.github.com> Date: Thu, 12 Dec 2024 23:38:33 +0100 Subject: [PATCH 82/99] Update outdated documentation for BitmapFrontEnd. (#3313) * Update documentation for BitmapFrontEnd - Changed arguments to start with a lowercase letter. - Fixed documentation ported over from flash(?), where the documented @:params would not align to function arguments. * Update flixel/system/frontEnds/BitmapFrontEnd.hx Co-authored-by: George Kurelic * Update flixel/system/frontEnds/BitmapFrontEnd.hx Co-authored-by: George Kurelic * Update flixel/system/frontEnds/BitmapFrontEnd.hx Co-authored-by: George Kurelic * Update flixel/system/frontEnds/BitmapFrontEnd.hx Co-authored-by: George Kurelic * Update flixel/system/frontEnds/BitmapFrontEnd.hx Co-authored-by: George Kurelic * Update flixel/system/frontEnds/BitmapFrontEnd.hx Co-authored-by: George Kurelic * Make docs follow the "rules" of documentation Co-authored-by: George Kurelic * Fix a @return doc having 3 spaces instead of 2 * More doc formatting changes --------- Co-authored-by: George Kurelic --- flixel/system/frontEnds/BitmapFrontEnd.hx | 81 ++++++++++++----------- 1 file changed, 41 insertions(+), 40 deletions(-) diff --git a/flixel/system/frontEnds/BitmapFrontEnd.hx b/flixel/system/frontEnds/BitmapFrontEnd.hx index fd6e85660a..f81c4957f3 100644 --- a/flixel/system/frontEnds/BitmapFrontEnd.hx +++ b/flixel/system/frontEnds/BitmapFrontEnd.hx @@ -1,6 +1,5 @@ package flixel.system.frontEnds; -import openfl.display.BitmapData; import flixel.graphics.FlxGraphic; import flixel.graphics.frames.FlxFrame; import flixel.math.FlxPoint; @@ -8,6 +7,7 @@ import flixel.math.FlxRect; import flixel.system.FlxAssets; import flixel.util.FlxColor; import openfl.Assets; +import openfl.display.BitmapData; #if FLX_OPENGL_AVAILABLE import lime.graphics.opengl.GL; #end @@ -114,27 +114,27 @@ class BitmapFrontEnd /** * Check the local bitmap cache to see if a bitmap with this key has been loaded already. * - * @param Key The string key identifying the bitmap. - * @return Whether or not this file can be found in the cache. + * @param key The key identifying the bitmap. + * @return Whether or not this file can be found in the cache. */ - public inline function checkCache(Key:String):Bool + public inline function checkCache(key:String):Bool { - return get(Key) != null; + return get(key) != null; } /** - * Generates a new BitmapData object (a colored rectangle) and caches it. + * Creates a new graphic of a colored rectangle and caches it. * - * @param Width How wide the rectangle should be. - * @param Height How high the rectangle should be. - * @param Color What color the rectangle should be (0xAARRGGBB) - * @param Unique Ensures that the bitmap data uses a new slot in the cache. - * @param Key Force the cache to use a specific Key to index the bitmap. - * @return The BitmapData we just created. + * @param width How wide the rectangle should be. + * @param height How high the rectangle should be. + * @param color What color the rectangle should be (0xAARRGGBB). + * @param unique Ensures that the bitmap data uses a new slot in the cache. + * @param key Force the cache to use a specific Key to index the bitmap. + * @return The created graphic. */ - public function create(Width:Int, Height:Int, Color:FlxColor, Unique:Bool = false, ?Key:String):FlxGraphic + public function create(width:Int, height:Int, color:FlxColor, unique = false, ?key:String):FlxGraphic { - return FlxGraphic.fromRectangle(Width, Height, Color, Unique, Key); + return FlxGraphic.fromRectangle(width, height, color, unique, key); } /** @@ -160,10 +160,10 @@ class BitmapFrontEnd } /** - * Caches specified FlxGraphic object. + * Caches the specified graphic. * - * @param graphic FlxGraphic to store in the cache. - * @return cached FlxGraphic object. + * @param graphic The graphic to cache. + * @return The cached graphic. */ public inline function addGraphic(graphic:FlxGraphic):FlxGraphic { @@ -172,9 +172,10 @@ class BitmapFrontEnd } /** - * Gets FlxGraphic object from this storage by specified key. - * @param key Key for FlxGraphic object (its name) - * @return FlxGraphic with the key name, or null if there is no such object + * Gets an FlxGraphic object from this storage from its key. + * + * @param key The FlxGraphics key (or name). + * @return The FlxGraphic with the specified key, or null if the object doesn't exist. */ public inline function get(key:String):FlxGraphic { @@ -182,10 +183,10 @@ class BitmapFrontEnd } /** - * Gets key from bitmap cache for specified BitmapData + * Gets a key from a cached BitmapData. * - * @param bmd BitmapData to find in cache - * @return BitmapData's key or null if there isn't such BitmapData in cache + * @param bmd BitmapData to find in the cache. + * @return The BitmapData's key or null if there isn't such BitmapData in cache. */ public function findKeyForBitmap(bmd:BitmapData):String { @@ -201,8 +202,8 @@ class BitmapFrontEnd /** * Helper method for getting cache key for FlxGraphic objects created from the class. * - * @param source BitmapData source class. - * @return Full name for provided class. + * @param source BitmapData source class. + * @return Full name for provided class. */ public inline function getKeyForClass(source:Class):String { @@ -212,12 +213,12 @@ class BitmapFrontEnd /** * Creates string key for further caching. * - * @param systemKey The first string key to use as a base for a new key. It's usually an asset key ("assets/image.png"). - * @param userKey The second string key to use as a base for a new key. It's usually a key provided by the user - * @param unique Whether generated key should be unique or not. - * @return Created key. + * @param systemKey The first string key to use as a base for a new key. It's usually an asset key ("assets/image.png"). + * @param userKey The second string key to use as a base for a new key. It's usually a key provided by the user + * @param unique Whether generated key should be unique or not. + * @return Created key. */ - public function generateKey(systemKey:String, userKey:String, unique:Bool = false):String + public function generateKey(systemKey:String, userKey:String, unique = false):String { var key:String = userKey; if (key == null) @@ -230,10 +231,10 @@ class BitmapFrontEnd } /** - * Gets unique key for bitmap cache + * Gets unique key for bitmap cache. * - * @param baseKey key's prefix - * @return unique key + * @param baseKey key's prefix. + * @return unique key. */ public function getUniqueKey(?baseKey:String):String { @@ -260,11 +261,11 @@ class BitmapFrontEnd * Generates key from provided base key and information about tile size and offsets in spritesheet * and the region of image to use as spritesheet graphics source. * - * @param baseKey Beginning of the key. Usually it is the key for original spritesheet graphics (like "assets/tile.png") - * @param frameSize the size of tile in spritesheet - * @param frameSpacing offsets between tiles in offsets - * @param region region of image to use as spritesheet graphics source - * @return Generated key for spritesheet with inserted spaces between tiles + * @param baseKey Beginning of the key. Usually it is the key for original spritesheet graphics (like "assets/tile.png"). + * @param frameSize The size of tile in spritesheet. + * @param frameSpacing Offsets between tiles in offsets. + * @param region Region of image to use as spritesheet graphics source. + * @return Generated key for spritesheet with inserted spaces between tiles. */ public function getKeyWithSpacesAndBorders(baseKey:String, ?frameSize:FlxPoint, ?frameSpacing:FlxPoint, ?frameBorder:FlxPoint, ?region:FlxRect):String { @@ -287,7 +288,7 @@ class BitmapFrontEnd /** * Totally removes specified FlxGraphic object. - * @param graphic object you want to remove and destroy. + * @param graphic The object you want to remove and destroy. */ public function remove(graphic:FlxGraphic):Void { @@ -302,7 +303,7 @@ class BitmapFrontEnd /** * Totally removes FlxGraphic object with specified key. - * @param key the key for cached FlxGraphic object. + * @param key Key of the cached graphic. */ public function removeByKey(key:String):Void { From 3560c23c02aa568d9cc6bc338194b4c135ed76f7 Mon Sep 17 00:00:00 2001 From: ACrazyTown <47027981+ACrazyTown@users.noreply.github.com> Date: Fri, 20 Dec 2024 17:40:13 +0100 Subject: [PATCH 83/99] Fix outdated references to FLX_SOUND_ADD_EXT (#3318) --- flixel/sound/FlxSound.hx | 2 +- flixel/system/frontEnds/SoundFrontEnd.hx | 6 +++--- tests/coverage/Project.xml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/flixel/sound/FlxSound.hx b/flixel/sound/FlxSound.hx index ff7f3e8213..b45f6c8f1e 100644 --- a/flixel/sound/FlxSound.hx +++ b/flixel/sound/FlxSound.hx @@ -337,7 +337,7 @@ class FlxSound extends FlxBasic /** * One of the main setup functions for sounds, this function loads a sound from an embedded MP3. * - * **Note:** If the `FLX_SOUND_ADD_EXT` flag is enabled, you may omit the file extension + * **Note:** If the `FLX_DEFAULT_SOUND_EXT` flag is enabled, you may omit the file extension * * @param EmbeddedSound An embedded Class object representing an MP3 file. * @param Looped Whether or not this sound should loop endlessly. diff --git a/flixel/system/frontEnds/SoundFrontEnd.hx b/flixel/system/frontEnds/SoundFrontEnd.hx index 4ecae68745..e07db4ec29 100644 --- a/flixel/system/frontEnds/SoundFrontEnd.hx +++ b/flixel/system/frontEnds/SoundFrontEnd.hx @@ -103,7 +103,7 @@ class SoundFrontEnd /** * Set up and play a looping background soundtrack. * - * **Note:** If the `FLX_SOUND_ADD_EXT` flag is enabled, you may omit the file extension + * **Note:** If the `FLX_DEFAULT_SOUND_EXT` flag is enabled, you may omit the file extension * * @param embeddedMusic The sound file you want to loop in the background. * @param volume How loud the sound should be, from 0 to 1. @@ -134,7 +134,7 @@ class SoundFrontEnd /** * Creates a new FlxSound object. * - * **Note:** If the `FLX_SOUND_ADD_EXT` flag is enabled, you may omit the file extension + * **Note:** If the `FLX_DEFAULT_SOUND_EXT` flag is enabled, you may omit the file extension * * @param embeddedSound The embedded sound resource you want to play. To stream, use the optional URL parameter instead. * @param volume How loud to play it (0 to 1). @@ -234,7 +234,7 @@ class SoundFrontEnd /** * Plays a sound from an embedded sound. Tries to recycle a cached sound first. * - * **Note:** If the `FLX_SOUND_ADD_EXT` flag is enabled, you may omit the file extension + * **Note:** If the `FLX_DEFAULT_SOUND_EXT` flag is enabled, you may omit the file extension * * @param embeddedSound The embedded sound resource you want to play. * @param volume How loud to play it (0 to 1). diff --git a/tests/coverage/Project.xml b/tests/coverage/Project.xml index 46a00af3da..daf79ceaa7 100644 --- a/tests/coverage/Project.xml +++ b/tests/coverage/Project.xml @@ -54,7 +54,7 @@ - +
@@ -78,6 +78,6 @@ - +
From ab51c0cb8c85848cb31f8552762b7e8830e3ab8e Mon Sep 17 00:00:00 2001 From: Ria <94221492+Ria424@users.noreply.github.com> Date: Fri, 27 Dec 2024 00:54:56 +0900 Subject: [PATCH 84/99] Fix typo in FlxAtlasFrames.hx (#3323) --- flixel/graphics/frames/FlxAtlasFrames.hx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flixel/graphics/frames/FlxAtlasFrames.hx b/flixel/graphics/frames/FlxAtlasFrames.hx index 161d3698d1..58c12c1043 100644 --- a/flixel/graphics/frames/FlxAtlasFrames.hx +++ b/flixel/graphics/frames/FlxAtlasFrames.hx @@ -35,12 +35,12 @@ class FlxAtlasFrames extends FlxFramesCollection /** * Parsing method for atlases generated from Aseprite's JSON export options. Note that Aseprite * and Texture Packer use the same JSON format, however this method honors frames' `duration` - * whereas `fromTexturePackerJson` ignores it by default (for backwrds compatibility reasons). + * whereas `fromTexturePackerJson` ignores it by default (for backwards compatibility reasons). * * @param source The image source (can be `FlxGraphic`, `String`, or `BitmapData`). * @param description Contents of JSON file with atlas description. * You can get it with `FlxG.assets.getText(path/to/description.json)`. - * Or you can just a pass path to the JSON file in the assets directory. + * Or you can just pass a path to the JSON file in the assets directory. * You can also directly pass in the parsed object. * @return Newly created `FlxAtlasFrames` collection. * @see [Exporting texture atlases with Aseprite](https://www.aseprite.org/docs/sprite-sheet/#texture-atlases) @@ -56,10 +56,10 @@ class FlxAtlasFrames extends FlxFramesCollection * @param source The image source (can be `FlxGraphic`, `String`, or `BitmapData`). * @param description Contents of JSON file with atlas description. * You can get it with `FlxG.assets.getText(path/to/description.json)`. - * Or you can just a pass path to the JSON file in the assets directory. + * Or you can just pass a path to the JSON file in the assets directory. * You can also directly pass in the parsed object. * @param useFrameDuration If true, any frame durations defined in the JSON will override the - * frameRate set in you `FlxAnimationController`. + * frameRate set in your `FlxAnimationController`. * Note: You can also use `fromAseprite` which uses duration. * @return Newly created `FlxAtlasFrames` collection. */ From 593f04ff6612652cbf413f06f2a791dda6e0a58c Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Thu, 26 Dec 2024 10:25:17 -0600 Subject: [PATCH 85/99] Fix camera.color (#3321) * fix camera.color * fix edge cases * Simplify FlxGraphicsShader * fix triangles --- flixel/graphics/tile/FlxDrawQuadsItem.hx | 1 - flixel/graphics/tile/FlxDrawTrianglesItem.hx | 1 - flixel/graphics/tile/FlxGraphicsShader.hx | 71 +++++--------------- 3 files changed, 18 insertions(+), 55 deletions(-) diff --git a/flixel/graphics/tile/FlxDrawQuadsItem.hx b/flixel/graphics/tile/FlxDrawQuadsItem.hx index bd73f8b346..adfa2bf6ed 100644 --- a/flixel/graphics/tile/FlxDrawQuadsItem.hx +++ b/flixel/graphics/tile/FlxDrawQuadsItem.hx @@ -130,7 +130,6 @@ class FlxDrawQuadsItem extends FlxDrawBaseItem shader.colorOffset.value = colorOffsets; } - setParameterValue(shader.hasTransform, true); setParameterValue(shader.hasColorTransform, colored || hasColorOffsets); #if (openfl > "8.7.0") diff --git a/flixel/graphics/tile/FlxDrawTrianglesItem.hx b/flixel/graphics/tile/FlxDrawTrianglesItem.hx index c1af4b6438..b1d4a64880 100644 --- a/flixel/graphics/tile/FlxDrawTrianglesItem.hx +++ b/flixel/graphics/tile/FlxDrawTrianglesItem.hx @@ -76,7 +76,6 @@ class FlxDrawTrianglesItem extends FlxDrawBaseItem shader.colorOffset.value = null; } - setParameterValue(shader.hasTransform, true); setParameterValue(shader.hasColorTransform, colored || hasColorOffsets); #if (openfl > "8.7.0") diff --git a/flixel/graphics/tile/FlxGraphicsShader.hx b/flixel/graphics/tile/FlxGraphicsShader.hx index e433b45a86..bd17b3e3e8 100644 --- a/flixel/graphics/tile/FlxGraphicsShader.hx +++ b/flixel/graphics/tile/FlxGraphicsShader.hx @@ -4,66 +4,31 @@ import openfl.display.GraphicsShader; class FlxGraphicsShader extends GraphicsShader { - @:glVertexSource(" - #pragma header - - attribute float alpha; - attribute vec4 colorMultiplier; - attribute vec4 colorOffset; - uniform bool hasColorTransform; - - void main(void) - { - #pragma body - - openfl_Alphav = openfl_Alpha * alpha; - - if (hasColorTransform) - { - openfl_ColorOffsetv = colorOffset / 255.0; - openfl_ColorMultiplierv = colorMultiplier; - } - }") @:glFragmentHeader(" - uniform bool hasTransform; + uniform float alpha; + uniform vec4 colorMultiplier; + uniform vec4 colorOffset; uniform bool hasColorTransform; - + + vec4 transform(bool has, vec4 color, vec4 mult, vec4 offset) + { + return mix(color, clamp(offset + (color * mult), 0.0, 1.0), float(has)); + } + vec4 flixel_texture2D(sampler2D bitmap, vec2 coord) { vec4 color = texture2D(bitmap, coord); - if (!hasTransform) - { - return color; - } - - if (color.a == 0.0) - { - return vec4(0.0, 0.0, 0.0, 0.0); - } - - if (!hasColorTransform) - { - return color * openfl_Alphav; - } - - color = vec4(color.rgb / color.a, color.a); - - color = clamp(openfl_ColorOffsetv + (color * openfl_ColorMultiplierv), 0.0, 1.0); - - if (color.a > 0.0) - { - return vec4(color.rgb * color.a * openfl_Alphav, color.a * openfl_Alphav); - } - return vec4(0.0, 0.0, 0.0, 0.0); + + color = transform(openfl_HasColorTransform, color, openfl_ColorMultiplierv, openfl_ColorOffsetv); + color = transform(hasColorTransform, color, colorMultiplier, colorOffset / 255.0); + + float _alpha = color.a * openfl_Alphav * alpha; + return vec4 (color.rgb * _alpha, _alpha); } ") - @:glFragmentSource(" - #pragma header - - void main(void) - { - gl_FragColor = flixel_texture2D(bitmap, openfl_TextureCoordv); - }") + @:glFragmentBody(" + gl_FragColor = flixel_texture2D(bitmap, openfl_TextureCoordv); + ") public function new() { super(); From 0283d8ef4f2675488d4e872dd9e2ec66e8d9cc23 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Thu, 26 Dec 2024 13:33:33 -0600 Subject: [PATCH 86/99] Revert "Fix camera.color (#3321)" (#3324) This reverts commit 593f04ff6612652cbf413f06f2a791dda6e0a58c. --- flixel/graphics/tile/FlxDrawQuadsItem.hx | 1 + flixel/graphics/tile/FlxDrawTrianglesItem.hx | 1 + flixel/graphics/tile/FlxGraphicsShader.hx | 71 +++++++++++++++----- 3 files changed, 55 insertions(+), 18 deletions(-) diff --git a/flixel/graphics/tile/FlxDrawQuadsItem.hx b/flixel/graphics/tile/FlxDrawQuadsItem.hx index adfa2bf6ed..bd73f8b346 100644 --- a/flixel/graphics/tile/FlxDrawQuadsItem.hx +++ b/flixel/graphics/tile/FlxDrawQuadsItem.hx @@ -130,6 +130,7 @@ class FlxDrawQuadsItem extends FlxDrawBaseItem shader.colorOffset.value = colorOffsets; } + setParameterValue(shader.hasTransform, true); setParameterValue(shader.hasColorTransform, colored || hasColorOffsets); #if (openfl > "8.7.0") diff --git a/flixel/graphics/tile/FlxDrawTrianglesItem.hx b/flixel/graphics/tile/FlxDrawTrianglesItem.hx index b1d4a64880..c1af4b6438 100644 --- a/flixel/graphics/tile/FlxDrawTrianglesItem.hx +++ b/flixel/graphics/tile/FlxDrawTrianglesItem.hx @@ -76,6 +76,7 @@ class FlxDrawTrianglesItem extends FlxDrawBaseItem shader.colorOffset.value = null; } + setParameterValue(shader.hasTransform, true); setParameterValue(shader.hasColorTransform, colored || hasColorOffsets); #if (openfl > "8.7.0") diff --git a/flixel/graphics/tile/FlxGraphicsShader.hx b/flixel/graphics/tile/FlxGraphicsShader.hx index bd17b3e3e8..e433b45a86 100644 --- a/flixel/graphics/tile/FlxGraphicsShader.hx +++ b/flixel/graphics/tile/FlxGraphicsShader.hx @@ -4,31 +4,66 @@ import openfl.display.GraphicsShader; class FlxGraphicsShader extends GraphicsShader { - @:glFragmentHeader(" - uniform float alpha; - uniform vec4 colorMultiplier; - uniform vec4 colorOffset; + @:glVertexSource(" + #pragma header + + attribute float alpha; + attribute vec4 colorMultiplier; + attribute vec4 colorOffset; uniform bool hasColorTransform; - - vec4 transform(bool has, vec4 color, vec4 mult, vec4 offset) + + void main(void) { - return mix(color, clamp(offset + (color * mult), 0.0, 1.0), float(has)); - } - + #pragma body + + openfl_Alphav = openfl_Alpha * alpha; + + if (hasColorTransform) + { + openfl_ColorOffsetv = colorOffset / 255.0; + openfl_ColorMultiplierv = colorMultiplier; + } + }") + @:glFragmentHeader(" + uniform bool hasTransform; + uniform bool hasColorTransform; + vec4 flixel_texture2D(sampler2D bitmap, vec2 coord) { vec4 color = texture2D(bitmap, coord); - - color = transform(openfl_HasColorTransform, color, openfl_ColorMultiplierv, openfl_ColorOffsetv); - color = transform(hasColorTransform, color, colorMultiplier, colorOffset / 255.0); - - float _alpha = color.a * openfl_Alphav * alpha; - return vec4 (color.rgb * _alpha, _alpha); + if (!hasTransform) + { + return color; + } + + if (color.a == 0.0) + { + return vec4(0.0, 0.0, 0.0, 0.0); + } + + if (!hasColorTransform) + { + return color * openfl_Alphav; + } + + color = vec4(color.rgb / color.a, color.a); + + color = clamp(openfl_ColorOffsetv + (color * openfl_ColorMultiplierv), 0.0, 1.0); + + if (color.a > 0.0) + { + return vec4(color.rgb * color.a * openfl_Alphav, color.a * openfl_Alphav); + } + return vec4(0.0, 0.0, 0.0, 0.0); } ") - @:glFragmentBody(" - gl_FragColor = flixel_texture2D(bitmap, openfl_TextureCoordv); - ") + @:glFragmentSource(" + #pragma header + + void main(void) + { + gl_FragColor = flixel_texture2D(bitmap, openfl_TextureCoordv); + }") public function new() { super(); From 21cb8689568d4c23a41526b7f0873d06439cd67d Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Mon, 30 Dec 2024 07:32:17 -0500 Subject: [PATCH 87/99] fix camera.color (#3326) * fix camera.color * doc --- flixel/graphics/tile/FlxGraphicsShader.hx | 71 ++++++++++------------- 1 file changed, 32 insertions(+), 39 deletions(-) diff --git a/flixel/graphics/tile/FlxGraphicsShader.hx b/flixel/graphics/tile/FlxGraphicsShader.hx index e433b45a86..5e1e01d0f2 100644 --- a/flixel/graphics/tile/FlxGraphicsShader.hx +++ b/flixel/graphics/tile/FlxGraphicsShader.hx @@ -4,66 +4,59 @@ import openfl.display.GraphicsShader; class FlxGraphicsShader extends GraphicsShader { - @:glVertexSource(" - #pragma header - + @:glVertexHeader(" attribute float alpha; attribute vec4 colorMultiplier; attribute vec4 colorOffset; uniform bool hasColorTransform; - - void main(void) + ") + @:glVertexBody(" + openfl_Alphav = openfl_Alpha * alpha; + + if (hasColorTransform) { - #pragma body - - openfl_Alphav = openfl_Alpha * alpha; - - if (hasColorTransform) + if (openfl_HasColorTransform) + { + openfl_ColorOffsetv = (openfl_ColorOffsetv * colorMultiplier) + (colorOffset / 255.0); + openfl_ColorMultiplierv *= colorMultiplier; + } + else { openfl_ColorOffsetv = colorOffset / 255.0; openfl_ColorMultiplierv = colorMultiplier; } - }") + } + ") @:glFragmentHeader(" - uniform bool hasTransform; + uniform bool hasTransform; // TODO: Is this still needed? Apparently, yes! uniform bool hasColorTransform; - vec4 flixel_texture2D(sampler2D bitmap, vec2 coord) { vec4 color = texture2D(bitmap, coord); - if (!hasTransform) - { + if (!(hasTransform || openfl_HasColorTransform)) return color; - } - + if (color.a == 0.0) - { return vec4(0.0, 0.0, 0.0, 0.0); - } - - if (!hasColorTransform) - { - return color * openfl_Alphav; - } - - color = vec4(color.rgb / color.a, color.a); - - color = clamp(openfl_ColorOffsetv + (color * openfl_ColorMultiplierv), 0.0, 1.0); - - if (color.a > 0.0) + + if (openfl_HasColorTransform || hasColorTransform) { - return vec4(color.rgb * color.a * openfl_Alphav, color.a * openfl_Alphav); + color = vec4 (color.rgb / color.a, color.a); + vec4 mult = vec4 (openfl_ColorMultiplierv.rgb, 1.0); + color = clamp (openfl_ColorOffsetv + (color * mult), 0.0, 1.0); + + if (color.a == 0.0) + return vec4 (0.0, 0.0, 0.0, 0.0); + + return vec4 (color.rgb * color.a * openfl_Alphav, color.a * openfl_Alphav); } - return vec4(0.0, 0.0, 0.0, 0.0); + + return color * openfl_Alphav; } ") - @:glFragmentSource(" - #pragma header - - void main(void) - { - gl_FragColor = flixel_texture2D(bitmap, openfl_TextureCoordv); - }") + @:glFragmentBody(" + gl_FragColor = flixel_texture2D(bitmap, openfl_TextureCoordv); + ") public function new() { super(); From 580d200b18574fbcdc518eacc99f362601102b2b Mon Sep 17 00:00:00 2001 From: George FunBook Date: Tue, 14 Jan 2025 09:24:48 -0600 Subject: [PATCH 88/99] update haxelib after merge --- haxelib.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/haxelib.json b/haxelib.json index fb21ebebe9..84c57f7ea8 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.9.0", - "releasenote": "Added FlxInputText, FlxG.assets, FlxBasePath and more", + "version": "6.0.0", + "releasenote": "Remove various deprecated tools", "contributors": ["haxeflixel", "Gama11", "GeoKureli"], "dependencies": { "lime": "", From 1272a65bea83cf523c4473a976da639912de9dfa Mon Sep 17 00:00:00 2001 From: CrusherNotDrip <90648119+CrusherNotDrip@users.noreply.github.com> Date: Sat, 18 Jan 2025 20:52:07 -0500 Subject: [PATCH 89/99] Update AssetFrontEnd.hx (#3337) --- flixel/system/frontEnds/AssetFrontEnd.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flixel/system/frontEnds/AssetFrontEnd.hx b/flixel/system/frontEnds/AssetFrontEnd.hx index a6eea14cc2..47fe7fe95d 100644 --- a/flixel/system/frontEnds/AssetFrontEnd.hx +++ b/flixel/system/frontEnds/AssetFrontEnd.hx @@ -35,7 +35,7 @@ using StringTools; * * ### Quick Setup for "Hot-Reloading" * To simplify the process mentioned above, the `FLX_CUSTOM_ASSETS_DIRECTORY` flag was created. - * By adding `-DFLX_CUSTOM_ASSETS_DIRECTORY="../../../assets"` to your lime build command + * By adding `-DFLX_CUSTOM_ASSETS_DIRECTORY="assets"` to your lime build command * it will automatically grab assets from your project root's assets folder rather than, the * default "export/hl/bin/assets". This will only work with a single asset root folder with one * asset library and will use the openfl asset system if the asset id starts with "flixel/" or From 71c1d3ea3754f6d2d0fa09b8bb718610a0021009 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Fri, 24 Jan 2025 20:17:50 -0600 Subject: [PATCH 90/99] Log pos (#3338) * change logs to include posInfos * fix flash errors * D'oh --- flixel/graphics/frames/bmfont/BMFontXml.hx | 17 ++++++------ flixel/system/debug/log/LogStyle.hx | 7 ++--- flixel/system/frontEnds/LogFrontEnd.hx | 30 +++++++++++----------- 3 files changed, 28 insertions(+), 26 deletions(-) diff --git a/flixel/graphics/frames/bmfont/BMFontXml.hx b/flixel/graphics/frames/bmfont/BMFontXml.hx index a8321bc687..833ef5fce7 100644 --- a/flixel/graphics/frames/bmfont/BMFontXml.hx +++ b/flixel/graphics/frames/bmfont/BMFontXml.hx @@ -2,6 +2,7 @@ package flixel.graphics.frames.bmfont; import flixel.FlxG; import flixel.system.debug.log.LogStyle; +import haxe.PosInfos; /** * Helps providing a fast dot-syntax access to the most common `Xml` methods. @@ -83,7 +84,7 @@ abstract BMFontXml(Xml) from Xml private abstract NodeAccess(Xml) from Xml to Xml { - inline function getHelper(name:String, ?invalid:(String)->Void):BMFontXml + inline function getHelper(name:String, ?invalid:(String, ?PosInfos)->Void):BMFontXml { final xml = this.elementsNamed(name).next(); if (xml == null) @@ -102,7 +103,7 @@ private abstract NodeAccess(Xml) from Xml to Xml public function get(name:String):BMFontXml { - return getHelper(name, (msg)->throw msg); + return getHelper(name, (msg, ?_)->throw msg); } public function getWarn(name:String) @@ -118,7 +119,7 @@ private abstract NodeAccess(Xml) from Xml to Xml private abstract AttribAccess(Xml) from Xml to Xml { - inline function stringHelper(name:String, ?invalid:(String)->Void, ?backup:String):String + inline function stringHelper(name:String, ?invalid:(String, ?PosInfos)->Void, ?backup:String):String { var value = backup; if (this.nodeType == Xml.Document) @@ -144,7 +145,7 @@ private abstract AttribAccess(Xml) from Xml to Xml public function string(name:String) { - return stringHelper(name, (msg)->throw msg); + return stringHelper(name, (msg, ?_)->throw msg); } public function stringWarn(name:String, ?backup:String) @@ -157,7 +158,7 @@ private abstract AttribAccess(Xml) from Xml to Xml return stringHelper(name, FlxG.log.error, backup); } - inline function intHelper(name:String, ?invalid:(String)->Void, backup:Int):Int + inline function intHelper(name:String, ?invalid:(String, ?PosInfos)->Void, backup:Int):Int { var value = backup; if (this.nodeType == Xml.Document) @@ -183,7 +184,7 @@ private abstract AttribAccess(Xml) from Xml to Xml public function int(name:String) { - return intHelper(name, (msg)->throw msg, 0); + return intHelper(name, (msg, ?_)->throw msg, 0); } public function intWarn(name:String, backup:Int) @@ -196,7 +197,7 @@ private abstract AttribAccess(Xml) from Xml to Xml return intHelper(name, FlxG.log.error, backup); } - inline function boolHelper(name:String, ?invalid:(String)->Void, backup:Bool):Bool + inline function boolHelper(name:String, ?invalid:(String, ?PosInfos)->Void, backup:Bool):Bool { var value = backup; if (this.nodeType == Xml.Document) @@ -222,7 +223,7 @@ private abstract AttribAccess(Xml) from Xml to Xml public function bool(name:String) { - return boolHelper(name, (msg)->throw msg, false); + return boolHelper(name, (msg, ?_)->throw msg, false); } public function boolWarn(name:String, backup:Bool) diff --git a/flixel/system/debug/log/LogStyle.hx b/flixel/system/debug/log/LogStyle.hx index cf0bee3829..91707aaab3 100644 --- a/flixel/system/debug/log/LogStyle.hx +++ b/flixel/system/debug/log/LogStyle.hx @@ -1,6 +1,7 @@ package flixel.system.debug.log; import flixel.util.FlxSignal; +import haxe.PosInfos; using flixel.util.FlxStringUtil; @@ -48,8 +49,8 @@ class LogStyle * **Note:** Unlike the deprecated `callbackFunction`, this is called every time, * even when logged with `once = true` and even in release mode. */ - public final onLog = new FlxTypedSignal<(data:Any)->Void>(); - + public final onLog = new FlxTypedSignal<(data:Any, ?pos:PosInfos) -> Void>(); + /** * Whether an exception is thrown when this LogStyle is used. * **Note**: Unlike other log style properties, this happens even in release mode. @@ -74,7 +75,7 @@ class LogStyle */ @:haxe.warning("-WDeprecated") public function new(prefix = "", color = "FFFFFF", size = 12, bold = false, italic = false, underlined = false, - ?errorSound:String, openConsole = false, ?callbackFunction:()->Void, ?callback:(Any)->Void, throwException = false) + ?errorSound:String, openConsole = false, ?callbackFunction:()->Void, ?callback:(Any, ?PosInfos)->Void, throwException = false) { this.prefix = prefix; this.color = color; diff --git a/flixel/system/frontEnds/LogFrontEnd.hx b/flixel/system/frontEnds/LogFrontEnd.hx index ab74996886..71031aca89 100644 --- a/flixel/system/frontEnds/LogFrontEnd.hx +++ b/flixel/system/frontEnds/LogFrontEnd.hx @@ -16,27 +16,27 @@ class LogFrontEnd public var redirectTraces(default, set):Bool = false; var _standardTraceFunction:(Dynamic, ?PosInfos)->Void; - - public inline function add(data:Dynamic):Void + + public inline function add(data:Dynamic, ?pos:PosInfos):Void { - advanced(data, LogStyle.NORMAL); + advanced(data, LogStyle.NORMAL, false, pos); } - - public inline function warn(data:Dynamic):Void + + public inline function warn(data:Dynamic, ?pos:PosInfos):Void { - advanced(data, LogStyle.WARNING, true); + advanced(data, LogStyle.WARNING, true, pos); } - - public inline function error(data:Dynamic):Void + + public inline function error(data:Dynamic, ?pos:PosInfos):Void { - advanced(data, LogStyle.ERROR, true); + advanced(data, LogStyle.ERROR, true, pos); } - - public inline function notice(data:Dynamic):Void + + public inline function notice(data:Dynamic, ?pos:PosInfos):Void { - advanced(data, LogStyle.NOTICE); + advanced(data, LogStyle.NOTICE, false, pos); } - + /** * Add an advanced log message to the debugger by also specifying a LogStyle. Backend to FlxG.log.add(), FlxG.log.warn(), FlxG.log.error() and FlxG.log.notice(). * @@ -45,7 +45,7 @@ class LogFrontEnd * @param fireOnce Whether you only want to log the Data in case it hasn't been added already */ @:haxe.warning("-WDeprecated") - public function advanced(data:Any, ?style:LogStyle, fireOnce = false):Void + public function advanced(data:Any, ?style:LogStyle, fireOnce = false, ?pos:PosInfos):Void { if (style == null) style = LogStyle.NORMAL; @@ -77,7 +77,7 @@ class LogFrontEnd } #end - style.onLog.dispatch(data); + style.onLog.dispatch(data, pos); if (style.throwException) throw style.toLogString(arrayData); From b386d54b99c9728755ca280e27e032fd399de664 Mon Sep 17 00:00:00 2001 From: George FunBook Date: Wed, 29 Jan 2025 12:26:45 -0600 Subject: [PATCH 91/99] update Changelog --- CHANGELOG.md | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 69178c8b1b..90feabedea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,5 @@ 6.0.0 (TBD) -#### Changes and improvements: -- `FlxSpritegroup`: Setting `origin` now causes members to pivot around the same point ([#2981](https://github.com/HaxeFlixel/flixel/pull/2981)) -- `FlxCamera`: Smoother camera lerping, particularly with non-fixed timesteps ([#2922](https://github.com/HaxeFlixel/flixel/pull/2922)) -- `FlxState`: Removed deprecated `switchTo` ([#2733](https://github.com/HaxeFlixel/flixel/pull/2733)) -- `FlxG`: Added deprecation warning on `switchState` with instances ([#2733](https://github.com/HaxeFlixel/flixel/pull/2733)) -- `FlxCamera`: Removed `defaultCameras` -- `FlxCamera`: Fixed `zoom` and `defaultZoom` so it works with values other than 1.0 ([#2907](https://github.com/HaxeFlixel/flixel/pull/2907)) -- `FlxBasic`: Added `getDefaultCamera`, used in nearly all methods taking an optional `camera` arg ([#3072](https://github.com/HaxeFlixel/flixel/pull/3072)) - #### Removals We removed many features and utilities that were previously deprecated - `flixel.util.FlxPath`: New package, `flixel.path.FlxPath` @@ -35,6 +26,23 @@ We removed many features and utilities that were previously deprecated - `FlxAssets.FlxTexturePackerSource`: Use `FlxTexturePackerJsonAsset`, instead - `FlxUnicodeUtil`: Use `UnicodeString`, instead +#### Changes and improvements: +- `FlxSpritegroup`: Setting `origin` now causes members to pivot around the same point ([#2981](https://github.com/HaxeFlixel/flixel/pull/2981)) +- `FlxCamera`: Smoother camera lerping, particularly with non-fixed timesteps ([#2922](https://github.com/HaxeFlixel/flixel/pull/2922)) +- `FlxState`: Removed deprecated `switchTo` ([#2733](https://github.com/HaxeFlixel/flixel/pull/2733)) +- `FlxG`: Added deprecation warning on `switchState` with instances ([#2733](https://github.com/HaxeFlixel/flixel/pull/2733)) +- `FlxCamera`: Removed `defaultCameras` +- `FlxCamera`: Fixed `zoom` and `defaultZoom` so it works with values other than 1.0 ([#2907](https://github.com/HaxeFlixel/flixel/pull/2907)) +- `FlxBasic`: Added `getDefaultCamera`, used in nearly all methods taking an optional `camera` arg ([#3072](https://github.com/HaxeFlixel/flixel/pull/3072)) +- `FlxG.log`: Add `PosInfos` args to loggers, for better tracing info ([#3338](https://github.com/HaxeFlixel/flixel/pull/3338)) + +#### New features: +- `FlxMath`: Add improved, euclidean division `mod` function ([#3341](https://github.com/HaxeFlixel/flixel/pull/3341)) + +#### Bugfixes: +- `FlxCamera`: Fix `color` field ([#3326](https://github.com/HaxeFlixel/flixel/pull/3326)) +- `FlxCamera`: Reset `bgColor` on reset ([#3254](https://github.com/HaxeFlixel/flixel/issues/3254)) + 5.9.0 (December 12, 2024) ------------------------------ #### New features: From 39e1fcf7608bdddd130f80c4ef1bddd96d33f693 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Wed, 29 Jan 2025 17:59:54 -0600 Subject: [PATCH 92/99] Add analog directional input to FlxVirtualPad (#3340) * add overloaded scale * add FlxReadOnlyPoint * deprecate statusAnimations * fix drawCircle centering * Add analog stick to FlxVirtualPad * fix code climate * D'oh * fix coverage * fix flash * add distance overloads * add FlxMath.getFrameLerp * honor camera in checkInput * add FlxVirtualStick deprecate FlxAnalog * rename to getElapsedLerp * fix multi-touch * D'oh! * doc * add FlxAnalogState helpers * rename signals, add statuses * add deadzone * remove lerp constructor arg * fix unit test warning * overload more shit * 5.10.0 * change 5.10->6 --- flixel/FlxCamera.hx | 2 +- flixel/FlxSprite.hx | 18 +- flixel/graphics/frames/FlxAtlasFrames.hx | 2 +- flixel/graphics/frames/FlxBitmapFont.hx | 4 +- flixel/graphics/frames/FlxFrame.hx | 6 +- flixel/graphics/frames/FlxImageFrame.hx | 2 +- flixel/graphics/frames/FlxTileFrames.hx | 2 +- flixel/input/actions/FlxActionInputAnalog.hx | 9 + flixel/math/FlxMath.hx | 12 + flixel/math/FlxPoint.hx | 268 +++++++++++++++-- flixel/path/FlxPath.hx | 4 +- flixel/system/debug/log/BitmapLog.hx | 4 +- flixel/text/FlxText.hx | 6 +- flixel/tile/FlxBaseTilemap.hx | 2 +- flixel/tile/FlxTilemap.hx | 4 +- flixel/ui/FlxAnalog.hx | 5 +- flixel/ui/FlxBar.hx | 2 +- flixel/ui/FlxButton.hx | 46 ++- flixel/ui/FlxVirtualPad.hx | 293 +++++++++++++------ flixel/ui/FlxVirtualStick.hx | 293 +++++++++++++++++++ flixel/util/FlxSpriteUtil.hx | 12 +- tests/unit/src/flixel/ui/FlxButtonTest.hx | 10 +- 22 files changed, 822 insertions(+), 184 deletions(-) create mode 100644 flixel/ui/FlxVirtualStick.hx diff --git a/flixel/FlxCamera.hx b/flixel/FlxCamera.hx index 3f423694e5..118b3a601f 100644 --- a/flixel/FlxCamera.hx +++ b/flixel/FlxCamera.hx @@ -1182,7 +1182,7 @@ class FlxCamera extends FlxBasic if (deadzone == null) { target.getMidpoint(_point); - _point.addPoint(targetOffset); + _point.add(targetOffset); _scrollTarget.set(_point.x - width * 0.5, _point.y - height * 0.5); } else diff --git a/flixel/FlxSprite.hx b/flixel/FlxSprite.hx index e643d5da6e..cb402cfb9d 100644 --- a/flixel/FlxSprite.hx +++ b/flixel/FlxSprite.hx @@ -833,11 +833,11 @@ class FlxSprite extends FlxObject @:noCompletion function drawSimple(camera:FlxCamera):Void { - getScreenPosition(_point, camera).subtractPoint(offset); + getScreenPosition(_point, camera).subtract(offset); if (isPixelPerfectRender(camera)) _point.floor(); - _point.copyToFlash(_flashPoint); + _point.copyTo(_flashPoint); camera.copyPixels(_frame, framePixels, _flashRect, _flashPoint, colorTransform, blend, antialiasing); } @@ -856,7 +856,7 @@ class FlxSprite extends FlxObject _matrix.rotateWithTrig(_cosAngle, _sinAngle); } - getScreenPosition(_point, camera).subtractPoint(offset); + getScreenPosition(_point, camera).subtract(offset); _point.add(origin.x, origin.y); _matrix.translate(_point.x, _point.y); @@ -1122,11 +1122,11 @@ class FlxSprite extends FlxObject result.subtract(worldPoint.x, worldPoint.y); result.negate(); - result.addPoint(offset); - result.subtractPoint(origin); + result.add(offset); + result.subtract(origin); result.scale(1 / scale.x, 1 / scale.y); result.degrees -= angle; - result.addPoint(origin); + result.add(origin); worldPoint.putWeak(); @@ -1148,11 +1148,11 @@ class FlxSprite extends FlxObject result.subtract(screenPoint.x, screenPoint.y); result.negate(); - result.addPoint(offset); - result.subtractPoint(origin); + result.add(offset); + result.subtract(origin); result.scale(1 / scale.x, 1 / scale.y); result.degrees -= angle; - result.addPoint(origin); + result.add(origin); screenPoint.putWeak(); diff --git a/flixel/graphics/frames/FlxAtlasFrames.hx b/flixel/graphics/frames/FlxAtlasFrames.hx index 58c12c1043..91fe6baf39 100644 --- a/flixel/graphics/frames/FlxAtlasFrames.hx +++ b/flixel/graphics/frames/FlxAtlasFrames.hx @@ -423,7 +423,7 @@ class FlxAtlasFrames extends FlxFramesCollection override public function addBorder(border:FlxPoint):FlxAtlasFrames { - var resultBorder = FlxPoint.weak().addPoint(this.border).addPoint(border); + var resultBorder = FlxPoint.weak().add(this.border).add(border); var atlasFrames = FlxAtlasFrames.findFrame(parent, resultBorder); if (atlasFrames != null) return atlasFrames; diff --git a/flixel/graphics/frames/FlxBitmapFont.hx b/flixel/graphics/frames/FlxBitmapFont.hx index ed06a3b71a..6ba8b53785 100644 --- a/flixel/graphics/frames/FlxBitmapFont.hx +++ b/flixel/graphics/frames/FlxBitmapFont.hx @@ -466,7 +466,7 @@ class FlxBitmapFont extends FlxFramesCollection final h:Float = charFrame.sourceSize.y + (offset != null && offset.y > 0 ? offset.y : 0); charFrame.sourceSize.set(w, h); if (offset != null) - charFrame.offset.addPoint(offset);//calls putWeak + charFrame.offset.add(offset);//calls putWeak charFrame.name = charName; pushFrame(charFrame, true); charMap.set(charCode, charFrame); @@ -536,7 +536,7 @@ class FlxBitmapFont extends FlxFramesCollection override public function addBorder(border:FlxPoint):FlxBitmapFont { - var resultBorder:FlxPoint = FlxPoint.weak().addPoint(this.border).addPoint(border); + var resultBorder:FlxPoint = FlxPoint.weak().add(this.border).add(border); var font:FlxBitmapFont = FlxBitmapFont.findFont(frame, resultBorder); if (font != null) diff --git a/flixel/graphics/frames/FlxFrame.hx b/flixel/graphics/frames/FlxFrame.hx index 8cc7e3c201..afd594f8fe 100644 --- a/flixel/graphics/frames/FlxFrame.hx +++ b/flixel/graphics/frames/FlxFrame.hx @@ -349,7 +349,7 @@ class FlxFrame implements IFlxDestroyable if (angle == FlxFrameAngle.ANGLE_0) { - offset.copyToFlash(_point); + offset.copyTo(_point); if (point != null) _point.offset(point.x, point.y); @@ -521,7 +521,7 @@ class FlxFrame implements IFlxDestroyable else { frameToFill.type = FlxFrameType.REGULAR; - frameToFill.offset.set(frameRect.x, frameRect.y).subtract(rect.x, rect.y).addPoint(offset); + frameToFill.offset.set(frameRect.x, frameRect.y).subtract(rect.x, rect.y).add(offset); final p1 = FlxPoint.weak(frameRect.x, frameRect.y); final p2 = FlxPoint.weak(frameRect.right, frameRect.bottom); @@ -623,7 +623,7 @@ class FlxFrame implements IFlxDestroyable else { clippedFrame.type = FlxFrameType.REGULAR; - clippedFrame.offset.set(frameRect.x, frameRect.y).addPoint(offset); + clippedFrame.offset.set(frameRect.x, frameRect.y).add(offset); var p1 = FlxPoint.weak(frameRect.x, frameRect.y); var p2 = FlxPoint.weak(frameRect.right, frameRect.bottom); diff --git a/flixel/graphics/frames/FlxImageFrame.hx b/flixel/graphics/frames/FlxImageFrame.hx index 6f3fc3c423..76be77a9d0 100644 --- a/flixel/graphics/frames/FlxImageFrame.hx +++ b/flixel/graphics/frames/FlxImageFrame.hx @@ -242,7 +242,7 @@ class FlxImageFrame extends FlxFramesCollection override public function addBorder(border:FlxPoint):FlxImageFrame { - var resultBorder:FlxPoint = FlxPoint.weak().addPoint(this.border).addPoint(border); + var resultBorder:FlxPoint = FlxPoint.weak().add(this.border).add(border); var imageFrame:FlxImageFrame = FlxImageFrame.findFrame(parent, frame.frame, resultBorder); if (imageFrame != null) diff --git a/flixel/graphics/frames/FlxTileFrames.hx b/flixel/graphics/frames/FlxTileFrames.hx index ae209f74b2..745a3fc227 100644 --- a/flixel/graphics/frames/FlxTileFrames.hx +++ b/flixel/graphics/frames/FlxTileFrames.hx @@ -514,7 +514,7 @@ class FlxTileFrames extends FlxFramesCollection override public function addBorder(border:FlxPoint):FlxTileFrames { - var resultBorder:FlxPoint = FlxPoint.get().addPoint(this.border).addPoint(border); + var resultBorder:FlxPoint = FlxPoint.get().add(this.border).add(border); var resultSize:FlxPoint = FlxPoint.get().copyFrom(tileSize).subtract(2 * border.x, 2 * border.y); var tileFrames:FlxTileFrames = FlxTileFrames.findFrame(parent, resultSize, region, atlasFrame, tileSpacing, resultBorder); if (tileFrames != null) diff --git a/flixel/input/actions/FlxActionInputAnalog.hx b/flixel/input/actions/FlxActionInputAnalog.hx index 1dff292005..7ced145bea 100644 --- a/flixel/input/actions/FlxActionInputAnalog.hx +++ b/flixel/input/actions/FlxActionInputAnalog.hx @@ -20,6 +20,15 @@ enum abstract FlxAnalogState(Int) from Int var STOPPED = cast FlxInputState.RELEASED; // is 0 var MOVED = cast FlxInputState.PRESSED; // is !0 var JUST_MOVED = cast FlxInputState.JUST_PRESSED; // became !0 on this frame + + public var moved(get, never):Bool; + inline function get_moved() return this == MOVED || justMoved; + public var justMoved(get, never):Bool; + inline function get_justMoved() return this == JUST_MOVED; + public var justStopped(get, never):Bool; + inline function get_justStopped() return this == JUST_STOPPED; + public var stopped(get, never):Bool; + inline function get_stopped() return this == STOPPED || justStopped; } /** diff --git a/flixel/math/FlxMath.hx b/flixel/math/FlxMath.hx index f4f7f1ef49..55fe7aa2cf 100644 --- a/flixel/math/FlxMath.hx +++ b/flixel/math/FlxMath.hx @@ -108,6 +108,18 @@ class FlxMath { return a + ratio * (b - a); } + + /** + * Adjusts the given lerp to account for the time that has passed + * + * @param lerp The ratio to lerp in 1/60th of a second + * @param elapsed The amount of time that has actually passed + * @since 6.0.0 + */ + public static function getElapsedLerp(lerp:Float, elapsed:Float):Float + { + return 1.0 - Math.pow(1.0 - lerp, elapsed * 60); + } /** * Checks if number is in defined range. A null bound means that side is unbounded. diff --git a/flixel/math/FlxPoint.hx b/flixel/math/FlxPoint.hx index db82a66419..3a2157aedc 100644 --- a/flixel/math/FlxPoint.hx +++ b/flixel/math/FlxPoint.hx @@ -322,7 +322,7 @@ import openfl.geom.Point; * @param y Amount to add to y * @return This point. */ - public inline function add(x:Float = 0, y:Float = 0):FlxPoint + public overload extern inline function add(x:Float = 0, y:Float = 0):FlxPoint { this.x += x; this.y += y; @@ -331,16 +331,44 @@ import openfl.geom.Point; /** * Adds the coordinates of another point to the coordinates of this point. + * @since 6.0.0 * * @param point The point to add to this point * @return This point. */ - public inline function addPoint(point:FlxPoint):FlxPoint + public overload inline extern function add(point:FlxPoint):FlxPoint { add(point.x, point.y); point.putWeak(); return this; } + + /** + * Adds the coordinates of another point to the coordinates of this point. + * @since 6.0.0 + * + * @param p Any Point. + * @return A reference to the altered point parameter. + */ + public overload inline extern function add(p:Point):FlxPoint + { + x += p.x; + y += p.y; + + return this; + } + + /** + * Adds the coordinates of another point to the coordinates of this point. + * + * @param point The point to add to this point + * @return This point. + */ + // @:deprecated("addPoint is deprecated, use add(point), instead")// 6.0.0 + public inline function addPoint(point:FlxPoint):FlxPoint + { + return add(point); + } /** * Subtracts from the coordinates of this point. @@ -349,7 +377,7 @@ import openfl.geom.Point; * @param y Amount to subtract from y * @return This point. */ - public inline function subtract(x:Float = 0, y:Float = 0):FlxPoint + public overload inline extern function subtract(x:Float = 0, y:Float = 0):FlxPoint { this.x -= x; this.y -= y; @@ -358,10 +386,38 @@ import openfl.geom.Point; /** * Subtracts the coordinates of another point from the coordinates of this point. + * @since 6.0.0 + * + * @param point The point to subtract from this point + * @return This point. + */ + public overload inline extern function subtract(point:FlxPoint):FlxPoint + { + subtract(point.x, point.y); + point.putWeak(); + return this; + } + + /** + * Subtracts the coordinates of another point from the coordinates of this point. + * @since 6.0.0 * * @param point The point to subtract from this point * @return This point. */ + public overload inline extern function subtract(point:Point):FlxPoint + { + subtract(point.x, point.y); + return this; + } + + /** + * Subtracts the coordinates of another point from the coordinates of this point. + * + * @param point The point to subtract from this point + * @return This point. + */ + // @:deprecated("subtractPoint is deprecated, use subtract(point), instead")// 6.0.0 public inline function subtractPoint(point:FlxPoint):FlxPoint { subtract(point.x, point.y); @@ -372,26 +428,51 @@ import openfl.geom.Point; /** * Scale this point. * - * @param x - scale x coefficient - * @param y - scale y coefficient, if omitted, x is used - * @return scaled point + * @param x The x scale coefficient + * @param y The y scale coefficient + * @return this point */ - public inline function scale(x:Float, ?y:Float):FlxPoint + public overload inline extern function scale(x:Float, y:Float):FlxPoint { - if (y == null) - y = x; - this.x *= x; this.y *= y; return this; } + + /** + * Scale this point. + * @since 6.0.0 + * + * @param amount The scale coefficient + * @return this point + */ + public overload inline extern function scale(amount:Float):FlxPoint + { + this.x *= amount; + this.y *= amount; + return this; + } + + /** + * Scale this point by another point. + * @since 6.0.0 + * + * @param point The x and y scale coefficient + * @return this point + */ + public overload inline extern function scale(point:Point):FlxPoint + { + scale(point.x, point.y); + return this; + } /** * Scale this point by another point. * - * @param point - The x and y scale coefficient + * @param point The x and y scale coefficient * @return scaled point */ + // @:deprecated("scalePoint is deprecated, use scale(point), instead")// 6.0.0 public inline function scalePoint(point:FlxPoint):FlxPoint { scale(point.x, point.y); @@ -438,19 +519,32 @@ import openfl.geom.Point; * @param p Any FlxPoint. * @return A reference to itself. */ - public inline function copyFrom(p:FlxPoint):FlxPoint + public overload inline extern function copyFrom(p:FlxPoint):FlxPoint { set(p.x, p.y); p.putWeak(); return this; } + /** + * Helper function, just copies the values from the specified Flash point. + * @since 6.0.0 + * + * @param p Any Point. + * @return A reference to itself. + */ + public overload inline extern function copyFrom(p:Point):FlxPoint + { + return this.set(p.x, p.y); + } + /** * Helper function, just copies the values from the specified Flash point. * * @param p Any Point. * @return A reference to itself. */ + // @:deprecated("copyFromFlash is deprecated, use copyFrom, instead")// 6.0.0 public inline function copyFromFlash(p:Point):FlxPoint { return this.set(p.x, p.y); @@ -462,7 +556,7 @@ import openfl.geom.Point; * @param p optional point to copy this point to * @return copy of this point */ - public inline function copyTo(?p:FlxPoint):FlxPoint + public overload inline extern function copyTo(?p:FlxPoint):FlxPoint { if (p == null) { @@ -473,22 +567,30 @@ import openfl.geom.Point; /** * Helper function, just copies the values from this point to the specified Flash point. + * @since 6.0.0 * * @param p Any Point. * @return A reference to the altered point parameter. */ - public inline function copyToFlash(?p:Point):Point + public overload inline extern function copyTo(p:Point):Point { - if (p == null) - { - p = new Point(); - } - p.x = x; p.y = y; return p; } + /** + * Helper function, just copies the values from this point to the specified Flash point. + * + * @param p Any Point. + * @return A reference to the altered point parameter. + */ + // @:deprecated("copyToFlash is deprecated, use copyTo, instead")// 6.0.0 + public inline function copyToFlash(?p:Point):Point + { + return copyTo(p != null ? p : new Point()); + } + /** * Helper function, just increases the values of the specified Flash point by the values of this point. * @@ -610,12 +712,47 @@ import openfl.geom.Point; * @param point A FlxPoint object to calculate the distance to. * @return The distance between the two points as a Float. */ - public function distanceTo(point:FlxPoint):Float + public overload inline extern function distanceTo(point:FlxPoint):Float + { + final result = distanceTo(point.x, point.y); + point.putWeak(); + return result; + } + + /** + * Calculate the distance to another position + * @since 6.0.0 + * + * @return The distance between the two positions as a Float. + */ + public overload inline extern function distanceTo(x:Float, y:Float):Float + { + return Math.sqrt(distanceSquaredTo(x, y)); + } + + /** + * Calculate the squared distance to another point. + * @since 6.0.0 + * + * @param point A FlxPoint object to calculate the distance to. + * @return The distance between the two points as a Float. + */ + public overload inline extern function distanceSquaredTo(point:FlxPoint):Float { - var dx:Float = x - point.x; - var dy:Float = y - point.y; + final result = distanceSquaredTo(point.x, point.y); point.putWeak(); - return FlxMath.vectorLength(dx, dy); + return result; + } + + /** + * Calculate the distance to another position + * @since 6.0.0 + * + * @return The distance between the two positions as a Float. + */ + public overload inline extern function distanceSquaredTo(x:Float, y:Float):Float + { + return (this.x - x) * (this.x - x) + (this.y - y) + (this.y - y); } /** @@ -1181,21 +1318,36 @@ import openfl.geom.Point; /** * The distance between points + * @since 6.0.0 */ - public inline function dist(p:FlxPoint):Float + public overload inline extern function dist(x:Float, y:Float):Float { - return Math.sqrt(distSquared(p)); + return distanceTo(x, y); } + /** + * The distance between points + */ + public overload inline extern function dist(p:FlxPoint):Float + { + return distanceTo(p); + } + /** * The squared distance between points */ - public inline function distSquared(p:FlxPoint):Float + public overload inline extern function distSquared(p:FlxPoint):Float { - var dx:Float = p.x - x; - var dy:Float = p.y - y; - p.putWeak(); - return dx * dx + dy * dy; + return distanceSquaredTo(p); + } + + /** + * The squared distance between positions + * @since 6.0.0 + */ + public overload inline extern function distSquared(x:Float, y:Float):Float + { + return distanceSquaredTo(x, y); } /** @@ -1510,6 +1662,62 @@ class FlxBasePoint implements IFlxPooled } } +/** + * A point that, once set, cannot be changed. Useful for objects + * that want to expose a readonly `x` and `y` value + * @since 6.0.0 + */ +@:forward +@:forward.new +abstract FlxReadOnlyPoint(FlxPoint) from FlxPoint +{ + public var x(get, never):Float; + public var y(get, never):Float; + + /** Length of the point */ + public var length(get, never):Float; + + /** The angle formed by the point with the horizontal axis (in degrees) */ + public var degrees(get, never):Float; + + /** The angle formed by the point with the horizontal axis (in radians) */ + public var radians(get, never):Float; + + inline function get_x():Float return this.x; + inline function get_y():Float return this.y; + inline function get_length():Float return this.length; + inline function get_radians():Float return this.radians; + inline function get_degrees():Float return this.degrees; + + // hide underlying mutators + inline function set(x = 0, y = 0):FlxReadOnlyPoint return this.set(x, y); + inline function add(x = 0, y = 0):FlxReadOnlyPoint return this.add(x, y); + inline function addPoint(point):FlxReadOnlyPoint return this.add(point); + inline function subtract(x = 0, y = 0):FlxReadOnlyPoint return this.subtract(x, y); + inline function subtractPoint(point):FlxReadOnlyPoint return this.subtract(point); + inline function scale(x = 0, y = 0):FlxReadOnlyPoint return this.scale(x, y); + inline function scalePoint(point):FlxReadOnlyPoint return this.scale(point); + inline function copyFrom(point):FlxReadOnlyPoint return this.copyFrom(point); + inline function copyFromFlash(point):FlxReadOnlyPoint return this.copyFrom(point); + inline function floor():FlxReadOnlyPoint return this.floor(); + inline function ceil():FlxReadOnlyPoint return this.ceil(); + inline function round():FlxReadOnlyPoint return this.round(); + inline function rotate(pivot, degrees):FlxReadOnlyPoint return this.pivotDegrees(pivot, degrees); + inline function pivotRadians(pivot, radians):FlxReadOnlyPoint return this.pivotRadians(pivot, radians); + inline function pivotDegrees(pivot, degrees):FlxReadOnlyPoint return this.pivotDegrees(pivot, degrees); + inline function transform(matrix):FlxReadOnlyPoint return this.transform(matrix); + inline function zero():FlxReadOnlyPoint return this.zero(); + inline function normalize():FlxReadOnlyPoint return this.normalize(); + inline function rotateByRadians(rads):FlxReadOnlyPoint return this.rotateByRadians(rads); + inline function rotateByDegrees(degs):FlxReadOnlyPoint return this.rotateByDegrees(degs); + inline function rotateWithTrig(sin, cos):FlxReadOnlyPoint return this.rotateWithTrig(sin, cos); + inline function setPolarRadians(length, radians):FlxReadOnlyPoint return this.setPolarRadians(length, radians); + inline function setPolarDegrees(length, degrees):FlxReadOnlyPoint return this.setPolarDegrees(length, degrees); + inline function negate():FlxReadOnlyPoint return this.negate(); + inline function truncate(max):FlxReadOnlyPoint return this.truncate(max); + inline function bounce(normal, coeff = 1.0):FlxReadOnlyPoint return this.bounce(normal, coeff); + inline function bounceWithFriction(normal, coeff = 1.0, friction = 0.0):FlxReadOnlyPoint return this.bounce(normal, coeff); +} /** * A FlxPoint that calls a function when set_x(), set_y() or set() is called. Used in FlxSpriteGroup. diff --git a/flixel/path/FlxPath.hx b/flixel/path/FlxPath.hx index bebfc54d21..6cfcb3316e 100644 --- a/flixel/path/FlxPath.hx +++ b/flixel/path/FlxPath.hx @@ -71,7 +71,7 @@ private class AnchorTools case TOP_LEFT: result; case CUSTOM(offset): - result.addPoint(offset); + result.add(offset); } } } @@ -399,7 +399,7 @@ class FlxPath extends FlxBasePath } else { - var velocity = object.velocity.copyFrom(node).subtractPoint(_point); + var velocity = object.velocity.copyFrom(node).subtract(_point); velocity.length = speed; angle = velocity.degrees; } diff --git a/flixel/system/debug/log/BitmapLog.hx b/flixel/system/debug/log/BitmapLog.hx index a973d35c06..e08feb6c4a 100644 --- a/flixel/system/debug/log/BitmapLog.hx +++ b/flixel/system/debug/log/BitmapLog.hx @@ -153,7 +153,7 @@ class BitmapLog extends Window if (_middleMouseDown) { var delta = FlxPoint.get(mouseX, mouseY); - _curMouseOffset.addPoint(delta.subtractPoint(_lastMousePos)); + _curMouseOffset.add(delta.subtract(_lastMousePos)); refreshCanvas(); _lastMousePos.set(mouseX, mouseY); } @@ -309,7 +309,7 @@ class BitmapLog extends Window _point.x = (_canvas.width / 2) - (_curBitmap.width * zoom / 2); _point.y = (_canvas.height / 2) - (_curBitmap.height * zoom / 2); - _point.addPoint(_curMouseOffset); + _point.add(_curMouseOffset); _matrix.identity(); _matrix.scale(zoom, zoom); diff --git a/flixel/text/FlxText.hx b/flixel/text/FlxText.hx index f7228b9ce1..c768fd654a 100644 --- a/flixel/text/FlxText.hx +++ b/flixel/text/FlxText.hx @@ -1032,11 +1032,11 @@ class FlxText extends FlxSprite override function drawSimple(camera:FlxCamera):Void { // same as super but checks _graphicOffset - getScreenPosition(_point, camera).subtractPoint(offset).subtractPoint(_graphicOffset); + getScreenPosition(_point, camera).subtract(offset).subtract(_graphicOffset); if (isPixelPerfectRender(camera)) _point.floor(); - _point.copyToFlash(_flashPoint); + _point.copyTo(_flashPoint); camera.copyPixels(_frame, framePixels, _flashRect, _flashPoint, colorTransform, blend, antialiasing); } @@ -1055,7 +1055,7 @@ class FlxText extends FlxSprite } // same as super but checks _graphicOffset - getScreenPosition(_point, camera).subtractPoint(offset).subtractPoint(_graphicOffset); + getScreenPosition(_point, camera).subtract(offset).subtract(_graphicOffset); _point.add(origin.x, origin.y); _matrix.translate(_point.x, _point.y); diff --git a/flixel/tile/FlxBaseTilemap.hx b/flixel/tile/FlxBaseTilemap.hx index ce637a0e5c..4858ac21b3 100644 --- a/flixel/tile/FlxBaseTilemap.hx +++ b/flixel/tile/FlxBaseTilemap.hx @@ -1603,7 +1603,7 @@ class FlxBaseTilemap extends FlxObject if (camera == null) camera = getDefaultCamera(); - worldPoint.subtractPoint(camera.scroll); + worldPoint.subtract(camera.scroll); worldPoint.putWeak(); } diff --git a/flixel/tile/FlxTilemap.hx b/flixel/tile/FlxTilemap.hx index 05d90ca10a..cee1fe130b 100644 --- a/flixel/tile/FlxTilemap.hx +++ b/flixel/tile/FlxTilemap.hx @@ -673,7 +673,7 @@ class FlxTypedTilemap extends FlxBaseTilemap if (buffer.isDirty(this, camera)) drawTilemap(buffer, camera); - getScreenPosition(_point, camera).subtractPoint(offset).add(buffer.x, buffer.y).copyToFlash(_flashPoint); + getScreenPosition(_point, camera).subtract(offset).add(buffer.x, buffer.y).copyTo(_flashPoint); buffer.draw(camera, _flashPoint, scale.x, scale.y); } else @@ -1232,7 +1232,7 @@ class FlxTypedTilemap extends FlxBaseTilemap } else { - getScreenPosition(_point, camera).subtractPoint(offset).copyToFlash(_helperPoint); + getScreenPosition(_point, camera).subtractPoint(offset).copyTo(_helperPoint); _helperPoint.x = isPixelPerfectRender(camera) ? Math.floor(_helperPoint.x) : _helperPoint.x; _helperPoint.y = isPixelPerfectRender(camera) ? Math.floor(_helperPoint.y) : _helperPoint.y; diff --git a/flixel/ui/FlxAnalog.hx b/flixel/ui/FlxAnalog.hx index c2888b234a..98c96b15ed 100644 --- a/flixel/ui/FlxAnalog.hx +++ b/flixel/ui/FlxAnalog.hx @@ -2,7 +2,7 @@ package flixel.ui; import flixel.FlxG; import flixel.FlxSprite; -import flixel.group.FlxSpriteGroup; +import flixel.group.FlxSpriteContainer; import flixel.input.touch.FlxTouch; import flixel.math.FlxAngle; import flixel.math.FlxMath; @@ -16,7 +16,8 @@ import flixel.util.FlxDestroyUtil; * * @author Ka Wing Chin */ -class FlxAnalog extends FlxSpriteGroup +@:deprecated("FlxAnalog is deprecated, use FlxVirtualStick or FlxVirtualPad, instead") +class FlxAnalog extends FlxSpriteContainer { /** * Shows the current state of the button. diff --git a/flixel/ui/FlxBar.hx b/flixel/ui/FlxBar.hx index 11997a8c72..dcc0ac13d1 100644 --- a/flixel/ui/FlxBar.hx +++ b/flixel/ui/FlxBar.hx @@ -880,7 +880,7 @@ class FlxBar extends FlxSprite _matrix.rotateWithTrig(_cosAngle, _sinAngle); } - getScreenPosition(_point, camera).subtractPoint(offset); + getScreenPosition(_point, camera).subtract(offset); _point.add(origin.x, origin.y); _matrix.translate(_point.x, _point.y); diff --git a/flixel/ui/FlxButton.hx b/flixel/ui/FlxButton.hx index 8c404a7319..d30f35318b 100644 --- a/flixel/ui/FlxButton.hx +++ b/flixel/ui/FlxButton.hx @@ -31,6 +31,22 @@ enum abstract FlxButtonState(Int) to Int /** The button is not interactible */ var DISABLED = 3; + + public function toInt() + { + return this; + } + + public function toString() + { + return switch (cast this:FlxButtonState) + { + case NORMAL: "normal"; + case HIGHLIGHT: "highlight"; + case PRESSED: "pressed"; + case DISABLED: "disabled"; + } + } } /** @@ -108,9 +124,9 @@ class FlxButton extends FlxTypedButton { if (Text != null) { - label = new FlxText(x + labelOffsets[FlxButtonState.NORMAL].x, y + labelOffsets[FlxButtonState.NORMAL].y, 80, Text); + label = new FlxText(x + labelOffsets[FlxButtonState.NORMAL.toInt()].x, y + labelOffsets[FlxButtonState.NORMAL.toInt()].y, 80, Text); label.setFormat(null, 8, 0x333333, "center"); - label.alpha = labelAlphas[status]; + label.alpha = labelAlphas[status.toInt()]; label.drawFrame(true); } } @@ -162,6 +178,7 @@ class FlxTypedButton extends FlxSprite implements IFlxInput * What animation should be played for each status. * Default is ["normal", "highlight", "pressed"]. */ + @:deprecated("statusAnimations is deprecated, use status.toString(), instead") public var statusAnimations:Array = ["normal", "highlight", "pressed", "disabled"]; /** @@ -230,7 +247,7 @@ class FlxTypedButton extends FlxSprite implements IFlxInput */ var currentInput:IFlxInput; - var lastStatus = -1; + var lastStatus:FlxButtonState = cast -1; /** * Creates a new `FlxTypedButton` object with a gray background. @@ -260,8 +277,7 @@ class FlxTypedButton extends FlxSprite implements IFlxInput #end #if FLX_NO_MOUSE // no need for highlight frame without mouse input - statusAnimations[HIGHLIGHT] = "normal"; - labelAlphas[HIGHLIGHT] = 1; + labelAlphas[HIGHLIGHT.toInt()] = 1; #end input = new FlxInput(0); @@ -271,10 +287,10 @@ class FlxTypedButton extends FlxSprite implements IFlxInput { super.graphicLoaded(); - setupAnimation("normal", NORMAL); - setupAnimation("highlight", HIGHLIGHT); - setupAnimation("pressed", PRESSED); - setupAnimation("disabled", DISABLED); + setupAnimation("normal", NORMAL.toInt()); + setupAnimation("highlight", (#if FLX_MOUSE HIGHLIGHT #else NORMAL #end).toInt()); + setupAnimation("pressed", PRESSED.toInt()); + setupAnimation("disabled", DISABLED.toInt()); } function loadDefaultGraphic():Void @@ -342,7 +358,7 @@ class FlxTypedButton extends FlxSprite implements IFlxInput function updateStatusAnimation():Void { - animation.play(statusAnimations[status]); + animation.play(status.toString()); } /** @@ -472,7 +488,7 @@ class FlxTypedButton extends FlxSprite implements IFlxInput function checkInput(pointer:FlxPointer, input:IFlxInput, justPressedPosition:FlxPoint, camera:FlxCamera):Bool { if (maxInputMovement != Math.POSITIVE_INFINITY - && justPressedPosition.distanceTo(pointer.getViewPosition(FlxPoint.weak())) > maxInputMovement + && justPressedPosition.distanceTo(pointer.getViewPosition(camera, FlxPoint.weak())) > maxInputMovement && input == currentInput) { currentInput = null; @@ -514,16 +530,16 @@ class FlxTypedButton extends FlxSprite implements IFlxInput { if (_spriteLabel != null) // Label positioning { - _spriteLabel.x = (pixelPerfectPosition ? Math.floor(x) : x) + labelOffsets[status].x; - _spriteLabel.y = (pixelPerfectPosition ? Math.floor(y) : y) + labelOffsets[status].y; + _spriteLabel.x = (pixelPerfectPosition ? Math.floor(x) : x) + labelOffsets[status.toInt()].x; + _spriteLabel.y = (pixelPerfectPosition ? Math.floor(y) : y) + labelOffsets[status.toInt()].y; } } function updateLabelAlpha() { - if (_spriteLabel != null && labelAlphas.length > (status : Int)) + if (_spriteLabel != null && labelAlphas.length > status.toInt()) { - _spriteLabel.alpha = alpha * labelAlphas[status]; + _spriteLabel.alpha = alpha * labelAlphas[status.toInt()]; } } diff --git a/flixel/ui/FlxVirtualPad.hx b/flixel/ui/FlxVirtualPad.hx index d313bc5059..37b0a5cbce 100644 --- a/flixel/ui/FlxVirtualPad.hx +++ b/flixel/ui/FlxVirtualPad.hx @@ -1,11 +1,14 @@ package flixel.ui; +import flixel.ui.FlxAnalog; import flixel.FlxG; import flixel.graphics.frames.FlxTileFrames; -import flixel.group.FlxSpriteGroup; +import flixel.group.FlxSpriteContainer; import flixel.math.FlxPoint; import flixel.system.FlxAssets; +import flixel.util.FlxColor; import flixel.util.FlxDestroyUtil; +import flixel.util.FlxSpriteUtil; /** * A gamepad which contains 4 directional buttons and 4 action buttons. @@ -13,137 +16,202 @@ import flixel.util.FlxDestroyUtil; * * @author Ka Wing Chin */ -class FlxVirtualPad extends FlxSpriteGroup +class FlxVirtualPad extends FlxSpriteContainer { - public var buttonA:FlxButton; - public var buttonB:FlxButton; - public var buttonC:FlxButton; - public var buttonY:FlxButton; - public var buttonX:FlxButton; - public var buttonLeft:FlxButton; - public var buttonUp:FlxButton; - public var buttonRight:FlxButton; - public var buttonDown:FlxButton; - /** * Group of directions buttons. */ - public var dPad:FlxSpriteGroup; - + public final dPad:Null; + /** * Group of action buttons. */ - public var actions:FlxSpriteGroup; - + public final actions:FlxVirtualActionButtons; + + /** + * An Analog directional input + */ + public final stick:Null; + + @:deprecated("buttonA is deprecated, use getButton(A), instead") + public var buttonA(get, never):Null; + inline function get_buttonA() return actions.getButton(A); + + @:deprecated("buttonB is deprecated, use getButton(B), instead") + public var buttonB(get, never):Null; + inline function get_buttonB() return actions.getButton(B); + + @:deprecated("buttonC is deprecated, use getButton(C), instead") + public var buttonC(get, never):Null; + inline function get_buttonC() return actions.getButton(C); + + @:deprecated("buttonY is deprecated, use getButton(Y), instead") + public var buttonY(get, never):Null; + inline function get_buttonY() return actions.getButton(Y); + + @:deprecated("buttonX is deprecated, use getButton(X), instead") + public var buttonX(get, never):Null; + inline function get_buttonX() return actions.getButton(X); + + @:deprecated("buttonLeft is deprecated, use getButton(LEFT), instead") + public var buttonLeft(get, never):Null; + inline function get_buttonLeft() return dPad.getButton(LEFT); + + @:deprecated("buttonUp is deprecated, use getButton(UP), instead") + public var buttonUp(get, never):Null; + inline function get_buttonUp() return dPad.getButton(UP); + + @:deprecated("buttonRight is deprecated, use getButton(RIGHT), instead") + public var buttonRight(get, never):Null; + inline function get_buttonRight() return dPad.getButton(RIGHT); + + @:deprecated("buttonDown is deprecated, use getButton(DOWN), instead") + public var buttonDown(get, never):Null; + inline function get_buttonDown() return dPad.getButton(DOWN); + /** * Create a gamepad which contains 4 directional buttons and 4 action buttons. * * @param DPadMode The D-Pad mode. `FULL` for example. * @param ActionMode The action buttons mode. `A_B_C` for example. */ - public function new(?DPad:FlxDPadMode, ?Action:FlxActionMode) + public function new(dPadMode = FlxDPadMode.FULL, actionMode = FlxActionMode.A_B_C) { super(); scrollFactor.set(); + + add(actions = new FlxVirtualActionButtons(0, 0, actionMode)); + actions.x = FlxG.width - actions.width; + + switch dPadMode + { + case ANALOG: + add(stick = new FlxVirtualStick()); + stick.y = height - stick.height; + default: + add(dPad = new FlxVirtualDPadButtons(0, 0, dPadMode)); + dPad.y = height - dPad.height; + } + actions.y = height - actions.height; + + y = FlxG.height - height; + + #if FLX_DEBUG + this.ignoreDrawDebug = true; + #end + } + + public function getButton(id:FlxVirtualInputID) + { + return switch id + { + case A | B | C | X | Y: actions.getButton(id); + case UP | DOWN | LEFT | RIGHT if (dPad == null): null; + case UP | DOWN | LEFT | RIGHT: dPad.getButton(id); + case STICK: null; + } + } +} - if (DPad == null) - DPad = FULL; - if (Action == null) - Action = A_B_C; - - dPad = new FlxSpriteGroup(); - dPad.scrollFactor.set(); - - actions = new FlxSpriteGroup(); - actions.scrollFactor.set(); +class FlxVirtualPadButtons extends FlxTypedSpriteContainer +{ + final buttons = new Map(); + + public function new (x = 0.0, y = 0.0) + { + super(x, y); + scrollFactor.set(); + + #if FLX_DEBUG + this.ignoreDrawDebug = true; + #end + } + + override public function destroy():Void + { + super.destroy(); + + buttons.clear(); + } + + public function addButton(x = 0.0, y = 0.0, id, ?onClick) + { + return buttons[id] = add(new FlxVirtualPadButton(x, y, id, onClick)); + } + + public function getButton(id) + { + return buttons[id]; + } +} - switch (DPad) +class FlxVirtualDPadButtons extends FlxVirtualPadButtons +{ + public function new (x = 0.0, y = 0.0, mode:FlxDPadMode) + { + super(x, y); + switch (mode) { case UP_DOWN: - dPad.add(add(buttonUp = createButton(0, FlxG.height - 85, 44, 45, "up"))); - dPad.add(add(buttonDown = createButton(0, FlxG.height - 45, 44, 45, "down"))); + addButton( 0, 0, UP ); + addButton( 0, 40, DOWN ); case LEFT_RIGHT: - dPad.add(add(buttonLeft = createButton(0, FlxG.height - 45, 44, 45, "left"))); - dPad.add(add(buttonRight = createButton(42, FlxG.height - 45, 44, 45, "right"))); + addButton( 0, 0, LEFT ); + addButton(42, 0, RIGHT); case UP_LEFT_RIGHT: - dPad.add(add(buttonUp = createButton(35, FlxG.height - 81, 44, 45, "up"))); - dPad.add(add(buttonLeft = createButton(0, FlxG.height - 45, 44, 45, "left"))); - dPad.add(add(buttonRight = createButton(69, FlxG.height - 45, 44, 45, "right"))); + addButton(35, 0, UP ); + addButton( 0, 36, LEFT ); + addButton(69, 36, RIGHT); case FULL: - dPad.add(add(buttonUp = createButton(35, FlxG.height - 116, 44, 45, "up"))); - dPad.add(add(buttonLeft = createButton(0, FlxG.height - 81, 44, 45, "left"))); - dPad.add(add(buttonRight = createButton(69, FlxG.height - 81, 44, 45, "right"))); - dPad.add(add(buttonDown = createButton(35, FlxG.height - 45, 44, 45, "down"))); + addButton(35, 0, UP ); + addButton( 0, 35, LEFT ); + addButton(69, 35, RIGHT); + addButton(35, 71, DOWN ); + case ANALOG: throw "Unexpected mode: ANALOG"; case NONE: // do nothing } + } +} - switch (Action) +class FlxVirtualActionButtons extends FlxVirtualPadButtons +{ + public function new (x = 0.0, y = 0.0, mode:FlxActionMode) + { + super(x, y); + switch (mode) { case A: - actions.add(add(buttonA = createButton(FlxG.width - 44, FlxG.height - 45, 44, 45, "a"))); + addButton( 0, 0, A); case A_B: - actions.add(add(buttonA = createButton(FlxG.width - 44, FlxG.height - 45, 44, 45, "a"))); - actions.add(add(buttonB = createButton(FlxG.width - 86, FlxG.height - 45, 44, 45, "b"))); + addButton(42, 0, A); + addButton( 0, 0, B); case A_B_C: - actions.add(add(buttonA = createButton(FlxG.width - 128, FlxG.height - 45, 44, 45, "a"))); - actions.add(add(buttonB = createButton(FlxG.width - 86, FlxG.height - 45, 44, 45, "b"))); - actions.add(add(buttonC = createButton(FlxG.width - 44, FlxG.height - 45, 44, 45, "c"))); + addButton( 0, 0, A); + addButton(42, 0, B); + addButton(84, 0, C); case A_B_X_Y: - actions.add(add(buttonY = createButton(FlxG.width - 86, FlxG.height - 85, 44, 45, "y"))); - actions.add(add(buttonX = createButton(FlxG.width - 44, FlxG.height - 85, 44, 45, "x"))); - actions.add(add(buttonB = createButton(FlxG.width - 86, FlxG.height - 45, 44, 45, "b"))); - actions.add(add(buttonA = createButton(FlxG.width - 44, FlxG.height - 45, 44, 45, "a"))); + addButton( 0, 0, Y); + addButton(42, 0, X); + addButton( 0, 40, B); + addButton(42, 40, A); case NONE: // do nothing } } +} - override public function destroy():Void - { - super.destroy(); - - dPad = FlxDestroyUtil.destroy(dPad); - actions = FlxDestroyUtil.destroy(actions); - - dPad = null; - actions = null; - buttonA = null; - buttonB = null; - buttonC = null; - buttonY = null; - buttonX = null; - buttonLeft = null; - buttonUp = null; - buttonDown = null; - buttonRight = null; - } - - /** - * @param X The x-position of the button. - * @param Y The y-position of the button. - * @param Width The width of the button. - * @param Height The height of the button. - * @param Graphic The image of the button. It must contains 3 frames (`NORMAL`, `HIGHLIGHT`, `PRESSED`). - * @param Callback The callback for the button. - * @return The button - */ - public function createButton(X:Float, Y:Float, Width:Int, Height:Int, Graphic:String, ?OnClick:Void->Void):FlxButton +@:forward +abstract FlxVirtualPadButton(FlxButton) to FlxButton +{ + public function new(x = 0.0, y = 0.0, id:FlxVirtualInputID, ?onClick) { - var button = new FlxButton(X, Y); - var frame = FlxAssets.getVirtualInputFrames().getByName(Graphic); - button.frames = FlxTileFrames.fromFrame(frame, FlxPoint.get(Width, Height)); - button.resetSizeFromFrame(); - button.solid = false; - button.immovable = true; - button.scrollFactor.set(); + this = new FlxButton(x, y, null, onClick); + this.frames = id.getFrames(); + this.resetSizeFromFrame(); + this.moves = true; #if FLX_DEBUG - button.ignoreDrawDebug = true; + this.ignoreDrawDebug = true; #end - - if (OnClick != null) - button.onDown.callback = OnClick; - - return button; } } @@ -154,6 +222,7 @@ enum FlxDPadMode LEFT_RIGHT; UP_LEFT_RIGHT; FULL; + ANALOG; } enum FlxActionMode @@ -164,3 +233,41 @@ enum FlxActionMode A_B_C; A_B_X_Y; } + +@:using(flixel.ui.FlxVirtualPad.FlxVirtualInputIDTools) +enum FlxVirtualInputID +{ + UP; + DOWN; + LEFT; + RIGHT; + A; + B; + C; + X; + Y; + STICK; +} + +private class FlxVirtualInputIDTools +{ + public static function getFrames(id:FlxVirtualInputID) + { + final name = switch id + { + case UP: "up"; + case DOWN: "down"; + case LEFT: "left"; + case RIGHT: "right"; + case A: "a"; + case B: "b"; + case C: "c"; + case X: "x"; + case Y: "y"; + case STICK: "stick"; + } + + final frame = FlxAssets.getVirtualInputFrames().getByName(name); + return FlxTileFrames.fromFrame(frame, FlxPoint.get(44, 45)); + } +} \ No newline at end of file diff --git a/flixel/ui/FlxVirtualStick.hx b/flixel/ui/FlxVirtualStick.hx new file mode 100644 index 0000000000..c278f654e1 --- /dev/null +++ b/flixel/ui/FlxVirtualStick.hx @@ -0,0 +1,293 @@ +package flixel.ui; + +import flixel.util.FlxColor; +import flixel.FlxG; +import flixel.FlxSprite; +import flixel.group.FlxSpriteContainer; +import flixel.input.FlxPointer; +import flixel.input.actions.FlxActionInputAnalog; +import flixel.input.touch.FlxTouch; +import flixel.math.FlxAngle; +import flixel.math.FlxMath; +import flixel.math.FlxPoint; +import flixel.math.FlxRect; +import flixel.system.FlxAssets; +import flixel.ui.FlxButton; +import flixel.util.FlxDestroyUtil; +import flixel.util.FlxSignal; + +/** + * A virtual thumbstick - useful for input on mobile devices. + */ +class FlxVirtualStick extends FlxSpriteContainer +{ + /** The current state of the button */ + public final value:FlxReadOnlyPoint = FlxPoint.get(); + + /** The top of the joystick, the part that moves */ + public final thumb:CircleSprite; + + /** The background of the joystick, also known as the base */ + public final base:CircleSprite; + + /** The radius in which the stick can move */ + public final radius:Float; + + /** Used to smooth the thumb's motion. Should be between 0 and 1.0. */ + public var lerp:Float = 0.25; + + /** The minimum absolute value, to consider this input active */ + public var deadzone = 0.1; + + public final onJustMove = new FlxSignal(); + public final onJustStop = new FlxSignal(); + public final onMove = new FlxSignal(); + + public var xStatus(default, null) = FlxAnalogState.STOPPED; + public var yStatus(default, null) = FlxAnalogState.STOPPED; + public var status(default, null) = FlxAnalogState.STOPPED; + + /** Used to track press events */ + final button:InvisibleCircleButton; + + var dragging = false; + + /** + * Create a virtual thumbstick - useful for input on mobile devices. + * + * @param x The location in screen space. + * @param y The location in screen space. + * @param radius The radius where the thumb can move. If 0, half the base's width will be used. + * @param baseGraphic The graphic you want to display as base of the joystick. + * @param thumbGraphic The graphic you want to display as thumb of the joystick. + */ + public function new(x = 0.0, y = 0.0, radius = 0.0, ?baseGraphic:FlxGraphicAsset, ?thumbGraphic:FlxGraphicAsset) + { + super(x, y); + + add(base = new CircleSprite(0, 0, baseGraphic, "base")); + add(thumb = new CircleSprite(0, 0, thumbGraphic, "thumb")); + + if (radius <= 0) + radius = base.radius; + this.radius = radius; + + base.x += radius; + base.y += radius; + thumb.x += radius; + thumb.y += radius; + + add(button = new InvisibleCircleButton(0, 0, this.radius)); + + moves = false; + solid = false; + + FlxG.watch.addFunction("stick.state", ()->button.status.toString()); + FlxG.watch.addFunction("base.x|y", ()->'${base.x} | ${base.y}'); + FlxG.watch.addFunction("thumb.x|y", ()->'${thumb.x} | ${thumb.y}'); + } + + override function destroy() + { + super.destroy(); + + thumb.destroy(); + base.destroy(); + + onJustMove.removeAll(); + onJustStop.removeAll(); + onMove.removeAll(); + } + + override function update(elapsed:Float) + { + super.update(elapsed); + + updateValue(cast value); + + final adjustedLerp = FlxMath.getElapsedLerp(lerp, elapsed); + final newX = x + radius - thumb.radius + value.x * radius; + final newY = y + radius - thumb.radius + value.y * radius; + thumb.x += (newX - thumb.x) * adjustedLerp; + thumb.y += (newY - thumb.y) * adjustedLerp; + } + + function updateValue(pos:FlxPoint) + { + final oldX = value.x; + final oldY = value.y; + + if (button.justPressed) + dragging = true; + else if (button.released && dragging) + dragging = false; + + final pos:FlxPoint = cast value; + if (dragging) + { + button.calcDeltaToPointer(getCameras()[0], pos); + pos.scale(1 / radius); + if (pos.lengthSquared > 1.0) + pos.normalize(); + + if (pos.x < deadzone && pos.x > -deadzone) + pos.x = 0; + + if (pos.y < deadzone && pos.y > -deadzone) + pos.y = 0; + } + else + pos.zero(); + + xStatus = getStatus(oldX, value.x); + yStatus = getStatus(oldY, value.y); + + if ((yStatus.justMoved && xStatus == STOPPED) || (xStatus.justMoved && yStatus == STOPPED)) + { + status = JUST_MOVED; + onJustMove.dispatch(); + onMove.dispatch(); + } + else if ((yStatus.justStopped && xStatus.stopped) || (xStatus.justStopped && yStatus.stopped)) + { + status = JUST_STOPPED; + onJustStop.dispatch(); + } + else if (xStatus.moved || yStatus.moved) + { + status = MOVED; + onMove.dispatch(); + } + else + { + status = STOPPED; + } + } + + function getStatus(prev:Float, curr:Float) + { + return if (prev == 0 && curr != 0) + JUST_MOVED; + else if (prev != 0 && curr != 0) + MOVED; + else if (prev != 0 && curr == 0) + JUST_STOPPED; + else if (prev == 0 && curr == 0) + STOPPED; + else + throw 'Unexpected case - prev: $prev, curr:$curr';// not possible + } +} + +@:forward +@:forward.new +abstract CircleSprite(FlxSprite) to FlxSprite +{ + public var radius(get, never):Float; + public var radiusSquared(get, never):Float; + + public function new (centerX = 0.0, centerY = 0.0, graphic, ?backupId:String) + { + this = new FlxSprite(centerX, centerY, graphic); + if (graphic == null) + { + this.frames = FlxAssets.getVirtualInputFrames(); + this.animation.frameName = backupId; + this.resetSizeFromFrame(); + } + this.x -= radius; + this.y -= radius; + this.moves = false; + + #if FLX_DEBUG + // this.ignoreDrawDebug = true; + #end + } + + inline function get_radius() return this.frameWidth * 0.5; + inline function get_radiusSquared() return radius * radius; +} + +/** + * Special button that covers the virtual stick and tracks mouse and touch + */ +class InvisibleCircleButton extends FlxTypedButton +{ + public var radius(get, never):Float; + public var lastPointer(default, null):Null; + + inline function get_radius():Float return frameWidth * 0.5; + + public function new (x = 0.0, y = 0.0, radius:Float, ?onClick) + { + super(x, y, onClick); + final size = Math.ceil(radius * 2); + loadGraphic(FlxG.bitmap.create(size, size * 4, FlxColor.WHITE), true, size, size); + } + + override function draw() + { + #if FLX_DEBUG + if (FlxG.debugger.drawDebug) + drawDebug(); + #end + } + + override function checkInput(pointer, input, justPressedPosition, camera):Bool + { + if (super.checkInput(pointer, input, justPressedPosition, camera)) + { + lastPointer = pointer; + return true; + } + + return false; + } + + override function updateButton() + { + if (currentInput != null) + { + if (currentInput.justReleased) + onUpHandler(); + return; + } + + super.updateButton(); + } + + override function onUpHandler() + { + super.onUpHandler(); + lastPointer = null; + } + + override function overlapsPoint(point:FlxPoint, inScreenSpace = false, ?camera:FlxCamera):Bool + { + if (!inScreenSpace) + return point.distanceSquaredTo(x + radius, y + radius) < radius * radius; + + if (camera == null) + camera = getCameras()[0]; + + return calcDeltaTo(point, camera, _point).lengthSquared < radius * radius; + } + + public function calcDeltaTo(point:FlxPoint, camera:FlxCamera, ?result:FlxPoint) + { + if (result == null) + result = FlxPoint.get(); + + final xPos = point.x - camera.scroll.x - radius; + final yPos = point.y - camera.scroll.y - radius; + getScreenPosition(result, camera); + point.putWeak(); + return result.subtract(xPos, yPos).negate(); + } + + public function calcDeltaToPointer(camera:FlxCamera, ?result:FlxPoint) + { + final point = lastPointer.getViewPosition(camera, FlxPoint.weak()); + return calcDeltaTo(point, camera, result); + } +} \ No newline at end of file diff --git a/flixel/util/FlxSpriteUtil.hx b/flixel/util/FlxSpriteUtil.hx index ad34e7da04..1846835606 100644 --- a/flixel/util/FlxSpriteUtil.hx +++ b/flixel/util/FlxSpriteUtil.hx @@ -458,8 +458,8 @@ class FlxSpriteUtil * This function draws a circle on a FlxSprite at position X,Y with the specified color. * * @param sprite The FlxSprite to manipulate - * @param X X coordinate of the circle's center (automatically centered on the sprite if -1) - * @param Y Y coordinate of the circle's center (automatically centered on the sprite if -1) + * @param X X coordinate of the circle's center (automatically centered on the bitmap if -1) + * @param Y Y coordinate of the circle's center (automatically centered on the bitmap if -1) * @param Radius Radius of the circle (makes sure the circle fully fits on the sprite's graphic if < 1, assuming and and y are centered) * @param FillColor The ARGB color to fill this circle with. FlxColor.TRANSPARENT (0x0) means no fill. * @param lineStyle A LineStyle typedef containing the params of Graphics.lineStyle() @@ -471,14 +471,10 @@ class FlxSpriteUtil { if (X == -1 || Y == -1) { - var midPoint = sprite.getGraphicMidpoint(); - if (X == -1) - X = midPoint.x - sprite.x; + X = sprite.frameWidth / 2; if (Y == -1) - Y = midPoint.y - sprite.y; - - midPoint.put(); + Y = sprite.frameHeight / 2; } if (Radius < 1) diff --git a/tests/unit/src/flixel/ui/FlxButtonTest.hx b/tests/unit/src/flixel/ui/FlxButtonTest.hx index 943c7c261e..1f3023ea9a 100644 --- a/tests/unit/src/flixel/ui/FlxButtonTest.hx +++ b/tests/unit/src/flixel/ui/FlxButtonTest.hx @@ -46,13 +46,9 @@ class FlxButtonTest extends FlxTest function assertStatusAnimationsExist() { - var normalName:String = button.statusAnimations[NORMAL]; - var highlightName:String = button.statusAnimations[HIGHLIGHT]; - var pressedName:String = button.statusAnimations[PRESSED]; - - Assert.isNotNull(button.animation.getByName(normalName)); - Assert.isNotNull(button.animation.getByName(highlightName)); - Assert.isNotNull(button.animation.getByName(pressedName)); + Assert.isNotNull(button.animation.getByName(NORMAL.toString())); + Assert.isNotNull(button.animation.getByName(HIGHLIGHT.toString())); + Assert.isNotNull(button.animation.getByName(PRESSED.toString())); } @Test // #1479 From 27a756b1b37a5f55e85e584c956394a3dfef9e41 Mon Sep 17 00:00:00 2001 From: Flainn Date: Wed, 29 Jan 2025 23:49:06 -0400 Subject: [PATCH 93/99] Remove unused legacy code & defines (#3059) * Remove legacy code & defines - Removed `FLX_POST_PROCESS` define & related code - Removed references to `openfl_next`, `lime_legacy` & `next` defines - Removed Lime & OpenFL version checks that are always true/false due to the current minimum versions * Removed `legacy` define being set in include.xml * Re-added `#if !flash` check in `initRenderMethod` I mistakenly removed the entire code due to it including `lime_legacy`. * Brought back `undump()` & `canBeDumped` as `refreshBitmap()` & `canBeRefreshed` respectively (old ones are now deprecated) - Also brought back `onAssetsReload()` & `getBitmapFromSystem()` * Added missing line breaks * remove old import * Remove another deprecated define * Restored mistakenly-removed define check * Rename `refreshBitmap()` to `refresh()` --------- Co-authored-by: George FunBook --- checkstyle.json | 1 - flixel/FlxCamera.hx | 2 - flixel/FlxG.hx | 83 +----- flixel/FlxGame.hx | 68 +---- flixel/effects/postprocess/PostProcess.hx | 260 ------------------- flixel/effects/postprocess/Shader.hx | 99 ------- flixel/graphics/FlxGraphic.hx | 75 ++---- flixel/graphics/tile/FlxDrawQuadsItem.hx | 10 +- flixel/graphics/tile/FlxDrawTrianglesItem.hx | 2 - flixel/input/android/FlxAndroidKey.hx | 4 +- flixel/system/FlxAssets.hx | 4 +- flixel/system/FlxBasePreloader.hx | 17 +- flixel/system/debug/console/Console.hx | 14 +- flixel/system/frontEnds/BitmapFrontEnd.hx | 53 +--- flixel/system/macros/FlxDefines.hx | 12 +- flixel/text/FlxText.hx | 1 - flixel/util/FlxSpriteUtil.hx | 22 +- include.xml | 2 - 18 files changed, 58 insertions(+), 671 deletions(-) delete mode 100644 flixel/effects/postprocess/PostProcess.hx delete mode 100644 flixel/effects/postprocess/Shader.hx diff --git a/checkstyle.json b/checkstyle.json index d350375773..a1f2045fd4 100644 --- a/checkstyle.json +++ b/checkstyle.json @@ -5,7 +5,6 @@ "FLX_NATIVE_CURSOR", "FLX_SOUND_TRAY", "FLX_POINTER_INPUT", - "FLX_POST_PROCESS", "FLX_RECORD" ], "defineCombinations": [ diff --git a/flixel/FlxCamera.hx b/flixel/FlxCamera.hx index 118b3a601f..7907da3c88 100644 --- a/flixel/FlxCamera.hx +++ b/flixel/FlxCamera.hx @@ -1676,9 +1676,7 @@ class FlxCamera extends FlxBasic final targetGraphics = (graphics == null) ? canvas.graphics : graphics; - #if (openfl > "8.7.0") targetGraphics.overrideBlendMode(null); - #end targetGraphics.beginFill(Color, FxAlpha); // i'm drawing rect with these parameters to avoid light lines at the top and left of the camera, // which could appear while cameras fading diff --git a/flixel/FlxG.hx b/flixel/FlxG.hx index 2e65a37dfc..8da349830d 100644 --- a/flixel/FlxG.hx +++ b/flixel/FlxG.hx @@ -1,6 +1,5 @@ package flixel; -import flixel.effects.postprocess.PostProcess; import flixel.math.FlxMath; import flixel.math.FlxRandom; import flixel.math.FlxRect; @@ -50,12 +49,6 @@ import flixel.input.FlxAccelerometer; #if FLX_POINTER_INPUT import flixel.input.FlxSwipe; #end -#if FLX_POST_PROCESS -import flixel.util.FlxDestroyUtil; -import openfl.display.OpenGLView; - -using flixel.util.FlxArrayUtil; -#end #if html5 import flixel.system.frontEnds.HTML5FrontEnd; @@ -515,62 +508,6 @@ class FlxG return child; } - public static function addPostProcess(postProcess:PostProcess):PostProcess - { - #if FLX_POST_PROCESS - if (OpenGLView.isSupported) - { - var postProcesses = game.postProcesses; - - // chaining - var length = postProcesses.length; - if (length > 0) - { - postProcesses[length - 1].to = postProcess; - } - - game.postProcessLayer.addChild(postProcess); - postProcesses.push(postProcess); - } - else - { - FlxG.log.error("Shaders are not supported on this platform."); - } - #end - - return postProcess; - } - - public static function removePostProcess(postProcess:PostProcess):Void - { - #if FLX_POST_PROCESS - var postProcesses = game.postProcesses; - if (postProcesses.remove(postProcess)) - { - chainPostProcesses(); - postProcess.to = null; - - FlxDestroyUtil.removeChild(game.postProcessLayer, postProcess); - } - #end - } - - #if FLX_POST_PROCESS - static function chainPostProcesses():Void - { - var postProcesses = game.postProcesses; - - if (postProcesses.length > 0) - { - for (i in 0...postProcesses.length - 1) - { - postProcesses[i].to = postProcesses[i + 1]; - } - postProcesses.last().to = null; - } - } - #end - /** * Opens a web page, by default a new tab or window. If the URL does not * already start with `"http://"` or `"https://"`, it gets added automatically. @@ -647,31 +584,13 @@ class FlxG static function initRenderMethod():Void { - renderMethod = BLITTING; - - #if (!lime_legacy && !flash) - #if (lime >= "7.0.0") + #if !flash renderMethod = switch (stage.window.context.type) { case OPENGL, OPENGLES, WEBGL: DRAW_TILES; default: BLITTING; } #else - if (!Lib.application.config.windows[0].hardware) - { - renderMethod = BLITTING; - } - else - { - renderMethod = switch (stage.window.renderer.type) - { - case OPENGL, CONSOLE: DRAW_TILES; - case CANVAS, FLASH, CAIRO: BLITTING; - default: BLITTING; - } - } - #end - #else #if web renderMethod = BLITTING; #else diff --git a/flixel/FlxGame.hx b/flixel/FlxGame.hx index 94dc171d17..d752a04a1d 100644 --- a/flixel/FlxGame.hx +++ b/flixel/FlxGame.hx @@ -15,10 +15,6 @@ import openfl.filters.BitmapFilter; #if desktop import openfl.events.FocusEvent; #end -#if FLX_POST_PROCESS -import flixel.effects.postprocess.PostProcess; -import openfl.display.OpenGLView; -#end #if FLX_DEBUG import flixel.system.debug.FlxDebugger; #end @@ -149,14 +145,6 @@ class FlxGame extends Sprite */ var _filters:Array; - #if (desktop && lime_legacy) - /** - * Ugly workaround to ensure consistent behaviour between flash and cpp - * (the focus event should not fire when the game starts up!) - */ - var _onFocusFiredOnce:Bool = false; - #end - #if FLX_FOCUS_LOST_SCREEN /** * The "focus lost" screen. @@ -230,18 +218,6 @@ class FlxGame extends Sprite var _recordingRequested:Bool = false; #end - #if FLX_POST_PROCESS - /** - * `Sprite` for postprocessing effects - */ - var postProcessLayer:Sprite = new Sprite(); - - /** - * Post process effects active on the `postProcessLayer`. - */ - var postProcesses:Array = []; - #end - /** * Instantiate a new game object. * @@ -330,11 +306,6 @@ class FlxGame extends Sprite addChild(_inputContainer); - #if FLX_POST_PROCESS - if (OpenGLView.isSupported) - addChild(postProcessLayer); - #end - // Creating the debugger overlay #if FLX_DEBUG debugger = new FlxDebugger(FlxG.stage.stageWidth, FlxG.stage.stageHeight); @@ -356,10 +327,7 @@ class FlxGame extends Sprite #end // Focus gained/lost monitoring - #if (desktop && openfl <= "4.0.0") - stage.addEventListener(FocusEvent.FOCUS_OUT, onFocusLost); - stage.addEventListener(FocusEvent.FOCUS_IN, onFocus); - #elseif (sys && openfl >= "9.3.0") + #if (sys && openfl >= "9.3.0") stage.nativeWindow.addEventListener(Event.DEACTIVATE, onFocusLost); stage.nativeWindow.addEventListener(Event.ACTIVATE, onFocus); #else @@ -394,15 +362,6 @@ class FlxGame extends Sprite return; // Don't run this function twice (bug in standalone flash player) #end - #if (desktop && lime_legacy) - // make sure the on focus event doesn't fire on startup - if (!_onFocusFiredOnce) - { - _onFocusFiredOnce = true; - return; - } - #end - #if mobile // just check if device orientation has been changed onResize(_); @@ -433,11 +392,6 @@ class FlxGame extends Sprite function onFocusLost(event:Event):Void { - #if next - if (event != null && event.target != FlxG.stage) - return; - #end - #if flash if (_lostFocus) return; // Don't run this function twice (bug in standalone flash player) @@ -472,11 +426,6 @@ class FlxGame extends Sprite var width:Int = FlxG.stage.stageWidth; var height:Int = FlxG.stage.stageHeight; - #if !flash - if (FlxG.renderTile) - FlxG.bitmap.onContext(); - #end - resizeGame(width, height); } @@ -502,11 +451,6 @@ class FlxGame extends Sprite if (soundTray != null) soundTray.screenCenter(); #end - - #if FLX_POST_PROCESS - for (postProcess in postProcesses) - postProcess.rebuild(); - #end } /** @@ -741,11 +685,6 @@ class FlxGame extends Sprite updateInput(); - #if FLX_POST_PROCESS - if (postProcesses[0] != null) - postProcesses[0].update(FlxG.elapsed); - #end - #if FLX_SOUND_SYSTEM FlxG.sound.update(FlxG.elapsed); #end @@ -867,11 +806,6 @@ class FlxGame extends Sprite if (FlxG.renderTile) FlxDrawBaseItem.drawCalls = 0; - #if FLX_POST_PROCESS - if (postProcesses[0] != null) - postProcesses[0].capture(); - #end - FlxG.cameras.lock(); if (FlxG.plugins.drawOnTop) diff --git a/flixel/effects/postprocess/PostProcess.hx b/flixel/effects/postprocess/PostProcess.hx deleted file mode 100644 index cfff5800da..0000000000 --- a/flixel/effects/postprocess/PostProcess.hx +++ /dev/null @@ -1,260 +0,0 @@ -package flixel.effects.postprocess; - -import openfl.geom.Rectangle; -#if FLX_POST_PROCESS -import flixel.FlxG; -import openfl.Assets; -import openfl.display.OpenGLView; -import openfl.gl.GL; -import openfl.gl.GLFramebuffer; -import openfl.gl.GLRenderbuffer; -import openfl.gl.GLTexture; -import openfl.gl.GLBuffer; -import openfl.utils.Float32Array; - -private class Uniform -{ - public var id:Int; - public var value:Float; - - public function new(id, value) - { - this.id = id; - this.value = value; - } -} - -/** - * Fullscreen post processing class. - * Uses GLSL shaders to produce post processing effects. - */ -class PostProcess extends OpenGLView -{ - var screenWidth:Int; - var screenHeight:Int; - - /** - * Create a new PostProcess object - * - * @param fragmentShader A GLSL file in your assets path - */ - public function new(fragmentShader:String) - { - super(); - uniforms = new Map(); - - // create and bind the framebuffer - framebuffer = GL.createFramebuffer(); - rebuild(); - #if (ios || tvos) - defaultFramebuffer = new GLFramebuffer(GL.version, 1); // faked framebuffer - #else - var status = GL.checkFramebufferStatus(GL.FRAMEBUFFER); - - switch (status) - { - case GL.FRAMEBUFFER_INCOMPLETE_ATTACHMENT: - trace("FRAMEBUFFER_INCOMPLETE_ATTACHMENT"); - case GL.FRAMEBUFFER_UNSUPPORTED: - trace("GL_FRAMEBUFFER_UNSUPPORTED"); - case GL.FRAMEBUFFER_COMPLETE: - default: - trace("Check frame buffer: " + status); - } - #end - - buffer = GL.createBuffer(); - GL.bindBuffer(GL.ARRAY_BUFFER, buffer); - GL.bufferData(GL.ARRAY_BUFFER, new Float32Array(#if !openfl_next cast #end vertices), GL.STATIC_DRAW); - GL.bindBuffer(GL.ARRAY_BUFFER, null); - - postProcessShader = new Shader([ - {src: VERTEX_SHADER, fragment: false}, - {src: Assets.getText(fragmentShader), fragment: true} - ]); - - // default shader variables - imageUniform = postProcessShader.uniform("uImage0"); - timeUniform = postProcessShader.uniform("uTime"); - resolutionUniform = postProcessShader.uniform("uResolution"); - - vertexSlot = postProcessShader.attribute("aVertex"); - texCoordSlot = postProcessShader.attribute("aTexCoord"); - } - - /** - * Set a uniform value in the shader - * - * @param uniform The uniform name within the shader source - * @param value Value to set the uniform to - */ - public function setUniform(uniform:String, value:Float):Void - { - if (uniforms.exists(uniform)) - { - var uniform = uniforms.get(uniform); - uniform.value = value; - } - else - { - var id:Int = postProcessShader.uniform(uniform); - if (id != -1) - { - uniforms.set(uniform, new Uniform(id, value)); - } - else - { - throw 'Uniform with name "$uniform" could not be found.'; - } - } - } - - /** - * Allows multi pass rendering by passing the framebuffer to another post processing class. - * Renders to a `PostProcess` framebuffer instead of the screen, if set. - * Set to `null` to render to the screen. - */ - public var to(never, set):PostProcess; - - function set_to(value:PostProcess):PostProcess - { - renderTo = (value == null ? defaultFramebuffer : value.framebuffer); - return value; - } - - /** - * Rebuilds the renderbuffer to match screen dimensions. - */ - public function rebuild() - { - GL.bindFramebuffer(GL.FRAMEBUFFER, framebuffer); - - if (texture != null) - GL.deleteTexture(texture); - if (renderbuffer != null) - GL.deleteRenderbuffer(renderbuffer); - - this.screenWidth = FlxG.stage.stageWidth; - this.screenHeight = FlxG.stage.stageHeight; - createTexture(screenWidth, screenHeight); - createRenderbuffer(screenWidth, screenHeight); - - GL.bindFramebuffer(GL.FRAMEBUFFER, null); - } - - inline function createRenderbuffer(width:Int, height:Int) - { - // Bind the renderbuffer and create a depth buffer - renderbuffer = GL.createRenderbuffer(); - - GL.bindRenderbuffer(GL.RENDERBUFFER, renderbuffer); - GL.renderbufferStorage(GL.RENDERBUFFER, GL.DEPTH_COMPONENT16, width, height); - - // Specify renderbuffer as depth attachment - GL.framebufferRenderbuffer(GL.FRAMEBUFFER, GL.DEPTH_ATTACHMENT, GL.RENDERBUFFER, renderbuffer); - } - - inline function createTexture(width:Int, height:Int) - { - texture = GL.createTexture(); - - GL.bindTexture(GL.TEXTURE_2D, texture); - GL.texImage2D(GL.TEXTURE_2D, 0, GL.RGB, width, height, 0, GL.RGB, GL.UNSIGNED_BYTE, null); - - GL.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_S, GL.CLAMP_TO_EDGE); - GL.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_T, GL.CLAMP_TO_EDGE); - GL.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.LINEAR); - GL.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MAG_FILTER, GL.LINEAR); - - // specify texture as color attachment - GL.framebufferTexture2D(GL.FRAMEBUFFER, GL.COLOR_ATTACHMENT0, GL.TEXTURE_2D, texture, 0); - } - - /** - * Capture what is subsequently rendered to this framebuffer. - */ - public function capture() - { - GL.bindFramebuffer(GL.FRAMEBUFFER, framebuffer); - GL.clear(GL.DEPTH_BUFFER_BIT | GL.COLOR_BUFFER_BIT); - } - - public function update(elapsed:Float) - { - time += elapsed; - } - - var framebuffer:GLFramebuffer; - var renderbuffer:GLRenderbuffer; - var texture:GLTexture; - - var postProcessShader:Shader; - var buffer:GLBuffer; - var renderTo:GLFramebuffer; - var defaultFramebuffer:GLFramebuffer = null; - - /* @Time accumulator passed to the shader */ - var time:Float = 0; - - var vertexSlot:Int; - var texCoordSlot:Int; - var imageUniform:Int; - var resolutionUniform:Int; - var timeUniform:Int; - var uniforms:Map; - - /* @Simple full screen vertex shader */ - static inline var VERTEX_SHADER:String = " -#ifdef GL_ES - precision mediump float; -#endif - -attribute vec2 aVertex; -attribute vec2 aTexCoord; -varying vec2 vTexCoord; - -void main() { - vTexCoord = aTexCoord; - gl_Position = vec4(aVertex, 0.0, 1.0); -}"; - - static var vertices(get, never):Array; - - static inline function get_vertices():Array - { - return [ - -1.0, -1.0, 0, 0, - 1.0, -1.0, 1, 0, - -1.0, 1.0, 0, 1, - 1.0, -1.0, 1, 0, - 1.0, 1.0, 1, 1, - -1.0, 1.0, 0, 1 - ]; - } -} -#else -class PostProcess -{ - public function new(shader:String) - { - FlxG.log.error("Post processing is only supported on the CPP and Neko targets of OpenFL legacy - for newer OpenFL versions, please use shader filters."); - } - - public function enable(?to:PostProcess) {} - - public function capture() {} - - public function rebuild() {} - - public function update(elapsed:Float) {} - - public function render(rect:Rectangle) {} - - public function setUniform(uniform:String, value:Float) {} - - public var to(never, set):PostProcess; - - public function set_to(value:PostProcess):PostProcess - return null; -} -#end diff --git a/flixel/effects/postprocess/Shader.hx b/flixel/effects/postprocess/Shader.hx deleted file mode 100644 index 304cde955a..0000000000 --- a/flixel/effects/postprocess/Shader.hx +++ /dev/null @@ -1,99 +0,0 @@ -package flixel.effects.postprocess; - -#if FLX_POST_PROCESS -import openfl.gl.GL; -import openfl.gl.GLProgram; -import openfl.gl.GLShader; - -/** - * GLSL Shader object - */ -class Shader -{ - var program:GLProgram; - - /** - * Creates a new Shader - * - * @param sources A list of GLSL shader sources to compile and link into a program - */ - public function new(sources:Array) - { - program = GL.createProgram(); - - for (source in sources) - { - var shader = compile(source.src, source.fragment ? GL.FRAGMENT_SHADER : GL.VERTEX_SHADER); - if (shader == null) - return; - GL.attachShader(program, shader); - GL.deleteShader(shader); - } - - GL.linkProgram(program); - - if (GL.getProgramParameter(program, GL.LINK_STATUS) == 0) - { - trace(GL.getProgramInfoLog(program)); - trace("VALIDATE_STATUS: " + GL.getProgramParameter(program, GL.VALIDATE_STATUS)); - trace("ERROR: " + GL.getError()); - return; - } - } - - /** - * Compiles the shader source into a GlShader object and prints any errors - * - * @param source The shader source code - * @param type The type of shader to compile (fragment, vertex) - */ - function compile(source:String, type:Int):GLShader - { - var shader = GL.createShader(type); - GL.shaderSource(shader, source); - GL.compileShader(shader); - - if (GL.getShaderParameter(shader, GL.COMPILE_STATUS) == 0) - { - trace(GL.getShaderInfoLog(shader)); - return null; - } - - return shader; - } - - /** - * Return the attribute location in this shader - * - * @param a The attribute name to find - */ - public inline function attribute(a:String):Int - { - return GL.getAttribLocation(program, a); - } - - /** - * Return the uniform location in this shader - * - * @param a The uniform name to find - */ - public inline function uniform(u:String):Int - { - return GL.getUniformLocation(program, u); - } - - /** - * Bind the program for rendering - */ - public inline function bind() - { - GL.useProgram(program); - } -} - -typedef ShaderSource = -{ - var src:String; - var fragment:Bool; -} -#end diff --git a/flixel/graphics/FlxGraphic.hx b/flixel/graphics/FlxGraphic.hx index 0414ea16b9..6dbf70adfc 100644 --- a/flixel/graphics/FlxGraphic.hx +++ b/flixel/graphics/FlxGraphic.hx @@ -303,11 +303,6 @@ class FlxGraphic implements IFlxDestroyable */ public var destroyOnNoUse(default, set):Bool = true; - /** - * Whether the `BitmapData` of this graphic object has been dumped or not. - */ - public var isDumped(default, null):Bool = false; - /** * Whether the `BitmapData` of this graphic object has been loaded or not. */ @@ -320,10 +315,12 @@ class FlxGraphic implements IFlxDestroyable public var isDestroyed(get, never):Bool; /** - * Whether the `BitmapData` of this graphic object can be dumped for decreased memory usage, - * but may cause some issues (when you need direct access to pixels of this graphic. - * If the graphic is dumped then you should call `undump()` and have total access to pixels. + * Whether the `BitmapData` of this graphic object can be refreshed. + * This is only the case for graphics with an `assetsKey` or `assetsClass`. */ + public var canBeRefreshed(get, never):Bool; + + @:deprecated("`canBeDumped` is deprecated, use `canBeRefreshed`") public var canBeDumped(get, never):Bool; /** @@ -416,58 +413,31 @@ class FlxGraphic implements IFlxDestroyable } /** - * Dumps bits of `BitmapData` to decrease memory usage, but you can't read/write pixels on it anymore - * (but you can call `onContext()` (or `undump()`) method which will restore it again). + * Refreshes the `BitmapData` of this graphic. */ - public function dump():Void - { - #if (lime_legacy && !flash) - if (FlxG.renderTile && canBeDumped) - { - bitmap.dumpBits(); - isDumped = true; - } - #end - } - - /** - * Undumps bits of the `BitmapData` - regenerates it and regenerate tilesheet data for this object - */ - public function undump():Void + public function refresh():Void { var newBitmap:BitmapData = getBitmapFromSystem(); if (newBitmap != null) bitmap = newBitmap; - isDumped = false; } - - /** - * Use this method to restore cached `BitmapData` (if it's possible). - * It's called automatically when the RESIZE event occurs. - */ - public function onContext():Void + + @:deprecated("`undump` is deprecated, use `refresh`") + public function undump():Void { - // no need to restore tilesheet if it hasn't been dumped - if (isDumped) - { - undump(); // restore everything - dump(); // and dump BitmapData again - } + refresh(); } - + /** * Asset reload callback for this graphic object. - * It regenerated its tilesheet and resets frame bitmaps. + * It regenerates its bitmap data. */ public function onAssetsReload():Void { - if (!canBeDumped) + if (!canBeRefreshed) return; - - var dumped:Bool = isDumped; - undump(); - if (dumped) - dump(); + + refresh(); } /** @@ -556,7 +526,7 @@ class FlxGraphic implements IFlxDestroyable /** * Gets the `BitmapData` for this graphic object from OpenFL. - * This method is used for undumping graphic. + * This method is used for refreshing bitmaps. */ function getBitmapFromSystem():BitmapData { @@ -568,10 +538,10 @@ class FlxGraphic implements IFlxDestroyable if (newBitmap != null) return FlxGraphic.getBitmap(newBitmap, unique); - + return null; } - + inline function get_isLoaded() { return bitmap != null && !bitmap.rect.isEmpty(); @@ -582,11 +552,16 @@ class FlxGraphic implements IFlxDestroyable return shader == null; } - inline function get_canBeDumped():Bool + inline function get_canBeRefreshed():Bool { return assetsClass != null || assetsKey != null; } + inline function get_canBeDumped():Bool + { + return canBeRefreshed; + } + public function incrementUseCount() { useCount++; diff --git a/flixel/graphics/tile/FlxDrawQuadsItem.hx b/flixel/graphics/tile/FlxDrawQuadsItem.hx index bd73f8b346..9b513a8106 100644 --- a/flixel/graphics/tile/FlxDrawQuadsItem.hx +++ b/flixel/graphics/tile/FlxDrawQuadsItem.hx @@ -3,15 +3,15 @@ package flixel.graphics.tile; import flixel.FlxCamera; import flixel.graphics.frames.FlxFrame; import flixel.graphics.tile.FlxDrawBaseItem.FlxDrawItemType; -import flixel.system.FlxAssets.FlxShader; import flixel.math.FlxMatrix; -import openfl.geom.ColorTransform; -import openfl.display.ShaderParameter; +import flixel.system.FlxAssets.FlxShader; import openfl.Vector; +import openfl.display.ShaderParameter; +import openfl.geom.ColorTransform; class FlxDrawQuadsItem extends FlxDrawBaseItem { - static inline var VERTICES_PER_QUAD = #if (openfl >= "8.5.0") 4 #else 6 #end; + static inline var VERTICES_PER_QUAD = 4; public var shader:FlxShader; @@ -133,9 +133,7 @@ class FlxDrawQuadsItem extends FlxDrawBaseItem setParameterValue(shader.hasTransform, true); setParameterValue(shader.hasColorTransform, colored || hasColorOffsets); - #if (openfl > "8.7.0") camera.canvas.graphics.overrideBlendMode(blend); - #end camera.canvas.graphics.beginShaderFill(shader); camera.canvas.graphics.drawQuads(rects, null, transforms); super.render(camera); diff --git a/flixel/graphics/tile/FlxDrawTrianglesItem.hx b/flixel/graphics/tile/FlxDrawTrianglesItem.hx index c1af4b6438..e0e919cad4 100644 --- a/flixel/graphics/tile/FlxDrawTrianglesItem.hx +++ b/flixel/graphics/tile/FlxDrawTrianglesItem.hx @@ -79,9 +79,7 @@ class FlxDrawTrianglesItem extends FlxDrawBaseItem setParameterValue(shader.hasTransform, true); setParameterValue(shader.hasColorTransform, colored || hasColorOffsets); - #if (openfl > "8.7.0") camera.canvas.graphics.overrideBlendMode(blend); - #end camera.canvas.graphics.beginShaderFill(shader); #else diff --git a/flixel/input/android/FlxAndroidKey.hx b/flixel/input/android/FlxAndroidKey.hx index 949951bb2c..efab92eda6 100644 --- a/flixel/input/android/FlxAndroidKey.hx +++ b/flixel/input/android/FlxAndroidKey.hx @@ -12,8 +12,8 @@ enum abstract FlxAndroidKey(Int) from Int to Int public static var toStringMap(default, null):Map = FlxMacroUtil.buildMap("flixel.input.android.FlxAndroidKey", true); var ANY = -2; var NONE = -1; - var MENU = #if (openfl >= "8.0.0") 0x4000010C #else 16777234 #end; - var BACK = #if (openfl >= "8.0.0") 0x4000010E #else 27 #end; + var MENU = 0x4000010C; + var BACK = 0x4000010E; @:from public static inline function fromString(s:String) diff --git a/flixel/system/FlxAssets.hx b/flixel/system/FlxAssets.hx index c6915bc94f..7bc4db3e92 100644 --- a/flixel/system/FlxAssets.hx +++ b/flixel/system/FlxAssets.hx @@ -14,8 +14,8 @@ import flixel.graphics.frames.bmfont.BMFont; import flixel.util.typeLimit.OneOfFour; import flixel.util.typeLimit.OneOfThree; import flixel.util.typeLimit.OneOfTwo; -import haxe.io.Bytes; import haxe.Json; +import haxe.io.Bytes; import haxe.xml.Access; import openfl.display.BitmapData; import openfl.display.Graphics; @@ -31,7 +31,7 @@ class GraphicLogo extends BitmapData {} class GraphicVirtualInput extends BitmapData {} @:file("assets/images/ui/virtual-input.txt") -class VirtualInputData extends #if (lime_legacy || nme) ByteArray #else ByteArrayData #end {} +class VirtualInputData extends #if nme ByteArray #else ByteArrayData #end {} typedef FlxTexturePackerJsonAsset = FlxJsonAsset; typedef FlxAsepriteJsonAsset = FlxJsonAsset; diff --git a/flixel/system/FlxBasePreloader.hx b/flixel/system/FlxBasePreloader.hx index e41ca98969..a5a0b7d005 100644 --- a/flixel/system/FlxBasePreloader.hx +++ b/flixel/system/FlxBasePreloader.hx @@ -1,6 +1,9 @@ package flixel.system; +import flixel.util.FlxColor; +import flixel.util.FlxStringUtil; import openfl.Lib; +import openfl.Vector; import openfl.display.Bitmap; import openfl.display.BitmapData; import openfl.display.GradientType; @@ -10,17 +13,14 @@ import openfl.display.Sprite; import openfl.display.StageAlign; import openfl.display.StageScaleMode; import openfl.events.Event; -import openfl.events.ProgressEvent; import openfl.events.MouseEvent; +import openfl.events.ProgressEvent; import openfl.geom.Matrix; import openfl.geom.Rectangle; import openfl.net.URLRequest; import openfl.text.TextField; import openfl.text.TextFormat; import openfl.text.TextFormatAlign; -import flixel.util.FlxColor; -import flixel.util.FlxStringUtil; -import openfl.Vector; class FlxBasePreloader extends DefaultPreloader { @@ -101,11 +101,6 @@ class FlxBasePreloader extends DefaultPreloader { super(); - #if (openfl <= "4.0.0") - removeChild(progress); - removeChild(outline); - #end - minDisplayTime = MinDisplayTime; if (AllowedURLs != null) allowedURLs = AllowedURLs; @@ -409,7 +404,6 @@ class FlxBasePreloader extends DefaultPreloader #end } -#if (openfl >= "8.0.0") // This is a slightly trimmed down version of the NMEPreloader present in older OpenFL versions private class DefaultPreloader extends Sprite { @@ -463,6 +457,3 @@ private class DefaultPreloader extends Sprite } } } -#else -private typedef DefaultPreloader = NMEPreloader; -#end diff --git a/flixel/system/debug/console/Console.hx b/flixel/system/debug/console/Console.hx index f179566d5d..f3159b62a3 100644 --- a/flixel/system/debug/console/Console.hx +++ b/flixel/system/debug/console/Console.hx @@ -1,15 +1,15 @@ package flixel.system.debug.console; #if FLX_DEBUG -import openfl.text.TextField; -import openfl.text.TextFormat; import flixel.FlxG; import flixel.FlxObject; import flixel.system.debug.FlxDebugger.GraphicConsole; -import flixel.system.debug.completion.CompletionList; import flixel.system.debug.completion.CompletionHandler; +import flixel.system.debug.completion.CompletionList; import flixel.util.FlxStringUtil; -#if (!next && sys) +import openfl.text.TextField; +import openfl.text.TextFormat; +#if sys import openfl.events.MouseEvent; #end #if hscript @@ -58,7 +58,7 @@ class Console extends Window */ var input:TextField; - #if (!next && sys) + #if sys var inputMouseDown:Bool = false; var stageMouseDown:Bool = false; #end @@ -123,7 +123,7 @@ class Console extends Window #end #end - #if (!next && sys) // workaround for broken TextField focus on native + #if sys // workaround for broken TextField focus on native input.addEventListener(MouseEvent.MOUSE_DOWN, function(_) { inputMouseDown = true; @@ -135,7 +135,7 @@ class Console extends Window #end } - #if (!next && sys) + #if sys @:access(flixel.FlxGame.onFocus) override public function update() { diff --git a/flixel/system/frontEnds/BitmapFrontEnd.hx b/flixel/system/frontEnds/BitmapFrontEnd.hx index f81c4957f3..3204b09b32 100644 --- a/flixel/system/frontEnds/BitmapFrontEnd.hx +++ b/flixel/system/frontEnds/BitmapFrontEnd.hx @@ -53,64 +53,13 @@ class BitmapFrontEnd for (key in _cache.keys()) { var obj = _cache.get(key); - if (obj != null && obj.canBeDumped) + if (obj != null && obj.canBeRefreshed) { obj.onAssetsReload(); } } } - /** - * New context handler. - * Regenerates tilesheets for all dumped graphics objects in the cache. - */ - public function onContext():Void - { - for (key in _cache.keys()) - { - var obj = _cache.get(key); - if (obj != null && obj.isDumped) - { - obj.onContext(); - } - } - } - - /** - * Dumps bits of all graphics in the cache. This frees some memory, but you can't read/write pixels on those graphics anymore. - * You can call undump() method for each FlxGraphic (or undumpCache()) object which will restore it again. - */ - public function dumpCache():Void - { - #if !web - for (key in _cache.keys()) - { - var obj = _cache.get(key); - if (obj != null && obj.canBeDumped) - { - obj.dump(); - } - } - #end - } - - /** - * Restores graphics of all dumped objects in the cache. - */ - public function undumpCache():Void - { - #if !web - for (key in _cache.keys()) - { - var obj = _cache.get(key); - if (obj != null && obj.isDumped) - { - obj.undump(); - } - } - #end - } - /** * Check the local bitmap cache to see if a bitmap with this key has been loaded already. * diff --git a/flixel/system/macros/FlxDefines.hx b/flixel/system/macros/FlxDefines.hx index 4bf4815839..58d00c41ed 100644 --- a/flixel/system/macros/FlxDefines.hx +++ b/flixel/system/macros/FlxDefines.hx @@ -4,12 +4,12 @@ import haxe.io.Path; import haxe.macro.Compiler; import haxe.macro.Context; import haxe.macro.Expr.Position; +using StringTools; #if (flixel_addons >= "3.2.2") import flixel.addons.system.macros.FlxAddonDefines; #end -using StringTools; private enum UserDefines { @@ -80,7 +80,6 @@ private enum HelperDefines FLX_NATIVE_CURSOR; FLX_SOUND_TRAY; FLX_POINTER_INPUT; - FLX_POST_PROCESS; FLX_JOYSTICK_API; FLX_GAMEINPUT_API; FLX_ACCELEROMETER; @@ -227,12 +226,8 @@ class FlxDefines if (!defined(FLX_NO_SOUND_SYSTEM) && !defined(FLX_NO_SOUND_TRAY)) define(FLX_SOUND_TRAY); - #if (lime >= "8.0.0") if (defined(FLX_NO_SOUND_SYSTEM) || defined("flash")) define(FLX_NO_PITCH); - #else - define(FLX_NO_PITCH); - #end if (!defined(FLX_NO_PITCH)) define(FLX_PITCH); @@ -252,11 +247,6 @@ class FlxDefines if (!defined(FLX_NO_TOUCH) || !defined(FLX_NO_MOUSE)) define(FLX_POINTER_INPUT); - #if (openfl < "4.0.0") - if (defined("cpp") || defined("neko")) - define(FLX_POST_PROCESS); - #end - if (defined("cpp") && defined("steamwrap")) define(FLX_STEAMWRAP); diff --git a/flixel/text/FlxText.hx b/flixel/text/FlxText.hx index c768fd654a..5b3a797f8b 100644 --- a/flixel/text/FlxText.hx +++ b/flixel/text/FlxText.hx @@ -22,7 +22,6 @@ import openfl.text.TextFormat; import openfl.text.TextFormatAlign; using flixel.util.FlxStringUtil; - #if flash import openfl.geom.Rectangle; #end diff --git a/flixel/util/FlxSpriteUtil.hx b/flixel/util/FlxSpriteUtil.hx index 1846835606..4e6de54a46 100644 --- a/flixel/util/FlxSpriteUtil.hx +++ b/flixel/util/FlxSpriteUtil.hx @@ -1,5 +1,15 @@ package flixel.util; +import flixel.FlxG; +import flixel.FlxObject; +import flixel.FlxSprite; +import flixel.effects.FlxFlicker; +import flixel.math.FlxMath; +import flixel.math.FlxPoint; +import flixel.math.FlxRect; +import flixel.system.FlxAssets; +import flixel.tweens.FlxEase; +import flixel.tweens.FlxTween; import openfl.display.BitmapData; import openfl.display.BitmapDataChannel; import openfl.display.BlendMode; @@ -12,16 +22,6 @@ import openfl.geom.ColorTransform; import openfl.geom.Matrix; import openfl.geom.Point; import openfl.geom.Rectangle; -import flixel.FlxG; -import flixel.FlxObject; -import flixel.FlxSprite; -import flixel.effects.FlxFlicker; -import flixel.math.FlxMath; -import flixel.math.FlxPoint; -import flixel.math.FlxRect; -import flixel.system.FlxAssets; -import flixel.tweens.FlxEase; -import flixel.tweens.FlxTween; // TODO: pad(): Pad the sprite out with empty pixels left/right/above/below it // TODO: rotateClockwise(): Takes the bitmapData from the given source FlxSprite and rotates it 90 degrees clockwise @@ -425,7 +425,6 @@ class FlxSpriteUtil return sprite; } - #if (flash || openfl >= "8.0.0") /** * This function draws a rounded rectangle on a FlxSprite. Same as drawRoundRect, * except it allows you to determine the radius of each corner individually. @@ -452,7 +451,6 @@ class FlxSpriteUtil endDraw(sprite, drawStyle); return sprite; } - #end /** * This function draws a circle on a FlxSprite at position X,Y with the specified color. diff --git a/include.xml b/include.xml index e1cb529dbf..9a0f3548b7 100644 --- a/include.xml +++ b/include.xml @@ -17,8 +17,6 @@ - - From 2f5d24a1cfc98798f10cf062790386fcd0323133 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Thu, 30 Jan 2025 11:36:19 -0600 Subject: [PATCH 94/99] FlxSave: Replace `FlxSaveStatus.ERROR` with SAVE_ERROR (#3294) * replace `FlxSaveStatus.ERROR` with SAVE_ERROR * update changelog * add link * Add deprecated ERROR back --- CHANGELOG.md | 5 ++++- flixel/util/FlxSave.hx | 34 ++++++++++++++++++++++++---------- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 90feabedea..b728b5f1de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ 6.0.0 (TBD) -#### Removals +#### Removals and Breaking Changes We removed many features and utilities that were previously deprecated - `flixel.util.FlxPath`: New package, `flixel.path.FlxPath` - `FlxSwipe::angle`: Use `FlxSwipe.degrees`, instead @@ -25,6 +25,9 @@ We removed many features and utilities that were previously deprecated - `FlxAssets.FlxAngelCodeSource`: Use `FlxAssets.FlxAngelCodeAsset`, instead - `FlxAssets.FlxTexturePackerSource`: Use `FlxTexturePackerJsonAsset`, instead - `FlxUnicodeUtil`: Use `UnicodeString`, instead +- `FlxState::switchTo`: Use `startOutro`, instead ([#2733](https://github.com/HaxeFlixel/flixel/pull/2733)) +- `FlxCamera.defaultCameras`: Use `FlxG.cameras.setDefaultDrawTarget`, instead +- `FlxSave`: Deprecate and remove all uses of `FlxSaveStatus.ERROR` for `FlxSaveStatus.SAVE_ERROR` ([#3294](https://github.com/HaxeFlixel/flixel/pull/3294)) #### Changes and improvements: - `FlxSpritegroup`: Setting `origin` now causes members to pivot around the same point ([#2981](https://github.com/HaxeFlixel/flixel/pull/2981)) diff --git a/flixel/util/FlxSave.hx b/flixel/util/FlxSave.hx index 629e9f3e2e..e364f26e08 100644 --- a/flixel/util/FlxSave.hx +++ b/flixel/util/FlxSave.hx @@ -2,7 +2,6 @@ package flixel.util; import flixel.util.FlxDestroyUtil.IFlxDestroyable; import haxe.Exception; -import openfl.errors.Error; import openfl.net.SharedObject; import openfl.net.SharedObjectFlushStatus; @@ -211,7 +210,7 @@ class FlxSave implements IFlxDestroyable return false; } } - catch (e:Error) + catch (e) { FlxG.log.error('Error:${e.message} name:"$name", path:"$path".'); destroy(); @@ -308,14 +307,14 @@ class FlxSave implements IFlxDestroyable try { - var result = _sharedObject.flush(minFileSize); + final result = _sharedObject.flush(minFileSize); if (result != FLUSHED) - status = ERROR("FlxSave is requesting extra storage space."); + status = SAVE_ERROR(STORAGE); } - catch (e:Error) + catch (e) { - status = ERROR("There was an problem flushing the save data."); + status = SAVE_ERROR(ENCODING(e)); } checkStatus(); @@ -353,8 +352,10 @@ class FlxSave implements IFlxDestroyable return true; case EMPTY: FlxG.log.warn("You must call save.bind() before you can read or write data."); - case ERROR(msg): - FlxG.log.error(msg); + case SAVE_ERROR(STORAGE): + FlxG.log.error("FlxSave is requesting extra storage space"); + case SAVE_ERROR(ENCODING(e)): + FlxG.log.error('There was an problem encoding the save data: ${e.message}'); case LOAD_ERROR(IO(e)): FlxG.log.error('IO ERROR: ${e.message}'); case LOAD_ERROR(INVALID_NAME(name, reason)): @@ -741,6 +742,15 @@ enum LoadFailureType PARSING(rawData:String, exception:Exception); } +enum SaveFailureType +{ + /** FlxSave is requesting extra storage space **/ + STORAGE; + + /** There was an problem encoding the save data */ + ENCODING(e:Exception); +} + enum FlxSaveStatus { /** @@ -754,12 +764,16 @@ enum FlxSaveStatus BOUND(name:String, ?path:String); /** - * There was an issue during `flush` + * There was an issue during `flush`. Previously known as `ERROR(msg:String)` */ - ERROR(msg:String); + SAVE_ERROR(type:SaveFailureType); /** * There was an issue while loading */ LOAD_ERROR(type:LoadFailureType); + + @:noCompletion + @:deprecated("FlxSaveStatus.ERROR is never used, it has been replaced by SAVE_ERROR") + ERROR(msg:String); } From 076f9cdb5ef82b0e7387e274fe9e82f5830e03bc Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Thu, 30 Jan 2025 12:25:54 -0600 Subject: [PATCH 95/99] remove implicit int casts to/from directions (#3308) * remove implicit int casts to/from directions * D'oh * D'oh! * deprecate operators and fix haxe 4.2.5 * order imports * remove casts, add explicit cast functions * fix not() and add tests * Doc * doc + tests --- flixel/FlxObject.hx | 4 +- flixel/group/FlxSpriteGroup.hx | 5 +- flixel/system/FlxQuadTree.hx | 4 +- flixel/system/macros/FlxDefines.hx | 8 +- flixel/tile/FlxTilemap.hx | 2 +- flixel/util/FlxDirection.hx | 46 ++++++++++- flixel/util/FlxDirectionFlags.hx | 80 +++++++++++++++---- .../src/flixel/util/FlxDirectionFlagsTest.hx | 76 +++++++----------- 8 files changed, 150 insertions(+), 75 deletions(-) diff --git a/flixel/FlxObject.hx b/flixel/FlxObject.hx index 3acd654348..3c9b1d4f3b 100644 --- a/flixel/FlxObject.hx +++ b/flixel/FlxObject.hx @@ -1247,14 +1247,14 @@ class FlxObject extends FlxBasic endDrawDebug(camera); } - function drawDebugBoundingBox(gfx:Graphics, rect:FlxRect, allowCollisions:Int, partial:Bool) + function drawDebugBoundingBox(gfx:Graphics, rect:FlxRect, allowCollisions:FlxDirectionFlags, partial:Bool) { // Find the color to use final color = getDebugBoundingBoxColor(allowCollisions); drawDebugBoundingBoxColor(gfx, rect, color); } - function getDebugBoundingBoxColor(allowCollisions:Int) + function getDebugBoundingBoxColor(allowCollisions:FlxDirectionFlags) { if (debugBoundingBoxColor != null) return debugBoundingBoxColor; diff --git a/flixel/group/FlxSpriteGroup.hx b/flixel/group/FlxSpriteGroup.hx index 8c4da0f1ef..a1f43596e1 100644 --- a/flixel/group/FlxSpriteGroup.hx +++ b/flixel/group/FlxSpriteGroup.hx @@ -13,6 +13,7 @@ import flixel.math.FlxRect; import flixel.system.FlxAssets; import flixel.util.FlxColor; import flixel.util.FlxDestroyUtil; +import flixel.util.FlxDirectionFlags; import flixel.util.FlxSort; /** @@ -753,7 +754,7 @@ class FlxTypedSpriteGroup extends FlxSprite return alpha = Value; } - override function set_facing(Value:Int):Int + override function set_facing(Value:FlxDirectionFlags):FlxDirectionFlags { if (exists && facing != Value) transformChildren(facingTransform, Value); @@ -1023,7 +1024,7 @@ class FlxTypedSpriteGroup extends FlxSprite inline function directAlphaTransform(Sprite:FlxSprite, Alpha:Float) Sprite.alpha = Alpha; // direct set - inline function facingTransform(Sprite:FlxSprite, Facing:Int) + inline function facingTransform(Sprite:FlxSprite, Facing:FlxDirectionFlags) Sprite.facing = Facing; inline function flipXTransform(Sprite:FlxSprite, FlipX:Bool) diff --git a/flixel/system/FlxQuadTree.hx b/flixel/system/FlxQuadTree.hx index 654a61379f..a922e2f925 100644 --- a/flixel/system/FlxQuadTree.hx +++ b/flixel/system/FlxQuadTree.hx @@ -616,7 +616,7 @@ class FlxQuadTree extends FlxRect { _iterator = iterator.next; } - if (_object != null && _object.exists && _object.allowCollisions > 0 && _iterator != null && _iterator.object != null && overlapNode()) + if (_object != null && _object.exists && _object.allowCollisions != NONE && _iterator != null && _iterator.object != null && overlapNode()) { overlapProcessed = true; } @@ -666,7 +666,7 @@ class FlxQuadTree extends FlxRect while (_iterator != null) { checkObject = _iterator.object; - if (_object == checkObject || !checkObject.exists || checkObject.allowCollisions <= 0) + if (_object == checkObject || !checkObject.exists || checkObject.allowCollisions == NONE) { _iterator = _iterator.next; continue; diff --git a/flixel/system/macros/FlxDefines.hx b/flixel/system/macros/FlxDefines.hx index 58d00c41ed..71eafd21c9 100644 --- a/flixel/system/macros/FlxDefines.hx +++ b/flixel/system/macros/FlxDefines.hx @@ -140,11 +140,11 @@ class FlxDefines checkOpenFLVersions(); #end - #if (flixel_addons < version("3.0.2")) - abortVersion("Flixel Addons", "3.0.2 or newer", "flixel-addons", (macro null).pos); + #if (flixel_addons < version("3.3.0")) + abortVersion("Flixel Addons", "3.3.0 or newer", "flixel-addons", (macro null).pos); #end - #if (flixel_ui < version("2.4.0")) - abortVersion("Flixel UI", "2.4.0 or newer", "flixel-addons", (macro null).pos); + #if (flixel_ui < version("2.6.2")) + abortVersion("Flixel UI", "2.6.2 or newer", "flixel_ui", (macro null).pos); #end } diff --git a/flixel/tile/FlxTilemap.hx b/flixel/tile/FlxTilemap.hx index cee1fe130b..80aecfc4d9 100644 --- a/flixel/tile/FlxTilemap.hx +++ b/flixel/tile/FlxTilemap.hx @@ -1538,7 +1538,7 @@ class FlxTypedTilemap extends FlxBaseTilemap return tileSprite; } - override function set_allowCollisions(value:Int):Int + override function set_allowCollisions(value:FlxDirectionFlags):FlxDirectionFlags { for (tile in _tileObjects) if (tile.index >= _collideIndex) diff --git a/flixel/util/FlxDirection.hx b/flixel/util/FlxDirection.hx index 7b07c061af..c389351294 100644 --- a/flixel/util/FlxDirection.hx +++ b/flixel/util/FlxDirection.hx @@ -4,16 +4,31 @@ package flixel.util; * Simple enum for orthogonal directions. Can be combined into `FlxDirectionFlags`. * @since 4.10.0 */ -enum abstract FlxDirection(Int) to Int +enum abstract FlxDirection(Int) { var LEFT = 0x0001; var RIGHT = 0x0010; var UP = 0x0100; var DOWN = 0x1000; - + + var self(get, never):FlxDirection; + inline function get_self():FlxDirection + { + #if (haxe >= version("4.3.0")) + return abstract; + #else + return cast this; + #end + } + + inline function new(value:Int) + { + this = value; + } + public function toString() { - return switch (cast this : FlxDirection) + return switch self { case LEFT: "L"; case RIGHT: "R"; @@ -21,4 +36,29 @@ enum abstract FlxDirection(Int) to Int case DOWN: "D"; } } + + @:deprecated("implicit cast from FlxDirection to Int is deprecated, use toInt()") + @:to + inline function toIntImplicit() + { + return toInt(); + } + + + inline public function toInt() + { + return this; + } + + @:deprecated("implicit cast from Int to FlxDirection is deprecated, use FlxDirection.fromInt") + @:from + inline static function fromIntImplicit(value:Int):FlxDirection + { + return fromInt(value); + } + + public inline static function fromInt(value:Int):FlxDirection + { + return new FlxDirection(value); + } } diff --git a/flixel/util/FlxDirectionFlags.hx b/flixel/util/FlxDirectionFlags.hx index 5b13ec4fc6..86d7b6ab49 100644 --- a/flixel/util/FlxDirectionFlags.hx +++ b/flixel/util/FlxDirectionFlags.hx @@ -7,7 +7,7 @@ import flixel.math.FlxAngle; * many `FlxObject` features like `allowCollisions` and `touching`. * @since 4.10.0 */ -enum abstract FlxDirectionFlags(Int) from Int from FlxDirection to Int +enum abstract FlxDirectionFlags(Int) { var LEFT = 0x0001; // FlxDirection.LEFT; var RIGHT = 0x0010; // FlxDirection.RIGHT; @@ -32,7 +32,18 @@ enum abstract FlxDirectionFlags(Int) from Int from FlxDirection to Int /** Special-case constant meaning any, or all directions. */ var ANY = 0x1111; // LEFT | RIGHT | UP | DOWN; - + + var self(get, never):FlxDirectionFlags; + + inline function get_self():FlxDirectionFlags + { + #if (haxe >= version("4.3.0")) + return abstract; + #else + return cast this; + #end + } + /** * Calculates the angle (in degrees) of the facing flags. * Returns 0 if two opposing flags are true. @@ -41,7 +52,7 @@ enum abstract FlxDirectionFlags(Int) from Int from FlxDirection to Int public var degrees(get, never):Float; function get_degrees():Float { - return switch (this) + return switch self { case RIGHT: 0; case DOWN: 90; @@ -82,13 +93,17 @@ enum abstract FlxDirectionFlags(Int) from Int from FlxDirection to Int public var right(get, never):Bool; inline function get_right() return has(RIGHT); - + inline function new(value:Int) + { + this = value; + } + /** * Returns true if this contains **all** of the supplied flags. */ public inline function has(dir:FlxDirectionFlags):Bool { - return this & dir == dir; + return this & dir.toInt() == dir.toInt(); } /** @@ -96,7 +111,7 @@ enum abstract FlxDirectionFlags(Int) from Int from FlxDirection to Int */ public inline function hasAny(dir:FlxDirectionFlags):Bool { - return this & dir > 0; + return this & dir.toInt() > 0; } /** @@ -104,7 +119,7 @@ enum abstract FlxDirectionFlags(Int) from Int from FlxDirection to Int */ public inline function with(dir:FlxDirectionFlags):FlxDirectionFlags { - return this | dir; + return fromInt(this | dir.toInt()); } /** @@ -112,12 +127,29 @@ enum abstract FlxDirectionFlags(Int) from Int from FlxDirection to Int */ public inline function without(dir:FlxDirectionFlags):FlxDirectionFlags { - return this & ~dir; + return fromInt(this & ~dir.toInt()); + } + + public inline function not():FlxDirectionFlags + { + return fromInt((~this & ANY.toInt())); } + @:deprecated("implicit cast from FlxDirectionFlags to Int is deprecated, use toInt") + @:to + inline function toIntImplicit() + { + return toInt(); + } + + public inline function toInt():Int + { + return this; + } + public function toString() { - if (this == NONE) + if (self == NONE) return "NONE"; var str = ""; @@ -146,16 +178,34 @@ enum abstract FlxDirectionFlags(Int) from Int from FlxDirection to Int | (down ? DOWN : NONE); } - // Expose int operators - @:op(A & B) static function and(a:FlxDirectionFlags, b:FlxDirectionFlags):FlxDirectionFlags; + @:deprecated("implicit cast from Int to FlxDirectionFlags is deprecated, use FlxDirectionFlags.fromInt") + @:from + inline static function fromIntImplicit(value:Int):FlxDirectionFlags + { + return fromInt(value); + } + + public inline static function fromInt(value:Int):FlxDirectionFlags + { + return new FlxDirectionFlags(value); + } + + @:from + inline static function fromDir(dir:FlxDirection):FlxDirectionFlags + { + return fromInt(dir.toInt()); + } + @:deprecated("FlxDirectionFlags operators are deprecated, use has(), instead")// Expose int operators + @:op(A & B) static function and(a:FlxDirectionFlags, b:FlxDirectionFlags):FlxDirectionFlags; + @:deprecated("FlxDirectionFlags operators are deprecated, use has(), instead") @:op(A | B) static function or(a:FlxDirectionFlags, b:FlxDirectionFlags):FlxDirectionFlags; - + @:deprecated("FlxDirectionFlags operators are deprecated, use has(), instead") @:op(A > B) static function gt(a:FlxDirectionFlags, b:FlxDirectionFlags):Bool; - + @:deprecated("FlxDirectionFlags operators are deprecated, use has(), instead") @:op(A < B) static function lt(a:FlxDirectionFlags, b:FlxDirectionFlags):Bool; - + @:deprecated("FlxDirectionFlags operators are deprecated, use has(), instead") @:op(A >= B) static function gte(a:FlxDirectionFlags, b:FlxDirectionFlags):Bool; - + @:deprecated("FlxDirectionFlags operators are deprecated, use has(), instead") @:op(A <= B) static function lte(a:FlxDirectionFlags, b:FlxDirectionFlags):Bool; } diff --git a/tests/unit/src/flixel/util/FlxDirectionFlagsTest.hx b/tests/unit/src/flixel/util/FlxDirectionFlagsTest.hx index a5f7f67f72..7765f538c3 100644 --- a/tests/unit/src/flixel/util/FlxDirectionFlagsTest.hx +++ b/tests/unit/src/flixel/util/FlxDirectionFlagsTest.hx @@ -2,6 +2,7 @@ package flixel.util; import massive.munit.Assert; import flixel.util.FlxDirectionFlags; +import haxe.PosInfos; /** * A bulk of these tests are copied from `FlxColor`. @@ -26,7 +27,7 @@ class FlxDirectionFlagsTest extends FlxTest } Assert.isTrue(f(null)); - Assert.isFalse(f(0)); + Assert.isFalse(f(cast 0)); Assert.isFalse(f(LEFT)); } @@ -153,55 +154,13 @@ class FlxDirectionFlagsTest extends FlxTest Assert.areEqual(ANY, dirs.with(ANY)); } - @Test - function operatorInts() - { - dirs = WALL; - Assert.isTrue((dirs & LEFT) > 0); - Assert.isTrue((dirs & LEFT) > NONE); - Assert.isTrue((dirs & 0x0001) > 0); - Assert.isTrue((dirs & 0x0001) > NONE); - Assert.isTrue((dirs & LEFT) >= 0x1); - Assert.isTrue((dirs & LEFT) >= LEFT); - Assert.isTrue((dirs & 0x0001) >= 0x1); - Assert.isTrue((dirs & 0x0001) >= LEFT); - Assert.isTrue((dirs & LEFT) == LEFT); - Assert.isTrue((dirs & LEFT) == 0x1); - Assert.isTrue((dirs & 0x0001) == LEFT); - Assert.isTrue((dirs & 0x0001) == 0x1); - - Assert.isFalse((dirs & LEFT) <= 0); - Assert.isFalse((dirs & LEFT) <= NONE); - Assert.isFalse((dirs & 0x0001) <= 0); - Assert.isFalse((dirs & 0x0001) <= NONE); - - dirs = NONE; - Assert.isTrue((dirs | LEFT) > 0); - Assert.isTrue((dirs | LEFT) > NONE); - Assert.isTrue((dirs | 0x0001) > 0); - Assert.isTrue((dirs | 0x0001) > NONE); - Assert.isTrue((dirs | LEFT) >= 0x1); - Assert.isTrue((dirs | LEFT) >= LEFT); - Assert.isTrue((dirs | 0x0001) >= 0x1); - Assert.isTrue((dirs | 0x0001) >= LEFT); - Assert.isTrue((dirs | LEFT) == LEFT); - Assert.isTrue((dirs | LEFT) == 0x1); - Assert.isTrue((dirs | 0x0001) == LEFT); - Assert.isTrue((dirs | 0x0001) == 0x1); - - Assert.isFalse((dirs | LEFT) <= 0); - Assert.isFalse((dirs | LEFT) <= NONE); - Assert.isFalse((dirs | 0x0001) <= 0); - Assert.isFalse((dirs | 0x0001) <= NONE); - } - @Test function testAngles() { - function assertDegrees(flags:FlxDirectionFlags, degrees:Float) + function assertDegrees(flags:FlxDirectionFlags, degrees:Float, margin = 0.001, ?pos:PosInfos) { - FlxAssert.areNear(flags.degrees, degrees); - FlxAssert.areNear(flags.radians, degrees / 180 * Math.PI); + FlxAssert.areNear(flags.degrees, degrees, margin, null, pos); + FlxAssert.areNear(flags.radians, degrees / 180 * Math.PI, margin, null, pos); } assertDegrees(RIGHT , 0 ); @@ -213,4 +172,29 @@ class FlxDirectionFlagsTest extends FlxTest assertDegrees(UP ,-90 ); assertDegrees(UP | RIGHT ,-45 ); } + + @Test + function testNot() + { + inline function assertNot(a:FlxDirectionFlags, b:FlxDirectionFlags, ?pos:PosInfos) + { + Assert.areEqual(a.not(), b, 'Value ${a.toInt()}:[$a].not() was not equal to expected value ${b.toInt()}:[$b]', pos); + Assert.areEqual(b.not(), a, 'Value ${b.toInt()}:[$b].not() was not equal to expected value ${a.toInt()}:[$a]', pos); + } + + assertNot(RIGHT | DOWN, LEFT | UP); + assertNot(RIGHT, LEFT | UP | DOWN); + assertNot(ANY, NONE); + } + + @Test + @:haxe.warning("-WDeprecated") + function implicitBackwardsCompat() + { + + Assert.isTrue(FlxDirectionFlags.NONE == 0); + Assert.isTrue(0 == FlxDirectionFlags.NONE); + Assert.isTrue(flixel.util.FlxDirection.LEFT == 0x0001); + Assert.isTrue(0x0001 == flixel.util.FlxDirection.LEFT); + } } From 6a601a3881ce9f2a3adb7460182046c40b4e2b78 Mon Sep 17 00:00:00 2001 From: George FunBook Date: Thu, 30 Jan 2025 12:43:03 -0600 Subject: [PATCH 96/99] update changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b728b5f1de..71de961eaf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,8 @@ We removed many features and utilities that were previously deprecated - `FlxState::switchTo`: Use `startOutro`, instead ([#2733](https://github.com/HaxeFlixel/flixel/pull/2733)) - `FlxCamera.defaultCameras`: Use `FlxG.cameras.setDefaultDrawTarget`, instead - `FlxSave`: Deprecate and remove all uses of `FlxSaveStatus.ERROR` for `FlxSaveStatus.SAVE_ERROR` ([#3294](https://github.com/HaxeFlixel/flixel/pull/3294)) +- `FlxDefines`: `FLX_POST_PROCESS` and all flags pertaining to outdated openfl/lime versions ([#3059](https://github.com/HaxeFlixel/flixel/pull/3059)) +- `FlxDirection` and `FlxDirectionFlags`: Deprecate implicit casts to/from Int and all operators ([#3308](https://github.com/HaxeFlixel/flixel/pull/3308)) #### Changes and improvements: - `FlxSpritegroup`: Setting `origin` now causes members to pivot around the same point ([#2981](https://github.com/HaxeFlixel/flixel/pull/2981)) @@ -38,9 +40,15 @@ We removed many features and utilities that were previously deprecated - `FlxCamera`: Fixed `zoom` and `defaultZoom` so it works with values other than 1.0 ([#2907](https://github.com/HaxeFlixel/flixel/pull/2907)) - `FlxBasic`: Added `getDefaultCamera`, used in nearly all methods taking an optional `camera` arg ([#3072](https://github.com/HaxeFlixel/flixel/pull/3072)) - `FlxG.log`: Add `PosInfos` args to loggers, for better tracing info ([#3338](https://github.com/HaxeFlixel/flixel/pull/3338)) +- `FlxSpriteUtil`: `drawCicle` now centers the image to the bitmap, if x/y are omitted ([#3340](https://github.com/HaxeFlixel/flixel/pull/3340)) #### New features: - `FlxMath`: Add improved, euclidean division `mod` function ([#3341](https://github.com/HaxeFlixel/flixel/pull/3341)) +- `FlxVirtualStick`: Add analog directional input to `FlxVirtualPad`, deprecated `FlxAnalog` ([#3340](https://github.com/HaxeFlixel/flixel/pull/3340)) +- `FlxButton`: Added `toString` and `toInt` methods to `FlxButtonState`, deprecate `statusAnimations` ([#3340](https://github.com/HaxeFlixel/flixel/pull/3340)) +- `FlxPoint`: Added `scale`, `dist`, `distSquared`, `distanceTo` and `distanceSquaredTo` overloaded methods ([#3340](https://github.com/HaxeFlixel/flixel/pull/3340)) +- `FlxMath`: Added `getElapsedLerp` for framerate independate lerping ([#3340](https://github.com/HaxeFlixel/flixel/pull/3340)) +- `FlxAnalogState`: add `moved`, `justMoved`, `stopped` and `justStopped` getters ([#3340](https://github.com/HaxeFlixel/flixel/pull/3340)) #### Bugfixes: - `FlxCamera`: Fix `color` field ([#3326](https://github.com/HaxeFlixel/flixel/pull/3326)) From 517606660d70f9ce163d2143b560b41d2e371baa Mon Sep 17 00:00:00 2001 From: George FunBook Date: Thu, 30 Jan 2025 14:04:10 -0600 Subject: [PATCH 97/99] finalize(?) changelog --- CHANGELOG.md | 170 +++++++++++++++++++++++++-------------------------- 1 file changed, 84 insertions(+), 86 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71de961eaf..ce3e196ba2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -6.0.0 (TBD) +# 6.0.0 (TBD) #### Removals and Breaking Changes We removed many features and utilities that were previously deprecated @@ -41,6 +41,7 @@ We removed many features and utilities that were previously deprecated - `FlxBasic`: Added `getDefaultCamera`, used in nearly all methods taking an optional `camera` arg ([#3072](https://github.com/HaxeFlixel/flixel/pull/3072)) - `FlxG.log`: Add `PosInfos` args to loggers, for better tracing info ([#3338](https://github.com/HaxeFlixel/flixel/pull/3338)) - `FlxSpriteUtil`: `drawCicle` now centers the image to the bitmap, if x/y are omitted ([#3340](https://github.com/HaxeFlixel/flixel/pull/3340)) +- `FlxCamera`: Calulate adjusted lerp only when needed ([#3106](https://github.com/HaxeFlixel/flixel/pull/3106)) #### New features: - `FlxMath`: Add improved, euclidean division `mod` function ([#3341](https://github.com/HaxeFlixel/flixel/pull/3341)) @@ -54,8 +55,8 @@ We removed many features and utilities that were previously deprecated - `FlxCamera`: Fix `color` field ([#3326](https://github.com/HaxeFlixel/flixel/pull/3326)) - `FlxCamera`: Reset `bgColor` on reset ([#3254](https://github.com/HaxeFlixel/flixel/issues/3254)) -5.9.0 (December 12, 2024) ------------------------------- +## 5.9.0 (December 12, 2024) + #### New features: - `FlxInputText`: Add improved input text to core flixel (flixel-ui's implementation will be deprecated) ([#3219](https://github.com/HaxeFlixel/flixel/pull/3219)) - `FlxReplay`: Add `getDuration` ([#3135](https://github.com/HaxeFlixel/flixel/pull/3135)) @@ -138,8 +139,8 @@ We removed many features and utilities that were previously deprecated - `FlxAction`: Fix bug where multiple `check` calls wipe analog fields ([#3277](https://github.com/HaxeFlixel/flixel/pull/3277)) - `FlxKeyManager`: Remove events on destroy, preventing crashes ([#3299](https://github.com/HaxeFlixel/flixel/pull/3299)) -5.8.0 (April 19, 2024) ------------------------------- +## 5.8.0 (April 19, 2024) + #### New features: - `FlxBitmapText`: Add `getRenderedText` ([#3120](https://github.com/HaxeFlixel/flixel/pull/3120)) @@ -148,18 +149,18 @@ We removed many features and utilities that were previously deprecated - `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: - `FlxBitmapFont`: Added `setCharFrame` ([#3037](https://github.com/HaxeFlixel/flixel/pull/3037)) - `FlxTimer`: Added static `wait` and `loops` methods ([#3040](https://github.com/HaxeFlixel/flixel/pull/3040)) @@ -197,19 +198,19 @@ We removed many features and utilities that were previously deprecated - `FlxAtlasFrames`: Prevent errors when adding frames of size 0 ([#3096](https://github.com/HaxeFlixel/flixel/pull/3096)) - `FlxSound`: Fix sound panning ([#2863](https://github.com/HaxeFlixel/flixel/pull/2863)) -5.6.2 (February 10, 2024) ------------------------------- +## 5.6.2 (February 10, 2024) + #### Changes and improvements: - `FlxBitmapFont`: Prevent crashes from missing xml fields in `fromAngelCode` ([#3029](https://github.com/HaxeFlixel/flixel/pull/3029)) -5.6.1 (February 9, 2024) ------------------------------- +## 5.6.1 (February 9, 2024) + #### Changes and improvements: - `FlxBitmapFont`: Downgraded crashes of missing xml fields to warnings in `fromAngelCode` ([#3025](https://github.com/HaxeFlixel/flixel/pull/3025)) - Corrected documenation for the recent `FlxG.switchstate` arg changes -5.6.0 (February 2, 2024) ------------------------------- +## 5.6.0 (February 2, 2024) + #### New features: - `FlxGraphic`: Added `isDestroyed` ([#2974](https://github.com/HaxeFlixel/flixel/pull/2974)) - `FlxBitmapFont`: Support for all BMFont output file types ([#2949](https://github.com/HaxeFlixel/flixel/pull/2949)) @@ -248,8 +249,8 @@ We removed many features and utilities that were previously deprecated - `FlxSignal`: Fix one-time listeners not being removed on hashlink ([#3004](https://github.com/HaxeFlixel/flixel/pull/3004)) - `QuadPath`: Prevent crash by avoiding divide by zero in `getCurveLength` ([#3019](https://github.com/HaxeFlixel/flixel/pull/3019)) -5.5.0 (November 8, 2023) ------------------------------- +## 5.5.0 (November 8, 2023) + #### New features: - `FlxG`: Added `animationTimeScale` ([#2937](https://github.com/HaxeFlixel/flixel/pull/2937)) @@ -263,8 +264,8 @@ We removed many features and utilities that were previously deprecated - `FlxBar`: Various fixes ([#2938](https://github.com/HaxeFlixel/flixel/pull/2938)) -5.4.1 (October 4, 2023) ------------------------------- +## 5.4.1 (October 4, 2023) + #### Changes and improvements: - Various improvements and new features for animations ([#2930](https://github.com/HaxeFlixel/flixel/pull/2930)) - `FlxAnimation`: Make `frameDuration` and `looped` public @@ -275,8 +276,8 @@ We removed many features and utilities that were previously deprecated #### Bugfixes: - `FlxSoundTray`: Fix sound tray hide animation ([#2923](https://github.com/HaxeFlixel/flixel/pull/2923)) -5.4.0 (September 28, 2023) ------------------------------- +## 5.4.0 (September 28, 2023) + #### New features: - **README.md**: Add Turkish translations - `AssetPaths`: Add `allFiles` field, and an arg in `FlxAssets.buildFileReferences` to change the identifier ([#2807](https://github.com/HaxeFlixel/flixel/pull/2807)) @@ -334,15 +335,15 @@ We removed many features and utilities that were previously deprecated - `FlxBitmapText`: Fix `textColor` not applied correctly ([#2918](https://github.com/HaxeFlixel/flixel/pull/2918)) - `FlxCamera`: Fix camera lerping speeds on lower fps ([#2920](https://github.com/HaxeFlixel/flixel/pull/2920)) -5.3.1 (May 7, 2023) ------------------------------- +## 5.3.1 (May 7, 2023) + #### Changes and improvements: - Change all `@:enum abstract` to `enum abstract` to prevent warnings in haxe 4.3.1 ([#2790](https://github.com/HaxeFlixel/flixel/pull/2790)) - `FlxAnimation`: Prevent crash when destroying sprites in an anim callback ([#2785](https://github.com/HaxeFlixel/flixel/pull/2785)) - `FlxCollision`: Fix gap in `createCameraWall` ([#2781](https://github.com/HaxeFlixel/flixel/pull/2781)) -5.3.0 (April 26, 2023) ------------------------------- +## 5.3.0 (April 26, 2023) + #### Dependencies: - Dropped support for haxe 4.0 and 4.1, use 4.2.5 or higher @@ -371,20 +372,20 @@ We removed many features and utilities that were previously deprecated - `LogFrontEnd`: Fixed null crashes when logging before `FlxGame` in created ([2779](https://github.com/HaxeFlixel/flixel/pull/2779)) - `FlxSave`: Fixed saves with multiple invalid characters ([#2779](https://github.com/HaxeFlixel/flixel/pull/2779)) -5.2.2 (February 15, 2023) ------------------------------- +## 5.2.2 (February 15, 2023) + #### Bugfixes: - `FlxGamePad`: Fix various "firstPressed" functions ([#2728](https://github.com/HaxeFlixel/flixel/pull/2728)) - `FlxSave`: Prevent crash when hiding debug windows, after `FlxG.save.bind` is called ([#2725](https://github.com/HaxeFlixel/flixel/pull/2725)) - `FlxCamera`: remove uses of camera.camera ([#2731](https://github.com/HaxeFlixel/flixel/pull/2731)) -5.2.1 (January 20, 2023) ------------------------------- +## 5.2.1 (January 20, 2023) + #### Bugfixes: - `FlxSave`: Fix save location on android and ios ([#2718](https://github.com/HaxeFlixel/flixel/pull/2718)) -5.2.0 January 17, 2023 ------------------------------- +## 5.2.0 January 17, 2023 + #### New features: - `FlxMouse`: added `deltaX`, `deltaY`, `deltaScreenX` and `deltaScreenY` ([#2709](https://github.com/HaxeFlixel/flixel/pull/2709)) - `FlxCamera`: added public `view` and `viewMargin` properties, deprecated old, private viewOffset fields([#2714](https://github.com/HaxeFlixel/flixel/pull/2714)) @@ -395,8 +396,8 @@ We removed many features and utilities that were previously deprecated #### Bugfixes: - `FlxSpriteGroup`: Fix `findMinY()` and `findMaxY()` returning `x` instead of `y` ([#2713](https://github.com/HaxeFlixel/flixel/pull/2713)) -5.1.0 December 22, 2022 ------------------------------- +## 5.1.0 December 22, 2022 + #### Changes and improvements: - `SoundFrontEnd`: added `soundTray` getter for `FlxG.game.soundTray` ([#2706](https://github.com/HaxeFlixel/flixel/pull/2706)) @@ -408,14 +409,14 @@ We removed many features and utilities that were previously deprecated - `FlxPoint`: fixed math error in `rotate`, `pivotDegrees` and `pivotRadians` ([#2700](https://github.com/HaxeFlixel/flixel/pull/2700)) - `FlxObject`: fixed `isTouching` and `wasTouching` to check **any** given instead of **all** ([#2705](https://github.com/HaxeFlixel/flixel/pull/2705)) -5.0.2 November 30, 2022 ------------------------------- +## 5.0.2 November 30, 2022 + #### Changes and improvements: - `FlxAssetPaths`: Warnings involving assets will point to that asset instead of the build macro. ([#2684](https://github.com/HaxeFlixel/flixel/pull/2684)) - `FlxTilemap`: Honors `FlxSprite.defaultAntialiasing` ([#2688](https://github.com/HaxeFlixel/flixel/pull/2688)) -5.0.1 November 23, 2022 ------------------------------- +## 5.0.1 November 23, 2022 + #### Bugfixes: - Fix lime < 8 not being properly defined to FLX_NO_PITCH ([#2678](https://github.com/HaxeFlixel/flixel/pull/2678)) - `AssetPaths`: various fixes ([#2680](https://github.com/HaxeFlixel/flixel/pull/2680)) @@ -425,17 +426,17 @@ We removed many features and utilities that were previously deprecated #### New features: - `FlxKeys`: Added `SCROLL_LOCK`, `NUMLOCK`, `WINDOWS`, `MENU`, `BREAK` and `NUMPADSLASH` keys ([#2638](https://github.com/HaxeFlixel/flixel/pull/2638)) -5.0.0 (November 20, 2022) ------------------------------- +# 5.0.0 (November 20, 2022) + The alpha was causing issues with CI due to haxelib issues. We're foregoing the alpha, since the new features are considiered "stable". -5.0.0-alpha.2 (November 19, 2022) ------------------------------- +## 5.0.0-alpha.2 (November 19, 2022) + #### Bugfixes: - `FlxDefines` prevent compile error when targeting lime 7 on non-sys targets ([#2676](https://github.com/HaxeFlixel/flixel/pull/2676)) -5.0.0-alpha (November 19, 2022) ------------------------------- +## 5.0.0-alpha (November 19, 2022) + #### New features: - `FlxMouse`: Added `released`, `releasedRight` and `releasedMiddle` ([#2496](https://github.com/HaxeFlixel/flixel/pull/2496)) @@ -494,8 +495,8 @@ The alpha was causing issues with CI due to haxelib issues. We're foregoing the - `FlxGame`: removed misleading `zoom` arg from constructor ([#2591](https://github.com/HaxeFlixel/flixel/pull/2591)) - `FlxMouseEventManager`: Changed from a static manager to an instance. Use `FlxMouseEvent` for the default manager ([#2540](https://github.com/HaxeFlixel/flixel/pull/2540)) -4.11.0 (January 26, 2022) ------------------------------- +## 4.11.0 (January 26, 2022) + #### Dependencies: - Dropped support for haxe 3, use 4.0.5 or higher @@ -522,8 +523,8 @@ The alpha was causing issues with CI due to haxelib issues. We're foregoing the - `FlxObject`: `screenCenter` defaults to `XY` rather than `null` ([#2441](https://github.com/HaxeFlixel/flixel/pull/2441)) - `FlxState`: Clarify restrictions in state constructors ([#2479](https://github.com/HaxeFlixel/flixel/pull/2479)) -4.10.0 (September 12, 2021) ------------------------------- +## 4.10.0 (September 12, 2021) + #### New features: - Added `FlxDirectionFlags` and `FlxDirection` ([#2303](https://github.com/HaxeFlixel/flixel/pull/2303)) @@ -545,8 +546,8 @@ The alpha was causing issues with CI due to haxelib issues. We're foregoing the - `FlxSpriteUtil`: enabled `drawRoundRectComplex()` for non-Flash targets ([#2332](https://github.com/HaxeFlixel/flixel/pull/2332)) - `FlxTween`: allowed `cancelTweensOf()` to cancel "grandchild" tweens ([#2354](https://github.com/HaxeFlixel/flixel/pull/2354)) -4.9.0 (April 11, 2021) ------------------------------- +## 4.9.0 (April 11, 2021) + #### Dependencies: - Compatibility with Haxe 4.2.x @@ -571,12 +572,12 @@ The alpha was causing issues with CI due to haxelib issues. We're foregoing the - `FlxBasic`: assign an incremented `ID` for each created instance ([#2266](https://github.com/HaxeFlixel/flixel/pull/2266)) - `FlxCamera`: deprecated `defaultCameras` in favor of default draw targets in `FlxG.cameras` ([#2296](https://github.com/HaxeFlixel/flixel/pull/2296)) -4.8.1 (July 16, 2020) ------------------------------- +## 4.8.1 (July 16, 2020) + - improved rendering performance on low-end devices -4.8.0 (July 2, 2020) ------------------------------- +## 4.8.0 (July 2, 2020) + #### New features: - `FlxSplash`: added `muted` (defaults to `true` on HTML5) - `FlxBaseKeyList`: added `NONE` ([#2253](https://github.com/HaxeFlixel/flixel/pull/2253)) @@ -593,8 +594,8 @@ The alpha was causing issues with CI due to haxelib issues. We're foregoing the #### Changes and improvements: - Fixed `Std.is()` deprecation warnings with Haxe 4.2 -4.7.0 (April 12, 2020) ------------------------------- +## 4.7.0 (April 12, 2020) + #### New features: - `FlxGroup`: added support for specifying `cameras` ([#2232](https://github.com/HaxeFlixel/flixel/pull/2232)) @@ -610,20 +611,20 @@ The alpha was causing issues with CI due to haxelib issues. We're foregoing the - `FlxAnimation`: changed `frameRate` to a `Float` ([#2252](https://github.com/HaxeFlixel/flixel/pull/2252)) -4.6.3 (August 21, 2019) ------------------------------- +## 4.6.3 (August 21, 2019) + - Compatibility with Haxe 4.0.0-rc.3 - `FlxAssetPaths`: added support for custom renaming ([#2227](https://github.com/HaxeFlixel/flixel/issues/2227)) -4.6.2 (June 19, 2019) ------------------------------- +## 4.6.2 (June 19, 2019) + - `FlxGraphicsShader`: fixed crashes on some old iOS devices ([#2219](https://github.com/HaxeFlixel/flixel/issues/2219)) - `FlxG.android`: - fixed `preventDefaultKeys` handling with OpenFL 8+ ([#2218](https://github.com/HaxeFlixel/flixel/issues/2218)) - fixed the key codes for `FlxAndroidKey.BACK` and `MENU` with OpenFL 8+ ([#2218](https://github.com/HaxeFlixel/flixel/issues/2218)) -4.6.1 (April 2, 2019) ------------------------------- +## 4.6.1 (April 2, 2019) + #### Bugfixes: - `FlxDebugger`: @@ -631,8 +632,8 @@ The alpha was causing issues with CI due to haxelib issues. We're foregoing the - clear the transform tool target on state switches - `FlxBasePreloader`: fixed a crash on the HashLink target -4.6.0 (February 4, 2019) ------------------------------- +## 4.6.0 (February 4, 2019) + #### Dependencies: - Compatibility with Haxe 4.0.0-rc.1 @@ -658,13 +659,13 @@ The alpha was causing issues with CI due to haxelib issues. We're foregoing the - Fixed `FlxSubState` not being updated in the frame it is entered ([#2204](https://github.com/HaxeFlixel/flixel/issues/2204)) - `FlxText`: fixed frame size not always being correct when `updateHitbox()` is called ([#2205](https://github.com/HaxeFlixel/flixel/issues/2205)) -4.5.1 (September 7, 2018) ------------------------------- +## 4.5.1 (September 7, 2018) + - Fixed compatibility with OpenFL 8.5.0 - `FlxSoundGroup`: fixed `add()` adding sounds twice -4.5.0 (August 10, 2018) ------------------------------- +## 4.5.0 (August 10, 2018) + #### Dependencies: - Added support for Lime 7 @@ -689,16 +690,16 @@ The alpha was causing issues with CI due to haxelib issues. We're foregoing the - `FlxSpriteUtil`: added an argument allowing to use a positioning function in `space()` ([#2154](https://github.com/HaxeFlixel/flixel/issues/2154)) - `FlxG.accelerometer`: enabled accelerometer support on HTML5 -4.4.2 (June 12, 2018) ------------------------------- +## 4.4.2 (June 12, 2018) + - Fixed compatibility with Haxe 4.0.0-preview.4 -4.4.1 (May 10, 2018) ------------------------------- +## 4.4.1 (May 10, 2018) + - Fixed an issue with code completion on the Flash target in VSCode -4.4.0 (May 4, 2018) ------------------------------- +## 4.4.0 (May 4, 2018) + #### Dependencies: - Added support for OpenFL 8 and Lime 6.3.0 ([#2136](https://github.com/HaxeFlixel/flixel/issues/2136)) @@ -732,8 +733,8 @@ The alpha was causing issues with CI due to haxelib issues. We're foregoing the - `FlxG.keys`: added arrow keys, space and tab to `preventDefaultKeys` on HTML5 - `FlxSpriteGroup`: added a `camera` setter override ([#2146](https://github.com/HaxeFlixel/flixel/issues/2146)) -4.3.0 (July 22, 2017) ------------------------------- +## 4.3.0 (July 22, 2017) + #### New features: - `FlxTween`: added `cancelChain()` ([#1988](https://github.com/HaxeFlixel/flixel/issues/1988)) @@ -794,12 +795,12 @@ The alpha was causing issues with CI due to haxelib issues. We're foregoing the - `FlxFlicker`: made `stop()` public ([#2084](https://github.com/HaxeFlixel/flixel/issues/2084)) - `FlxAnalog`: several fixes and improvements ([#2073](https://github.com/HaxeFlixel/flixel/issues/2073)) -4.2.1 (March 4, 2017) ------------------------------- +## 4.2.1 (March 4, 2017) + - fixed rendering with Haxe 3.4.0 and OpenFL Next -4.2.0 (October 11, 2016) ------------------------------- +## 4.2.0 (October 11, 2016) + #### New features: * `FlxG.html5`: added `platform` and `onMobile` ([#1897](https://github.com/HaxeFlixel/flixel/issues/1897)) @@ -873,12 +874,11 @@ The alpha was causing issues with CI due to haxelib issues. We're foregoing the * clearing the cache now only affects unused graphics ([#1968](https://github.com/HaxeFlixel/flixel/issues/1968)) * `FlxFramesCollection`: frame sizes are now checked and trimmed ([#1966](https://github.com/HaxeFlixel/flixel/issues/1966)) -4.1.1 (August 5, 2016) ------------------------------- +## 4.1.1 (August 5, 2016) + * fixed the check for Lime <= 2.9.1 -4.1.0 (July 10, 2016) ------------------------------- +## 4.1.0 (July 10, 2016) #### New features: @@ -944,8 +944,7 @@ The alpha was causing issues with CI due to haxelib issues. We're foregoing the * `FlxG.debugger`: changed `drawDebugChanged` to be dispatched _after_ `drawDebug` is updated * `FlxDefines`: added a check for incompatible OpenFL / Lime versions (should be < 4.0.0 / < 3.0.0 respectively) -4.0.1 (March 19, 2016) ------------------------------- +## 4.0.1 (March 19, 2016) * `FlxDebugger`: [HTML5] fixed version text color ([#1727](https://github.com/HaxeFlixel/flixel/issues/1727)) * `FlxFlicker` / `LabelValuePair`: fixed DCE issues ([#1757](https://github.com/HaxeFlixel/flixel/issues/1757)) @@ -962,8 +961,7 @@ The alpha was causing issues with CI due to haxelib issues. We're foregoing the * [HTML5] fixed formatting for amounts > Int32 * Debugger Stats window: fixed paused time being taken into account for average FPS -4.0.0 (February 16, 2016) ------------------------------- +# 4.0.0 (February 16, 2016) ### Restructures: From 531a432d628548c09cd6dfe6d5b5216855ab61c7 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Thu, 30 Jan 2025 15:33:11 -0600 Subject: [PATCH 98/99] enable glsl3 (when openfl does) (#3347) --- flixel/graphics/tile/FlxGraphicsShader.hx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flixel/graphics/tile/FlxGraphicsShader.hx b/flixel/graphics/tile/FlxGraphicsShader.hx index 5e1e01d0f2..343eb13eb6 100644 --- a/flixel/graphics/tile/FlxGraphicsShader.hx +++ b/flixel/graphics/tile/FlxGraphicsShader.hx @@ -9,7 +9,7 @@ class FlxGraphicsShader extends GraphicsShader attribute vec4 colorMultiplier; attribute vec4 colorOffset; uniform bool hasColorTransform; - ") + ", true) @:glVertexBody(" openfl_Alphav = openfl_Alpha * alpha; @@ -26,7 +26,7 @@ class FlxGraphicsShader extends GraphicsShader openfl_ColorMultiplierv = colorMultiplier; } } - ") + ", true) @:glFragmentHeader(" uniform bool hasTransform; // TODO: Is this still needed? Apparently, yes! uniform bool hasColorTransform; @@ -53,10 +53,10 @@ class FlxGraphicsShader extends GraphicsShader return color * openfl_Alphav; } - ") + ", true) @:glFragmentBody(" gl_FragColor = flixel_texture2D(bitmap, openfl_TextureCoordv); - ") + ", true) public function new() { super(); From fffb1a74cf08f63dacc2ab09976340563f5b6e6d Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 17 Feb 2025 20:25:42 -0500 Subject: [PATCH 99/99] Query max texture size only once. --- flixel/system/frontEnds/BitmapFrontEnd.hx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/flixel/system/frontEnds/BitmapFrontEnd.hx b/flixel/system/frontEnds/BitmapFrontEnd.hx index 3204b09b32..e46bc88f4e 100644 --- a/flixel/system/frontEnds/BitmapFrontEnd.hx +++ b/flixel/system/frontEnds/BitmapFrontEnd.hx @@ -342,10 +342,14 @@ class BitmapFrontEnd } #if FLX_OPENGL_AVAILABLE + static var _maxTextureSize:Int = -1; function get_maxTextureSize():Int { - if (FlxG.stage.window.context.attributes.hardware) - return cast GL.getParameter(GL.MAX_TEXTURE_SIZE); + if (_maxTextureSize > 0) return _maxTextureSize; + + if (FlxG.stage.window.context.attributes.hardware) { + return (_maxTextureSize = cast GL.getParameter(GL.MAX_TEXTURE_SIZE)); + } return -1; }