Implement dragging

This commit is contained in:
thepaperpilot 2023-02-19 00:40:39 -06:00
parent bd5ccff23d
commit 93712b407c
4 changed files with 105 additions and 11 deletions

View file

@ -1,16 +1,53 @@
<template>
<Tooltip
:display="character && selected == null ? characters[character.type].nickname : ''"
:display="
character && selected == null && dragging === false
? characters[character.type].nickname
: ''
"
:direction="Direction.Up"
>
<div
class="character"
:class="{ selected: isSelected, empty: character == null && selected == null }"
:class="{
selected: isSelected,
empty: character == null && selected == null,
dragging,
isDragging,
draggingOver
}"
draggable="true"
:ondragstart="() => (dragging = true)"
:ondragend="() => (dragging = false)"
:ondragenter="() => (draggingOver = true)"
:ondragleave="() => (draggingOver = false)"
:ondragover="(e: MouseEvent) => {
// Copied from the v-if clauses on both move indicators
if (selected != null && !isShop && (character?.type !== selected.type || isSelected)) {
e.preventDefault();
}
if (character != null &&
selected != null &&
!isSelected &&
character.type === selected.type &&
character.exp < 6) {
e.preventDefault();
}
}"
:ondrop="
() => {
draggingOver = false;
emits('drop');
}
"
>
<span
class="move-indicator"
v-if="
selected != null && !isShop && (character?.type !== selected.type || isSelected)
selected != null &&
!isShop &&
(character?.type !== selected.type || isSelected) &&
dragging === false
"
>
<span class="material-icons">straight</span></span
@ -52,7 +89,7 @@
<script setup lang="ts">
import Tooltip from "features/tooltips/Tooltip.vue";
import { Direction } from "util/common";
import { characters } from "./projEntry";
import { ref, watch } from "vue";
import heart from "../../public/Heart.png";
import level1_0 from "../../public/Lvl 1_0.png";
import level1_1 from "../../public/Lvl 1_1.png";
@ -60,13 +97,31 @@ import level2_0 from "../../public/Lvl 2_0.png";
import level2_1 from "../../public/Lvl 2_1.png";
import level2_2 from "../../public/Lvl 2_2.png";
import level3 from "../../public/Lvl 3.png";
import { characters } from "./projEntry";
defineProps<{
character?: Character | null;
isSelected?: boolean;
isShop?: boolean;
isDragging?: boolean;
selected?: Character | null;
}>();
const dragging = ref(false);
const draggingOver = ref(false);
const emits = defineEmits<{
(e: "dragstart"): void;
(e: "dragend"): void;
(e: "drop"): void;
}>();
watch(dragging, dragging => {
if (dragging) {
emits("dragstart");
} else {
emits("dragend");
}
});
</script>
<style scoped>
@ -84,10 +139,15 @@ defineProps<{
cursor: pointer;
}
.character * {
pointer-events: none;
}
.character-display img {
image-rendering: pixelated;
width: 10vmin;
height: 10vmin;
filter: drop-shadow(2px 4px 6px black);
}
.character::after {
@ -102,7 +162,7 @@ defineProps<{
z-index: -1;
}
.character.selected::before {
.character.selected:not(.dragging)::before {
content: "";
position: absolute;
top: 0;
@ -113,7 +173,8 @@ defineProps<{
z-index: 1;
}
.character:not(.selected):not(.empty):hover::before {
.character:not(.selected):not(.empty):not(.dragging):not(.isDragging):hover::before,
.character:not(.selected):not(.empty):not(.dragging).draggingOver::before {
content: "";
position: absolute;
top: 0;
@ -193,7 +254,8 @@ defineProps<{
transition: all 0.5s ease, color 0s;
}
.character:hover .move-indicator .material-icons {
.character:not(.isDragging):hover .move-indicator .material-icons,
.character.draggingOver .move-indicator .material-icons {
color: var(--feature-foreground);
}

View file

@ -44,6 +44,12 @@
transition-duration: 0s;
}
.startStream {
height: 16vmin;
cursor: pointer;
filter: drop-shadow(2px 4px 6px black);
}
.waiting {
font-size: 4vmin;
height: 16vmin;

View file

@ -100,6 +100,8 @@ export const main = createLayer("main", function (this: BaseLayer) {
}
}));
const isDragging = ref(false);
return {
name: "Game",
minimizable: false,
@ -143,7 +145,19 @@ export const main = createLayer("main", function (this: BaseLayer) {
: shop.value[selectedShopItem.value]
: team.value[selectedCharacter.value]
}
isDragging={isDragging.value}
onClick={clickCharacter(i)}
onDragstart={() => {
isDragging.value = true;
selectedCharacter.value = i;
selectedShopItem.value = null;
}}
onDragend={() => {
isDragging.value = false;
selectedCharacter.value = null;
selectedShopItem.value = null;
}}
onDrop={() => clickCharacter(i)()}
/>
))}
</Row>
@ -167,6 +181,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
character={item == null ? undefined : item}
isSelected={selectedShopItem.value === i}
isShop={true}
isDragging={isDragging.value}
onClick={(e: MouseEvent) => {
if (item == null) {
return;
@ -175,6 +190,16 @@ export const main = createLayer("main", function (this: BaseLayer) {
selectedCharacter.value = null;
e.stopPropagation();
}}
onDragstart={() => {
isDragging.value = true;
selectedCharacter.value = null;
selectedShopItem.value = i;
}}
onDragend={() => {
isDragging.value = false;
selectedCharacter.value = null;
selectedShopItem.value = null;
}}
/>
))}
</Row>
@ -183,7 +208,8 @@ export const main = createLayer("main", function (this: BaseLayer) {
<div class="waiting">Finding opposing team...</div>
) : (
<img
style="height: 16vmin; cursor: pointer"
class="startStream"
draggable="false"
onClick={() => {
emit("stream");
findingMatch.value = true;
@ -207,7 +233,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
});
function clickCharacter(index: number) {
return (e: MouseEvent) => {
return (e?: MouseEvent) => {
if (main.selectedCharacter.value != null && main.selectedCharacter.value !== index) {
if (
main.team.value[main.selectedCharacter.value]?.type ===
@ -237,7 +263,7 @@ function clickCharacter(index: number) {
} else {
main.selectedCharacter.value = index;
}
e.stopPropagation();
e?.stopPropagation();
};
}

View file

@ -8,7 +8,7 @@
>
<slot />
<component v-if="elementComp" :is="elementComp" />
<transition name="fade">
<transition name="fade" :css="!!comp">
<div
v-if="isShown"
class="tooltip"