npm run format
This commit is contained in:
parent
dca773b8c9
commit
87815dd68e
@ -4,12 +4,7 @@
|
|||||||
<span>{{ chip }}</span>
|
<span>{{ chip }}</span>
|
||||||
<i class="cursor-pointer text-white font-light font-default not-italic hover:text-gray-50" @click="deleteChip(i)">X</i>
|
<i class="cursor-pointer text-white font-light font-default not-italic hover:text-gray-50" @click="deleteChip(i)">X</i>
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input class="outline-none border-none max-w-[250px] p-1 m-1 text-white" v-model="currentInput" @keypress.enter.prevent="saveChip" @keydown.delete="backspaceDelete" />
|
||||||
class="outline-none border-none max-w-[250px] p-1 m-1 text-white"
|
|
||||||
v-model="currentInput"
|
|
||||||
@keypress.enter.prevent="saveChip"
|
|
||||||
@keydown.delete="backspaceDelete"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -28,9 +23,13 @@ const emit = defineEmits(['update:modelValue'])
|
|||||||
const currentInput = ref('')
|
const currentInput = ref('')
|
||||||
const internalValue = ref(props.modelValue || [])
|
const internalValue = ref(props.modelValue || [])
|
||||||
|
|
||||||
watch(() => props.modelValue, (newVal) => {
|
watch(
|
||||||
|
() => props.modelValue,
|
||||||
|
(newVal) => {
|
||||||
internalValue.value = newVal || []
|
internalValue.value = newVal || []
|
||||||
}, { immediate: true })
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
|
||||||
const saveChip = (event) => {
|
const saveChip = (event) => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
@ -42,7 +41,10 @@ const saveChip = (event) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const deleteChip = (index) => {
|
const deleteChip = (index) => {
|
||||||
emit('update:modelValue', internalValue.value.filter((_, i) => i !== index))
|
emit(
|
||||||
|
'update:modelValue',
|
||||||
|
internalValue.value.filter((_, i) => i !== index)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const backspaceDelete = (event) => {
|
const backspaceDelete = (event) => {
|
||||||
|
@ -63,5 +63,4 @@ import { useAssetManagerStore } from '@/stores/assetManager'
|
|||||||
|
|
||||||
const assetManagerStore = useAssetManagerStore()
|
const assetManagerStore = useAssetManagerStore()
|
||||||
const selectedCategory = ref('tiles')
|
const selectedCategory = ref('tiles')
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -124,5 +124,4 @@ onMounted(() => {
|
|||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
assetManagerStore.setSelectedObject(null)
|
assetManagerStore.setSelectedObject(null)
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -9,13 +9,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-bind="containerProps" class="overflow-y-auto relative" @scroll="onScroll">
|
<div v-bind="containerProps" class="overflow-y-auto relative" @scroll="onScroll">
|
||||||
<div v-bind="wrapperProps" ref="elementToScroll">
|
<div v-bind="wrapperProps" ref="elementToScroll">
|
||||||
<a
|
<a v-for="{ data: object } in list" :key="object.id" class="relative p-2.5 cursor-pointer block" :class="{ 'bg-cyan/80': assetManagerStore.selectedObject?.id === object.id }" @click="assetManagerStore.setSelectedObject(object as Object)">
|
||||||
v-for="{ data: object } in list"
|
|
||||||
:key="object.id"
|
|
||||||
class="relative p-2.5 cursor-pointer block"
|
|
||||||
:class="{ 'bg-cyan/80': assetManagerStore.selectedObject?.id === object.id }"
|
|
||||||
@click="assetManagerStore.setSelectedObject(object as Object)"
|
|
||||||
>
|
|
||||||
<div class="flex items-center gap-2.5">
|
<div class="flex items-center gap-2.5">
|
||||||
<div class="h-[28px] w-[75px] max-w-[75px] flex justify-center">
|
<div class="h-[28px] w-[75px] max-w-[75px] flex justify-center">
|
||||||
<img class="h-[28px]" :src="`${config.server_endpoint}/assets/objects/${object.id}.png`" alt="Object" />
|
<img class="h-[28px]" :src="`${config.server_endpoint}/assets/objects/${object.id}.png`" alt="Object" />
|
||||||
@ -76,22 +70,17 @@ const filteredObjects = computed(() => {
|
|||||||
if (!searchQuery.value) {
|
if (!searchQuery.value) {
|
||||||
return assetManagerStore.objectList
|
return assetManagerStore.objectList
|
||||||
}
|
}
|
||||||
return assetManagerStore.objectList.filter((object) =>
|
return assetManagerStore.objectList.filter((object) => object.name.toLowerCase().includes(searchQuery.value.toLowerCase()))
|
||||||
object.name.toLowerCase().includes(searchQuery.value.toLowerCase())
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const { list, containerProps, wrapperProps, scrollTo } = useVirtualList(
|
const { list, containerProps, wrapperProps, scrollTo } = useVirtualList(filteredObjects, {
|
||||||
filteredObjects,
|
itemHeight: 48
|
||||||
{
|
})
|
||||||
itemHeight: 48,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
const virtualList = ref({ scrollTo })
|
const virtualList = ref({ scrollTo })
|
||||||
|
|
||||||
const onScroll = () => {
|
const onScroll = () => {
|
||||||
let scrollTop = elementToScroll.value.style.marginTop.replace('px', '');
|
let scrollTop = elementToScroll.value.style.marginTop.replace('px', '')
|
||||||
|
|
||||||
if (scrollTop > 80) {
|
if (scrollTop > 80) {
|
||||||
hasScrolled.value = true
|
hasScrolled.value = true
|
||||||
|
@ -9,13 +9,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-bind="containerProps" class="overflow-y-auto relative" @scroll="onScroll">
|
<div v-bind="containerProps" class="overflow-y-auto relative" @scroll="onScroll">
|
||||||
<div v-bind="wrapperProps" ref="elementToScroll">
|
<div v-bind="wrapperProps" ref="elementToScroll">
|
||||||
<a
|
<a v-for="{ data: tile } in list" :key="tile.id" class="relative p-2.5 cursor-pointer block" :class="{ 'bg-cyan/80': assetManagerStore.selectedTile?.id === tile.id }" @click="assetManagerStore.setSelectedTile(tile)">
|
||||||
v-for="{ data: tile } in list"
|
|
||||||
:key="tile.id"
|
|
||||||
class="relative p-2.5 cursor-pointer block"
|
|
||||||
:class="{ 'bg-cyan/80': assetManagerStore.selectedTile?.id === tile.id }"
|
|
||||||
@click="assetManagerStore.setSelectedTile(tile)"
|
|
||||||
>
|
|
||||||
<div class="flex items-center gap-2.5">
|
<div class="flex items-center gap-2.5">
|
||||||
<div class="h-[28px] w-[75px] max-w-[75px] flex justify-center">
|
<div class="h-[28px] w-[75px] max-w-[75px] flex justify-center">
|
||||||
<img class="h-[28px]" :src="`${config.server_endpoint}/assets/tiles/${tile.id}.png`" alt="Tile" />
|
<img class="h-[28px]" :src="`${config.server_endpoint}/assets/tiles/${tile.id}.png`" alt="Tile" />
|
||||||
@ -76,22 +70,17 @@ const filteredTiles = computed(() => {
|
|||||||
if (!searchQuery.value) {
|
if (!searchQuery.value) {
|
||||||
return assetManagerStore.tileList
|
return assetManagerStore.tileList
|
||||||
}
|
}
|
||||||
return assetManagerStore.tileList.filter((tile) =>
|
return assetManagerStore.tileList.filter((tile) => tile.name.toLowerCase().includes(searchQuery.value.toLowerCase()))
|
||||||
tile.name.toLowerCase().includes(searchQuery.value.toLowerCase())
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const { list, containerProps, wrapperProps, scrollTo } = useVirtualList(
|
const { list, containerProps, wrapperProps, scrollTo } = useVirtualList(filteredTiles, {
|
||||||
filteredTiles,
|
itemHeight: 48
|
||||||
{
|
})
|
||||||
itemHeight: 48,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
const virtualList = ref({ scrollTo })
|
const virtualList = ref({ scrollTo })
|
||||||
|
|
||||||
const onScroll = () => {
|
const onScroll = () => {
|
||||||
let scrollTop = elementToScroll.value.style.marginTop.replace('px', '');
|
let scrollTop = elementToScroll.value.style.marginTop.replace('px', '')
|
||||||
|
|
||||||
if (scrollTop > 80) {
|
if (scrollTop > 80) {
|
||||||
hasScrolled.value = true
|
hasScrolled.value = true
|
||||||
|
@ -19,13 +19,7 @@
|
|||||||
<template #modalBody>
|
<template #modalBody>
|
||||||
<div class="m-[15px]">
|
<div class="m-[15px]">
|
||||||
<div class="mb-4 flex flex-wrap gap-2">
|
<div class="mb-4 flex flex-wrap gap-2">
|
||||||
<button
|
<button v-for="tag in uniqueTags" :key="tag" @click="toggleTag(tag)" class="btn-cyan" :class="{ 'opacity-50': !selectedTags.includes(tag) }">
|
||||||
v-for="tag in uniqueTags"
|
|
||||||
:key="tag"
|
|
||||||
@click="toggleTag(tag)"
|
|
||||||
class="btn-cyan"
|
|
||||||
:class="{ 'opacity-50': !selectedTags.includes(tag) }"
|
|
||||||
>
|
|
||||||
{{ tag }}
|
{{ tag }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -70,21 +64,21 @@ watch(objectDepth, (depth) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const uniqueTags = computed(() => {
|
const uniqueTags = computed(() => {
|
||||||
const allTags = zoneEditorStore.objectList.flatMap(obj => obj.tags || [])
|
const allTags = zoneEditorStore.objectList.flatMap((obj) => obj.tags || [])
|
||||||
return Array.from(new Set(allTags))
|
return Array.from(new Set(allTags))
|
||||||
})
|
})
|
||||||
|
|
||||||
const filteredObjects = computed(() => {
|
const filteredObjects = computed(() => {
|
||||||
return zoneEditorStore.objectList.filter((object) => {
|
return zoneEditorStore.objectList.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
|
||||||
})
|
})
|
||||||
});
|
})
|
||||||
|
|
||||||
const toggleTag = (tag: string) => {
|
const toggleTag = (tag: string) => {
|
||||||
if (selectedTags.value.includes(tag)) {
|
if (selectedTags.value.includes(tag)) {
|
||||||
selectedTags.value = selectedTags.value.filter(t => t !== tag)
|
selectedTags.value = selectedTags.value.filter((t) => t !== tag)
|
||||||
} else {
|
} else {
|
||||||
selectedTags.value.push(tag)
|
selectedTags.value.push(tag)
|
||||||
}
|
}
|
||||||
|
@ -3,41 +3,13 @@
|
|||||||
<div class="self-end mt-2 flex gap-2">
|
<div class="self-end mt-2 flex gap-2">
|
||||||
<div>
|
<div>
|
||||||
<label class="mb-1.5 font-titles block text-sm text-gray-700 hidden" for="depth">Depth</label>
|
<label class="mb-1.5 font-titles block text-sm text-gray-700 hidden" for="depth">Depth</label>
|
||||||
<input
|
<input v-model="objectDepth" @mousedown.stop @input="handleDepthInput" class="input-cyan max-w-[90px] px-2 py-1 border rounded" type="number" name="depth" placeholder="Depth" :disabled="!isObjectSelected" />
|
||||||
v-model="objectDepth"
|
|
||||||
@mousedown.stop
|
|
||||||
@input="handleDepthInput"
|
|
||||||
class="input-cyan max-w-[90px] px-2 py-1 border rounded"
|
|
||||||
type="number"
|
|
||||||
name="depth"
|
|
||||||
placeholder="Depth"
|
|
||||||
:disabled="!isObjectSelected"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button @mousedown.stop @click="handleDelete" class="btn-bordeaux py-1.5 px-[15px]" :disabled="!isObjectSelected">
|
||||||
@mousedown.stop
|
|
||||||
@click="handleDelete"
|
|
||||||
class="btn-bordeaux py-1.5 px-[15px]"
|
|
||||||
:disabled="!isObjectSelected"
|
|
||||||
>
|
|
||||||
<img src="/assets/icons/trashcan.svg" class="w-4 h-4" alt="Delete" />
|
<img src="/assets/icons/trashcan.svg" class="w-4 h-4" alt="Delete" />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button @mousedown.stop @click="zoneEditorStore.setSelectedObject(zoneEditorStore.selectedZoneObject?.object)" class="btn-cyan py-1.5 px-[15px]" :disabled="!isObjectSelected">S</button>
|
||||||
@mousedown.stop
|
<button @mousedown.stop @click="handleMove" class="btn-cyan py-1.5 px-[15px] min-w-[100px]" :disabled="!isObjectSelected">Move</button>
|
||||||
@click="zoneEditorStore.setSelectedObject(zoneEditorStore.selectedZoneObject?.object)"
|
|
||||||
class="btn-cyan py-1.5 px-[15px]"
|
|
||||||
:disabled="!isObjectSelected"
|
|
||||||
>
|
|
||||||
S
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
@mousedown.stop
|
|
||||||
@click="handleMove"
|
|
||||||
class="btn-cyan py-1.5 px-[15px] min-w-[100px]"
|
|
||||||
:disabled="!isObjectSelected"
|
|
||||||
>
|
|
||||||
Move
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -53,9 +25,12 @@ const objectDepth = ref(zoneEditorStore.objectDepth)
|
|||||||
|
|
||||||
const isObjectSelected = computed(() => !!zoneEditorStore.selectedZoneObject)
|
const isObjectSelected = computed(() => !!zoneEditorStore.selectedZoneObject)
|
||||||
|
|
||||||
watch(() => zoneEditorStore.selectedZoneObject, (selectedZoneObject) => {
|
watch(
|
||||||
|
() => zoneEditorStore.selectedZoneObject,
|
||||||
|
(selectedZoneObject) => {
|
||||||
objectDepth.value = selectedZoneObject?.depth ?? 0
|
objectDepth.value = selectedZoneObject?.depth ?? 0
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
const handleDepthInput = () => {
|
const handleDepthInput = () => {
|
||||||
const depth = parseFloat(objectDepth.value)
|
const depth = parseFloat(objectDepth.value)
|
||||||
|
@ -15,13 +15,7 @@
|
|||||||
<template #modalBody>
|
<template #modalBody>
|
||||||
<div class="m-[15px]">
|
<div class="m-[15px]">
|
||||||
<div class="mb-4 flex flex-wrap gap-2">
|
<div class="mb-4 flex flex-wrap gap-2">
|
||||||
<button
|
<button v-for="tag in uniqueTags" :key="tag" @click="toggleTag(tag)" class="btn-cyan" :class="{ 'opacity-50': !selectedTags.includes(tag) }">
|
||||||
v-for="tag in uniqueTags"
|
|
||||||
:key="tag"
|
|
||||||
@click="toggleTag(tag)"
|
|
||||||
class="btn-cyan"
|
|
||||||
:class="{ 'opacity-50': !selectedTags.includes(tag) }"
|
|
||||||
>
|
|
||||||
{{ tag }}
|
{{ tag }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -64,29 +58,26 @@ const searchQuery = ref('')
|
|||||||
const selectedTags = ref<string[]>([])
|
const selectedTags = ref<string[]>([])
|
||||||
|
|
||||||
const uniqueTags = computed(() => {
|
const uniqueTags = computed(() => {
|
||||||
const allTags = zoneEditorStore.tileList.flatMap(tile => tile.tags || [])
|
const allTags = zoneEditorStore.tileList.flatMap((tile) => tile.tags || [])
|
||||||
return Array.from(new Set(allTags))
|
return Array.from(new Set(allTags))
|
||||||
})
|
})
|
||||||
|
|
||||||
const filteredTiles = computed(() => {
|
const filteredTiles = computed(() => {
|
||||||
return zoneEditorStore.tileList.filter((tile) => {
|
return zoneEditorStore.tileList.filter((tile) => {
|
||||||
const matchesSearch = !searchQuery.value || tile.name.toLowerCase().includes(searchQuery.value.toLowerCase());
|
const matchesSearch = !searchQuery.value || tile.name.toLowerCase().includes(searchQuery.value.toLowerCase())
|
||||||
const matchesTags = selectedTags.value.length === 0 || (tile.tags && selectedTags.value.some(tag => tile.tags.includes(tag)));
|
const matchesTags = selectedTags.value.length === 0 || (tile.tags && selectedTags.value.some((tag) => tile.tags.includes(tag)))
|
||||||
return matchesSearch && matchesTags;
|
return matchesSearch && matchesTags
|
||||||
})
|
})
|
||||||
});
|
})
|
||||||
|
|
||||||
const { list, containerProps, wrapperProps, scrollTo } = useVirtualList(
|
const { list, containerProps, wrapperProps, scrollTo } = useVirtualList(filteredTiles, {
|
||||||
filteredTiles,
|
|
||||||
{
|
|
||||||
itemHeight: 40,
|
itemHeight: 40,
|
||||||
itemWidth: 72,
|
itemWidth: 72
|
||||||
},
|
})
|
||||||
)
|
|
||||||
|
|
||||||
const toggleTag = (tag: string) => {
|
const toggleTag = (tag: string) => {
|
||||||
if (selectedTags.value.includes(tag)) {
|
if (selectedTags.value.includes(tag)) {
|
||||||
selectedTags.value = selectedTags.value.filter(t => t !== tag)
|
selectedTags.value = selectedTags.value.filter((t) => t !== tag)
|
||||||
} else {
|
} else {
|
||||||
selectedTags.value.push(tag)
|
selectedTags.value.push(tag)
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<GmPanel v-if="isLoaded && gameStore.character?.role === 'gm'" />
|
<GmPanel v-if="isLoaded && gameStore.character?.role === 'gm'" />
|
||||||
|
|
||||||
<div v-if="!zoneEditorStore.active">
|
<div v-if="!zoneEditorStore.active">
|
||||||
<Game :config="gameConfig" @create="createGame" >
|
<Game :config="gameConfig" @create="createGame">
|
||||||
<Scene name="main" @preload="preloadScene" @create="createScene">
|
<Scene name="main" @preload="preloadScene" @create="createScene">
|
||||||
<div class="flex absolute justify-between left-0 right-0 top-[48px] mx-[48px] my-0">
|
<div class="flex absolute justify-between left-0 right-0 top-[48px] mx-[48px] my-0">
|
||||||
<Hud />
|
<Hud />
|
||||||
@ -21,7 +21,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="zoneEditorStore.active">
|
<div v-if="zoneEditorStore.active">
|
||||||
<Game :config="gameConfig" @create="createGame" >
|
<Game :config="gameConfig" @create="createGame">
|
||||||
<Scene name="main" @preload="preloadScene" @create="createScene">
|
<Scene name="main" @preload="preloadScene" @create="createScene">
|
||||||
<ZoneEditor v-if="isLoaded" :key="zoneEditorStore.zone?.id ?? 0" />
|
<ZoneEditor v-if="isLoaded" :key="zoneEditorStore.zone?.id ?? 0" />
|
||||||
</Scene>
|
</Scene>
|
||||||
|
22
src/types.ts
22
src/types.ts
@ -11,17 +11,17 @@ export type Asset = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type Sprite = {
|
export type Sprite = {
|
||||||
id: string;
|
id: string
|
||||||
name: string;
|
name: string
|
||||||
origin_x: number;
|
origin_x: number
|
||||||
origin_y: number;
|
origin_y: number
|
||||||
frameSpeed: number;
|
frameSpeed: number
|
||||||
isAnimated: boolean;
|
isAnimated: boolean
|
||||||
isLooping: boolean;
|
isLooping: boolean
|
||||||
isPlayableCharacter: boolean;
|
isPlayableCharacter: boolean
|
||||||
isEnemy: boolean;
|
isEnemy: boolean
|
||||||
createdAt: Date;
|
createdAt: Date
|
||||||
updatedAt: Date;
|
updatedAt: Date
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Tile = {
|
export type Tile = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user