forked from noxious/client
refactoring pointer events and input handling improvements
This commit is contained in:
parent
791830fd6f
commit
9618e07bc6
@ -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 = []
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
})
|
})
|
||||||
|
@ -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>
|
||||||
|
@ -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()
|
||||||
|
@ -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
|
||||||
})
|
})
|
||||||
|
@ -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')
|
||||||
|
|
||||||
|
@ -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')
|
||||||
|
@ -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]
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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)
|
||||||
|
@ -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,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user