diff --git a/project.xml b/project.xml index ca1e52bc..4c48a50f 100644 --- a/project.xml +++ b/project.xml @@ -186,7 +186,6 @@ - diff --git a/source/funkin/backend/FunkinSprite.hx b/source/funkin/backend/FunkinSprite.hx index be2ff6fe..f8df791b 100644 --- a/source/funkin/backend/FunkinSprite.hx +++ b/source/funkin/backend/FunkinSprite.hx @@ -125,15 +125,6 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I public function measureHit(curMeasure:Int) { } - - public override function getScreenBounds(?newRect:FlxRect, ?camera:FlxCamera):FlxRect - { - __doPreZoomScaleProcedure(camera); - var r = super.getScreenBounds(newRect, camera); - __doPostZoomScaleProcedure(); - return r; - } - public override function drawComplex(camera:FlxCamera) { super.drawComplex(camera); diff --git a/source/funkin/editors/character/CharacterAnimsWindow.hx b/source/funkin/editors/character/CharacterAnimsWindow.hx deleted file mode 100644 index eafa2de1..00000000 --- a/source/funkin/editors/character/CharacterAnimsWindow.hx +++ /dev/null @@ -1,176 +0,0 @@ -package funkin.editors.character; - -import flixel.group.FlxGroup; -import flixel.util.FlxColor; -import flixel.math.FlxPoint; -import funkin.game.Character; - -class CharacterAnimsWindow extends UIWindow { - public var character:Character; - - public var buttons:FlxGroup = new FlxGroup(); - public var animButtons:Map = []; - - public var addButton:UIButton; - public var addIcon:FlxSprite; - - public function new(character:Character) { - super(800-23,140+23+46,450+23,511-23, "Character Animations"); - this.character = character; - - createButtons(); - buttons.cameras = [CharacterEditor.instance.animsCamera]; - members.push(buttons); - } - - public function createButtons() { - for (i=>anim in character.getNameList()) - createNewButton(anim, character.getAnimOffset(anim), false, -1, false); - - addButton = new UIButton(25, 16+((32+16)*(character.getNameList().length)), "", - function () { - CharacterEditor.instance.createAnimWithUI(); - } - , 426); - addButton.cameras = [CharacterEditor.instance.animsCamera]; - addButton.color = FlxColor.GREEN; - - addIcon = new FlxSprite(addButton.x + (440/2) - 8, addButton.y + (32/2) - 8).loadGraphic(Paths.image('editors/charter/add-button')); - addIcon.cameras = [CharacterEditor.instance.animsCamera]; - addIcon.antialiasing = false; - addButton.members.push(addIcon); - - members.push(addButton); - updateButtonsPos(); - } - - public function createNewButton(anim:String, offset:FlxPoint, ghost:Bool = false, id:Int = -1, ?updatePos:Bool = true) { - var button = new CharacterAnimButtons(0,0, anim, offset); - if (id == -1) buttons.add(button); - else buttons.members.insert(id, button); - animButtons.set(anim,button); - - if (updatePos) - updateButtonsPos(); - } - - public function removeButton(anim:String) { - var button:CharacterAnimButtons = animButtons.get(anim); - buttons.members.remove(button); - button.destroy(); - - updateButtonsPos(); - } - - public function updateButtonsPos() { - for (i => button in buttons.members) - cast(button, CharacterAnimButtons).updatePos(23,16+((32+16)*i)); - - addButton.y = 16+((32+16)*(buttons.members.length)); - addIcon.x = addButton.x + (440/2) - 8; addIcon.y = addButton.y + (32/2) - 8; - } - - public inline function changeCurAnim(anim:String) { - for (_anim => button in animButtons) - button.alpha = _anim == anim ? 1 : 0.25; - } - - var scrollY:Float = 0; - - public override function update(elapsed:Float) { - super.update(elapsed); - - __rect.x = x; __rect.y = y+23; - __rect.width = bWidth; __rect.height = bHeight-23; - if(UIState.state.isOverlapping(this, __rect)) { - var nextscrollY = scrollY - FlxG.mouse.wheel * 12; - if (nextscrollY >= 0 && nextscrollY + CharacterEditor.instance.animsCamera.height <= (addButton.y +32 +23)) - scrollY = nextscrollY; - hovered = true; - } else - hovered = false; - - for (button in buttons.members) - cast(button, UISprite).selectable = hovered; - addButton.selectable = hovered; - - CharacterEditor.instance.animsCamera.scroll.y = FlxMath.lerp(CharacterEditor.instance.animsCamera.scroll.y, scrollY, 1/3); - - //addButtonIndicator.y = CharacterEditor.instance.animsCamera.height - addButtonIndicator.width + CharacterEditor.instance.animsCamera.scroll.y; - } -} - -class CharacterAnimButtons extends UIButton { - public var anim:String = ""; - - public var editButton:UIButton; - public var editIcon:FlxSprite; - - public var ghostButton:UIButton; - public var ghostIcon:FlxSprite; - - public var deleteButton:UIButton; - public var deleteIcon:FlxSprite; - - public function new(x:Float,y:Float,anim:String, offset:FlxPoint) { - this.anim = anim; - super(x,y, '$anim (${offset.x}, ${offset.y})', function () { - CharacterEditor.instance.playAnimation(this.anim); - }, 282); - - ghostButton = new UIButton(x+282+17, y, "", function () { - CharacterEditor.instance.ghostAnim(this.anim); - }, 32); - members.push(ghostButton); - - ghostIcon = new FlxSprite(ghostButton.x + 8, ghostButton.y + 8).loadGraphic(Paths.image('editors/character/ghost-button'), true, 16, 16); - ghostIcon.animation.add("alive", [0]); - ghostIcon.animation.add("dead", [1]); - ghostIcon.animation.play("dead"); ghostIcon.alpha = 0.5; - ghostIcon.antialiasing = false; - ghostIcon.updateHitbox(); - members.push(ghostIcon); - - editButton = new UIButton(ghostButton.x+32+17, y, "", function () { - CharacterEditor.instance.editAnimWithUI(this.anim); - }, 32); - members.push(editButton); - - editIcon = new FlxSprite(editButton.x + 8, editButton.y + 8).loadGraphic(Paths.image('editors/character/edit-button')); - editIcon.antialiasing = false; - members.push(editIcon); - - deleteButton = new UIButton(editButton.x+32+17, y, "", function () { - CharacterEditor.instance.deleteAnim(this.anim); - }, 32); - deleteButton.color = FlxColor.RED; - members.push(deleteButton); - - deleteIcon = new FlxSprite(deleteButton.x + (15/2), deleteButton.y + 8).loadGraphic(Paths.image('editors/character/delete-button')); - deleteIcon.antialiasing = false; - members.push(deleteIcon); - } - - public override function update(elapsed:Float) { - editButton.selectable = ghostButton.selectable = deleteButton.selectable = selectable; - super.update(elapsed); - } - - public function updateInfo(anim:String, offset:FlxPoint, ghost:Bool) { - this.anim = anim; - - field.text = '$anim (${offset.x}, ${offset.y})'; - ghostIcon.animation.play(ghost ? "alive" : "dead"); - ghostIcon.alpha = ghost ? 1 : 0.5; - } - - public inline function updatePos(x:Float, y:Float) { - // buttons - this.x = x; this.y = ghostButton.y = editButton.y = deleteButton.y = y; - deleteButton.x = (editButton.x = (ghostButton.x = (x+282+17))+32+17)+32+17; - // icons - ghostIcon.x = ghostButton.x + 8; ghostIcon.y = ghostButton.y + 8; - editIcon.x = editButton.x + 8; editIcon.y = editButton.y + 8; - deleteIcon.x = deleteButton.x + (15/2); deleteIcon.y = deleteButton.y + 8; - } -} \ No newline at end of file diff --git a/source/funkin/editors/character/CharacterEditor.hx b/source/funkin/editors/character/CharacterEditor.hx index 67923e5d..f2674a45 100644 --- a/source/funkin/editors/character/CharacterEditor.hx +++ b/source/funkin/editors/character/CharacterEditor.hx @@ -2,7 +2,6 @@ package funkin.editors.character; import haxe.xml.Printer; import haxe.xml.Access; -import funkin.editors.character.CharacterAnimsWindow.CharacterAnimButtons; import funkin.backend.utils.XMLUtil.AnimData; import flixel.math.FlxPoint; import flixel.animation.FlxAnimation; @@ -32,7 +31,7 @@ class CharacterEditor extends UIState { // WINDOWS public var characterPropertiresWindow:CharacterPropertiesWindow; - public var characterAnimsWindow:CharacterAnimsWindow; + public var characterAnimsWindow:UIButtonList; // camera for the character itself so that it can be unzoomed/zoomed in again public var charCamera:FlxCamera; @@ -237,7 +236,9 @@ class CharacterEditor extends UIState { topMenuSpr.cameras = uiGroup.cameras = [uiCamera]; characterPropertiresWindow = new CharacterPropertiesWindow(); - characterAnimsWindow = new CharacterAnimsWindow(character); + characterAnimsWindow = new UIButtonList(777, 209, 473, 488, "Character Animations", function() CharacterEditor.instance.createAnimWithUI()); + for (i=>anim in character.getNameList()) + characterAnimsWindow.insert(new CharacterAnimButtons(0,0, anim, character.getAnimOffset(anim)), 0); uiGroup.add(characterPropertiresWindow); uiGroup.add(characterAnimsWindow); @@ -375,9 +376,10 @@ class CharacterEditor extends UIState { ghosts.setOffsets(anim, offsets.clone()); } - for (anim in character.getNameList()) - characterAnimsWindow.animButtons[anim].updateInfo(anim, character.getAnimOffset(anim), ghosts.animGhosts[anim].visible); - + for (button in characterAnimsWindow.buttons.members) { + var charButton:CharacterAnimButtons = cast(button, CharacterAnimButtons); + charButton.updateInfo(charButton.anim, character.getAnimOffset(charButton.anim), ghosts.animGhosts[charButton.anim].visible); + } changeOffset(character.getAnimName(), FlxPoint.get(0, 0), false); // apply da new offsets } if (v != null) @@ -434,10 +436,10 @@ class CharacterEditor extends UIState { })); } - public function createAnim(animData:AnimData, animID:Int = -1, addtoUndo:Bool = true) { + public function createAnim(animData:AnimData, animID:Int = 0, addtoUndo:Bool = true) { XMLUtil.addAnimToSprite(character, animData); ghosts.createGhost(animData.name); - characterAnimsWindow.createNewButton(animData.name, FlxPoint.get(animData.x,animData.y), false, animID); + characterAnimsWindow.insert(new CharacterAnimButtons(0, 0, animData.name, FlxPoint.get(animData.x,animData.y)), animID); playAnimation(animData.name); @@ -447,12 +449,13 @@ class CharacterEditor extends UIState { public function editAnim(name:String, animData:AnimData, addtoUndo:Bool = true) { var oldAnimData:AnimData = character.animDatas.get(name); - var button:CharacterAnimButtons = characterAnimsWindow.animButtons[name]; + var buttoner:CharacterAnimButtons = null; + for (i in characterAnimsWindow.members) if (cast(i, CharacterAnimButtons).anim == name) buttoner = cast i; ghosts.removeGhost(name); XMLUtil.addAnimToSprite(character, animData); ghosts.createGhost(animData.name); - button.updateInfo(animData.name, character.getAnimOffset(animData.name), ghosts.animGhosts[animData.name].visible); + buttoner.updateInfo(animData.name, character.getAnimOffset(animData.name), ghosts.animGhosts[animData.name].visible); if (character.getAnimName() == animData.name) // update anim ifs its currently selected playAnimation(animData.name); @@ -475,7 +478,13 @@ class CharacterEditor extends UIState { character.removeAnimation(name); if (character.animOffsets.exists(name)) character.animOffsets.remove(name); if (character.animDatas.exists(name)) character.animDatas.remove(name); - characterAnimsWindow.removeButton(name); + for(i in characterAnimsWindow.buttons.members) { + if(i is CharacterAnimButtons) { + var i:CharacterAnimButtons = cast i; + if(i.anim == name) + characterAnimsWindow.remove(i); + } + } if (addtoUndo) addToUndo(CDeleteAnim(oldID, oldAnimData)); @@ -504,7 +513,8 @@ class CharacterEditor extends UIState { var ghost:Character = ghosts.animGhosts.get(anim); ghost.visible = !ghost.visible; - var button:CharacterAnimButtons = characterAnimsWindow.animButtons[anim]; + var button:CharacterAnimButtons = null; + for (i in characterAnimsWindow.members) if (cast(i, CharacterAnimButtons).anim == anim) button = cast(i ,CharacterAnimButtons); button.updateInfo(anim, character.getAnimOffset(anim), ghost.visible); } @@ -520,7 +530,12 @@ class CharacterEditor extends UIState { public function playAnimation(anim:String) { character.playAnim(anim, true); - characterAnimsWindow.changeCurAnim(anim); + for(i in characterAnimsWindow.buttons.members) { + if(i is CharacterAnimButtons) { + var i:CharacterAnimButtons = cast i; + i.alpha = i.anim == anim ? 1 : 0.25; + } + } } function _offsets_left(_) { @@ -563,7 +578,7 @@ class CharacterEditor extends UIState { if (character.getNameList().length == 0) return; character.animOffsets.set(anim, character.getAnimOffset(anim) + change); - characterAnimsWindow.animButtons[anim].updateInfo(anim, character.getAnimOffset(anim), ghosts.animGhosts[anim].visible); + for (i in characterAnimsWindow.members) if (cast(i, CharacterAnimButtons).anim == anim) cast(i ,CharacterAnimButtons).updateInfo(anim, character.getAnimOffset(anim), ghosts.animGhosts[anim].visible); character.frameOffset.set(character.getAnimOffset(anim).x, character.getAnimOffset(anim).y); ghosts.updateOffsets(anim, change); @@ -579,10 +594,9 @@ class CharacterEditor extends UIState { for (anim => offsets in character.animOffsets) anim => offsets.clone() ]; - for (anim in character.getNameList()) { character.animOffsets[anim].zero(); - characterAnimsWindow.animButtons[anim].updateInfo(anim, character.getAnimOffset(anim), ghosts.animGhosts[anim].visible); + for (i in characterAnimsWindow.members) if (cast(i, CharacterAnimButtons).anim == anim) cast(i ,CharacterAnimButtons).updateInfo(anim, character.getAnimOffset(anim), ghosts.animGhosts[anim].visible); } ghosts.clearOffsets(); @@ -614,7 +628,82 @@ class CharacterEditor extends UIState { } #end } +class CharacterAnimButtons extends UIButton { + public var anim:String = ""; + public var editButton:UIButton; + public var editIcon:FlxSprite; + + public var ghostButton:UIButton; + public var ghostIcon:FlxSprite; + + public var deleteButton:UIButton; + public var deleteIcon:FlxSprite; + + public function new(x:Float,y:Float,anim:String, offset:FlxPoint) { + this.anim = anim; + super(x,y, '$anim (${offset.x}, ${offset.y})', function () { + CharacterEditor.instance.playAnimation(this.anim); + }, 282); + + ghostButton = new UIButton(x+282+17, y, "", function () { + CharacterEditor.instance.ghostAnim(this.anim); + }, 32); + members.push(ghostButton); + + ghostIcon = new FlxSprite(ghostButton.x + 8, ghostButton.y + 8).loadGraphic(Paths.image('editors/character/ghost-button'), true, 16, 16); + ghostIcon.animation.add("alive", [0]); + ghostIcon.animation.add("dead", [1]); + ghostIcon.animation.play("dead"); ghostIcon.alpha = 0.5; + ghostIcon.antialiasing = false; + ghostIcon.updateHitbox(); + members.push(ghostIcon); + + editButton = new UIButton(ghostButton.x+32+17, y, "", function () { + CharacterEditor.instance.editAnimWithUI(this.anim); + }, 32); + members.push(editButton); + + editIcon = new FlxSprite(editButton.x + 8, editButton.y + 8).loadGraphic(Paths.image('editors/character/edit-button')); + editIcon.antialiasing = false; + members.push(editIcon); + + deleteButton = new UIButton(editButton.x+32+17, y, "", function () { + CharacterEditor.instance.deleteAnim(this.anim); + }, 32); + deleteButton.color = 0xFFFF0000; + members.push(deleteButton); + + deleteIcon = new FlxSprite(deleteButton.x + (15/2), deleteButton.y + 8).loadGraphic(Paths.image('editors/character/delete-button')); + deleteIcon.antialiasing = false; + members.push(deleteIcon); + } + + public override function update(elapsed:Float) { + editButton.selectable = ghostButton.selectable = deleteButton.selectable = selectable; + hovered = !deleteButton.hovered; + updatePos(); + super.update(elapsed); + } + + public function updateInfo(anim:String, offset:FlxPoint, ghost:Bool) { + this.anim = anim; + + field.text = '$anim (${offset.x}, ${offset.y})'; + ghostIcon.animation.play(ghost ? "alive" : "dead"); + ghostIcon.alpha = ghost ? 1 : 0.5; + } + + public inline function updatePos() { + // buttons + deleteButton.x = (editButton.x = (ghostButton.x = (x+282+17))+32+17)+32+17; + deleteButton.y = editButton.y = ghostButton.y = y; + // icons + ghostIcon.x = ghostButton.x + 8; ghostIcon.y = ghostButton.y + 8; + editIcon.x = editButton.x + 8; editIcon.y = editButton.y + 8; + deleteIcon.x = deleteButton.x + (15/2); deleteIcon.y = deleteButton.y + 8; + } +} enum CharacterChange { CEditInfo(oldInfo:Xml, newInfo:Xml); CCreateAnim(animID:Int, animData:AnimData); diff --git a/source/funkin/editors/ui/UIButton.hx b/source/funkin/editors/ui/UIButton.hx index ad722970..01358431 100644 --- a/source/funkin/editors/ui/UIButton.hx +++ b/source/funkin/editors/ui/UIButton.hx @@ -5,6 +5,7 @@ import flixel.graphics.frames.FlxFrame; class UIButton extends UISliceSprite { public var callback:Void->Void = null; public var field:UIText; + public var shouldPress = true; public override function new(x:Float, y:Float, text:String, callback:Void->Void, w:Int = 120, h:Int = 32) { super(x, y, w, h, 'editors/ui/button'); @@ -27,13 +28,13 @@ class UIButton extends UISliceSprite { public override function onHovered() { super.onHovered(); - if (FlxG.mouse.justReleased && callback != null) + if (FlxG.mouse.justReleased && callback != null && shouldPress) callback(); } public override function update(elapsed:Float) { - super.update(elapsed); field.follow(this, 0, (bHeight - field.height) / 2); + super.update(elapsed); } public override function draw() { diff --git a/source/funkin/editors/ui/UIButtonList.hx b/source/funkin/editors/ui/UIButtonList.hx new file mode 100644 index 00000000..9539f8e9 --- /dev/null +++ b/source/funkin/editors/ui/UIButtonList.hx @@ -0,0 +1,90 @@ +package funkin.editors.ui; + +import flixel.FlxCamera; +import flixel.group.FlxGroup; +import flixel.util.FlxColor; +import flixel.math.FlxPoint; +import funkin.game.Character; + +class UIButtonList extends UIWindow { + public var character:Character; + + public var buttons:FlxTypedGroup = new FlxTypedGroup(); + public var addButton:UIButton; + public var addIcon:FlxSprite; + public var buttonCameras:FlxCamera; + + var _buttonYOffset:Float = 16; + + public function new(x:Int, y:Int, width:Int, height:Int, windowName:String, addButtonCallback:Void->Void = null, buttonYOffset = 16) { + super(x, y, width, height, windowName); + members.push(buttons); + _buttonYOffset = buttonYOffset; + buttonCameras = new FlxCamera(x, y+36, width, height-38); + FlxG.cameras.add(buttonCameras, false); + buttonCameras.bgColor = 0; + + addButton = new UIButton(25, 16, "", addButtonCallback != null ? addButtonCallback : function() return false, 426); + addButton.color = 0xFF00FF00; + + addIcon = new FlxSprite(addButton.x + (440/2) - 8, addButton.y + (32/2) - 8).loadGraphic(Paths.image('editors/charter/add-button')); + addIcon.antialiasing = false; + addButton.members.push(addIcon); + add(addButton); + } + public function add(button:UIButton) + insert(button, buttons.members.length); + public function insert(button:UIButton, position:Int) { + buttons.insert(position, button); + button.cameras = [buttonCameras]; + for (i => button in buttons.members) + button.setPosition(16, -scrollY + (button.bHeight + _buttonYOffset) * i); + } + public function remove(button:UIButton) { + buttons.remove(button, true); + button.destroy(); + } + var _curMoving:UIButton = null; + var _curMovingInterval:Float = 0; + public function updateButtonsPos(elapsed:Float) { + for (i => button in buttons.members) { + if (_curMoving != button) { + button.y = CoolUtil.fpsLerp(button.y, -scrollY + (button.bHeight + _buttonYOffset) * i, 0.1); + button.shouldPress = true; + } + if (button != addButton && button.hovered && FlxG.mouse.justPressed) _curMoving = button; + } + if (_curMoving != null) { + _curMovingInterval += FlxG.mouse.deltaY; + if (Math.abs(_curMovingInterval) > addButton.bHeight / 2) { + _curMovingInterval += 100; + _curMoving.shouldPress = false; + _curMoving.y = CoolUtil.fpsLerp(_curMoving.y, FlxG.mouse.getScreenPosition(buttonCameras).y - (_curMoving.bHeight / 2), 0.2); + buttons.sort(function(o,a,b) return flixel.util.FlxSort.byValues(o, a == addButton ? 999 : a.y + 40, b == addButton ? 999 : b.y + 40), -1); + } + if (FlxG.mouse.justReleased) { + _curMoving = null; + _curMovingInterval = 0; + } + } + addIcon.x = addButton.x + (220) - 8; addIcon.y = addButton.y + (16) - 8; + } + + var scrollY:Float = 0; + + public override function update(elapsed:Float) { + updateButtonsPos(elapsed); + super.update(elapsed); + __rect.x = x; __rect.y = y+23; + __rect.width = bWidth; __rect.height = bHeight-23; + var nextscrollY = scrollY - ((hovered = UIState.state.isOverlapping(this, __rect)) ? FlxG.mouse.wheel : 0) * 12; + if (_curMoving != null) { + nextscrollY -= Math.min((bHeight - 100) - FlxG.mouse.getScreenPosition(buttonCameras).y, 0) / 5; + nextscrollY += Math.min(FlxG.mouse.getScreenPosition(buttonCameras).y - 100, 0) / 5; + } + scrollY = FlxMath.bound(nextscrollY, 0, -16 + Math.abs(Math.min(bHeight - (addButton.bHeight + _buttonYOffset) * (buttons.members.length+1), 0))); + for (button in buttons.members) + if (button != null) button.selectable = (hovered && button.callback != null); + addButton.selectable = hovered; + } +} \ No newline at end of file