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> <template>
<Tooltip <Tooltip
:display="character && selected == null ? characters[character.type].nickname : ''" :display="
character && selected == null && dragging === false
? characters[character.type].nickname
: ''
"
:direction="Direction.Up" :direction="Direction.Up"
> >
<div <div
class="character" 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 <span
class="move-indicator" class="move-indicator"
v-if=" 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 <span class="material-icons">straight</span></span
@ -52,7 +89,7 @@
<script setup lang="ts"> <script setup lang="ts">
import Tooltip from "features/tooltips/Tooltip.vue"; import Tooltip from "features/tooltips/Tooltip.vue";
import { Direction } from "util/common"; import { Direction } from "util/common";
import { characters } from "./projEntry"; import { ref, watch } from "vue";
import heart from "../../public/Heart.png"; import heart from "../../public/Heart.png";
import level1_0 from "../../public/Lvl 1_0.png"; import level1_0 from "../../public/Lvl 1_0.png";
import level1_1 from "../../public/Lvl 1_1.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_1 from "../../public/Lvl 2_1.png";
import level2_2 from "../../public/Lvl 2_2.png"; import level2_2 from "../../public/Lvl 2_2.png";
import level3 from "../../public/Lvl 3.png"; import level3 from "../../public/Lvl 3.png";
import { characters } from "./projEntry";
defineProps<{ defineProps<{
character?: Character | null; character?: Character | null;
isSelected?: boolean; isSelected?: boolean;
isShop?: boolean; isShop?: boolean;
isDragging?: boolean;
selected?: Character | null; 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> </script>
<style scoped> <style scoped>
@ -84,10 +139,15 @@ defineProps<{
cursor: pointer; cursor: pointer;
} }
.character * {
pointer-events: none;
}
.character-display img { .character-display img {
image-rendering: pixelated; image-rendering: pixelated;
width: 10vmin; width: 10vmin;
height: 10vmin; height: 10vmin;
filter: drop-shadow(2px 4px 6px black);
} }
.character::after { .character::after {
@ -102,7 +162,7 @@ defineProps<{
z-index: -1; z-index: -1;
} }
.character.selected::before { .character.selected:not(.dragging)::before {
content: ""; content: "";
position: absolute; position: absolute;
top: 0; top: 0;
@ -113,7 +173,8 @@ defineProps<{
z-index: 1; 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: ""; content: "";
position: absolute; position: absolute;
top: 0; top: 0;
@ -193,7 +254,8 @@ defineProps<{
transition: all 0.5s ease, color 0s; 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); color: var(--feature-foreground);
} }

View file

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

View file

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

View file

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