CameraTools/GroupTools bugfixing and sprite scale support

This commit is contained in:
2022-08-02 02:24:22 +00:00
parent 744f99bc46
commit 9e8036deb2
6 changed files with 192 additions and 152 deletions

View File

@@ -5,9 +5,13 @@
(prop &mut :FlxCamera uiCamera) (prop &mut :FlxCamera uiCamera)
(method &override :Void create [] (method &override :Void create []
(#when debug
(add cameraBounds))
(add logTexts) (add logTexts)
(set Prelude.printStr log) (set Prelude.printStr log)
(set pieceCamera FlxG.camera) (set pieceCamera FlxG.camera)
(set cameraBounds.cameras [pieceCamera])
(set uiCamera (new FlxCamera)) (set uiCamera (new FlxCamera))
(set uiCamera.bgColor FlxColor.TRANSPARENT) (set uiCamera.bgColor FlxColor.TRANSPARENT)
(pieceCamera.copyFrom FlxG.camera) (pieceCamera.copyFrom FlxG.camera)
@@ -23,10 +27,19 @@
(prop &mut :EntryType typeAdding Todo) (prop &mut :EntryType typeAdding Todo)
(prop &mut :FlxInputText entryNameText) (prop &mut :FlxInputText entryNameText)
(prop :FlxSprite cameraBounds (new FlxSprite))
(method &override :Void update [:Float elapsed] (method &override :Void update [:Float elapsed]
(super.update elapsed) (super.update elapsed)
(#when debug
(let [b (pieceCamera.getScrollBounds)]
(set cameraBounds.x b.x)
(set cameraBounds.y b.y)
(cameraBounds.makeGraphic (Std.int b.width) (Std.int b.height) FlxColor.TRANSPARENT true)
(cameraBounds.drawRect 0 0 b.width b.height FlxColor.TRANSPARENT (object color FlxColor.LIME thickness 5))))
(pieceCamera.updateScrollWheelZoom elapsed 1) (pieceCamera.updateScrollWheelZoom elapsed 5)
(pieceCamera.updateMouseBorderControl elapsed KEYBOARD_SCROLL_SPEED 0.002 uiCamera) (pieceCamera.updateMouseBorderControl elapsed KEYBOARD_SCROLL_SPEED 0.002 uiCamera)
// Hold left-click to hide the habit text and see the image clearly: // Hold left-click to hide the habit text and see the image clearly:
@@ -42,7 +55,7 @@
(set save.data.backgroundIndex #{(save.data.backgroundIndex + 1) % backgroundOptions.length;}#) (set save.data.backgroundIndex #{(save.data.backgroundIndex + 1) % backgroundOptions.length;}#)
(save.flush) (save.flush)
// setModel so the entry text gets remade in inverted/lightened colors when necessary // setModel so the entry text gets remade in inverted/lightened colors when necessary
(setModel model (nth model.rewardFiles rewardFileIndex)))) (refreshModel)))
(method startAdding [:EntryType type] (method startAdding [:EntryType type]
(set typeAdding type) (set typeAdding type)
@@ -54,8 +67,9 @@
(when FlxG.keys.justPressed.ENTER (when FlxG.keys.justPressed.ENTER
(cond (cond
(entryNameText (entryNameText
// addEntry() calls save()
(model.addEntry typeAdding [entryNameText.text]) (model.addEntry typeAdding [entryNameText.text])
(setModel model (nth model.rewardFiles rewardFileIndex)) (refreshModel)
(entryNameText.kill) (entryNameText.kill)
(set entryNameText null)) (set entryNameText null))
(true (true
@@ -79,11 +93,11 @@
(when FlxG.keys.justPressed.LEFT (when FlxG.keys.justPressed.LEFT
(unless (= rewardFileIndex 0) (unless (= rewardFileIndex 0)
(-= rewardFileIndex 1) (-= rewardFileIndex 1)
(setModel model (nth model.rewardFiles rewardFileIndex)))) (refreshModel)))
(when FlxG.keys.justPressed.RIGHT (when FlxG.keys.justPressed.RIGHT
(unless (= rewardFileIndex maxRewardFile) (unless (= rewardFileIndex maxRewardFile)
(+= rewardFileIndex 1) (+= rewardFileIndex 1)
(setModel model (nth model.rewardFiles rewardFileIndex))))) (refreshModel))))
// Handle keyboard input: // Handle keyboard input:
(when (and shortcutHandler !entryNameText) (when (and shortcutHandler !entryNameText)
(shortcutHandler.update))) (shortcutHandler.update)))
@@ -110,6 +124,7 @@
(prop &mut :Map<FlxExtendedSprite,Int> indexMap (new Map)) (prop &mut :Map<FlxExtendedSprite,Int> indexMap (new Map))
(prop &mut :Map<Int,FlxExtendedSprite> spriteMap (new Map)) // Because rewardSprites will be re-ordered in depth handling, this is required (prop &mut :Map<Int,FlxExtendedSprite> spriteMap (new Map)) // Because rewardSprites will be re-ordered in depth handling, this is required
(prop &mut lastRewardFileIndex -1)
(prop &mut rewardFileIndex 0) (prop &mut rewardFileIndex 0)
(prop &mut maxRewardFile 0) (prop &mut maxRewardFile 0)
@@ -144,129 +159,130 @@
(set save.data.backgroundIndex 0)) (set save.data.backgroundIndex 0))
(set pieceCamera.bgColor (nth backgroundOptions save.data.backgroundIndex)) (set pieceCamera.bgColor (nth backgroundOptions save.data.backgroundIndex))
(let [rewardSprite (unless (= lastRewardFileIndex rewardFileIndex)
(new FlxSprite 0 0 (let [rewardSprite
(BitmapData.fromFile (new FlxSprite 0 0
currentRewardFile.path))] (BitmapData.fromFile
(when rewardSprites currentRewardFile.path))]
(remove rewardSprites)) (when rewardSprites
(rewardSprite.setGraphicSize FlxG.width 0) (remove rewardSprites))
(rewardSprite.updateHitbox) (rewardSprite.setGraphicSize FlxG.width 0)
(when (> rewardSprite.height FlxG.height) (rewardSprite.updateHitbox)
(rewardSprite.setGraphicSize 0 FlxG.height)) (when (> rewardSprite.height FlxG.height)
(rewardSprite.updateHitbox) (rewardSprite.setGraphicSize 0 FlxG.height))
(rewardSprite.screenCenter) (rewardSprite.updateHitbox)
(rewardSprite.screenCenter)
(set pieceCamera.zoom rewardSprite.scale.x) (set pieceCamera.zoom rewardSprite.scale.x)
(set rewardSprites (new FlxTypedGroup)) (set rewardSprites (new FlxTypedGroup))
(doFor map [matchingPiecesLeft matchingPiecesRight matchingPiecesUp matchingPiecesDown] (doFor map [matchingPiecesLeft matchingPiecesRight matchingPiecesUp matchingPiecesDown]
(map.clear)) (map.clear))
(connectedPieces.clear) (connectedPieces.clear)
(doFor i (range TOTAL_PIECES) (dictSet connectedPieces i [])) (doFor i (range TOTAL_PIECES) (dictSet connectedPieces i []))
(indexMap.clear) (indexMap.clear)
(let [r (new FlxRandom (Strings.hashCode currentRewardFile.path)) (let [r (new FlxRandom (Strings.hashCode currentRewardFile.path))
graphicWidth rewardSprite.pixels.width graphicWidth rewardSprite.pixels.width
graphicHeight rewardSprite.pixels.height graphicHeight rewardSprite.pixels.height
pieceAssetWidth (Std.int (/ graphicWidth PUZZLE_WIDTH)) pieceAssetWidth (Std.int (/ graphicWidth PUZZLE_WIDTH))
pieceAssetHeight (Std.int (/ graphicHeight PUZZLE_HEIGHT)) pieceAssetHeight (Std.int (/ graphicHeight PUZZLE_HEIGHT))
j (new Jigsawx pieceAssetWidth pieceAssetHeight EDGE_LEEWAY BUBBLE_SIZE PUZZLE_HEIGHT PUZZLE_WIDTH r) j (new Jigsawx pieceAssetWidth pieceAssetHeight EDGE_LEEWAY BUBBLE_SIZE PUZZLE_HEIGHT PUZZLE_WIDTH r)
PIECE_WIDTH PIECE_WIDTH
(/ rewardSprite.width PUZZLE_WIDTH) (/ rewardSprite.width PUZZLE_WIDTH)
PIECE_HEIGHT PIECE_HEIGHT
(/ rewardSprite.height PUZZLE_HEIGHT) (/ rewardSprite.height PUZZLE_HEIGHT)
:Array<FlxPoint> startingPoints []] :Array<FlxPoint> startingPoints []]
(let [&mut i 0] (let [&mut i 0]
(doFor y (range PUZZLE_HEIGHT) (doFor y (range PUZZLE_HEIGHT)
(doFor x (range PUZZLE_WIDTH) (doFor x (range PUZZLE_WIDTH)
(startingPoints.push (startingPoints.push
(new FlxPoint (+ rewardSprite.x (* x PIECE_WIDTH)) (+ rewardSprite.y (* y PIECE_HEIGHT)))) (new FlxPoint (+ rewardSprite.x (* x PIECE_WIDTH)) (+ rewardSprite.y (* y PIECE_HEIGHT))))
(+= i 1)))) (+= i 1))))
(r.shuffle startingPoints) (r.shuffle startingPoints)
(set jigsaw j) (set jigsaw j)
(r.shuffle jigsaw.jigs) (r.shuffle jigsaw.jigs)
(localVar spriteGrid (for y (range PUZZLE_HEIGHT) (for x (range PUZZLE_WIDTH) null))) (localVar spriteGrid (for y (range PUZZLE_HEIGHT) (for x (range PUZZLE_WIDTH) null)))
(localVar indexGrid (for y (range PUZZLE_HEIGHT) (for x (range PUZZLE_WIDTH) 0))) (localVar indexGrid (for y (range PUZZLE_HEIGHT) (for x (range PUZZLE_WIDTH) 0)))
(doFor i (range (min TOTAL_PIECES (- p currentRewardFile.startingPoints))) (doFor i (range (min TOTAL_PIECES (- p currentRewardFile.startingPoints)))
(let [jig (nth jigsaw.jigs i) (let [jig (nth jigsaw.jigs i)
pos (ifLet [point (dictGet (the Map<Int,FlxPoint> save.data.storedPositions) i)] pos (ifLet [point (dictGet (the Map<Int,FlxPoint> save.data.storedPositions) i)]
point point
(nth startingPoints i)) (nth startingPoints i))
s (new FlxExtendedSprite pos.x pos.y) s (new FlxExtendedSprite pos.x pos.y)
source (new FlxSprite) source (new FlxSprite)
mask (new FlxSprite) mask (new FlxSprite)
sourceRect (new Rectangle jig.xy.x jig.xy.y jig.wh.x jig.wh.y)] sourceRect (new Rectangle jig.xy.x jig.xy.y jig.wh.x jig.wh.y)]
(set s.priorityID i) (set s.priorityID i)
(setNth spriteGrid jig.row jig.col s) (setNth spriteGrid jig.row jig.col s)
(setNth indexGrid jig.row jig.col i) (setNth indexGrid jig.row jig.col i)
(dictSet pieceData i jig) (dictSet pieceData i jig)
(dictSet indexMap s i) (dictSet indexMap s i)
(dictSet spriteMap i s) (dictSet spriteMap i s)
(set s.draggable true) (set s.draggable true)
(s.enableMouseDrag false true) (s.enableMouseDrag false true)
(set s.mouseStartDragCallback (set s.mouseStartDragCallback
->:Void [s x y] ->:Void [s x y]
{ {
// Bring currently held pieces to the front: // Bring currently held pieces to the front:
(rewardSprites.bringToFront s) (rewardSprites.bringToFront s)
(set s.priorityID (+ 1 .priorityID (last (the kiss.List<FlxExtendedSprite> rewardSprites.members)))) (set s.priorityID (+ 1 .priorityID (last (the kiss.List<FlxExtendedSprite> rewardSprites.members))))
(doFor connected (recursivelyConnectedPieces s) (doFor connected (recursivelyConnectedPieces s)
(rewardSprites.bringToFront connected)) (rewardSprites.bringToFront connected))
(set draggingSprite s)
(set draggingLastPos (new FlxPoint s.x s.y))
})
(set s.mouseStopDragCallback
->:Void [s x y]
{
(set draggingSprite null)
(checkMatches i)
(dictSet (the Map<Int,FlxPoint> save.data.storedPositions) i (new FlxPoint s.x s.y))
(doFor connected (recursivelyConnectedPieces s)
(checkMatches (dictGet indexMap connected))
(log "uh $(dictGet indexMap connected)")
(dictSet (the Map<Int,FlxPoint> save.data.storedPositions) (dictGet indexMap connected) (new FlxPoint connected.x connected.y)))
(pieceCamera.calculateScrollBounds rewardSprites SCROLL_BOUND_MARGIN) (set draggingSprite s)
(save.flush) (set draggingLastPos (new FlxPoint s.x s.y))
}) })
(set s.mouseStopDragCallback
(source.makeGraphic (Std.int sourceRect.width) (Std.int sourceRect.height) FlxColor.TRANSPARENT true) ->:Void [s x y]
(source.pixels.copyPixels rewardSprite.pixels sourceRect (new Point 0 0)) {
(set draggingSprite null)
(mask.makeGraphic (Std.int sourceRect.width) (Std.int sourceRect.height) FlxColor.TRANSPARENT true) (checkMatches i)
(drawPieceShape mask jig FlxColor.BLACK) (dictSet (the Map<Int,FlxPoint> save.data.storedPositions) i (new FlxPoint s.x s.y))
(FlxSpriteUtil.alphaMask s source.pixels mask.pixels) (doFor connected (recursivelyConnectedPieces s)
(checkMatches (dictGet indexMap connected))
(dictSet (the Map<Int,FlxPoint> save.data.storedPositions) (dictGet indexMap connected) (new FlxPoint connected.x connected.y)))
(pieceCamera.calculateScrollBounds rewardSprites uiCamera SCROLL_BOUND_MARGIN)
(save.flush)
})
(source.makeGraphic (Std.int sourceRect.width) (Std.int sourceRect.height) FlxColor.TRANSPARENT true)
(source.pixels.copyPixels rewardSprite.pixels sourceRect (new Point 0 0))
(mask.makeGraphic (Std.int sourceRect.width) (Std.int sourceRect.height) FlxColor.TRANSPARENT true)
(drawPieceShape mask jig FlxColor.BLACK)
(FlxSpriteUtil.alphaMask s source.pixels mask.pixels)
(set s.cameras [pieceCamera]) (set s.cameras [pieceCamera])
(#when debug (#when debug
(let [matchZones [(matchZoneLeft s) (matchZoneRight s)(matchZoneUp s)(matchZoneDown s)]] (let [matchZones [(matchZoneLeft s) (matchZoneRight s)(matchZoneUp s)(matchZoneDown s)]]
(doFor z matchZones (doFor z matchZones
(FlxSpriteUtil.drawRect s (- z.x s.x) (- z.y s.y) z.width z.height FlxColor.TRANSPARENT (object thickness 1 color FlxColor.RED))))) (FlxSpriteUtil.drawRect s (- z.x s.x) (- z.y s.y) z.width z.height FlxColor.TRANSPARENT (object thickness 1 color FlxColor.RED)))))
(rewardSprites.add s))) (rewardSprites.add s)))
(doFor row (range PUZZLE_HEIGHT) (doFor row (range PUZZLE_HEIGHT)
(doFor col (range PUZZLE_WIDTH) (doFor col (range PUZZLE_WIDTH)
(let [id (nth indexGrid row col)] (let [id (nth indexGrid row col)]
// combination of try/whenLet should cover target languages // combination of try/whenLet should cover target languages
// where out-of-bounds nth throws an error AND languages // where out-of-bounds nth throws an error AND languages
// where it returns null // where it returns null
(try (whenLet [toLeft (nth spriteGrid row (- col 1))] (try (whenLet [toLeft (nth spriteGrid row (- col 1))]
(dictSet matchingPiecesLeft id toLeft)) (catch [e] null)) (dictSet matchingPiecesLeft id toLeft)) (catch [e] null))
(try (whenLet [toRight (nth spriteGrid row (+ col 1))] (try (whenLet [toRight (nth spriteGrid row (+ col 1))]
(dictSet matchingPiecesRight id toRight)) (catch [e] null)) (dictSet matchingPiecesRight id toRight)) (catch [e] null))
(try (whenLet [toUp (nth spriteGrid (- row 1) col)] (try (whenLet [toUp (nth spriteGrid (- row 1) col)]
(dictSet matchingPiecesUp id toUp)) (catch [e] null)) (dictSet matchingPiecesUp id toUp)) (catch [e] null))
(try (whenLet [toDown (nth spriteGrid (+ row 1) col)] (try (whenLet [toDown (nth spriteGrid (+ row 1) col)]
(dictSet matchingPiecesDown id toDown)) (catch [e] null))))) (dictSet matchingPiecesDown id toDown)) (catch [e] null)))))
(add rewardSprites) (add rewardSprites)
(doFor i (range TOTAL_PIECES) (doFor i (range TOTAL_PIECES)
(checkMatches i)))) (checkMatches i)))))
(set lastRewardFileIndex rewardFileIndex)
(pieceCamera.calculateScrollBounds rewardSprites SCROLL_BOUND_MARGIN) (pieceCamera.calculateScrollBounds rewardSprites uiCamera SCROLL_BOUND_MARGIN)
(when entryTexts (remove entryTexts)) (when entryTexts (remove entryTexts))
(set entryTexts (new FlxTypedGroup)) (set entryTexts (new FlxTypedGroup))
@@ -307,6 +323,10 @@
(shortcutHandler.start))) (shortcutHandler.start)))
(shortcutHandler.start)) (shortcutHandler.start))
(method refreshModel [&opt m]
(let [m (or m model)]
(setModel m (nth m.rewardFiles rewardFileIndex))))
(prop &mut textY 0) (prop &mut textY 0)
// Color currently used for making text, may be inverted or lightened to contrast with background: // Color currently used for making text, may be inverted or lightened to contrast with background:
(prop &mut :FlxColor _color FlxColor.BLACK) (prop &mut :FlxColor _color FlxColor.BLACK)
@@ -361,8 +381,8 @@
(prop &mut c 0) (prop &mut c 0)
(method :Void connectPiece [id self toSprite] (method :Void connectPiece [id self toSprite]
(let [thisConnectedPieces (dictGet connectedPieces ~id) (let [thisConnectedPieces (dictGet connectedPieces id)
toConnectedPieces (dictGet connectedPieces ~(dictGet indexMap toSprite))] toConnectedPieces (dictGet connectedPieces (dictGet indexMap toSprite))]
(+= c 1) (+= c 1)
// Don't add duplicates // Don't add duplicates
(thisConnectedPieces.remove toSprite) (thisConnectedPieces.remove toSprite)
@@ -388,13 +408,13 @@
(unless .isEmpty (mzl.intersection mzr) (unless .isEmpty (mzl.intersection mzr)
(connectPiece id s toRight))) (connectPiece id s toRight)))
(whenLet [toUp (dictGet matchingPiecesUp id) (whenLet [toUp (dictGet matchingPiecesUp id)
mzu ~(matchZoneUp s) mzu (matchZoneUp s)
mzd ~(matchZoneDown toUp)] mzd (matchZoneDown toUp)]
(unless .isEmpty (mzu.intersection mzd) (unless .isEmpty (mzu.intersection mzd)
(connectPiece id s toUp))) (connectPiece id s toUp)))
(whenLet [toDown (dictGet matchingPiecesDown id) (whenLet [toDown (dictGet matchingPiecesDown id)
mzd ~(matchZoneDown s) mzd (matchZoneDown s)
mzu ~(matchZoneUp toDown)] mzu (matchZoneUp toDown)]
(unless .isEmpty (mzu.intersection mzd) (unless .isEmpty (mzu.intersection mzd)
(connectPiece id s toDown))))) (connectPiece id s toDown)))))

