1
0
forked from noxious/client

Map editor improvements

This commit is contained in:
Dennis Postma 2025-01-05 00:07:55 +01:00
parent ae0841889b
commit ef807982a5
10 changed files with 57 additions and 57 deletions

View File

@ -15,7 +15,7 @@ export type HttpResponse<T> = {
export type AssetDataT = { export type AssetDataT = {
key: string key: string
data: string data: string
group: 'tiles' | 'objects' | 'sprites' | 'sprite_animations' | 'sound' | 'music' | 'ui' | 'font' | 'other' group: 'tiles' | 'map_objects' | 'sprites' | 'sprite_animations' | 'sound' | 'music' | 'ui' | 'font' | 'other'
updatedAt: Date updatedAt: Date
originX?: number originX?: number
originY?: number originY?: number

View File

@ -1,5 +1,5 @@
<template> <template>
<MapObject v-for="mapObject in mapStore.map?.mapObjects" :tilemap="tilemap" :mapObject /> <MapObject v-for="mapObject in mapStore.map?.mapObjects" :tilemap="tilemap" :placedMapObject />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">

View File

@ -1,5 +1,5 @@
<template> <template>
<Image v-if="gameStore.getLoadedAsset(props.mapObject.object.id)" v-bind="imageProps" /> <Image v-if="gameStore.getLoadedAsset(props.placedMapObject.mapObject.id)" v-bind="imageProps" />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -12,29 +12,29 @@ import { computed } from 'vue'
const props = defineProps<{ const props = defineProps<{
tilemap: Phaser.Tilemaps.Tilemap tilemap: Phaser.Tilemaps.Tilemap
mapObject: PlacedMapObject placedMapObject: PlacedMapObject
}>() }>()
const gameStore = useGameStore() const gameStore = useGameStore()
const scene = useScene() const scene = useScene()
const imageProps = computed(() => ({ const imageProps = computed(() => ({
depth: calculateIsometricDepth(props.mapObject.positionX, props.mapObject.positionY, props.mapObject.object.frameWidth, props.mapObject.object.frameHeight), depth: calculateIsometricDepth(props.placedMapObject.positionX, props.placedMapObject.positionY, props.placedMapObject.mapObject.frameWidth, props.placedMapObject.mapObject.frameHeight),
x: tileToWorldX(props.tilemap, props.mapObject.positionX, props.mapObject.positionY), x: tileToWorldX(props.tilemap, props.placedMapObject.positionX, props.placedMapObject.positionY),
y: tileToWorldY(props.tilemap, props.mapObject.positionX, props.mapObject.positionY), y: tileToWorldY(props.tilemap, props.placedMapObject.positionX, props.placedMapObject.positionY),
flipX: props.mapObject.isRotated, flipX: props.placedMapObject.isRotated,
texture: props.mapObject.object.id, texture: props.placedMapObject.mapObject.id,
originY: Number(props.mapObject.object.originX), originY: Number(props.placedMapObject.mapObject.originX),
originX: Number(props.mapObject.object.originY) originX: Number(props.placedMapObject.mapObject.originY)
})) }))
loadTexture(scene, { loadTexture(scene, {
key: props.mapObject.object.id, key: props.placedMapObject.mapObject.id,
data: '/assets/objects/' + props.mapObject.object.id + '.png', data: '/assets/map_objects/' + props.placedMapObject.mapObject.id + '.png',
group: 'objects', group: 'map_objects',
updatedAt: props.mapObject.object.updatedAt, updatedAt: props.placedMapObject.mapObject.updatedAt,
frameWidth: props.mapObject.object.frameWidth, frameWidth: props.placedMapObject.mapObject.frameWidth,
frameHeight: props.mapObject.object.frameHeight frameHeight: props.placedMapObject.mapObject.frameHeight
} as AssetDataT).catch((error) => { } as AssetDataT).catch((error) => {
console.error('Error loading texture:', error) console.error('Error loading texture:', error)
}) })

View File

@ -98,11 +98,11 @@ function removeObject() {
}) })
} }
function refreshObjectList(unsetSelectedObject = true) { function refreshObjectList(unsetSelectedMapObject = true) {
gameStore.connection?.emit('gm:mapObject:list', {}, (response: MapObject[]) => { gameStore.connection?.emit('gm:mapObject:list', {}, (response: MapObject[]) => {
assetManagerStore.setMapObjectList(response) assetManagerStore.setMapObjectList(response)
if (unsetSelectedObject) { if (unsetSelectedMapObject) {
assetManagerStore.setSelectedMapObject(null) assetManagerStore.setSelectedMapObject(null)
} }

View File

@ -20,7 +20,7 @@ import MapObjects from '@/components/gameMaster/mapEditor/mapPartials/MapObjects
import MapTiles from '@/components/gameMaster/mapEditor/mapPartials/MapTiles.vue' import MapTiles from '@/components/gameMaster/mapEditor/mapPartials/MapTiles.vue'
import MapList from '@/components/gameMaster/mapEditor/partials/MapList.vue' import MapList from '@/components/gameMaster/mapEditor/partials/MapList.vue'
import MapSettings from '@/components/gameMaster/mapEditor/partials/MapSettings.vue' import MapSettings from '@/components/gameMaster/mapEditor/partials/MapSettings.vue'
import ObjectList from '@/components/gameMaster/mapEditor/partials/ObjectList.vue' import ObjectList from '@/components/gameMaster/mapEditor/partials/MapObjectList.vue'
import TeleportModal from '@/components/gameMaster/mapEditor/partials/TeleportModal.vue' import TeleportModal from '@/components/gameMaster/mapEditor/partials/TeleportModal.vue'
import TileList from '@/components/gameMaster/mapEditor/partials/TileList.vue' import TileList from '@/components/gameMaster/mapEditor/partials/TileList.vue'
// Components // Components

View File

@ -1,6 +1,6 @@
<template> <template>
<SelectedMapObject v-if="selectedMapObject" :mapObject="selectedMapObject" :movingMapObject="movingMapObject" @move="moveMapObject" @rotate="rotateMapObject" @delete="deleteMapObject" /> <SelectedMapObject v-if="selectedMapObject" :mapObject="selectedMapObject" :movingMapObject="movingMapObject" @move="moveMapObject" @rotate="rotateMapObject" @delete="deleteMapObject" />
<MapObject v-for="mapObject in mapEditorStore.map?.mapObjects" :tilemap="tilemap" :mapObject :selectedMapObject :movingMapObject @pointerup="clickMapObject(mapObject)" /> <MapObject v-for="mapObject in mapEditorStore.map?.placedMapObjects" :tilemap="tilemap" :mapObject :selectedMapObject :movingMapObject @pointerup="clickMapObject(mapObject)" />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -33,7 +33,7 @@ function pencil(pointer: Phaser.Input.Pointer) {
if (mapEditorStore.drawMode !== 'object') return if (mapEditorStore.drawMode !== 'object') return
// Check if there is a selected object // Check if there is a selected object
if (!mapEditorStore.selectedObject) return if (!mapEditorStore.selectedMapObject) return
// Check if left mouse button is pressed // Check if left mouse button is pressed
if (!pointer.isDown) return if (!pointer.isDown) return
@ -56,8 +56,8 @@ function pencil(pointer: Phaser.Input.Pointer) {
id: uuidv4(), id: uuidv4(),
mapId: mapEditorStore.map.id, mapId: mapEditorStore.map.id,
map: mapEditorStore.map, map: mapEditorStore.map,
objectId: mapEditorStore.selectedObject.id, objectId: mapEditorStore.selectedMapObject.id,
object: mapEditorStore.selectedObject, object: mapEditorStore.selectedMapObject,
depth: 0, depth: 0,
isRotated: false, isRotated: false,
positionX: tile.x, positionX: tile.x,
@ -123,11 +123,11 @@ function objectPicker(pointer: Phaser.Input.Pointer) {
if (!tile) return if (!tile) return
// Check if object already exists on position // Check if object already exists on position
const existingObject = mapEditorStore.map.placedMapObjects.find((object) => object.positionX === tile.x && object.positionY === tile.y) const existingMapObject = mapEditorStore.map.placedMapObjects.find((object) => object.positionX === tile.x && object.positionY === tile.y)
if (!existingObject) return if (!existingMapObject) return
// Select the object // Select the object
mapEditorStore.setSelectedObject(existingObject) mapEditorStore.setSelectedMapObject(existingMapObject)
} }
function moveMapObject(id: string) { function moveMapObject(id: string) {
@ -184,7 +184,7 @@ function clickMapObject(mapObject: MapObjectT) {
// 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.setSelectedObject(mapObject.object) mapEditorStore.setSelectedMapObject(mapObject.mapObject)
} }
} }
@ -204,20 +204,20 @@ onUnmounted(() => {
scene.input.off(Phaser.Input.Events.POINTER_DOWN, objectPicker) scene.input.off(Phaser.Input.Events.POINTER_DOWN, objectPicker)
}) })
// watch mapEditorStore.objectList and update originX and originY of objects in mapObjects // watch mapEditorStore.mapObjectList and update originX and originY of objects in mapObjects
watch( watch(
() => mapEditorStore.objectList, () => mapEditorStore.mapObjectList,
(newObjects) => { (newObjects) => {
if (!mapEditorStore.map) return if (!mapEditorStore.map) return
console.log(mapEditorStore.map.placedMapObjects) console.log(mapEditorStore.map.placedMapObjects)
const updatedMapObjects = mapEditorStore.map.placedMapObjects.map((mapObject) => { const updatedMapObjects = mapEditorStore.map.placedMapObjects.map((mapObject) => {
const updatedObject = newObjects.find((obj) => obj.id === mapObject.object.id) const updatedObject = newObjects.find((obj) => obj.id === mapObject.mapObject.id)
if (updatedObject) { if (updatedObject) {
return { return {
...mapObject, ...mapObject,
object: { object: {
...mapObject.object, ...mapObject.mapObject,
originX: updatedObject.originX, originX: updatedObject.originX,
originY: updatedObject.originY originY: updatedObject.originY
} }
@ -232,12 +232,12 @@ watch(
mapObjects: updatedMapObjects mapObjects: updatedMapObjects
}) })
// Update selectedObject if it's set // Update selectedMapObject if it's set
if (mapEditorStore.selectedObject) { if (mapEditorStore.selectedMapObject) {
const updatedObject = newObjects.find((obj) => obj.id === mapEditorStore.selectedObject?.id) const updatedObject = newObjects.find((obj) => obj.id === mapEditorStore.selectedMapObject?.id)
if (updatedObject) { if (updatedObject) {
mapEditorStore.setSelectedObject({ mapEditorStore.setSelectedMapObject({
...mapEditorStore.selectedObject, ...mapEditorStore.selectedMapObject,
originX: updatedObject.originX, originX: updatedObject.originX,
originY: updatedObject.originY originY: updatedObject.originY
}) })

View File

@ -26,7 +26,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import type { Map } from '@/application/types' import type { Map, UUID } from '@/application/types'
import CreateMap from '@/components/gameMaster/mapEditor/partials/CreateMap.vue' import CreateMap from '@/components/gameMaster/mapEditor/partials/CreateMap.vue'
import Modal from '@/components/utilities/Modal.vue' import Modal from '@/components/utilities/Modal.vue'
import { useGameStore } from '@/stores/gameStore' import { useGameStore } from '@/stores/gameStore'
@ -46,14 +46,14 @@ function fetchMaps() {
}) })
} }
function loadMap(id: number) { function loadMap(id: UUID) {
gameStore.connection?.emit('gm:map:request', { mapId: id }, (response: Map) => { gameStore.connection?.emit('gm:map:request', { mapId: id }, (response: Map) => {
mapEditorStore.setMap(response) mapEditorStore.setMap(response)
}) })
mapEditorStore.toggleMapListModal() mapEditorStore.toggleMapListModal()
} }
function deleteMap(id: number) { function deleteMap(id: UUID) {
gameStore.connection?.emit('gm:map:delete', { mapId: id }, () => { gameStore.connection?.emit('gm:map:delete', { mapId: id }, () => {
fetchMaps() fetchMaps()
}) })

View File

@ -1,5 +1,5 @@
<template> <template>
<Modal :isModalOpen="mapEditorStore.isObjectListModalShown" :modal-width="645" :modal-height="260" @modal:close="() => (mapEditorStore.isObjectListModalShown = false)" :bg-style="'none'"> <Modal :isModalOpen="mapEditorStore.isMapObjectListModalShown" :modal-width="645" :modal-height="260" @modal:close="() => (mapEditorStore.isMapObjectListModalShown = false)" :bg-style="'none'">
<template #modalHeader> <template #modalHeader>
<h3 class="text-lg text-white">Objects</h3> <h3 class="text-lg text-white">Objects</h3>
</template> </template>
@ -20,16 +20,16 @@
</div> </div>
<div class="h-full overflow-auto"> <div class="h-full overflow-auto">
<div class="flex justify-between flex-wrap gap-2.5 items-center"> <div class="flex justify-between flex-wrap gap-2.5 items-center">
<div v-for="(object, index) in filteredObjects" :key="index" class="max-w-1/4 inline-block"> <div v-for="(mapObject, index) in filteredMapObjects" :key="index" class="max-w-1/4 inline-block">
<img <img
class="border-2 border-solid max-w-full" class="border-2 border-solid max-w-full"
:src="`${config.server_endpoint}/assets/objects/${object.id}.png`" :src="`${config.server_endpoint}/assets/objects/${mapObject.id}.png`"
alt="Object" alt="Object"
@click="mapEditorStore.setSelectedObject(object)" @click="mapEditorStore.setSelectedMapObject(mapObject)"
:class="{ :class="{
'cursor-pointer transition-all duration-300': true, 'cursor-pointer transition-all duration-300': true,
'border-cyan shadow-lg scale-105': mapEditorStore.selectedObject?.id === object.id, 'border-cyan shadow-lg scale-105': mapEditorStore.selectedMapObject?.id === mapObject.id,
'border-transparent hover:border-gray-300': mapEditorStore.selectedObject?.id !== object.id 'border-transparent hover:border-gray-300': mapEditorStore.selectedMapObject?.id !== mapObject.id
}" }"
/> />
</div> </div>
@ -42,7 +42,7 @@
<script setup lang="ts"> <script setup lang="ts">
import config from '@/application/config' import config from '@/application/config'
import type { MapObject, PlacedMapObject } from '@/application/types' import type { MapObject } from '@/application/types'
import Modal from '@/components/utilities/Modal.vue' import Modal from '@/components/utilities/Modal.vue'
import { useGameStore } from '@/stores/gameStore' import { useGameStore } from '@/stores/gameStore'
import { useMapEditorStore } from '@/stores/mapEditorStore' import { useMapEditorStore } from '@/stores/mapEditorStore'
@ -55,12 +55,12 @@ const searchQuery = ref('')
const selectedTags = ref<string[]>([]) const selectedTags = ref<string[]>([])
const uniqueTags = computed(() => { const uniqueTags = computed(() => {
const allTags = mapEditorStore.objectList.flatMap((obj) => obj.tags || []) const allTags = mapEditorStore.mapObjectList.flatMap((obj) => obj.tags || [])
return Array.from(new Set(allTags)) return Array.from(new Set(allTags))
}) })
const filteredObjects = computed(() => { const filteredMapObjects = computed(() => {
return mapEditorStore.objectList.filter((object) => { return mapEditorStore.mapObjectList.filter((object) => {
const matchesSearch = !searchQuery.value || object.name.toLowerCase().includes(searchQuery.value.toLowerCase()) const matchesSearch = !searchQuery.value || object.name.toLowerCase().includes(searchQuery.value.toLowerCase())
const matchesTags = selectedTags.value.length === 0 || (object.tags && selectedTags.value.some((tag) => object.tags.includes(tag))) const matchesTags = selectedTags.value.length === 0 || (object.tags && selectedTags.value.some((tag) => object.tags.includes(tag)))
return matchesSearch && matchesTags return matchesSearch && matchesTags
@ -77,7 +77,7 @@ const toggleTag = (tag: string) => {
onMounted(async () => { onMounted(async () => {
isModalOpen.value = true isModalOpen.value = true
gameStore.connection?.emit('gm:mapObject:list', {}, (response: MapObject[]) => { gameStore.connection?.emit('', {}, (response: MapObject[]) => {
mapEditorStore.setMapObjectList(response) mapEditorStore.setMapObjectList(response)
}) })
}) })

View File

@ -33,7 +33,7 @@ export const useAssetManagerStore = defineStore('assetManager', () => {
mapObjectList.value = objects mapObjectList.value = objects
} }
function setSelectedObject(object: MapObject | null) { function setSelectedMapObject(object: MapObject | null) {
selectedMapObject.value = object selectedMapObject.value = object
} }
@ -86,7 +86,7 @@ export const useAssetManagerStore = defineStore('assetManager', () => {
setSelectedTile, setSelectedTile,
setMapObjectList, setMapObjectList,
setCharacterTypeList, setCharacterTypeList,
setSelectedMapObject: setSelectedObject, setSelectedMapObject: setSelectedMapObject,
setSpriteList, setSpriteList,
setSelectedSprite, setSelectedSprite,
setSelectedCharacterType, setSelectedCharacterType,

View File

@ -21,7 +21,7 @@ export const useMapEditorStore = defineStore('mapEditor', {
tileList: [] as Tile[], tileList: [] as Tile[],
mapObjectList: [] as MapObject[], mapObjectList: [] as MapObject[],
selectedTile: '', selectedTile: '',
selectedObject: null as MapObject | null, selectedMapObject: null as MapObject | null,
isTileListModalShown: false, isTileListModalShown: false,
isMapObjectListModalShown: false, isMapObjectListModalShown: false,
isMapListModalShown: false, isMapListModalShown: false,
@ -91,8 +91,8 @@ export const useMapEditorStore = defineStore('mapEditor', {
setSelectedTile(tile: string) { setSelectedTile(tile: string) {
this.selectedTile = tile this.selectedTile = tile
}, },
setSelectedObject(object: MapObject) { setSelectedMapObject(object: MapObject) {
this.selectedObject = object this.selectedMapObject = object
}, },
toggleSettingsModal() { toggleSettingsModal() {
this.isSettingsModalShown = !this.isSettingsModalShown this.isSettingsModalShown = !this.isSettingsModalShown
@ -122,7 +122,7 @@ export const useMapEditorStore = defineStore('mapEditor', {
this.tool = 'move' this.tool = 'move'
this.drawMode = 'tile' this.drawMode = 'tile'
this.selectedTile = '' this.selectedTile = ''
this.selectedObject = null this.selectedMapObject = null
this.isTileListModalShown = false this.isTileListModalShown = false
this.isMapObjectListModalShown = false this.isMapObjectListModalShown = false
this.isSettingsModalShown = false this.isSettingsModalShown = false