From f69f05ff1f9bbac07a91f349c5a98d57159d9a6e Mon Sep 17 00:00:00 2001 From: TheAlternateDoctor Date: Sun, 27 Aug 2023 22:30:11 +0200 Subject: [PATCH 01/11] Bump version --- .gitignore | 3 +++ build.gradle | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 1a103f5..e4bccda 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ .gradle/ .idea/ +.vscode/ build/ lib/ out/ +bin/ +gradlew diff --git a/build.gradle b/build.gradle index 664004c..dac092c 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ group 'rhmodding' -version '1.4.2' +version '1.4.3' buildscript { repositories { From 60e9610854d974f4d43b2d4ac866f2c8a34ad6a6 Mon Sep 17 00:00:00 2001 From: TheAlternateDoctor Date: Sun, 27 Aug 2023 22:30:26 +0200 Subject: [PATCH 02/11] Fixed Linux zoom somehow --- src/main/kotlin/rhmodding/bread/editor/Editor.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/rhmodding/bread/editor/Editor.kt b/src/main/kotlin/rhmodding/bread/editor/Editor.kt index 42d018a..22f93e3 100644 --- a/src/main/kotlin/rhmodding/bread/editor/Editor.kt +++ b/src/main/kotlin/rhmodding/bread/editor/Editor.kt @@ -143,7 +143,7 @@ abstract class Editor(val app: Bread, val mainPane: MainPane, va } } else { if (evt.deltaX > 0 || evt.deltaY > 0) { - zoomFactor *= 2.0.pow(1 / 8.0) + zoomFactor *= 1.190507733 } else { zoomFactor /= 2.0.pow(1 / 8.0) } From ee49b6e1f6ad28bd0dc4a203d7754ca654fda234 Mon Sep 17 00:00:00 2001 From: TheAlternateDoctor Date: Sun, 27 Aug 2023 22:30:40 +0200 Subject: [PATCH 03/11] Add/Del/Dupe anims --- .../rhmodding/bread/editor/AnimationsTab.kt | 30 +++++++++++ .../rhmodding/bread/editor/BCCADEditor.kt | 50 +++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/src/main/kotlin/rhmodding/bread/editor/AnimationsTab.kt b/src/main/kotlin/rhmodding/bread/editor/AnimationsTab.kt index c5559f4..b801b18 100644 --- a/src/main/kotlin/rhmodding/bread/editor/AnimationsTab.kt +++ b/src/main/kotlin/rhmodding/bread/editor/AnimationsTab.kt @@ -142,6 +142,7 @@ open class AnimationsTab(editor: Editor) : EditorSubTab(ed editor.repaintCanvas() } + children += Button("Add New Step").apply { setOnAction { editor.addAnimationStep(currentAnimation, editor.createAnimationStep()) @@ -486,6 +487,35 @@ open class AnimationsTab(editor: Editor) : EditorSubTab(ed } } + open fun updateFieldsForAnim() { + numAnimationsLabel.text = "(${data.animations.size} total animation${if (data.animations.size == 1) "" else "s"})" + numAniStepsLabel.text = "(${currentAnimation.steps.size} total step${if (currentAnimation.steps.size == 1) "" else "s"})" + if (currentAnimation.steps.isEmpty()) { + disableStepControls.value = true + return + } + val step = currentAnimationStep + disableStepControls.value = false + + stepSpriteSpinner.valueFactoryProperty().get().value = step.spriteIndex.toInt() + stepDelaySpinner.valueFactoryProperty().get().value = step.delay.toInt() + stepStretchXSpinner.valueFactoryProperty().get().value = step.stretchX.toDouble() + stepStretchYSpinner.valueFactoryProperty().get().value = step.stretchY.toDouble() + stepRotationSpinner.valueFactoryProperty().get().value = step.rotation.toDouble() + stepOpacitySpinner.valueFactoryProperty().get().value = step.opacity.toInt() + playbackSlider.apply { + this.min = 0.0 + this.max = (currentAnimation.steps.size - 1).toDouble() + this.blockIncrement = 1.0 + this.majorTickUnit = if (max <= 5.0) 1.0 else if (max < 8.0) 2.0 else 4.0 + this.minorTickCount = (majorTickUnit.toInt() - 1).coerceAtMost(max.toInt() - 1) + this.isShowTickMarks = true + this.isShowTickLabels = true + this.isSnapToTicks = true + this.value = aniStepSpinner.value.toDouble() + } + } + protected open fun getAnimationNameForGifExport(): String { val spinnerValue: Int = animationSpinner.value return "animation_${spinnerValue.toString().padStart(data.animations.size.toString().length, '0')}" diff --git a/src/main/kotlin/rhmodding/bread/editor/BCCADEditor.kt b/src/main/kotlin/rhmodding/bread/editor/BCCADEditor.kt index 521ebfa..00c2386 100644 --- a/src/main/kotlin/rhmodding/bread/editor/BCCADEditor.kt +++ b/src/main/kotlin/rhmodding/bread/editor/BCCADEditor.kt @@ -162,6 +162,56 @@ class BCCADEditor(app: Bread, mainPane: MainPane, dataFile: File, data: BCCAD, i } }) sectionAnimation.children.add(2, HBox().apply { + styleClass += "hbox" + alignment = Pos.CENTER_LEFT + fun updateAnimSpinners(goToMax: Boolean) { + (animationSpinner.valueFactory as SpinnerValueFactory.IntegerSpinnerValueFactory).also { + it.max = (data.animations.size - 1).coerceAtLeast(0) + it.value = if (goToMax) it.max else it.value.coerceAtMost(it.max) + } + // updateFieldsForAnim() + editor.repaintCanvas() + } + + + children += Button("Add animation").apply { + setOnAction { + TextInputDialog().apply { + this.title = "Adding animation" + this.headerText = "Add animation named:\n" + editor.app.addBaseStyleToDialog(this.dialogPane) + }.showAndWait().ifPresent { newName -> + if (newName.isNotBlank()) { + val n = newName.take(127) + val newAnimation: Animation = Animation() + newAnimation.name = n + animationNameLabel.text = n + data.animations.add(newAnimation) + updateAnimSpinners(true) + editor.updateContextMenu() + } + } + } + } + children += Button("Duplicate").apply { + setOnAction { + val animation = currentAnimation as Animation + animation.name += "_dup" + data.animations.add(animation) + updateAnimSpinners(true) + editor.updateContextMenu() + } + } + children += Button("Remove").apply { + setOnAction { + val animation = currentAnimation as Animation + data.animations.remove(animation) + updateAnimSpinners(true) + editor.updateContextMenu() + } + } + }) + sectionAnimation.children.add(3, HBox().apply { styleClass += "hbox" alignment = Pos.CENTER_LEFT children += Label("Is interpolated?:").apply { From 44a458a96ab8b90f1d93dd31239a60e48a848679 Mon Sep 17 00:00:00 2001 From: TheAlternateDoctor Date: Sun, 27 Aug 2023 22:39:37 +0200 Subject: [PATCH 04/11] AnimStep Move Up/Down --- .../rhmodding/bread/editor/AnimationsTab.kt | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/main/kotlin/rhmodding/bread/editor/AnimationsTab.kt b/src/main/kotlin/rhmodding/bread/editor/AnimationsTab.kt index b801b18..d7fcddc 100644 --- a/src/main/kotlin/rhmodding/bread/editor/AnimationsTab.kt +++ b/src/main/kotlin/rhmodding/bread/editor/AnimationsTab.kt @@ -32,6 +32,7 @@ import rhmodding.bread.util.em import rhmodding.bread.util.intSpinnerFactory import rhmodding.bread.util.spinnerArrowKeysAndScroll import java.io.File +import java.util.Collections import javax.imageio.ImageIO import kotlin.math.roundToInt @@ -175,6 +176,28 @@ open class AnimationsTab(editor: Editor) : EditorSubTab(ed } } } + children += HBox().apply { + styleClass += "hbox" + alignment = Pos.CENTER_LEFT + children += Button("Move Up").apply { + disableProperty().bind(disableStepControls) + setOnAction { + if (aniStepSpinner.value < currentAnimation.steps.size - 1) { + Collections.swap(currentAnimation.steps, aniStepSpinner.value, aniStepSpinner.value + 1) + aniStepSpinner.increment(1) + } + } + } + children += Button("Move Down").apply { + disableProperty().bind(disableStepControls) + setOnAction { + if (aniStepSpinner.value > 0) { + Collections.swap(currentAnimation.steps, aniStepSpinner.value, aniStepSpinner.value - 1) + aniStepSpinner.decrement(1) + } + } + } + } children += HBox().apply { styleClass += "hbox" alignment = Pos.CENTER_LEFT From dad3d5d30c2f0d26f6c26e70fd7f39c536b82247 Mon Sep 17 00:00:00 2001 From: TheAlternateDoctor Date: Sun, 27 Aug 2023 23:16:59 +0200 Subject: [PATCH 05/11] Copy/Paste parts --- .../rhmodding/bread/editor/SpritesTab.kt | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/main/kotlin/rhmodding/bread/editor/SpritesTab.kt b/src/main/kotlin/rhmodding/bread/editor/SpritesTab.kt index 4937e76..069e7ab 100644 --- a/src/main/kotlin/rhmodding/bread/editor/SpritesTab.kt +++ b/src/main/kotlin/rhmodding/bread/editor/SpritesTab.kt @@ -34,6 +34,7 @@ open class SpritesTab(editor: Editor) : EditorSubTab(edito isFillWidth = true } val disablePartControls: BooleanProperty = SimpleBooleanProperty(false) + val disablePasteControls: BooleanProperty = SimpleBooleanProperty(true) val partPropertiesVBox: VBox = VBox().apply { disableProperty().bind(disablePartControls) } @@ -53,6 +54,11 @@ open class SpritesTab(editor: Editor) : EditorSubTab(edito val numSpritesLabel: Label = Label("") val numSpritePartsLabel: Label = Label("") + + var copyPart: ISpritePart = editor.createSpritePart().apply { + regionW = 0u + regionH = 0u + } protected var lastEditedRegion: ISpritePart = editor.createSpritePart().apply { regionW = 0u @@ -270,6 +276,53 @@ open class SpritesTab(editor: Editor) : EditorSubTab(edito } } } + children += HBox().apply { + fun updateSpritePartSpinners(goToMax: Boolean) { + (spritePartSpinner.valueFactory as SpinnerValueFactory.IntegerSpinnerValueFactory).also { + it.max = (currentSprite.parts.size - 1).coerceAtLeast(0) + it.value = if (goToMax) it.max else it.value.coerceAtMost(it.max) + } + updateFieldsForPart() + editor.repaintCanvas() + } + + styleClass += "hbox" + alignment = Pos.CENTER_LEFT + children += Button("Copy").apply { + disableProperty().bind(disablePartControls) + setOnAction { + disablePasteControls.value = false + copyPart = currentPart + } + } + children += Button("Cut").apply { + disableProperty().bind(disablePartControls) + setOnAction { + disablePasteControls.value = false + copyPart = currentPart + if (currentSprite.parts.isNotEmpty()) { + val alert = Alert(Alert.AlertType.CONFIRMATION) + editor.app.addBaseStyleToDialog(alert.dialogPane) + alert.title = "Cut this sprite part?" + alert.headerText = "Cut this sprite part?" + alert.contentText = "Are you sure you want to cut this sprite part?\nYou won't be able to undo this action." + if (alert.showAndWait().get() == ButtonType.OK) { + editor.removeSpritePart(currentSprite, currentPart) + updateSpritePartSpinners(false) + } + } + } + } + children += Button("Paste").apply { + disableProperty().bind(disablePasteControls) + setOnAction { + if (currentSprite.parts.isNotEmpty()) { + editor.addSpritePart(currentSprite, copyPart) + updateSpritePartSpinners(true) + } + } + } + } children += HBox().apply { styleClass += "hbox" alignment = Pos.CENTER_LEFT From a8fd568626c89dc080fd842c75e47cedd8e214e0 Mon Sep 17 00:00:00 2001 From: TheAlternateDoctor Date: Sun, 27 Aug 2023 23:22:56 +0200 Subject: [PATCH 06/11] Copy/Cut/Paste animation step --- .../rhmodding/bread/editor/AnimationsTab.kt | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/main/kotlin/rhmodding/bread/editor/AnimationsTab.kt b/src/main/kotlin/rhmodding/bread/editor/AnimationsTab.kt index d7fcddc..c79d268 100644 --- a/src/main/kotlin/rhmodding/bread/editor/AnimationsTab.kt +++ b/src/main/kotlin/rhmodding/bread/editor/AnimationsTab.kt @@ -43,6 +43,7 @@ open class AnimationsTab(editor: Editor) : EditorSubTab(ed isFillWidth = true } val disableStepControls: BooleanProperty = SimpleBooleanProperty(false) + val disablePasteControls: BooleanProperty = SimpleBooleanProperty(true) val stepPropertiesVBox: VBox = VBox().apply { disableProperty().bind(disableStepControls) } @@ -69,6 +70,8 @@ open class AnimationsTab(editor: Editor) : EditorSubTab(ed val currentAnimationStep: IAnimationStep get() = currentAnimation.steps[aniStepSpinner.value] + var copyStep: IAnimationStep = editor.createAnimationStep() + var currentTimeline: ObjectProperty = SimpleObjectProperty(null as Timeline?).apply { addListener { _, old, new -> old?.stop() @@ -198,6 +201,53 @@ open class AnimationsTab(editor: Editor) : EditorSubTab(ed } } } + children += HBox().apply { + fun updateStepSpinners(goToMax: Boolean) { + (aniStepSpinner.valueFactory as SpinnerValueFactory.IntegerSpinnerValueFactory).also { + it.max = (currentAnimation.steps.size - 1).coerceAtLeast(0) + it.value = if (goToMax) it.max else it.value.coerceAtMost(it.max) + } + updateFieldsForStep() + editor.repaintCanvas() + } + + styleClass += "hbox" + alignment = Pos.CENTER_LEFT + children += Button("Copy").apply { + disableProperty().bind(disableStepControls) + setOnAction { + disablePasteControls.value = false + copyStep = currentAnimationStep + } + } + children += Button("Cut").apply { + disableProperty().bind(disableStepControls) + setOnAction { + disablePasteControls.value = false + copyStep = currentAnimationStep + if (currentAnimation.steps.isNotEmpty()) { + val alert = Alert(Alert.AlertType.CONFIRMATION) + editor.app.addBaseStyleToDialog(alert.dialogPane) + alert.title = "Cut this animation step?" + alert.headerText = "Cut this animation step?" + alert.contentText = "Are you sure you want to cut this animation step?\nYou won't be able to undo this action." + if (alert.showAndWait().get() == ButtonType.OK) { + editor.removeAnimationStep(currentAnimation, currentAnimationStep) + updateStepSpinners(false) + } + } + } + } + children += Button("Paste").apply { + disableProperty().bind(disablePasteControls) + setOnAction { + if (currentAnimation.steps.isNotEmpty()) { + editor.addAnimationStep(currentAnimation, copyStep) + updateStepSpinners(true) + } + } + } + } children += HBox().apply { styleClass += "hbox" alignment = Pos.CENTER_LEFT From 1edc831d8fd941371188056bd8177d1abdcc4cac Mon Sep 17 00:00:00 2001 From: TheAlternateDoctor Date: Sun, 27 Aug 2023 23:24:38 +0200 Subject: [PATCH 07/11] *Actually* bump version everywhere --- src/main/kotlin/rhmodding/bread/Bread.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/rhmodding/bread/Bread.kt b/src/main/kotlin/rhmodding/bread/Bread.kt index 28d1fa3..86e2e4b 100644 --- a/src/main/kotlin/rhmodding/bread/Bread.kt +++ b/src/main/kotlin/rhmodding/bread/Bread.kt @@ -57,7 +57,7 @@ class Bread : Application() { } const val GITHUB: String = "https://github.com/rhmodding/bread" const val LICENSE_NAME: String = "Apache License 2.0" - val VERSION: Version = Version(1, 4, 2) + val VERSION: Version = Version(1, 4, 3) val rootFolder: File = File(System.getProperty("user.home")).resolve(".rhmodding/bread/").apply { mkdirs() } val windowIcons: List by lazy { listOf(BreadIcon.icon32, BreadIcon.icon64) } From 1401ac4000b7e675abb099cf7e7159d3e271596a Mon Sep 17 00:00:00 2001 From: TheAlternateDoctor Date: Sun, 27 Aug 2023 23:33:04 +0200 Subject: [PATCH 08/11] Added confirmation window for remove animation --- .../kotlin/rhmodding/bread/editor/BCCADEditor.kt | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/rhmodding/bread/editor/BCCADEditor.kt b/src/main/kotlin/rhmodding/bread/editor/BCCADEditor.kt index 00c2386..c409496 100644 --- a/src/main/kotlin/rhmodding/bread/editor/BCCADEditor.kt +++ b/src/main/kotlin/rhmodding/bread/editor/BCCADEditor.kt @@ -204,10 +204,16 @@ class BCCADEditor(app: Bread, mainPane: MainPane, dataFile: File, data: BCCAD, i } children += Button("Remove").apply { setOnAction { - val animation = currentAnimation as Animation - data.animations.remove(animation) - updateAnimSpinners(true) - editor.updateContextMenu() + val alert = Alert(Alert.AlertType.CONFIRMATION) + editor.app.addBaseStyleToDialog(alert.dialogPane) + alert.title = "Remove this animation?" + alert.headerText = "Remove this animation?" + alert.contentText = "Are you sure you want to remove this animation?\nYou won't be able to undo this action." + if (alert.showAndWait().get() == ButtonType.OK) { + editor.removeAnimation(currentAnimation) + updateAnimSpinners(true) + editor.updateContextMenu() + } } } }) From 91133e0359be8ad605c682e33decac6822206328 Mon Sep 17 00:00:00 2001 From: TheAlternateDoctor Date: Mon, 28 Aug 2023 14:42:56 +0200 Subject: [PATCH 09/11] Fixed duplicate animation --- src/main/kotlin/rhmodding/bread/editor/BCCADEditor.kt | 8 +++++--- src/main/kotlin/rhmodding/bread/editor/Editor.kt | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/rhmodding/bread/editor/BCCADEditor.kt b/src/main/kotlin/rhmodding/bread/editor/BCCADEditor.kt index c409496..6fca110 100644 --- a/src/main/kotlin/rhmodding/bread/editor/BCCADEditor.kt +++ b/src/main/kotlin/rhmodding/bread/editor/BCCADEditor.kt @@ -195,9 +195,11 @@ class BCCADEditor(app: Bread, mainPane: MainPane, dataFile: File, data: BCCAD, i } children += Button("Duplicate").apply { setOnAction { - val animation = currentAnimation as Animation - animation.name += "_dup" - data.animations.add(animation) + editor.addAnimation(currentAnimation.copy()) + val animation = data.animations.last() + val curAnim = currentAnimation as Animation + animation.name = curAnim.name + "_dup" + animationNameLabel.text = curAnim.name + "_dup" updateAnimSpinners(true) editor.updateContextMenu() } diff --git a/src/main/kotlin/rhmodding/bread/editor/Editor.kt b/src/main/kotlin/rhmodding/bread/editor/Editor.kt index 22f93e3..e040c48 100644 --- a/src/main/kotlin/rhmodding/bread/editor/Editor.kt +++ b/src/main/kotlin/rhmodding/bread/editor/Editor.kt @@ -271,7 +271,7 @@ abstract class Editor(val app: Bread, val mainPane: MainPane, va val blockColorEven = canvasColors[if (!darkGrid) 0 else 2] val blockColorOdd = canvasColors[if (!darkGrid) 1 else 3] -// val blockStartX = ((canvas.width / 2 - canvas.width / zoomFactor / 2.0) / blockSize).toInt() - 2 + // val blockStartX = ((canvas.width / 2 - canvas.width / zoomFactor / 2.0) / blockSize).toInt() - 2 val blocksInViewableAreaX = (canvas.width / blockSize / zoomFactor).toInt() val blocksInViewableAreaY = (canvas.height / blockSize / zoomFactor).toInt() @@ -295,7 +295,7 @@ abstract class Editor(val app: Bread, val mainPane: MainPane, va // Origin lines if (originLines) { g.save() -// g.transform(getCanvasCameraTransformation()) + // g.transform(getCanvasCameraTransformation()) g.transform(Affine(Translate(panX, panY))) val originLineWidth = 1.0 val xAxis = if (darkGrid && showGrid) Color(0.5, 0.5, 1.0, 0.75) else Color(0.0, 0.0, 1.0, 0.75) From f8d291e8262437800924686953536ad8f9fca3ae Mon Sep 17 00:00:00 2001 From: TheAlternateDoctor Date: Mon, 28 Aug 2023 16:56:27 +0200 Subject: [PATCH 10/11] Added Zoom and Pan options to Add Sprite window --- .../rhmodding/bread/editor/SpritesTab.kt | 139 +++++++++++++++++- 1 file changed, 132 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/rhmodding/bread/editor/SpritesTab.kt b/src/main/kotlin/rhmodding/bread/editor/SpritesTab.kt index 069e7ab..5b07632 100644 --- a/src/main/kotlin/rhmodding/bread/editor/SpritesTab.kt +++ b/src/main/kotlin/rhmodding/bread/editor/SpritesTab.kt @@ -14,6 +14,10 @@ import javafx.scene.control.* import javafx.scene.input.MouseButton import javafx.scene.layout.* import javafx.scene.paint.Color +import javafx.scene.text.TextAlignment +import javafx.scene.transform.Affine +import javafx.scene.transform.Scale +import javafx.scene.transform.Translate import javafx.stage.Modality import javafx.stage.Stage import rhmodding.bread.model.bccad.Animation as BCCADAnimation @@ -26,6 +30,8 @@ import rhmodding.bread.util.spinnerArrowKeysAndScroll import java.util.* import kotlin.math.absoluteValue import kotlin.math.max +import kotlin.math.roundToInt +import kotlin.math.pow open class SpritesTab(editor: Editor) : EditorSubTab(editor, "Sprites") { @@ -70,6 +76,17 @@ open class SpritesTab(editor: Editor) : EditorSubTab(edito val currentPart: ISpritePart get() = currentSprite.parts[spritePartSpinner.value] + val zoomLabel: Label = Label("Zoom: 100%").apply { + textAlignment = TextAlignment.RIGHT + } + var zoomFactor: Double = 1.0 + set(value) { + field = value.coerceIn(0.10, 4.0) + zoomLabel.text = "Zoom: ${(field * 100).roundToInt()}%" + } + var panX: Double = 0.0 + var panY: Double = 0.0 + init { this.content = ScrollPane(body).apply { this.hbarPolicy = ScrollPane.ScrollBarPolicy.AS_NEEDED @@ -432,6 +449,7 @@ open class SpritesTab(editor: Editor) : EditorSubTab(edito val copy: ISpritePart = spritePart.copy() val regionPicker = Stage() val sheet = editor.texture + regionPicker.apply { title = "Edit Sprite Part Region" isResizable = false @@ -443,11 +461,19 @@ open class SpritesTab(editor: Editor) : EditorSubTab(edito val scaleFactor = (512.0 / max(sheet.width, sheet.height)).coerceAtMost(1.0) val canvas = Canvas(sheet.width * scaleFactor, sheet.height * scaleFactor) val fxSheet = SwingFXUtils.toFXImage(sheet, null) + val darkGrid = CheckBox("Dark grid").apply { isSelected = editor.darkGridCheckbox.isSelected } + fun getCanvasSheetCameraTransformation(zoomFactor: Double, canvas: Canvas): Affine { + return Affine().apply { + this.append(Translate(panX, panY)) + this.append(Scale(zoomFactor, zoomFactor, canvas.width / 2, canvas.height / 2)) + } + } + fun repaintSheetCanvas(fillRegionRect: Boolean = false, regX: Double = copy.regionX.toDouble() * scaleFactor, regY: Double = copy.regionY.toDouble() * scaleFactor, @@ -456,6 +482,8 @@ open class SpritesTab(editor: Editor) : EditorSubTab(edito val g = canvas.graphicsContext2D g.clearRect(0.0, 0.0, canvas.width, canvas.height) editor.drawCheckerBackground(canvas, showGrid = true, originLines = false, darkGrid = darkGrid.isSelected) + g.save() + g.transform(getCanvasSheetCameraTransformation(zoomFactor, canvas)) g.drawImage(fxSheet, 0.0, 0.0, canvas.width, canvas.height) if (fillRegionRect) { g.fill = Color(1.0, 0.0, 0.0, 0.35) @@ -464,6 +492,7 @@ open class SpritesTab(editor: Editor) : EditorSubTab(edito } g.stroke = Color.RED g.strokeRect(regX, regY, regW, regH) + g.restore() } repaintSheetCanvas() @@ -518,6 +547,23 @@ open class SpritesTab(editor: Editor) : EditorSubTab(edito regionWSpinner.valueFactory.value = copy.regionW.toInt() regionHSpinner.valueFactory.value = copy.regionH.toInt() } + + //Used to move the pans while zooming out + fun verifyPan(){ + val maxPanX = fxSheet.getWidth()*(zoomFactor-1)/2 + if(panX > maxPanX){ + panX = maxPanX + } else if(panX < maxPanX*-1){ + panX = maxPanX*-1 + } + + val maxPanY = fxSheet.getHeight()*(zoomFactor-1)/2 + if(panY > maxPanY){ + panY = maxPanY + } else if(panY < maxPanY*-1){ + panY = maxPanY*-1 + } + } // Dragging support with(canvas) { @@ -526,6 +572,10 @@ open class SpritesTab(editor: Editor) : EditorSubTab(edito var w = 0 var h = 0 + var isPanningCanvas = false + var prevDragX = 0.0 + var prevDragY = 0.0 + fun reset() { x = -1 y = -1 @@ -535,16 +585,17 @@ open class SpritesTab(editor: Editor) : EditorSubTab(edito originalRegionLabel.text = originalRegionLabelText } + setOnMousePressed { e -> if (e.button == MouseButton.PRIMARY) { - x = (e.x / scaleFactor).toInt() - y = (e.y / scaleFactor).toInt() + // CALC + val centerImgX = fxSheet.getWidth()/2 + val centerImgY = fxSheet.getHeight()/2 + x = ((((e.x - centerImgX - panX) / zoomFactor) + centerImgX) / scaleFactor).toInt() + y = ((((e.y - centerImgY - panY) / zoomFactor) + centerImgX) / scaleFactor).toInt() repaintSheetCanvas(true, 0.0, 0.0, 0.0, 0.0) draggingProperty.value = true - originalRegionLabel.text = "Drag an area, right click to cancel" - } else if (e.button == MouseButton.SECONDARY && x >= 0 && y >= 0) { - reset() - repaintSheetCanvas(false) + originalRegionLabel.text = "Drag an area" } } setOnMouseReleased { e -> @@ -565,12 +616,20 @@ open class SpritesTab(editor: Editor) : EditorSubTab(edito repaintSheetCanvas(false) } reset() + } else if (e.button == MouseButton.SECONDARY) { + isPanningCanvas = false + prevDragX = 0.0 + prevDragY = 0.0 } } setOnMouseDragged { e -> if (e.button == MouseButton.PRIMARY && x >= 0 && y >= 0) { + val centerImgX = fxSheet.getWidth() / 2 + val centerImgY = fxSheet.getHeight() / 2 w = (e.x / scaleFactor).toInt() - x h = (e.y / scaleFactor).toInt() - y + w = ((((e.x - centerImgX - panX) / zoomFactor) + centerImgX) / scaleFactor).toInt() - x + h = ((((e.y - centerImgY - panY) / zoomFactor) + centerImgX) / scaleFactor).toInt() - y val regionX = if (w < 0) x + w else x val regionY = if (h < 0) y + h else y @@ -579,10 +638,50 @@ open class SpritesTab(editor: Editor) : EditorSubTab(edito // Repaint canvas and update label originalRegionLabel.text = "New region: ($regionX, $regionY, $regionW, $regionH)" repaintSheetCanvas(true, regionX.toDouble() * scaleFactor, regionY.toDouble() * scaleFactor, regionW.toDouble() * scaleFactor, regionH.toDouble() * scaleFactor) + } else if (e.button == MouseButton.SECONDARY){ + if (!isPanningCanvas) { + isPanningCanvas = true + } else { + val diffX = e.x - prevDragX + val diffY = e.y - prevDragY + + panX += diffX + panY += diffY + + verifyPan() + } + prevDragX = e.x + prevDragY = e.y + repaintSheetCanvas() } } } + //Zoom support? + canvas.onScroll = EventHandler { evt -> + if (evt.isShiftDown) { + if (evt.deltaX > 0 || evt.deltaY > 0) { + zoomFactor += 0.01 + } else { + if (zoomFactor > 1.0){ + zoomFactor -= 0.01 + } + } + } else { + if (evt.deltaX > 0 || evt.deltaY > 0) { + zoomFactor *= 1.190507733 + } else { + if (zoomFactor > 1.0){ + zoomFactor /= 2.0.pow(1 / 8.0) + if(zoomFactor < 1.0) { + zoomFactor = 1.0 + } + } + } + } + verifyPan() + repaintSheetCanvas() + } bottom = VBox().apply { styleClass += "vbox" alignment = Pos.TOP_CENTER @@ -591,7 +690,33 @@ open class SpritesTab(editor: Editor) : EditorSubTab(edito children += HBox().apply { styleClass += "hbox" alignment = Pos.CENTER_LEFT - children += Label("Adjust the region using the spinners below and/or by left clicking and dragging on the canvas.\nYou may want to find the exact region in an image editor first.") + children += Label("Adjust the region using the spinners below and/or by left clicking and dragging on the canvas.") + } + children += HBox().apply { + styleClass += "hbox" + alignment = Pos.CENTER_LEFT + children += Button("Reset Preview").apply { + setOnAction { + zoomFactor = 1.0 + panX = 0.0 + panY = 0.0 + repaintSheetCanvas() + } + } + children += Button("Reset Panning").apply { + setOnAction { + panX = 0.0 + panY = 0.0 + repaintSheetCanvas() + } + } + children += Button("Reset Zoom").apply { + setOnAction { + zoomFactor = 1.0 + repaintSheetCanvas() + } + } + children += zoomLabel } children += GridPane().apply { styleClass += "grid-pane" From 3daff8d7250ad9dad243538dae5485647e20db5c Mon Sep 17 00:00:00 2001 From: TheAlternateDoctor Date: Sun, 3 Sep 2023 01:11:44 +0200 Subject: [PATCH 11/11] Fixed copy paste --- src/main/kotlin/rhmodding/bread/editor/AnimationsTab.kt | 2 +- src/main/kotlin/rhmodding/bread/editor/SpritesTab.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/rhmodding/bread/editor/AnimationsTab.kt b/src/main/kotlin/rhmodding/bread/editor/AnimationsTab.kt index c79d268..827c0f4 100644 --- a/src/main/kotlin/rhmodding/bread/editor/AnimationsTab.kt +++ b/src/main/kotlin/rhmodding/bread/editor/AnimationsTab.kt @@ -242,7 +242,7 @@ open class AnimationsTab(editor: Editor) : EditorSubTab(ed disableProperty().bind(disablePasteControls) setOnAction { if (currentAnimation.steps.isNotEmpty()) { - editor.addAnimationStep(currentAnimation, copyStep) + editor.addAnimationStep(currentAnimation, copyStep.copy()) updateStepSpinners(true) } } diff --git a/src/main/kotlin/rhmodding/bread/editor/SpritesTab.kt b/src/main/kotlin/rhmodding/bread/editor/SpritesTab.kt index 5b07632..961528e 100644 --- a/src/main/kotlin/rhmodding/bread/editor/SpritesTab.kt +++ b/src/main/kotlin/rhmodding/bread/editor/SpritesTab.kt @@ -334,7 +334,7 @@ open class SpritesTab(editor: Editor) : EditorSubTab(edito disableProperty().bind(disablePasteControls) setOnAction { if (currentSprite.parts.isNotEmpty()) { - editor.addSpritePart(currentSprite, copyPart) + editor.addSpritePart(currentSprite, copyPart.copy()) updateSpritePartSpinners(true) } }