Changes to mapeditorcomposable, fix pencil and fill tool for tiles

Locked in, made mapeditor my bi-
This commit is contained in:
Colin Kallemein 2025-01-26 23:28:15 +01:00
parent cfac1d508b
commit 14aa696197
15 changed files with 206 additions and 101 deletions

View File

@ -17,24 +17,24 @@ import BackgroundImageLoader from '@/components/utilities/BackgroundImageLoader.
import Debug from '@/components/utilities/Debug.vue'
import Notifications from '@/components/utilities/Notifications.vue'
import { useGameStore } from '@/stores/gameStore'
import { useMapEditorStore } from '@/stores/mapEditorStore'
import { useMapEditorComposable } from '@/composables/useMapEditorComposable'
import { computed, watch } from 'vue'
const gameStore = useGameStore()
const mapEditorStore = useMapEditorStore()
const mapEditor = useMapEditorComposable()
const currentScreen = computed(() => {
if (!gameStore.game.isLoaded) return Loading
if (!gameStore.connection) return Login
if (!gameStore.token) return Login
if (!gameStore.character) return Characters
if (mapEditorStore.active) return MapEditor
if (mapEditor.active.value) return MapEditor
return Game
})
// Watch mapEditorStore.active and empty gameStore.game.loadedAssets
// Watch mapEditor.active and empty gameStore.game.loadedAssets
watch(
() => mapEditorStore.active,
() => mapEditor.active.value,
() => {
gameStore.game.loadedTextures = []
}

View File

@ -6,7 +6,7 @@
<button @mousedown.stop class="btn-cyan py-1.5 px-4 min-w-24">Users</button>
<button @mousedown.stop class="btn-cyan py-1.5 px-4 min-w-24">Chats</button>
<button @mousedown.stop class="btn-cyan active py-1.5 px-4 min-w-24">Asset manager</button>
<button class="btn-cyan py-1.5 px-4 min-w-24" type="button" @click="() => mapEditorStore.toggleActive()">Map editor</button>
<button class="btn-cyan py-1.5 px-4 min-w-24" type="button" @click="() => mapEditor.toggleActive()">Map editor</button>
</div>
</template>
<template #modalBody>
@ -21,11 +21,11 @@
import AssetManager from '@/components/gameMaster/assetManager/AssetManager.vue'
import Modal from '@/components/utilities/Modal.vue'
import { useGameStore } from '@/stores/gameStore'
import { useMapEditorStore } from '@/stores/mapEditorStore'
import { useMapEditorComposable } from '@/composables/useMapEditorComposable'
import { ref } from 'vue'
const gameStore = useGameStore()
const mapEditorStore = useMapEditorStore()
const mapEditor = useMapEditorComposable()
let toggle = ref('asset-manager')
</script>

View File

@ -29,7 +29,6 @@ import ChipsInput from '@/components/forms/ChipsInput.vue'
import { TileStorage } from '@/storage/storages'
import { useAssetManagerStore } from '@/stores/assetManagerStore'
import { useGameStore } from '@/stores/gameStore'
import { useMapEditorStore } from '@/stores/mapEditorStore'
import { computed, onBeforeUnmount, onMounted, ref, toRaw, watch } from 'vue'
const gameStore = useGameStore()

View File

@ -8,13 +8,13 @@
import MapEventTiles from '@/components/gameMaster/mapEditor/mapPartials/MapEventTiles.vue'
import MapTiles from '@/components/gameMaster/mapEditor/mapPartials/MapTiles.vue'
import PlacedMapObjects from '@/components/gameMaster/mapEditor/mapPartials/PlacedMapObjects.vue'
import { useMapEditorStore } from '@/stores/mapEditorStore'
import { useMapEditorComposable } from '@/composables/useMapEditorComposable'
import { onMounted, onUnmounted, shallowRef } from 'vue'
const mapEditorStore = useMapEditorStore()
const mapEditor = useMapEditorComposable()
const tileMap = shallowRef<Phaser.Tilemaps.Tilemap>()
onUnmounted(() => {
mapEditorStore.reset()
mapEditor.reset()
})
</script>

View File

@ -8,7 +8,6 @@ import Controls from '@/components/utilities/Controls.vue'
import { createTileArray, getTile, placeTile, setLayerTiles } from '@/composables/mapComposable'
import { useMapEditorComposable } from '@/composables/useMapEditorComposable'
import { TileStorage } from '@/storage/storages'
import { useMapEditorStore } from '@/stores/mapEditorStore'
import { useScene } from 'phavuer'
import { onMounted, onUnmounted, shallowRef, watch } from 'vue'
@ -18,7 +17,6 @@ const emit = defineEmits(['tileMap:create'])
const scene = useScene()
const mapEditor = useMapEditorComposable()
const mapEditorStore = useMapEditorStore()
const tileStorage = new TileStorage()
const tileMap = shallowRef<Phaser.Tilemaps.Tilemap>()
@ -62,15 +60,16 @@ function pencil(pointer: Phaser.Input.Pointer) {
// Check if map is set
if (!mapEditor.currentMap.value) return
console.log(mapEditor.tool.value)
// Check if tool is pencil
if (mapEditorStore.tool !== 'pencil') return
if (mapEditor.tool.value !== 'pencil') return
// Check if draw mode is tile
if (mapEditorStore.drawMode !== 'tile') return
if (mapEditor.drawMode.value !== 'tile') return
// Check if there is a selected tile
if (!mapEditorStore.selectedTile) return
if (!mapEditor.selectedTile.value) return // Changed this line to access .value
// Check if left mouse button is pressed
if (!pointer.isDown) return
@ -83,10 +82,10 @@ function pencil(pointer: Phaser.Input.Pointer) {
if (!tile) return
// Place tile
placeTile(tileMap.value, tileLayer.value, tile.x, tile.y, mapEditorStore.selectedTile)
placeTile(tileMap.value, tileLayer.value, tile.x, tile.y, mapEditor.selectedTile.value)
// Adjust mapEditorStore.map.tiles
mapEditor.currentMap.value.tiles[tile.y][tile.x] = mapEditor.currentMap.value.tiles[tile.y][tile.x]
// Adjust mapEditor tiles
mapEditor.currentMap.value.tiles[tile.y][tile.x] = mapEditor.selectedTile.value
}
function eraser(pointer: Phaser.Input.Pointer) {
@ -96,10 +95,10 @@ function eraser(pointer: Phaser.Input.Pointer) {
if (!mapEditor.currentMap.value) return
// Check if tool is pencil
if (mapEditorStore.tool !== 'eraser') return
if (mapEditor.tool.value !== 'eraser') return
// Check if draw mode is tile
if (mapEditorStore.eraserMode !== 'tile') return
if (mapEditor.eraserMode.value !== 'tile') return
// Check if left mouse button is pressed
if (!pointer.isDown) return
@ -117,7 +116,7 @@ function eraser(pointer: Phaser.Input.Pointer) {
// Place tile
placeTile(tileMap.value, tileLayer.value, tile.x, tile.y, 'blank_tile')
// Adjust mapEditorStore.map.tiles
// Adjust mapEditor.map.tiles
mapEditor.currentMap.value.tiles[tile.y][tile.x] = 'blank_tile'
}
@ -128,10 +127,10 @@ function paint(pointer: Phaser.Input.Pointer) {
if (!mapEditor.currentMap.value) return
// Check if tool is pencil
if (mapEditorStore.tool !== 'paint') return
if (mapEditor.tool.value !== 'paint') return
// Check if there is a selected tile
if (!mapEditorStore.selectedTile) return
if (!mapEditor.selectedTile.value) return
// Check if left mouse button is pressed
if (!pointer.isDown) return
@ -143,10 +142,10 @@ function paint(pointer: Phaser.Input.Pointer) {
if (pointer.event.altKey) return
// Set new tileArray with selected tile
setLayerTiles(tileMap.value, tileLayer.value, createTileArray(tileMap.value.width, tileMap.value.height, mapEditorStore.selectedTile))
setLayerTiles(tileMap.value, tileLayer.value, createTileArray(tileMap.value.width, tileMap.value.height, mapEditor.selectedTile.value))
// Adjust mapEditorStore.map.tiles
mapEditor.currentMap.value.tiles = createTileArray(tileMap.value.width, tileMap.value.height, mapEditor.currentMap.value.tiles)
// Adjust mapEditor.map.tiles
mapEditor.currentMap.value.tiles = createTileArray(tileMap.value.width, tileMap.value.height, mapEditor.selectedTile.value)
}
// When alt is pressed, and the pointer is down, select the tile that the pointer is over
@ -157,10 +156,10 @@ function tilePicker(pointer: Phaser.Input.Pointer) {
if (!mapEditor.currentMap.value) return
// Check if tool is pencil
if (mapEditorStore.tool !== 'pencil') return
if (mapEditor.tool.value !== 'pencil') return
// Check if draw mode is tile
if (mapEditorStore.drawMode !== 'tile') return
if (mapEditor.drawMode.value !== 'tile') return
// Check if left mouse button is pressed
if (!pointer.isDown) return
@ -176,17 +175,17 @@ function tilePicker(pointer: Phaser.Input.Pointer) {
if (!tile) return
// Select the tile
mapEditorStore.setSelectedMapObject(mapEditor.currentMap.value.tiles[tile.y][tile.x])
mapEditor.setSelectedTile(mapEditor.currentMap.value.tiles[tile.y][tile.x])
}
watch(
() => mapEditorStore.shouldClearTiles,
() => mapEditor.shouldClearTiles.value,
(shouldClear) => {
if (shouldClear && mapEditor.currentMap.value && tileMap.value && tileLayer.value) {
const blankTiles = createTileArray(tileMap.value.width, tileMap.value.height, 'blank_tile')
setLayerTiles(tileMap.value, tileLayer.value, blankTiles)
mapEditor.currentMap.value.tiles = blankTiles
mapEditorStore.resetClearTilesFlag()
mapEditor.resetClearTilesFlag()
}
}
)

View File

@ -1,5 +1,5 @@
<template>
<Modal :isModalOpen="mapEditorStore.isCreateMapModalShown" @modal:close="() => mapEditorStore.toggleCreateMapModal()" :modal-width="300" :modal-height="420" :is-resizable="false" :bg-style="'none'">
<Modal :isModalOpen="mapEditor.isCreateMapModalShown.value" @modal:close="() => mapEditor.toggleCreateMapModal()" :modal-width="300" :modal-height="420" :is-resizable="false" :bg-style="'none'">
<template #modalHeader>
<h3 class="m-0 font-medium shrink-0 text-white">Create new map</h3>
</template>
@ -39,13 +39,13 @@ import type { Map } from '@/application/types'
import Modal from '@/components/utilities/Modal.vue'
import { MapStorage } from '@/storage/storages'
import { useGameStore } from '@/stores/gameStore'
import { useMapEditorStore } from '@/stores/mapEditorStore'
import { useMapEditorComposable } from '@/composables/useMapEditorComposable'
import { ref } from 'vue'
const emit = defineEmits(['create'])
const gameStore = useGameStore()
const mapEditorStore = useMapEditorStore()
const mapEditor = useMapEditorComposable()
const mapStorage = new MapStorage()
const name = ref('')
@ -79,6 +79,6 @@ async function submit() {
})
// Close modal
mapEditorStore.toggleCreateMapModal()
mapEditor.toggleCreateMapModal()
}
</script>

View File

@ -1,5 +1,5 @@
<template>
<Modal :is-modal-open="mapEditorStore.isMapListModalShown" @modal:close="() => mapEditorStore.toggleMapListModal()" :is-resizable="false" :modal-width="300" :modal-height="360" :bg-style="'none'">
<Modal :is-modal-open="mapEditor.isMapListModalShown.value" @modal:close="() => mapEditor.toggleMapListModal()" :is-resizable="false" :modal-width="300" :modal-height="360" :bg-style="'none'">
<template #modalHeader>
<h3 class="text-lg text-white">Maps</h3>
</template>
@ -7,7 +7,7 @@
<div class="my-4 mx-auto h-full">
<div class="text-center mb-4 px-2 flex gap-2.5">
<button class="btn-cyan py-1.5 min-w-[calc(50%_-_5px)]" @click="fetchMaps">Refresh</button>
<button class="btn-cyan py-1.5 min-w-[calc(50%_-_5px)]" @click="() => mapEditorStore.toggleCreateMapModal()">New</button>
<button class="btn-cyan py-1.5 min-w-[calc(50%_-_5px)]" @click="() => mapEditor.toggleCreateMapModal()">New</button>
</div>
<div class="overflow-y-auto h-[calc(100%-20px)]">
<div class="relative p-2.5 cursor-pointer flex gap-y-2.5 gap-x-5 flex-wrap" v-for="(map, index) in mapList" :key="map.id">
@ -25,7 +25,7 @@
</template>
</Modal>
<CreateMap @create="fetchMaps" v-if="mapEditorStore.isMapListModalShown" />
<CreateMap @create="fetchMaps" v-if="mapEditor.isMapListModalShown.value" />
</template>
<script setup lang="ts">
@ -35,11 +35,9 @@ import Modal from '@/components/utilities/Modal.vue'
import { useMapEditorComposable } from '@/composables/useMapEditorComposable'
import { MapStorage } from '@/storage/storages'
import { useGameStore } from '@/stores/gameStore'
import { useMapEditorStore } from '@/stores/mapEditorStore'
import { onMounted, ref } from 'vue'
const gameStore = useGameStore()
const mapEditorStore = useMapEditorStore()
const mapEditor = useMapEditorComposable()
const mapStorage = new MapStorage()
@ -57,7 +55,7 @@ function loadMap(id: UUID) {
gameStore.connection?.emit('gm:map:request', { mapId: id }, (response: Map) => {
mapEditor.loadMap(response)
})
mapEditorStore.toggleMapListModal()
mapEditor.toggleMapListModal()
}
async function deleteMap(id: UUID) {

View File

@ -1,5 +1,5 @@
<template>
<Modal :isModalOpen="mapEditorStore.isMapObjectListModalShown" :modal-width="645" :modal-height="260" @modal:close="() => (mapEditorStore.isMapObjectListModalShown = false)" :bg-style="'none'">
<Modal :isModalOpen="mapEditor.isMapObjectListModalShown.value" :modal-width="645" :modal-height="260" @modal:close="() => (mapEditor.isMapObjectListModalShown.value = false)" :bg-style="'none'">
<template #modalHeader>
<h3 class="text-lg text-white">Map objects</h3>
</template>
@ -25,11 +25,11 @@
class="border-2 border-solid max-w-full"
:src="`${config.server_endpoint}/textures/map_objects/${mapObject.id}.png`"
alt="Object"
@click="mapEditorStore.setSelectedMapObject(mapObject)"
@click="mapEditor.setSelectedMapObject(mapObject)"
:class="{
'cursor-pointer transition-all duration-300': true,
'border-cyan shadow-lg scale-105': mapEditorStore.selectedMapObject?.id === mapObject.id,
'border-transparent hover:border-gray-300': mapEditorStore.selectedMapObject?.id !== mapObject.id
'border-cyan shadow-lg scale-105': mapEditor.selectedMapObject.value?.id === mapObject.id,
'border-transparent hover:border-gray-300': mapEditor.selectedMapObject.value?.id !== mapObject.id
}"
/>
</div>
@ -45,14 +45,13 @@ import config from '@/application/config'
import type { MapObject } from '@/application/types'
import Modal from '@/components/utilities/Modal.vue'
import { MapObjectStorage } from '@/storage/storages'
import { useGameStore } from '@/stores/gameStore'
import { useMapEditorStore } from '@/stores/mapEditorStore'
import { useMapEditorComposable } from '@/composables/useMapEditorComposable'
import { liveQuery } from 'dexie'
import { computed, onMounted, onUnmounted, ref } from 'vue'
const mapObjectStorage = new MapObjectStorage()
const isModalOpen = ref(false)
const mapEditorStore = useMapEditorStore()
const mapEditor = useMapEditorComposable()
const searchQuery = ref('')
const selectedTags = ref<string[]>([])
const mapObjectList = ref<MapObject[]>([])

View File

@ -1,5 +1,5 @@
<template>
<Modal :is-modal-open="mapEditorStore.isSettingsModalShown" @modal:close="() => mapEditorStore.toggleSettingsModal()" :modal-width="600" :modal-height="430" :bg-style="'none'">
<Modal :is-modal-open="mapEditor.isSettingsModalShown.value" @modal:close="() => mapEditor.toggleSettingsModal()" :modal-width="600" :modal-height="430" :bg-style="'none'">
<template #modalHeader>
<h3 class="m-0 font-medium shrink-0 text-white">Map settings</h3>
</template>
@ -51,11 +51,9 @@ import type { UUID } from '@/application/types'
import { uuidv4 } from '@/application/utilities'
import Modal from '@/components/utilities/Modal.vue'
import { useMapEditorComposable } from '@/composables/useMapEditorComposable'
import { useMapEditorStore } from '@/stores/mapEditorStore'
import { ref, watch } from 'vue'
const mapEditor = useMapEditorComposable()
const mapEditorStore = useMapEditorStore()
const screen = ref('settings')
const name = ref(mapEditor.currentMap.value?.name)

View File

@ -1,5 +1,5 @@
<template>
<Modal :isModalOpen="mapEditorStore.isTileListModalShown" :modal-width="645" :modal-height="600" @modal:close="() => (mapEditorStore.isTileListModalShown = false)" :bg-style="'none'">
<Modal :isModalOpen="mapEditor.isTileListModalShown.value" :modal-width="645" :modal-height="600" @modal:close="() => (mapEditor.isTileListModalShown.value = false)" :bg-style="'none'">
<template #modalHeader>
<h3 class="text-lg text-white">Tiles</h3>
</template>
@ -85,12 +85,12 @@ import config from '@/application/config'
import type { Tile } from '@/application/types'
import Modal from '@/components/utilities/Modal.vue'
import { TileStorage } from '@/storage/storages'
import { useMapEditorStore } from '@/stores/mapEditorStore'
import { useMapEditorComposable } from '@/composables/useMapEditorComposable'
import { liveQuery } from 'dexie'
import { computed, onMounted, onUnmounted, ref } from 'vue'
const tileStorage = new TileStorage()
const mapEditorStore = useMapEditorStore()
const mapEditor = useMapEditorComposable()
const searchQuery = ref('')
const selectedTags = ref<string[]>([])
const tileCategories = ref<Map<string, string>>(new Map())
@ -222,11 +222,11 @@ function closeGroup() {
}
function selectTile(tile: string) {
mapEditorStore.setSelectedTile(tile)
mapEditor.setSelectedTile(tile)
}
function isActiveTile(tile: Tile): boolean {
return mapEditorStore.selectedTile === tile.id
return mapEditor.selectedTile.value === tile.id
}
let subscription: any = null

View File

@ -2,20 +2,20 @@
<div class="flex justify-center p-5">
<div class="toolbar fixed bottom-0 left-0 m-3 rounded flex bg-gray solid border-solid border-2 border-gray-500 text-gray-300 p-1.5 px-3 h-10">
<div ref="toolbar" class="tools flex gap-2.5" v-if="mapEditor.currentMap.value">
<button class="flex justify-center items-center min-w-10 p-0 relative" :class="{ 'border-0 border-b-[3px] border-solid border-cyan gap-2.5': mapEditorStore.tool === 'move' }" @click="handleClick('move')">
<img class="invert w-5 h-5" src="/assets/icons/mapEditor/move.svg" alt="Move camera" /> <span class="h-5" :class="{ 'ml-2.5': mapEditorStore.tool !== 'move' }">(M)</span>
<button class="flex justify-center items-center min-w-10 p-0 relative" :class="{ 'border-0 border-b-[3px] border-solid border-cyan gap-2.5': mapEditor.tool.value === 'move' }" @click="handleClick('move')">
<img class="invert w-5 h-5" src="/assets/icons/mapEditor/move.svg" alt="Move camera" /> <span class="h-5" :class="{ 'ml-2.5': mapEditor.tool.value !== 'move' }">(M)</span>
</button>
<div class="w-px bg-cyan"></div>
<button class="flex justify-center items-center min-w-10 p-0 relative" :class="{ 'border-0 border-b-[3px] border-solid border-cyan gap-2.5': mapEditorStore.tool === 'pencil' }" @click="handleClick('pencil')">
<img class="invert w-5 h-5" src="/assets/icons/mapEditor/pencil.svg" alt="Pencil" /> <span class="h-5" :class="{ 'ml-2.5': mapEditorStore.tool !== 'pencil' }">(P)</span>
<div class="select" v-if="mapEditorStore.tool === 'pencil'">
<button class="flex justify-center items-center min-w-10 p-0 relative" :class="{ 'border-0 border-b-[3px] border-solid border-cyan gap-2.5': mapEditor.tool.value === 'pencil' }" @click="handleClick('pencil')">
<img class="invert w-5 h-5" src="/assets/icons/mapEditor/pencil.svg" alt="Pencil" /> <span class="h-5" :class="{ 'ml-2.5': mapEditor.tool.value !== 'pencil' }">(P)</span>
<div class="select" v-if="mapEditor.tool.value === 'pencil'">
<div class="select-trigger group capitalize flex gap-3.5" :class="{ open: selectPencilOpen }">
{{ mapEditorStore.drawMode.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" alt="" />
</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="selectPencilOpen && mapEditorStore.tool === 'pencil'">
<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="selectPencilOpen && mapEditor.tool.value === 'pencil'">
<span class="py-2 px-2.5 relative hover:bg-cyan hover:text-white" @click="setDrawMode('tile')">
Tile
<div class="absolute w-4/5 left-1/2 -translate-x-1/2 bottom-0 h-px bg-cyan"></div>
@ -35,11 +35,11 @@
<div class="w-px bg-cyan"></div>
<button class="flex justify-center items-center min-w-10 p-0 relative" :class="{ 'border-0 border-b-[3px] border-solid border-cyan gap-2.5': mapEditorStore.tool === 'eraser' }" @click="handleClick('eraser')">
<img class="invert w-5 h-5" src="/assets/icons/mapEditor/eraser.svg" alt="Eraser" /> <span class="h-5" :class="{ 'ml-2.5': mapEditorStore.tool !== 'eraser' }">(E)</span>
<div class="select" v-if="mapEditorStore.tool === 'eraser'">
<button class="flex justify-center items-center min-w-10 p-0 relative" :class="{ 'border-0 border-b-[3px] border-solid border-cyan gap-2.5': mapEditor.tool.value === 'eraser' }" @click="handleClick('eraser')">
<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-trigger group capitalize flex gap-3.5" :class="{ open: selectEraserOpen }">
{{ mapEditorStore.eraserMode.replace('_', ' ') }}
{{ mapEditor.eraserMode.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" />
</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">
@ -62,8 +62,8 @@
<div class="w-px bg-cyan"></div>
<button class="flex justify-center items-center min-w-10 p-0 relative" :class="{ 'border-0 border-b-[3px] border-solid border-cyan gap-2.5': mapEditorStore.tool === 'paint' }" @click="handleClick('paint')">
<img class="invert w-5 h-5" src="/assets/icons/mapEditor/paint.svg" alt="Paint bucket" /> <span class="h-5" :class="{ 'ml-2.5': mapEditorStore.tool !== 'paint' }">(B)</span>
<button class="flex justify-center items-center min-w-10 p-0 relative" :class="{ 'border-0 border-b-[3px] border-solid border-cyan gap-2.5': mapEditor.tool.value === 'paint' }" @click="handleClick('paint')">
<img class="invert w-5 h-5" src="/assets/icons/mapEditor/paint.svg" alt="Paint bucket" /> <span class="h-5" :class="{ 'ml-2.5': mapEditor.tool.value !== 'paint' }">(B)</span>
</button>
<div class="w-px bg-cyan"></div>
@ -72,10 +72,10 @@
</div>
<div class="toolbar fixed bottom-0 right-0 m-3 rounded flex bg-gray solid border-solid border-2 border-gray-500 text-gray-300 p-1.5 px-3 h-10 space-x-2">
<button class="btn-cyan px-3.5" @click="() => mapEditorStore.toggleMapListModal()">Load</button>
<button class="btn-cyan px-3.5" @click="() => mapEditor.toggleMapListModal()">Load</button>
<button class="btn-cyan px-3.5" @click="() => emit('save')" v-if="mapEditor.currentMap.value">Save</button>
<button class="btn-cyan px-3.5" @click="() => emit('clear')" v-if="mapEditor.currentMap.value">Clear</button>
<button class="btn-cyan px-3.5" @click="() => mapEditorStore.toggleActive()">Exit</button>
<button class="btn-cyan px-3.5" @click="() => mapEditor.toggleActive()">Exit</button>
</div>
</div>
</div>
@ -83,12 +83,10 @@
<script setup lang="ts">
import { useMapEditorComposable } from '@/composables/useMapEditorComposable'
import { useMapEditorStore } from '@/stores/mapEditorStore'
import { onClickOutside } from '@vueuse/core'
import { onBeforeUnmount, onMounted, ref } from 'vue'
const mapEditor = useMapEditorComposable()
const mapEditorStore = useMapEditorStore()
const emit = defineEmits(['save', 'clear'])
@ -101,24 +99,24 @@ let selectEraserOpen = ref(false)
// drawMode
function setDrawMode(value: string) {
mapEditorStore.isTileListModalShown = value === 'tile'
mapEditorStore.isMapObjectListModalShown = value === 'map_object'
mapEditor.isTileListModalShown.value = value === 'tile'
mapEditor.isMapObjectListModalShown.value = value === 'map_object'
mapEditorStore.setDrawMode(value)
mapEditor.setDrawMode(value)
selectPencilOpen.value = false
}
// drawMode
function setEraserMode(value: string) {
mapEditorStore.setEraserMode(value)
mapEditor.setEraserMode(value)
selectEraserOpen.value = false
}
function handleClick(tool: string) {
if (tool === 'settings') {
mapEditorStore.toggleSettingsModal()
mapEditor.toggleSettingsModal()
} else {
mapEditorStore.setTool(tool)
mapEditor.setTool(tool)
}
selectPencilOpen.value = tool === 'pencil' ? !selectPencilOpen.value : false
@ -127,8 +125,8 @@ function handleClick(tool: string) {
function cycleToolMode(tool: 'pencil' | 'eraser') {
const modes = ['tile', 'object', 'teleport', 'blocking tile']
const currentMode = tool === 'pencil' ? mapEditorStore.drawMode : mapEditorStore.eraserMode
const currentIndex = modes.indexOf(currentMode)
const currentMode = tool === 'pencil' ? mapEditor.drawMode : mapEditor.eraserMode
const currentIndex = modes.indexOf(currentMode.value)
const nextIndex = (currentIndex + 1) % modes.length
const nextMode = modes[nextIndex]
@ -141,7 +139,7 @@ function cycleToolMode(tool: 'pencil' | 'eraser') {
function initKeyShortcuts(event: KeyboardEvent) {
// Check if map is set
if (!mapEditorStore.map) return
if (!mapEditor.currentMap.value) return
// prevent if focused on composables
if (document.activeElement?.tagName === 'INPUT') return
@ -156,7 +154,7 @@ function initKeyShortcuts(event: KeyboardEvent) {
if (keyActions.hasOwnProperty(event.key)) {
const tool = keyActions[event.key]
if ((tool === 'pencil' || tool === 'eraser') && mapEditorStore.tool === tool) {
if ((tool === 'pencil' || tool === 'eraser') && mapEditor.tool.value === tool) {
cycleToolMode(tool)
} else {
handleClick(tool)

View File

@ -32,14 +32,12 @@ import { loadAllTilesIntoScene } from '@/composables/mapComposable'
import { useMapEditorComposable } from '@/composables/useMapEditorComposable'
import { MapStorage } from '@/storage/storages'
import { useGameStore } from '@/stores/gameStore'
import { useMapEditorStore } from '@/stores/mapEditorStore'
import { Game, Scene } from 'phavuer'
import { ref } from 'vue'
const mapStorage = new MapStorage()
const mapEditor = useMapEditorComposable()
const gameStore = useGameStore()
const mapEditorStore = useMapEditorStore()
const isLoaded = ref(false)
@ -92,8 +90,8 @@ function save() {
placedMapObjects: mapEditor.currentMap.value.placedMapObjects?.map(({ id, mapObject, depth, isRotated, positionX, positionY }) => ({ id, mapObject, depth, isRotated, positionX, positionY })) ?? []
}
if (mapEditorStore.isSettingsModalShown) {
mapEditorStore.toggleSettingsModal()
if (mapEditor.isSettingsModalShown.value) {
mapEditor.toggleSettingsModal()
}
gameStore.connection?.emit('gm:map:update', data, (response: MapT) => {
@ -106,6 +104,6 @@ function clear() {
// Clear placed objects, event tiles and tiles
mapEditor.clearMap()
mapEditorStore.triggerClearTiles()
mapEditor.triggerClearTiles()
}
</script>

View File

@ -1,13 +1,13 @@
import config from '@/application/config'
import { getTile, tileToWorldXY } from '@/composables/mapComposable'
import { useGameStore } from '@/stores/gameStore'
import { useMapEditorStore } from '@/stores/mapEditorStore'
import { useMapEditorComposable } from '@/composables/useMapEditorComposable'
import { computed, ref, type Ref } from 'vue'
export function useMapEditorPointerHandlers(scene: Phaser.Scene, layer: Phaser.Tilemaps.TilemapLayer, waypoint: Ref<{ visible: boolean; x: number; y: number }>, camera: Phaser.Cameras.Scene2D.Camera) {
const gameStore = useGameStore()
const mapEditorStore = useMapEditorStore()
const isMoveTool = computed(() => mapEditorStore.tool === 'move')
const mapEditor = useMapEditorComposable()
const isMoveTool = computed(() => mapEditor.tool.value === 'move')
const pointerStartPosition = ref({ x: 0, y: 0 })
const dragThreshold = 5 // pixels

View File

@ -1,7 +1,32 @@
import type { Map } from '@/application/types'
import type { Map, MapObject } from '@/application/types'
import { ref } from 'vue'
export type TeleportSettings = {
toMapId: string
toPositionX: number
toPositionY: number
toRotation: number
}
const currentMap = ref<Map | null>(null)
const active = ref(false)
const tool = ref('move')
const drawMode = ref('tile')
const eraserMode = ref('tile')
const selectedTile = ref('')
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 teleportSettings = ref<TeleportSettings>({
toMapId: '',
toPositionX: 0,
toPositionY: 0,
toRotation: 0
})
export function useMapEditorComposable() {
const loadMap = (map: Map) => {
@ -16,16 +41,107 @@ export function useMapEditorComposable() {
const clearMap = () => {
if (!currentMap.value) return
currentMap.value.placedMapObjects = []
currentMap.value.mapEventTiles = []
currentMap.value.tiles = []
}
const toggleActive = () => {
if (active.value) reset()
active.value = !active.value
}
const setTool = (newTool: string) => {
tool.value = newTool
}
const setDrawMode = (mode: string) => {
drawMode.value = mode
}
const setEraserMode = (mode: string) => {
eraserMode.value = mode
}
const setSelectedTile = (tile: string) => {
selectedTile.value = tile
}
const setSelectedMapObject = (object: MapObject) => {
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) => {
teleportSettings.value = settings
}
const triggerClearTiles = () => {
shouldClearTiles.value = true
}
const resetClearTilesFlag = () => {
shouldClearTiles.value = false
}
const reset = () => {
tool.value = 'move'
drawMode.value = 'tile'
selectedTile.value = ''
selectedMapObject.value = null
isTileListModalShown.value = false
isMapObjectListModalShown.value = false
isSettingsModalShown.value = false
isMapListModalShown.value = false
isCreateMapModalShown.value = false
shouldClearTiles.value = false
}
return {
// State
currentMap,
active,
tool,
drawMode,
eraserMode,
selectedTile,
selectedMapObject,
isTileListModalShown,
isMapObjectListModalShown,
isMapListModalShown,
isCreateMapModalShown,
isSettingsModalShown,
shouldClearTiles,
teleportSettings,
// Methods
loadMap,
updateProperty,
clearMap
clearMap,
toggleActive,
setTool,
setDrawMode,
setEraserMode,
setSelectedTile,
setSelectedMapObject,
toggleSettingsModal,
toggleMapListModal,
toggleCreateMapModal,
setTeleportSettings,
triggerClearTiles,
resetClearTilesFlag,
reset
}
}
}

View File

@ -1,20 +1,20 @@
import { useMapEditorStore } from '@/stores/mapEditorStore'
import { computed, watch, type Ref } from 'vue'
import { useGamePointerHandlers } from './pointerHandlers/useGamePointerHandlers'
import { useMapEditorPointerHandlers } from './pointerHandlers/useMapEditorPointerHandlers'
import { useMapEditorComposable } from '@/composables/useMapEditorComposable'
export function usePointerHandlers(scene: Phaser.Scene, layer: Phaser.Tilemaps.TilemapLayer, waypoint: Ref<{ visible: boolean; x: number; y: number }>, camera: Phaser.Cameras.Scene2D.Camera) {
const mapEditorStore = useMapEditorStore()
const mapEditor = useMapEditorComposable()
const gameHandlers = useGamePointerHandlers(scene, layer, waypoint, camera)
const mapEditorHandlers = useMapEditorPointerHandlers(scene, layer, waypoint, camera)
const currentHandlers = computed(() => (mapEditorStore.active ? mapEditorHandlers : gameHandlers))
const currentHandlers = computed(() => (mapEditor.active.value ? mapEditorHandlers : gameHandlers))
const setupPointerHandlers = () => currentHandlers.value.setupPointerHandlers()
const cleanupPointerHandlers = () => currentHandlers.value.cleanupPointerHandlers()
watch(
() => mapEditorStore.active,
() => mapEditor.active.value,
() => {
cleanupPointerHandlers()
setupPointerHandlers()