diff --git a/src/defaults/config/editor.lua b/src/defaults/config/editor.lua index a6390b2a..ee5a9710 100644 --- a/src/defaults/config/editor.lua +++ b/src/defaults/config/editor.lua @@ -3,6 +3,7 @@ return { toolActionButton = 1, contextMenuButton = 2, canvasMoveButton = 2, + canvasZoomExtentsButton = 3, objectCloneButton = 3, copyUsesClipboard = true, diff --git a/src/input_devices/viewport_device.lua b/src/input_devices/viewport_device.lua new file mode 100644 index 00000000..476838ad --- /dev/null +++ b/src/input_devices/viewport_device.lua @@ -0,0 +1,76 @@ +local configs = require("configs") +local viewportHandler = require("viewport_handler") +local mapItemUtils = require("map_item_utils") +local loadedState = require("loaded_state") +local utils = require("utils") + +local viewportDevice = {} + +function viewportDevice.mousedragmoved(x, y, dx, dy, button, istouch) + local movementButton = configs.editor.canvasMoveButton + local viewport = viewportHandler.viewport + + if button == movementButton then + viewport.x -= dx + viewport.y -= dy + + viewportHandler.persistCamera() + + return true + end +end + +function viewportDevice.mousemoved(x, y, dx, dy, istouch) + local viewport = viewportHandler.viewport + + if istouch then + viewport.x -= dx + viewport.y -= dy + + viewportHandler.persistCamera() + + return true + end +end + +function viewportDevice.mouseclicked(x, y, button, istouch, presses) + local zoomToExtentsButton = configs.editor.canvasZoomExtentsButton + local map = loadedState.map + + if not map then + return + end + + if button == zoomToExtentsButton and presses % 2 == 0 then + local tlx, tly, brx, bry = mapItemUtils.getMapBounds(map) + local rectangle = utils.rectangle(tlx, tly, brx - tlx, bry - tly) + + viewportHandler.zoomToRectangle(rectangle) + viewportHandler.persistCamera() + end +end + +function viewportDevice.resize(width, height) + viewportHandler.updateSize(width, height) +end + +function viewportDevice.wheelmoved(dx, dy) + if dy > 0 then + viewportHandler.zoomIn() + + return true + + elseif dy < 0 then + viewportHandler.zoomOut() + + return true + end +end + +function viewportDevice.visible(visible) + local viewport = viewportHandler.viewport + + viewport.visible = visible +end + +return viewportDevice diff --git a/src/map_image.lua b/src/map_image.lua index ef9981d5..54844dd2 100644 --- a/src/map_image.lua +++ b/src/map_image.lua @@ -1,26 +1,14 @@ local loadedState = require("loaded_state") local utils = require("utils") local celesteRender = require("celeste_render") -local viewportHandler = require("viewport_handler") +local mapItemUtils = require("map_item_utils") local mapImageGenerator = {} -function mapImageGenerator.getMapBounds(map) - local rectangles = {} - - for _, room in ipairs(map.rooms) do - local rectangle = utils.rectangle(room.x, room.y, room.width, room.height) - - table.insert(rectangles, rectangle) - end - - return utils.rectangleBounds(rectangles) -end - local function getImageState(map) local imageState = utils.deepcopy(loadedState) - local tlx, tly, brx, bry = mapImageGenerator.getMapBounds(map) + local tlx, tly, brx, bry = mapItemUtils.getMapBounds(map) local width, height = brx - tlx, bry - tly imageState.map = map diff --git a/src/map_item_utils.lua b/src/map_item_utils.lua index dcecbbae..df72bb50 100644 --- a/src/map_item_utils.lua +++ b/src/map_item_utils.lua @@ -10,6 +10,18 @@ local celesteRender = require("celeste_render") local mapItemUtils = {} +function mapItemUtils.getMapBounds(map) + local rectangles = {} + + for _, room in ipairs(map.rooms) do + local rectangle = utils.rectangle(room.x, room.y, room.width, room.height) + + table.insert(rectangles, rectangle) + end + + return utils.rectangleBounds(rectangles) +end + function mapItemUtils.deleteRoom(map, room) for i, r in ipairs(map.rooms) do if r.name == room.name then diff --git a/src/scenes/editor.lua b/src/scenes/editor.lua index c3508525..d94da65f 100644 --- a/src/scenes/editor.lua +++ b/src/scenes/editor.lua @@ -46,7 +46,7 @@ function editorScene:firstEnter() local updater = require("updater") local hotkeyHandler = require("hotkey_handler") - local viewportHandler = require("viewport_handler") + local viewportDevice = require("input_devices.viewport_device") local hotkeyDevice = hotkeyHandler.createHotkeyDevice(standardHotkeys) local backupDevice = backups.createBackupDevice() local userInterfaceDevice = require("ui.ui_device") @@ -59,7 +59,7 @@ function editorScene:firstEnter() inputDevice.newInputDevice(self.inputDevices, inputCaptureDevice) inputDevice.newInputDevice(self.inputDevices, userInterfaceDevice) - inputDevice.newInputDevice(self.inputDevices, viewportHandler.device) + inputDevice.newInputDevice(self.inputDevices, viewportDevice) inputDevice.newInputDevice(self.inputDevices, hotkeyDevice) inputDevice.newInputDevice(self.inputDevices, backupDevice) inputDevice.newInputDevice(self.inputDevices, mapLoaderDevice) diff --git a/src/utils/utils.lua b/src/utils/utils.lua index 05095834..87c362f7 100644 --- a/src/utils/utils.lua +++ b/src/utils/utils.lua @@ -164,6 +164,28 @@ function utils.subtractRectangle(r1, r2) return remaining end +function utils.getBestScale(width, height, maxWidth, maxHeight, maxScale, preMultiplied) + local scaleX = maxScale or 1 + local scaleY = maxScale or 1 + + if maxScale and not preMultiplied then + width *= scaleX + height *= scaleY + end + + while width >= maxWidth do + width /= 2 + scaleX /= 2 + end + + while height >= maxHeight do + height /= 2 + scaleY /= 2 + end + + return math.min(scaleX, scaleY) +end + function utils.getFileHandle(path, mode, internal) if internal then return love.filesystem.newFile(path, mode:gsub("b", "")) diff --git a/src/viewport_handler.lua b/src/viewport_handler.lua index c63efba7..1a6b7e07 100644 --- a/src/viewport_handler.lua +++ b/src/viewport_handler.lua @@ -1,10 +1,6 @@ -local inputDevice = require("input_device") local utils = require("utils") -local configs = require("configs") local persistence = require("persistence") -local movementButton = configs.editor.canvasMoveButton - local viewportHandler = {} local viewport = { @@ -19,10 +15,7 @@ local viewport = { visible = true } -local viewportDevice = {} - viewportHandler.viewport = viewport -viewportHandler.device = viewportDevice function viewportHandler.roomVisible(room, viewport) return utils.aabbCheckInline( @@ -124,12 +117,16 @@ function viewportHandler.moveToPosition(x, y, scale, centered) viewportHandler.persistCamera() end -function viewportHandler.enable() - viewportHandler.device._enabled = true -end +function viewportHandler.zoomToRectangle(rectangle) + local windowWidth, windowHeight = love.graphics.getDimensions() + local halfWidth = math.floor(rectangle.width / 2) + local halfHeight = math.floor(rectangle.height / 2) -function viewportHandler.disable() - viewportHandler.device._enabled = false + local scale = utils.getBestScale(rectangle.width, rectangle.height, windowWidth, windowHeight) + local moveX = rectangle.x + halfWidth + local moveY = rectangle.y + halfHeight + + viewportHandler.moveToPosition(moveX, moveY, scale, true) end function viewportHandler.drawRelativeTo(x, y, func, customViewport) @@ -146,47 +143,5 @@ function viewportHandler.drawRelativeTo(x, y, func, customViewport) love.graphics.pop() end -function viewportDevice.mousedragmoved(x, y, dx, dy, button, istouch) - if button == movementButton then - viewport.x -= dx - viewport.y -= dy - - viewportHandler.persistCamera() - - return true - end -end - -function viewportDevice.mousemoved(x, y, dx, dy, istouch) - if istouch then - viewport.x -= dx - viewport.y -= dy - - viewportHandler.persistCamera() - - return true - end -end - -function viewportDevice.resize(width, height) - viewportHandler.updateSize(width, height) -end - -function viewportDevice.wheelmoved(dx, dy) - if dy > 0 then - viewportHandler.zoomIn() - - return true - - elseif dy < 0 then - viewportHandler.zoomOut() - - return true - end -end - -function viewportDevice.visible(visible) - viewport.visible = visible -end return viewportHandler \ No newline at end of file