@@ -76,6 +76,7 @@ let startHeight = 0
let preFullScreenState = { x: 0, y: 0, width: 0, height: 0 }
const modalStyle = computed(() => ({
+ borderRadius: isFullScreen.value ? '0' : '10px',
top: isFullScreen.value ? '0' : `${y.value}px`,
left: isFullScreen.value ? '0' : `${x.value}px`,
width: isFullScreen.value ? '100vw' : `${width.value}px`,
diff --git a/src/components/utilities/zoneEditor/partials/Toolbar.vue b/src/components/utilities/zoneEditor/partials/Toolbar.vue
index 9d75dc5..d307709 100644
--- a/src/components/utilities/zoneEditor/partials/Toolbar.vue
+++ b/src/components/utilities/zoneEditor/partials/Toolbar.vue
@@ -161,7 +161,7 @@ onBeforeUnmount(() => {
function initKeyShortcuts(event: KeyboardEvent) {
if (!zoneEditorStore.zone) return
- // prevent if focussed on input
+ // prevent if focussed on composables
if (document.activeElement?.tagName === 'INPUT') return
if (event.key === 'm') {
diff --git a/src/composables/useCameraControls.ts b/src/composables/useCameraControls.ts
new file mode 100644
index 0000000..5cad3c2
--- /dev/null
+++ b/src/composables/useCameraControls.ts
@@ -0,0 +1,46 @@
+import { ref } from 'vue'
+import { useGameStore } from '@/stores/game'
+
+export function useCameraControls(scene: Phaser.Scene): any {
+ const gameStore = useGameStore()
+ const camera = ref(scene.cameras.main)
+ const isDragging = ref(false)
+ let pointerDownTimer: number | null = null
+ let pointerUpTimer: number | null = null
+
+ const DRAG_DELAY = 150
+ const MOVE_RESET_DELAY = 100
+
+ function onPointerDown(pointer: Phaser.Input.Pointer) {
+ if (pointer.event instanceof MouseEvent || pointer.event.altKey) {
+ pointerDownTimer = setTimeout(() => {
+ isDragging.value = true
+ gameStore.setMovingCamera(true)
+ }, DRAG_DELAY)
+ }
+ }
+
+ function onPointerUp() {
+ if (pointerDownTimer) {
+ clearTimeout(pointerDownTimer)
+ pointerDownTimer = null
+ }
+ isDragging.value = false
+
+ if (pointerUpTimer) {
+ clearTimeout(pointerUpTimer)
+ }
+
+ pointerUpTimer = setTimeout(() => {
+ gameStore.setMovingCamera(false)
+ }, MOVE_RESET_DELAY)
+ }
+
+ scene.input.on(Phaser.Input.Events.POINTER_DOWN, onPointerDown)
+ scene.input.on(Phaser.Input.Events.POINTER_UP, onPointerUp)
+
+ return {
+ camera,
+ isDragging
+ }
+}
\ No newline at end of file
diff --git a/src/composables/usePointerHandlers.ts b/src/composables/usePointerHandlers.ts
new file mode 100644
index 0000000..ae63b46
--- /dev/null
+++ b/src/composables/usePointerHandlers.ts
@@ -0,0 +1,92 @@
+import config from '@/config'
+import { computed, ref, type Ref, watch } from 'vue'
+import { getTile, tileToWorldXY } from '@/services/zone'
+import { useGameStore } from '@/stores/game'
+import { useZoneEditorStore } from '@/stores/zoneEditor'
+
+export function usePointerHandlers(
+ scene: Phaser.Scene,
+ layer: Phaser.Tilemaps.TilemapLayer,
+ waypoint: Ref<{ visible: boolean; x: number; y: number }>,
+ camera: Ref
,
+ isDragging: Ref
+) {
+ const gameStore = useGameStore()
+ const zoneEditorStore = useZoneEditorStore()
+
+ function updateWaypoint(pointer: Phaser.Input.Pointer) {
+ const { x: px, y: py } = camera.value.getWorldPoint(pointer.x, pointer.y)
+ const pointerTile = getTile(px, py, layer)
+
+ if (!pointerTile) {
+ waypoint.value.visible = false
+ return
+ }
+
+ const worldPoint = tileToWorldXY(layer, pointerTile.x, pointerTile.y)
+ waypoint.value = {
+ visible: true,
+ x: worldPoint.position_x,
+ y: worldPoint.position_y + config.tile_size.y + 15
+ }
+ }
+
+ const isMoveTool = computed(() => zoneEditorStore.tool === 'move')
+
+ watch(isMoveTool, (newValue) => {
+ if (newValue) {
+ scene.input.on(Phaser.Input.Events.POINTER_MOVE, dragZone)
+ } else {
+ scene.input.off(Phaser.Input.Events.POINTER_MOVE, dragZone)
+ }
+ })
+
+ function dragZone(pointer: Phaser.Input.Pointer) {
+ if (!isDragging.value) return
+ const { x, y, prevPosition } = pointer
+ camera.value.scrollX -= (x - prevPosition.x) / camera.value.zoom
+ camera.value.scrollY -= (y - prevPosition.y) / camera.value.zoom
+ }
+
+ function clickTile(pointer: Phaser.Input.Pointer) {
+ const { x: px, y: py } = camera.value.getWorldPoint(pointer.x, pointer.y)
+ const pointerTile = getTile(px, py, layer)
+
+ if (!pointerTile) {
+ return
+ }
+ gameStore.connection?.emit('character:move', { position_x: pointerTile.x, position_y: pointerTile.y })
+ }
+
+ function handleZoom(pointer: Phaser.Input.Pointer, _: unknown, __: unknown, deltaY: number) {
+ if (pointer.event instanceof WheelEvent && pointer.event.altKey) {
+ scene.scale.setZoom(scene.scale.zoom - deltaY * 0.01)
+ camera.value = scene.cameras.main
+ }
+ }
+
+ function setupPointerHandlers() {
+ scene.input.on(Phaser.Input.Events.POINTER_MOVE, updateWaypoint)
+ scene.input.on(Phaser.Input.Events.POINTER_WHEEL, handleZoom)
+
+ // These are for in-game only, not for in the zone editor
+ if (!zoneEditorStore.active) {
+ scene.input.on(Phaser.Input.Events.POINTER_UP, clickTile)
+ }
+ }
+
+ function cleanupPointerHandlers() {
+ scene.input.off(Phaser.Input.Events.POINTER_MOVE, updateWaypoint)
+ scene.input.off(Phaser.Input.Events.POINTER_WHEEL, handleZoom)
+
+ // These are for in-game only, not for in the zone editor
+ if (!zoneEditorStore.active) {
+ scene.input.off(Phaser.Input.Events.POINTER_UP, clickTile)
+ }
+ }
+
+ return {
+ setupPointerHandlers,
+ cleanupPointerHandlers
+ }
+}
\ No newline at end of file