1
0
forked from noxious/client

refactoring pointer events and input handling improvements

This commit is contained in:
Andrei 2025-01-26 19:07:27 -06:00
parent 791830fd6f
commit 9618e07bc6
11 changed files with 123 additions and 158 deletions

View File

@ -2,7 +2,7 @@
<Debug /> <Debug />
<Notifications /> <Notifications />
<BackgroundImageLoader /> <BackgroundImageLoader />
<GmPanel v-if="gameStore.character?.role === 'gm'" @open-map-editor="isEditorShown = true"/> <GmPanel v-if="gameStore.character?.role === 'gm'" @open-map-editor="mapEditor.active.value = true"/>
<component :is="currentScreen" /> <component :is="currentScreen" />
</template> </template>
@ -22,21 +22,20 @@ import { computed, ref, useTemplateRef, watch } from 'vue'
import { useMapEditorComposable } from '@/composables/useMapEditorComposable' import { useMapEditorComposable } from '@/composables/useMapEditorComposable'
const gameStore = useGameStore() const gameStore = useGameStore()
const mapEditor = useMapEditorComposable()
const isEditorShown = ref(false)
const currentScreen = computed(() => { const currentScreen = computed(() => {
if (!gameStore.game.isLoaded) return Loading if (!gameStore.game.isLoaded) return Loading
if (!gameStore.connection) return Login if (!gameStore.connection) return Login
if (!gameStore.token) return Login if (!gameStore.token) return Login
if (!gameStore.character) return Characters if (!gameStore.character) return Characters
if (isEditorShown.value) return MapEditor if (mapEditor.active.value) return MapEditor
return Game return Game
}) })
// Watch mapEditor.active and empty gameStore.game.loadedAssets // Watch mapEditor.active and empty gameStore.game.loadedAssets
watch( watch(
() => isEditorShown.value, () => mapEditor.active.value,
() => { () => {
gameStore.game.loadedTextures = [] gameStore.game.loadedTextures = []
} }

View File

@ -1,5 +1,5 @@
<template> <template>
<MapTiles ref="mapTiles" :tileMap="tileMap" @tileMap:create="tileMap = $event" /> <MapTiles ref="mapTiles" @tileMap:create="tileMap = $event" />
<PlacedMapObjects ref="mapObjects" v-if="tileMap" :tileMap="tileMap as Phaser.Tilemaps.Tilemap" /> <PlacedMapObjects ref="mapObjects" v-if="tileMap" :tileMap="tileMap as Phaser.Tilemaps.Tilemap" />
<MapEventTiles ref="eventTiles" v-if="tileMap" :tileMap="tileMap as Phaser.Tilemaps.Tilemap" /> <MapEventTiles ref="eventTiles" v-if="tileMap" :tileMap="tileMap as Phaser.Tilemaps.Tilemap" />
</template> </template>
@ -11,25 +11,16 @@ import MapEventTiles from '@/components/gameMaster/mapEditor/mapPartials/MapEven
import MapTiles from '@/components/gameMaster/mapEditor/mapPartials/MapTiles.vue' import MapTiles from '@/components/gameMaster/mapEditor/mapPartials/MapTiles.vue'
import PlacedMapObjects from '@/components/gameMaster/mapEditor/mapPartials/PlacedMapObjects.vue' import PlacedMapObjects from '@/components/gameMaster/mapEditor/mapPartials/PlacedMapObjects.vue'
import { useMapEditorComposable } from '@/composables/useMapEditorComposable' import { useMapEditorComposable } from '@/composables/useMapEditorComposable'
import { onMounted, onUnmounted, shallowRef } from 'vue' import { onUnmounted, shallowRef, useTemplateRef} from 'vue'
const mapEditor = useMapEditorComposable()
const tileMap = shallowRef<Phaser.Tilemaps.Tilemap>() const tileMap = shallowRef<Phaser.Tilemaps.Tilemap>()
const selectedMap = ref<MapT>()
const mapEditorStore = useMapEditorStore()
const mapEditor = useMapEditorComposable() const mapEditor = useMapEditorComposable()
const mapTiles = useTemplateRef('mapTiles') const mapTiles = useTemplateRef('mapTiles')
const mapObjects = useTemplateRef('mapObjects') const mapObjects = useTemplateRef('mapObjects')
const eventTiles = useTemplateRef('eventTiles') const eventTiles = useTemplateRef('eventTiles')
const scene = useScene()
function handlePointer(pointer: Phaser.Input.Pointer) { function handlePointer(pointer: Phaser.Input.Pointer) {
if (!mapTiles.value || !mapObjects.value || !eventTiles.value) return
// Check if left mouse button is pressed // Check if left mouse button is pressed
if (!pointer.isDown) return if (!pointer.isDown) return
@ -40,26 +31,16 @@ function handlePointer(pointer: Phaser.Input.Pointer) {
if (!pointer.event.altKey) return if (!pointer.event.altKey) return
// Check if draw mode is tile // Check if draw mode is tile
switch (mapEditorStore.drawMode) { switch (mapEditor.drawMode.value) {
case 'tile': case 'tile':
mapTiles.value.handlePointer(pointer) mapTiles.value?.handlePointer(pointer)
// case 'map_object': // case 'map_object':
// mapObjects.value.handlePointer(pointer) // mapObjects.value.handlePointer(pointer)
case 'event tile': case 'event tile':
eventTiles.value.handlePointer(pointer) eventTiles.value?.handlePointer(pointer)
} }
} }
watch(() => mapEditor.currentMap, async (map) => {
if (!map.value) return
selectedMap.value = map.value
})
onMounted(() => {
scene.input.on(Phaser.Input.Events.POINTER_MOVE, handlePointer)
scene.input.on(Phaser.Input.Events.POINTER_DOWN, handlePointer)
})
onUnmounted(() => { onUnmounted(() => {
mapEditor.reset() mapEditor.reset()
}) })

View File

@ -6,13 +6,12 @@
import { MapEventTileType, type MapEventTile } from '@/application/types' import { MapEventTileType, type MapEventTile } from '@/application/types'
import { uuidv4 } from '@/application/utilities' import { uuidv4 } from '@/application/utilities'
import { getTile, tileToWorldX, tileToWorldY } from '@/composables/mapComposable' import { getTile, tileToWorldX, tileToWorldY } from '@/composables/mapComposable'
import { useMapEditorStore } from '@/stores/mapEditorStore'
import { Image, useScene } from 'phavuer' import { Image, useScene } from 'phavuer'
import { type Map as MapT } from "@/application/types" import { type Map as MapT } from "@/application/types"
import { useMapEditorComposable } from '@/composables/useMapEditorComposable' import { useMapEditorComposable } from '@/composables/useMapEditorComposable'
import { shallowRef, watch } from 'vue' import { onMounted, onUnmounted, shallowRef, watch } from 'vue'
const mapEditorStore = useMapEditorStore() const scene = useScene()
const mapEditor = useMapEditorComposable() const mapEditor = useMapEditorComposable()
defineExpose({handlePointer}) defineExpose({handlePointer})
@ -44,22 +43,22 @@ function pencil(pointer: Phaser.Input.Pointer, map: MapT) {
if (existingEventTile) return if (existingEventTile) return
// If teleport, check if there is a selected map // If teleport, check if there is a selected map
if (mapEditorStore.drawMode === 'teleport' && !mapEditorStore.teleportSettings.toMapId) return if (mapEditor.drawMode.value === 'teleport' && !mapEditor.teleportSettings.value.toMapId) return
const newEventTile = { const newEventTile = {
id: uuidv4(), id: uuidv4(),
mapId: map?.id, mapId: map?.id,
map: map?.id, map: map?.id,
type: mapEditorStore.drawMode === 'blocking tile' ? MapEventTileType.BLOCK : MapEventTileType.TELEPORT, type: mapEditor.drawMode.value === 'blocking tile' ? MapEventTileType.BLOCK : MapEventTileType.TELEPORT,
positionX: tile.x, positionX: tile.x,
positionY: tile.y, positionY: tile.y,
teleport: teleport:
mapEditorStore.drawMode === 'teleport' mapEditor.drawMode.value === 'teleport'
? { ? {
toMap: mapEditorStore.teleportSettings.toMapId, toMap: mapEditor.teleportSettings.value.toMapId,
toPositionX: mapEditorStore.teleportSettings.toPositionX, toPositionX: mapEditor.teleportSettings.value.toPositionX,
toPositionY: mapEditorStore.teleportSettings.toPositionY, toPositionY: mapEditor.teleportSettings.value.toPositionY,
toRotation: mapEditorStore.teleportSettings.toRotation toRotation: mapEditor.teleportSettings.value.toRotation
} }
: undefined : undefined
} }
@ -91,12 +90,23 @@ function handlePointer(pointer: Phaser.Input.Pointer) {
// Check if shift is not pressed, this means we are moving the camera // Check if shift is not pressed, this means we are moving the camera
if (pointer.event.shiftKey) return if (pointer.event.shiftKey) return
if (mapEditorStore.drawMode !== 'blocking tile' && mapEditorStore.drawMode !== 'teleport') return if (mapEditor.drawMode.value !== 'blocking tile' && mapEditor.drawMode.value !== 'teleport') return
switch (mapEditorStore.tool) { switch (mapEditor.tool.value) {
case 'pencil': pencil(pointer, map) case 'pencil': pencil(pointer, map)
case 'eraser': erase(pointer, map) case 'eraser': erase(pointer, map)
} }
} }
onMounted(() => {
scene.input.on(Phaser.Input.Events.POINTER_MOVE, handlePointer)
scene.input.on(Phaser.Input.Events.POINTER_DOWN, handlePointer)
})
onUnmounted(() => {
scene.input.off(Phaser.Input.Events.POINTER_MOVE, handlePointer)
scene.input.off(Phaser.Input.Events.POINTER_DOWN, handlePointer)
})
</script> </script>

View File

@ -34,7 +34,9 @@ function createTileMap() {
format: Phaser.Tilemaps.Formats.ARRAY_2D format: Phaser.Tilemaps.Formats.ARRAY_2D
}) })
return new Phaser.Tilemaps.Tilemap(scene, mapData) const newTileMap = new Phaser.Tilemaps.Tilemap(scene, mapData)
emit('tileMap:create', newTileMap)
return newTileMap
} }
async function createTileLayer(currentTileMap: Phaser.Tilemaps.Tilemap) { async function createTileLayer(currentTileMap: Phaser.Tilemaps.Tilemap) {
@ -55,81 +57,88 @@ async function createTileLayer(currentTileMap: Phaser.Tilemaps.Tilemap) {
return layer return layer
} }
function pencil(pointer: Phaser.Input.Pointer, tileMap: Phaser.Tilemaps.Tilemap, tileLayer: Phaser.Tilemaps.TilemapLayer) { function pencil(pointer: Phaser.Input.Pointer) {
var map = mapEditor.currentMap.value
if (!map) return
// Check if there is a tile
const tile = tileLayer.getTileAtWorldXY(pointer.worldX, pointer.worldY)
if (!tile) return
// Place tile
placeTile(tileMap, tileLayer, tile.x, tile.y, mapEditorStore.selectedTile)
// Adjust mapEditorStore.map.tiles
tileMap.tiles[tile.y][tile.x] = map.tiles[tile.y][tile.x]
}
function eraser(pointer: Phaser.Input.Pointer, tileMap: Phaser.Tilemaps.Tilemap, tileLayer: Phaser.Tilemaps.TilemapLayer) {
let map = mapEditor.currentMap.value let map = mapEditor.currentMap.value
if (!map) return if (!map) return
// Check if there is a selected tile
if (!mapEditor.selectedTile.value) return
console.log(tileMap.value, tileLayer.value)
if (!tileMap.value || !tileLayer.value) return
// Check if there is a tile // Check if there is a tile
const tile = getTile(tileLayer, pointer.worldX, pointer.worldY) const tile = getTile(tileLayer.value, pointer.worldX, pointer.worldY)
if (!tile) return if (!tile) return
// Place tile // Place tile
placeTile(tileMap, tileLayer, tile.x, tile.y, 'blank_tile') placeTile(tileMap.value, tileLayer.value, tile.x, tile.y, mapEditor.selectedTile.value)
// Adjust mapEditorStore.map.tiles
map.tiles[tile.y][tile.x] = map.tiles[tile.y][tile.x]
}
function eraser(pointer: Phaser.Input.Pointer) {
let map = mapEditor.currentMap.value
if (!map) return
if (!tileMap.value || !tileLayer.value) return
// Check if there is a tile
const tile = getTile(tileLayer.value, pointer.worldX, pointer.worldY)
if (!tile) return
// Place tile
placeTile(tileMap.value, tileLayer.value, tile.x, tile.y, 'blank_tile')
// Adjust mapEditorStore.map.tiles // Adjust mapEditorStore.map.tiles
map.tiles[tile.y][tile.x] = 'blank_tile' map.tiles[tile.y][tile.x] = 'blank_tile'
} }
function paint(pointer: Phaser.Input.Pointer, tileMap: Phaser.Tilemaps.Tilemap, tileLayer: Phaser.Tilemaps.TilemapLayer) { function paint(pointer: Phaser.Input.Pointer) {
if (!tileMap.value || !tileLayer.value) return
// Set new tileArray with selected tile // Set new tileArray with selected tile
setLayerTiles(tileMap, tileLayer, createTileArray(tileMap.width, tileMap.height, mapEditorStore.selectedTile)) const tileArray = createTileArray(tileMap.value.width, tileMap.value.height, mapEditor.selectedTile.value)
setLayerTiles(tileMap.value, tileLayer.value, tileArray)
// Adjust mapEditorStore.map.tiles // Adjust mapEditorStore.map.tiles
if (mapEditor.currentMap.value) { if (mapEditor.currentMap.value) {
mapEditor.currentMap.value.tiles = createTileArray(tileMap.width, tileMap.height, mapEditorStore.selectedTile) mapEditor.currentMap.value.tiles = tileArray
} }
} }
// When alt is pressed, and the pointer is down, select the tile that the pointer is over // When alt is pressed, and the pointer is down, select the tile that the pointer is over
function tilePicker(pointer: Phaser.Input.Pointer, tileLayer: Phaser.Tilemaps.TilemapLayer) { function tilePicker(pointer: Phaser.Input.Pointer) {
let map = mapEditor.currentMap.value let map = mapEditor.currentMap.value
if (!map) return if (!map) return
// Check if there is a tile // Check if there is a tile
const tile = getTile(tileLayer, pointer.worldX, pointer.worldY) const tile = getTile(tileLayer.value!, pointer.worldX, pointer.worldY)
if (!tile) return if (!tile) return
// Select the tile // Select the tile
mapEditorStore.setSelectedTile(map.tiles[tile.y][tile.x]) mapEditor.setSelectedTile(map.tiles[tile.y][tile.x])
} }
watch( watch(
() => mapEditorStore.shouldClearTiles, () => mapEditor.shouldClearTiles,
(shouldClear) => { (shouldClear) => {
if (shouldClear && mapEditor.currentMap.value && tileMap.value && tileLayer.value) { if (shouldClear && mapEditor.currentMap.value && tileMap.value && tileLayer.value) {
const blankTiles = createTileArray(tileLayer.value.width, tileLayer.value.height, 'blank_tile') const blankTiles = createTileArray(tileLayer.value.width, tileLayer.value.height, 'blank_tile')
setLayerTiles(tileMap.value, tileLayer.value, blankTiles) setLayerTiles(tileMap.value, tileLayer.value, blankTiles)
mapEditor.currentMap.value.tiles = blankTiles mapEditor.currentMap.value.tiles = blankTiles
mapEditorStore.resetClearTilesFlag() mapEditor.resetClearTilesFlag()
} }
} }
) )
function handlePointer(pointer: Phaser.Input.Pointer) { function handlePointer(pointer: Phaser.Input.Pointer) {
if (!mapEditor.currentMap.value) return
if (!tileMap.value || !tileLayer.value) return if (!tileMap.value || !tileLayer.value) return
// Check if tool is pencil // Check if tool is pencil
if (mapEditorStore.drawMode !== 'tile') return if (mapEditor.drawMode.value !== 'tile') return
// Check if there is a selected tile
if (!mapEditorStore.selectedTile) return
// Check if left mouse button is pressed // Check if left mouse button is pressed
if (!pointer.isDown) return if (!pointer.isDown) return
@ -138,24 +147,26 @@ function handlePointer(pointer: Phaser.Input.Pointer) {
if (pointer.event.shiftKey) return if (pointer.event.shiftKey) return
// Check if alt is pressed // Check if alt is pressed
if (!pointer.event.altKey) return if (pointer.event.altKey) return
// Check if draw mode is tile // Check if draw mode is tile
switch (mapEditorStore.tool) { switch (mapEditor.tool.value) {
case 'pencil': case 'pencil':
pencil(pointer, tileMap.value, tileLayer.value) pencil(pointer)
break
case 'eraser': case 'eraser':
eraser(pointer, tileMap.value, tileLayer.value) eraser(pointer)
break
case 'paint': case 'paint':
paint(pointer, tileMap.value, tileLayer.value) paint(pointer)
break
case 'tile picker': case 'tile picker':
tilePicker(pointer, tileLayer.value) tilePicker(pointer)
break
} }
} }
onMounted(async () => { onMounted(async () => {
if (!mapEditor.currentMap.value?.tiles) return if (!mapEditor.currentMap.value) return
console.log(mapEditor.currentMap.value)
tileMap.value = createTileMap() tileMap.value = createTileMap()
tileLayer.value = await createTileLayer(tileMap.value) tileLayer.value = await createTileLayer(tileMap.value)
@ -174,9 +185,15 @@ onMounted(async () => {
} }
setLayerTiles(tileMap.value, tileLayer.value, blankTiles) setLayerTiles(tileMap.value, tileLayer.value, blankTiles)
scene.input.on(Phaser.Input.Events.POINTER_MOVE, handlePointer)
scene.input.on(Phaser.Input.Events.POINTER_DOWN, handlePointer)
}) })
onUnmounted(() => { onUnmounted(() => {
scene.input.off(Phaser.Input.Events.POINTER_MOVE, handlePointer)
scene.input.off(Phaser.Input.Events.POINTER_DOWN, handlePointer)
if (tileMap.value) { if (tileMap.value) {
tileMap.value.destroyLayer('tiles') tileMap.value.destroyLayer('tiles')
tileMap.value.removeAllLayers() tileMap.value.removeAllLayers()

View File

@ -1,6 +1,6 @@
<template> <template>
<SelectedPlacedMapObjectComponent v-if="selectedPlacedMapObject" :placedMapObject="selectedPlacedMapObject" @move="moveMapObject" @rotate="rotatePlacedMapObject" @delete="deletePlacedMapObject" /> <SelectedPlacedMapObjectComponent v-if="selectedPlacedMapObject" :placedMapObject="selectedPlacedMapObject" @move="moveMapObject" @rotate="rotatePlacedMapObject" @delete="deletePlacedMapObject" />
<PlacedMapObject v-for="placedMapObject in mapEditor.currentMap.value?.placedMapObjects" :tilemap="tileMap" :placedMapObject :selectedPlacedMapObject :movingPlacedMapObject @pointerup="clickPlacedMapObject(placedMapObject)" /> <PlacedMapObject v-for="placedMapObject in mapEditor.currentMap.value?.placedMapObjects" :tileMap="tileMap" :placedMapObject :selectedPlacedMapObject :movingPlacedMapObject @pointerup="clickPlacedMapObject(placedMapObject)" />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -15,7 +15,6 @@ import { ref, watch } from 'vue'
import { useMapEditorComposable } from '@/composables/useMapEditorComposable' import { useMapEditorComposable } from '@/composables/useMapEditorComposable'
const scene = useScene() const scene = useScene()
const mapEditorStore = useMapEditorStore()
const mapEditor = useMapEditorComposable() const mapEditor = useMapEditorComposable()
const selectedPlacedMapObject = ref<PlacedMapObjectT | null>(null) const selectedPlacedMapObject = ref<PlacedMapObjectT | null>(null)
const movingPlacedMapObject = ref<PlacedMapObjectT | null>(null) const movingPlacedMapObject = ref<PlacedMapObjectT | null>(null)
@ -39,7 +38,7 @@ function pencil(pointer: Phaser.Input.Pointer, tileMapLayer: Phaser.Tilemaps.Til
id: uuidv4(), id: uuidv4(),
depth: 0, depth: 0,
map: map, map: map,
mapObject: mapEditorStore.selectedMapObject!, mapObject: mapEditor.selectedMapObject.value!,
isRotated: false, isRotated: false,
positionX: tile.x, positionX: tile.x,
positionY: tile.y positionY: tile.y
@ -72,7 +71,7 @@ function objectPicker(pointer: Phaser.Input.Pointer, tileMapLayer: Phaser.Tilema
if (!existingPlacedMapObject) return if (!existingPlacedMapObject) return
// Select the object // Select the object
mapEditorStore.setSelectedMapObject(existingPlacedMapObject.mapObject) mapEditor.setSelectedMapObject(existingPlacedMapObject.mapObject)
} }
function moveMapObject(id: string, tileMapLayer: Phaser.Tilemaps.TilemapLayer, map: MapT) { function moveMapObject(id: string, tileMapLayer: Phaser.Tilemaps.TilemapLayer, map: MapT) {
@ -120,7 +119,7 @@ function clickPlacedMapObject(placedMapObject: PlacedMapObjectT) {
// If alt is pressed, select the object // If alt is pressed, select the object
if (scene.input.activePointer.event.altKey) { if (scene.input.activePointer.event.altKey) {
mapEditorStore.setSelectedMapObject(placedMapObject.mapObject) mapEditor.setSelectedMapObject(placedMapObject.mapObject)
} }
} }
@ -128,7 +127,7 @@ function handlePointer(pointer: Phaser.Input.Pointer, tileMapLayer: Phaser.Tilem
const map = mapEditor.currentMap.value const map = mapEditor.currentMap.value
if (!map) return if (!map) return
if (mapEditorStore.drawMode !== 'map_object') return if (mapEditor.drawMode.value !== 'map_object') return
// Check if left mouse button is pressed // Check if left mouse button is pressed
if (!pointer.isDown) return if (!pointer.isDown) return
@ -140,9 +139,9 @@ function handlePointer(pointer: Phaser.Input.Pointer, tileMapLayer: Phaser.Tilem
if (pointer.event.altKey) return if (pointer.event.altKey) return
// Check if tool is pencil // Check if tool is pencil
switch (mapEditorStore.tool) { switch (mapEditor.tool.value) {
case 'pencil': case 'pencil':
if (mapEditorStore.selectedMapObject) pencil(pointer, tileMapLayer, map) if (mapEditor.selectedMapObject.value) pencil(pointer, tileMapLayer, map)
case 'eraser': case 'eraser':
eraser(pointer, tileMapLayer, map) eraser(pointer, tileMapLayer, map)
case 'object picker': case 'object picker':
@ -176,11 +175,11 @@ watch(
map.placedMapObjects = [...map.placedMapObjects, ...updatedMapObjects] map.placedMapObjects = [...map.placedMapObjects, ...updatedMapObjects]
// Update mapObject if it's set // Update mapObject if it's set
if (mapEditorStore.selectedMapObject) { if (mapEditor.selectedMapObject.value) {
const updatedMapObject = map.placedMapObjects.find((obj) => obj.id === mapEditorStore.selectedMapObject?.id) const updatedMapObject = map.placedMapObjects.find((obj) => obj.id === mapEditor.selectedMapObject.value?.id)
if (updatedMapObject) { if (updatedMapObject) {
mapEditorStore.setSelectedMapObject({ mapEditor.setSelectedMapObject({
...mapEditorStore.selectedMapObject, ...mapEditor.selectedMapObject.value,
originX: updatedMapObject.positionX, originX: updatedMapObject.positionX,
originY: updatedMapObject.positionY originY: updatedMapObject.positionY
}) })

View File

@ -40,12 +40,11 @@ import Modal from '@/components/utilities/Modal.vue'
import { MapStorage } from '@/storage/storages' import { MapStorage } from '@/storage/storages'
import { useGameStore } from '@/stores/gameStore' import { useGameStore } from '@/stores/gameStore'
import { useMapEditorComposable } from '@/composables/useMapEditorComposable' import { useMapEditorComposable } from '@/composables/useMapEditorComposable'
import { ref } from 'vue' import { ref, useTemplateRef } from 'vue'
const emit = defineEmits(['create']) const emit = defineEmits(['create'])
const gameStore = useGameStore() const gameStore = useGameStore()
const mapEditor = useMapEditorComposable()
const mapStorage = new MapStorage() const mapStorage = new MapStorage()
const modalRef = useTemplateRef('modalRef') const modalRef = useTemplateRef('modalRef')

View File

@ -51,7 +51,7 @@ import type { UUID } from '@/application/types'
import { uuidv4 } from '@/application/utilities' import { uuidv4 } from '@/application/utilities'
import Modal from '@/components/utilities/Modal.vue' import Modal from '@/components/utilities/Modal.vue'
import { useMapEditorComposable } from '@/composables/useMapEditorComposable' import { useMapEditorComposable } from '@/composables/useMapEditorComposable'
import { ref, watch } from 'vue' import { ref, useTemplateRef, watch } from 'vue'
const mapEditor = useMapEditorComposable() const mapEditor = useMapEditorComposable()
const screen = ref('settings') const screen = ref('settings')

View File

@ -39,7 +39,7 @@
<img class="invert w-5 h-5" src="/assets/icons/mapEditor/eraser.svg" alt="Eraser" /> <span class="h-5" :class="{ 'ml-2.5': mapEditor.tool.value !== 'eraser' }">(E)</span> <img class="invert w-5 h-5" src="/assets/icons/mapEditor/eraser.svg" alt="Eraser" /> <span class="h-5" :class="{ 'ml-2.5': mapEditor.tool.value !== 'eraser' }">(E)</span>
<div class="select" v-if="mapEditor.tool.value === 'eraser'"> <div class="select" v-if="mapEditor.tool.value === 'eraser'">
<div class="select-trigger group capitalize flex gap-3.5" :class="{ open: selectEraserOpen }"> <div class="select-trigger group capitalize flex gap-3.5" :class="{ open: selectEraserOpen }">
{{ mapEditor.eraserMode.value.replace('_', ' ') }} {{ mapEditor.drawMode.value.replace('_', ' ') }}
<img class="group-[.open]:rotate-180 invert w-5 h-5 rotate-0 transition ease-in-out duration-200" src="/assets/icons/mapEditor/chevron.svg" /> <img class="group-[.open]:rotate-180 invert w-5 h-5 rotate-0 transition ease-in-out duration-200" src="/assets/icons/mapEditor/chevron.svg" />
</div> </div>
<div class="flex flex-col absolute bottom-full mb-5 left-1/2 -translate-x-1/2 bg-gray rounded min-w-28 border border-gray-500 border-solid text-left" v-show="selectEraserOpen"> <div class="flex flex-col absolute bottom-full mb-5 left-1/2 -translate-x-1/2 bg-gray rounded min-w-28 border border-gray-500 border-solid text-left" v-show="selectEraserOpen">
@ -113,7 +113,7 @@ function setDrawMode(value: string) {
// drawMode // drawMode
function setEraserMode(value: string) { function setEraserMode(value: string) {
mapEditorStore.setTool('eraser') mapEditor.setTool('eraser')
selectEraserOpen.value = false selectEraserOpen.value = false
} }
@ -130,7 +130,7 @@ function handleClick(tool: string) {
function cycleToolMode(tool: 'pencil' | 'eraser') { function cycleToolMode(tool: 'pencil' | 'eraser') {
const modes = ['tile', 'object', 'teleport', 'blocking tile'] const modes = ['tile', 'object', 'teleport', 'blocking tile']
const currentIndex = modes.indexOf(mapEditorStore.drawMode) const currentIndex = modes.indexOf(mapEditor.drawMode.value)
const nextIndex = (currentIndex + 1) % modes.length const nextIndex = (currentIndex + 1) % modes.length
const nextMode = modes[nextIndex] const nextMode = modes[nextIndex]

View File

@ -4,7 +4,7 @@
<Scene name="main" @preload="preloadScene"> <Scene name="main" @preload="preloadScene">
<div v-if="!isLoaded" class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 text-white text-3xl font-ui">Loading...</div> <div v-if="!isLoaded" class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 text-white text-3xl font-ui">Loading...</div>
<div v-else> <div v-else>
<Map :key="currentMap?.id" /> <Map :key="mapEditor.currentMap.value?.id" />
<Toolbar ref="toolbar" @save="save" @clear="clear" @open-maps="mapModal?.open()" @open-settings="mapSettingsModal?.open()" <Toolbar ref="toolbar" @save="save" @clear="clear" @open-maps="mapModal?.open()" @open-settings="mapSettingsModal?.open()"
@close-editor="$emit('close-editor')" @close-editor="$emit('close-editor')"
@open-tile-list="tileModal?.open()" @open-tile-list="tileModal?.open()"
@ -36,13 +36,11 @@ import { useMapEditorComposable } from '@/composables/useMapEditorComposable'
import { MapStorage } from '@/storage/storages' import { MapStorage } from '@/storage/storages'
import { useGameStore } from '@/stores/gameStore' import { useGameStore } from '@/stores/gameStore'
import { Game, Scene } from 'phavuer' import { Game, Scene } from 'phavuer'
import { provide, ref, useTemplateRef, watch } from 'vue' import { ref, useTemplateRef, watch } from 'vue'
const mapStorage = new MapStorage() const mapStorage = new MapStorage()
const mapEditor = useMapEditorComposable() const mapEditor = useMapEditorComposable()
const gameStore = useGameStore() const gameStore = useGameStore()
const mapEditorStore = useMapEditorStore()
const currentMap = ref<MapT | null>(null)
const toolbar = useTemplateRef("toolbar") const toolbar = useTemplateRef("toolbar")
const mapModal = useTemplateRef("mapModal") const mapModal = useTemplateRef("mapModal")
@ -88,18 +86,19 @@ const preloadScene = async (scene: Phaser.Scene) => {
} }
function save() { function save() {
if (!currentMap.value) return const currentMap = mapEditor.currentMap.value
if (!currentMap) return
const data = { const data = {
mapId: currentMap.value.id, mapId: currentMap.id,
name: currentMap.value.name, name: currentMap.name,
width: currentMap.value.width, width: currentMap.width,
height: currentMap.value.height, height: currentMap.height,
tiles: currentMap.value.tiles, tiles: currentMap.tiles,
pvp: currentMap.value.pvp, pvp: currentMap.pvp,
mapEffects: currentMap.value.mapEffects?.map(({ id, effect, strength }) => ({ id, effect, strength })) ?? [], mapEffects: currentMap.mapEffects?.map(({ id, effect, strength }) => ({ id, effect, strength })) ?? [],
mapEventTiles: currentMap.value.mapEventTiles?.map(({ id, type, positionX, positionY, teleport }) => ({ id, type, positionX, positionY, teleport })) ?? [], mapEventTiles: currentMap.mapEventTiles?.map(({ id, type, positionX, positionY, teleport }) => ({ id, type, positionX, positionY, teleport })) ?? [],
placedMapObjects: currentMap.value.placedMapObjects?.map(({ id, mapObject, depth, isRotated, positionX, positionY }) => ({ id, mapObject, depth, isRotated, positionX, positionY })) ?? [] placedMapObjects: currentMap.placedMapObjects?.map(({ id, mapObject, depth, isRotated, positionX, positionY }) => ({ id, mapObject, depth, isRotated, positionX, positionY })) ?? []
} }
gameStore.connection?.emit('gm:map:update', data, (response: MapT) => { gameStore.connection?.emit('gm:map:update', data, (response: MapT) => {
@ -107,13 +106,10 @@ function save() {
}) })
} }
watch(() => mapEditor.currentMap, (value) => { currentMap.value = value.value })
function clear() { function clear() {
if (!currentMap.value) return if (!mapEditor.currentMap.value) return
// Clear placed objects, event tiles and tiles // Clear placed objects, event tiles and tiles
mapEditor.clearMap() mapEditor.clearMap()
mapEditor.triggerClearTiles()
} }
</script> </script>

View File

@ -28,7 +28,7 @@ export function useMapEditorPointerHandlers(scene: Phaser.Scene, layer: Phaser.T
} }
function handlePointerDown(pointer: Phaser.Input.Pointer) { function handlePointerDown(pointer: Phaser.Input.Pointer) {
pointerStartPosition.value = pointer.position pointerStartPosition.value = { x: pointer.x, y: pointer.y }
if (isMoveTool.value || pointer.event.shiftKey) { if (isMoveTool.value || pointer.event.shiftKey) {
gameStore.setPlayerDraggingCamera(true) gameStore.setPlayerDraggingCamera(true)
} }
@ -37,9 +37,11 @@ export function useMapEditorPointerHandlers(scene: Phaser.Scene, layer: Phaser.T
function dragMap(pointer: Phaser.Input.Pointer) { function dragMap(pointer: Phaser.Input.Pointer) {
if (!gameStore.game.isPlayerDraggingCamera) return if (!gameStore.game.isPlayerDraggingCamera) return
const distance = Phaser.Math.Distance.Between(pointerStartPosition.value.x, pointerStartPosition.value.y, pointer.x, pointer.y)
// If the distance is less than the drag threshold, return // If the distance is less than the drag threshold, return
// We do this to prevent the camera from scrolling too quickly // We do this to prevent the camera from scrolling too quickly
const distance = Phaser.Math.Distance.Between(pointerStartPosition.value.x, pointerStartPosition.value.y, pointer.x, pointer.y)
if (distance <= dragThreshold) return if (distance <= dragThreshold) return
camera.setScroll(camera.scrollX - (pointer.x - pointer.prevPosition.x) / camera.zoom, camera.scrollY - (pointer.y - pointer.prevPosition.y) / camera.zoom) camera.setScroll(camera.scrollX - (pointer.x - pointer.prevPosition.x) / camera.zoom, camera.scrollY - (pointer.y - pointer.prevPosition.y) / camera.zoom)

View File

@ -12,14 +12,8 @@ const currentMap = ref<Map | null>(null)
const active = ref(false) const active = ref(false)
const tool = ref('move') const tool = ref('move')
const drawMode = ref('tile') const drawMode = ref('tile')
const eraserMode = ref('tile')
const selectedTile = ref('') const selectedTile = ref('')
const selectedMapObject = ref<MapObject | null>(null) const selectedMapObject = ref<MapObject | null>(null)
const isTileListModalShown = ref(false)
const isMapObjectListModalShown = ref(false)
const isMapListModalShown = ref(false)
const isCreateMapModalShown = ref(false)
const isSettingsModalShown = ref(false)
const shouldClearTiles = ref(false) const shouldClearTiles = ref(false)
const teleportSettings = ref<TeleportSettings>({ const teleportSettings = ref<TeleportSettings>({
toMapId: '', toMapId: '',
@ -59,10 +53,6 @@ export function useMapEditorComposable() {
drawMode.value = mode drawMode.value = mode
} }
const setEraserMode = (mode: string) => {
eraserMode.value = mode
}
const setSelectedTile = (tile: string) => { const setSelectedTile = (tile: string) => {
selectedTile.value = tile selectedTile.value = tile
} }
@ -71,19 +61,6 @@ export function useMapEditorComposable() {
selectedMapObject.value = object selectedMapObject.value = object
} }
const toggleSettingsModal = () => {
isSettingsModalShown.value = !isSettingsModalShown.value
}
const toggleMapListModal = () => {
isMapListModalShown.value = !isMapListModalShown.value
isCreateMapModalShown.value = false
}
const toggleCreateMapModal = () => {
isCreateMapModalShown.value = !isCreateMapModalShown.value
}
const setTeleportSettings = (settings: TeleportSettings) => { const setTeleportSettings = (settings: TeleportSettings) => {
teleportSettings.value = settings teleportSettings.value = settings
} }
@ -101,11 +78,6 @@ export function useMapEditorComposable() {
drawMode.value = 'tile' drawMode.value = 'tile'
selectedTile.value = '' selectedTile.value = ''
selectedMapObject.value = null selectedMapObject.value = null
isTileListModalShown.value = false
isMapObjectListModalShown.value = false
isSettingsModalShown.value = false
isMapListModalShown.value = false
isCreateMapModalShown.value = false
shouldClearTiles.value = false shouldClearTiles.value = false
} }
@ -115,14 +87,8 @@ export function useMapEditorComposable() {
active, active,
tool, tool,
drawMode, drawMode,
eraserMode,
selectedTile, selectedTile,
selectedMapObject, selectedMapObject,
isTileListModalShown,
isMapObjectListModalShown,
isMapListModalShown,
isCreateMapModalShown,
isSettingsModalShown,
shouldClearTiles, shouldClearTiles,
teleportSettings, teleportSettings,
@ -133,12 +99,8 @@ export function useMapEditorComposable() {
toggleActive, toggleActive,
setTool, setTool,
setDrawMode, setDrawMode,
setEraserMode,
setSelectedTile, setSelectedTile,
setSelectedMapObject, setSelectedMapObject,
toggleSettingsModal,
toggleMapListModal,
toggleCreateMapModal,
setTeleportSettings, setTeleportSettings,
triggerClearTiles, triggerClearTiles,
resetClearTilesFlag, resetClearTilesFlag,