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