diff --git a/source/funkin/backend/utils/BitmapUtil.hx b/source/funkin/backend/utils/BitmapUtil.hx index d7984d2d..4e0816ed 100644 --- a/source/funkin/backend/utils/BitmapUtil.hx +++ b/source/funkin/backend/utils/BitmapUtil.hx @@ -74,21 +74,37 @@ class BitmapUtil { * @param bitmap The bitmap to be cropped */ public static function crop(bitmap:BitmapData) { - var minX:Int = bitmap.width; - var minY:Int = bitmap.height; - var maxX:Int = 0; var maxY:Int = 0; + var bitmapBounds:Rectangle = BitmapUtil.bounds(bitmap); + + var croppedBitmap:BitmapData = new BitmapData(Std.int(bitmapBounds.width), Std.int(bitmapBounds.height), true, 0x00000000); + croppedBitmap.copyPixels(bitmap, bitmapBounds, new Point(0,0)); + return croppedBitmap; + } + + /** + * Get bounds of non empty pixels in the bitmap + * @param bitmap + * @return + */ + public static function bounds(bitmap:BitmapData, ?limit:Rectangle = null):Rectangle { + var minX:Int = limit != null ? Std.int(limit.width) : bitmap.width; + var minY:Int = limit != null ? Std.int(limit.height) : bitmap.height; + var maxX:Int = limit != null ? Std.int(limit.x) : 0; + var maxY:Int = limit != null ? Std.int(limit.y) : 0; for (y in 0...bitmap.height) - for (x in 0...bitmap.width) + for (x in 0...bitmap.width) { + if (limit != null && !(x >= limit.x && x <= limit.x + limit.width && y >= limit.y && y <= limit.y + limit.height)) continue; + if (bitmap.getPixel32(x, y) != 0x00000000) { if (x < minX) minX = x; if (y < minY) minY = y; if (x > maxX) maxX = x; if (y > maxY) maxY = y; } - - var croppedBitmap:BitmapData = new BitmapData(maxX-minX+1, maxY-minY+1, true, 0x00000000); - croppedBitmap.copyPixels(bitmap, new Rectangle(minX, minY, croppedBitmap.width, croppedBitmap.height), new Point(0,0)); - return croppedBitmap; + } + + + return new Rectangle(minX, minY, maxX-minX+1, maxY-minY+1); } } \ No newline at end of file diff --git a/source/funkin/editors/character/CharacterAnimButton.hx b/source/funkin/editors/character/CharacterAnimButton.hx index 68bddd8f..29b34bf7 100644 --- a/source/funkin/editors/character/CharacterAnimButton.hx +++ b/source/funkin/editors/character/CharacterAnimButton.hx @@ -1,5 +1,6 @@ package funkin.editors.character; +import openfl.geom.Rectangle; import funkin.backend.utils.XMLUtil.AnimData; import flixel.math.FlxPoint; import flixel.util.FlxColor; @@ -41,7 +42,7 @@ class CharacterAnimButton extends UIButton { field.fieldWidth = 0; framesOffset = 9; field.visible = false; - animationDisplayBG = new UISliceSprite(x+12, y+12+18+12, 128, 128, 'editors/ui/inputbox'); + animationDisplayBG = new UISliceSprite(x+12, y+12+18+12, 128, 128, 'editors/ui/inputbox-small'); members.push(animationDisplayBG); nameTextBox = new UITextBox(animationDisplayBG.x+126+16, animationDisplayBG.y, animData.name, 116, 22, false, true); @@ -102,12 +103,18 @@ class CharacterAnimButton extends UIButton { super.draw(); if (parent.displayAnimsFramesList.exists(anim)) { - parent.displayWindowSprite.frame = parent.displayWindowSprite.frames.frames[parent.displayAnimsFramesList.get(anim)]; + var displayData:{frame:Int, scale:Float, animBounds:Rectangle} = parent.displayAnimsFramesList.get(anim); + parent.displayWindowSprite.frame = parent.displayWindowSprite.frames.frames[displayData.frame]; - parent.displayWindowSprite.scale.x = parent.displayWindowSprite.scale.y = 104/parent.displayWindowSprite.frame.sourceSize.y; + parent.displayWindowSprite.scale.x = parent.displayWindowSprite.scale.y = displayData.scale; parent.displayWindowSprite.updateHitbox(); + + // parent.displayWindowSprite.origin.set(); - parent.displayWindowSprite.follow(this, 16+(128/2)-((parent.displayWindowSprite.frame.sourceSize.x*parent.displayWindowSprite.scale.x)/2), 12+18+11+12); + parent.displayWindowSprite.follow( + this, 16+(128/2)-((parent.displayWindowSprite.frame.sourceSize.x*displayData.scale)/2), + 12+18+11+(128/2)-((parent.displayWindowSprite.frame.sourceSize.y*displayData.scale)/2) + ); parent.displayWindowSprite.draw(); } } diff --git a/source/funkin/editors/character/CharacterAnimsWindow.hx b/source/funkin/editors/character/CharacterAnimsWindow.hx index 7e96927d..508b24bf 100644 --- a/source/funkin/editors/character/CharacterAnimsWindow.hx +++ b/source/funkin/editors/character/CharacterAnimsWindow.hx @@ -1,13 +1,18 @@ package funkin.editors.character; +import flixel.graphics.FlxGraphic; +import openfl.geom.Rectangle; import flixel.graphics.frames.FlxFrame; import funkin.game.Character; +using funkin.backend.utils.BitmapUtil; + class CharacterAnimsWindow extends UIButtonList { public var character:Character; public var displayWindowSprite:FlxSprite; - public var displayAnimsFramesList:Map = []; + public var displayWindowGraphic:FlxGraphic; + public var displayAnimsFramesList:Map = []; public function new(x:Float, y:Float, character:Character) { super(x, y, Std.int(500-16), 419, "", FlxPoint.get(Std.int(500-16-32), 184)); @@ -17,15 +22,25 @@ class CharacterAnimsWindow extends UIButtonList { buttonCameras.pixelPerfectRender = true; + if (Assets.exists(Paths.image('characters/${character.sprite}'))) + displayWindowGraphic = FlxG.bitmap.add(Assets.getBitmapData(Paths.image('characters/${character.sprite}'), true, false)); + displayWindowSprite = new FlxSprite(); displayWindowSprite.loadGraphicFromSprite(character); displayWindowSprite.antialiasing = character.antialiasing; displayWindowSprite.flipX = character.flipX; @:privateAccess - for (name => anim in displayWindowSprite.animation._animations) - displayAnimsFramesList.set(name, anim.frames.getDefault([0])[0]); + for (name => anim in displayWindowSprite.animation._animations) { + var frameIndex:Int = anim.frames.getDefault([0])[0]; + var frame:FlxFrame = displayWindowSprite.frames.frames[frameIndex]; + var frameRect:Rectangle = new Rectangle(frame.offset.x, frame.offset.y, frame.sourceSize.x, frame.sourceSize.y); + var animBounds:Rectangle = displayWindowGraphic != null ? displayWindowGraphic.bitmap.bounds(frameRect) : frameRect; + + displayAnimsFramesList.set(name, {frame: anim.frames.getDefault([0])[0], scale: 104/animBounds.height, animBounds: animBounds}); + } + for (anim in character.getAnimOrder()) add(new CharacterAnimButton(0,0, character.animDatas.get(anim), this)); }