View File

@@ -19,12 +19,11 @@ class Main extends Sprite
}; };
function reloadModel(_) { function reloadModel(_) {
if (t.draggingSprite == null) { if (t.draggingSprite == null) {
// TODO don't change camera position and zoom when this happens: t.refreshModel(new HabitModel(habitFile));
t.setModel(new HabitModel(habitFile));
t.model.save(); t.model.save();
} }
} }
reloadModel(null); t.setModel(new HabitModel(habitFile));
new FlxTimer().start(30, reloadModel, 0); new FlxTimer().start(30, reloadModel, 0);
} }

View File

@@ -7,6 +7,7 @@ import flash.display.BitmapData;
import flixel.FlxCamera; import flixel.FlxCamera;
import flixel.math.FlxVector; import flixel.math.FlxVector;
import flixel.math.FlxPoint; import flixel.math.FlxPoint;
import flixel.math.FlxRect;
import flixel.FlxSprite; import flixel.FlxSprite;
import flixel.FlxG; import flixel.FlxG;
import flixel.util.FlxColor; import flixel.util.FlxColor;

View File

@@ -76,20 +76,36 @@
(<= (- bottom margin) mPos.y) (<= (- bottom margin) mPos.y)
(<= (- bottom margin) mPos.y bottom))))) (<= (- bottom margin) mPos.y bottom)))))
(function updateScrollWheelZoom [:FlxCamera camera :Float elapsed :Float speed] // GOTCHA: if you change FlxG.camera to a moving camera, you MUST provide a default camera for FlxG.mouse.getScreenPosition()
#{ (function updateScrollWheelZoom [:FlxCamera camera :Float elapsed :Float speed &opt :FlxCamera screenCamera]
if (FlxG.mouse.wheel != 0) { (case FlxG.mouse.wheel
camera.zoom += (FlxG.mouse.wheel * elapsed * speed); (0 null)
} (v
}#) (let [deltaZoom (* camera.zoom v elapsed speed)
scrollPosition (camera.scroll.copyTo)
mouseWorldPosition (FlxG.mouse.getWorldPosition camera)]
(+= camera.zoom deltaZoom)
(let [newMouseWorldPosition (FlxG.mouse.getWorldPosition camera)
deltaMousePosition (newMouseWorldPosition.subtractPoint mouseWorldPosition)]
(camera.scroll.subtractPoint deltaMousePosition))
// Undo any scrolling that expands the viewport past its bounds
**(unless (.containsPoint (getScrollBounds camera) camera.scroll)
(-= camera.zoom deltaZoom)
(set camera.scroll scrollPosition))))
(otherwise null)))
(function calculateScrollBounds <>[:FlxObject T] [:FlxCamera camera :FlxTypedGroup<T> group &opt :Float margin] (function getScrollBounds [:FlxCamera camera]
(let [r (GroupTools.calculateBounds group margin)] (.fromTwoPoints (new FlxRect) (new FlxPoint camera.minScrollX camera.minScrollY) (new FlxPoint camera.maxScrollX camera.maxScrollY)))
(camera.setScrollBoundsRect r.x r.y r.width r.height)))
(function extendScrollBounds [:FlxCamera camera :FlxObject object &opt :Float margin] // GOTCHA: if you change FlxG.camera to a moving camera, you MUST provide a default camera for FlxG.mouse.getScreenPosition()
(function calculateScrollBounds <>[:FlxSprite T] [:FlxCamera camera :FlxTypedGroup<T> group &opt :FlxCamera screenCamera :Float margin]
(let [r (GroupTools.calculateScreenBounds group screenCamera margin)]
(camera.setScrollBoundsRect r.x r.y ~r.width ~r.height)))
// GOTCHA: if you change FlxG.camera to a moving camera, you MUST provide a default camera for FlxG.mouse.getScreenPosition()
(function extendScrollBounds [:FlxCamera camera :FlxSprite sprite &opt :FlxCamera screenCamera :Float margin]
// if the given object is out of bounds, extend the bounds // if the given object is out of bounds, extend the bounds
(let [r (object.getRotatedBounds)] (let [r (sprite.getScreenBounds camera)]
(setMin camera.minScrollX (- r.left margin)) (setMin camera.minScrollX (- r.left margin))
(setMin camera.minScrollY (- r.top margin)) (setMin camera.minScrollY (- r.top margin))
(setMax camera.maxScrollX (+ r.right margin)) (setMax camera.maxScrollX (+ r.right margin))

View File

@@ -6,7 +6,9 @@ import flixel.FlxObject;
import flixel.FlxState; import flixel.FlxState;
import flixel.math.FlxRect; import flixel.math.FlxRect;
import flixel.math.FlxPoint; import flixel.math.FlxPoint;
import flixel.FlxCamera;
import flixel.group.FlxGroup; import flixel.group.FlxGroup;
import flixel.FlxSprite;
@:build(kiss.Kiss.build()) @:build(kiss.Kiss.build())
class GroupTools {} class GroupTools {}

View File

@@ -8,20 +8,22 @@
(group.remove obj) (group.remove obj)
(group.insert 0 obj))) (group.insert 0 obj)))
(function :FlxRect calculateBounds <>[:FlxObject T] [:FlxTypedGroup<T> group &opt :Float margin] (function :FlxRect calculateScreenBounds <>[:FlxSprite T] [:FlxTypedGroup<T> group &opt :FlxCamera camera :Float margin]
(unless margin (set margin 0)) (unless margin (set margin 0))
(let [&mut minX 0 (let [s (group.getFirstAlive)
&mut maxX 0 r (new FlxRect)
&mut minY 0 bounds (s.getScreenBounds r camera)
&mut maxY 0 &mut minX bounds.left
r (new FlxRect)] &mut maxX bounds.right
&mut minY bounds.top
&mut maxY bounds.bottom]
(group.forEach ->object (group.forEach ->sprite
(let [bounds (object.getRotatedBounds r)] (let [bounds (sprite.getScreenBounds r camera)]
(set minX (min minX bounds.left)) (setMin minX bounds.left)
(set minY (min minY bounds.top)) (setMin minY bounds.top)
(set maxX (max maxX bounds.right)) (setMax maxX bounds.right)
(set maxY (max maxY bounds.bottom)))) (setMax maxY bounds.bottom)))
(r.fromTwoPoints (r.fromTwoPoints
(new FlxPoint (- minX margin) (- minY margin)) (new FlxPoint (- minX margin) (- minY margin))