diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..a809479 --- /dev/null +++ b/.env.example @@ -0,0 +1,3 @@ +NUXT_PUBLIC_ENDPOINT=http://localhost:8765 +NUXT_PUBLIC_DISCORD_LOGIN_ENDPOINT=https://discord.com/oauth2/authorize?client_id= +NUXT_DEV_MODE=TRUE \ No newline at end of file diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml index f38970a..1e81ac1 100644 --- a/.gitea/workflows/build.yml +++ b/.gitea/workflows/build.yml @@ -6,6 +6,7 @@ on: push: branches: - main + - feat/netcode-rework jobs: release-image: diff --git a/components/CardPreview.vue b/components/CardPreview.vue index 31231eb..539fe10 100644 --- a/components/CardPreview.vue +++ b/components/CardPreview.vue @@ -10,6 +10,7 @@ export interface Props { interactible?: boolean; noEffects?: boolean; used_effects_indexes?: number[]; + discardable?: boolean; } const props = withDefaults(defineProps(), { @@ -18,9 +19,17 @@ const props = withDefaults(defineProps(), { locked: () => true, interactible: () => true, noEffects: () => false, + discardable: () => false, }); -const emit = defineEmits(["click", "effectClick"]); +const emit = defineEmits([ + "click", + "effectClick", + "drop", + "move", + "startMove", + "stopMove", +]); const settingsStore = useSettingsStore(); @@ -28,12 +37,35 @@ const childCount = ref(0); const card = ref(); +const dragStatus = ref<{ + hasClickedDown: boolean; + dragging: boolean; + intervalEvent?: ReturnType; +}>({ + hasClickedDown: false, + dragging: false, +}); +const initialOffsetX = ref(0); +const initialOffsetY = ref(0); + +const mousePageX = ref(0); +const mousePageY = ref(0); + +const offsetX = ref(0); +const offsetY = ref(0); +const offsetWidth = ref(0); +const offsetHeight = ref(0); + +const translateX = ref(0); +const translateY = ref(0); + const extension = computed(() => { if (settingsStore.cardStyle == CardStyles.SVG) { return ".svg"; } return ".png"; }); + function cardClick() { if (!props.card_id) return; emit("click"); @@ -61,8 +93,126 @@ function rightClickUp(e: MouseEvent) { isZooming.value = false; } +function startDrag(e: MouseEvent) { + emit("startMove"); + dragStatus.value.dragging = true; + translateX.value = 0; + translateY.value = 0; + const cardElement = card.value; + if (!cardElement) { + return; + } + mousePageX.value = e.pageX; + mousePageY.value = e.pageY; + initialOffsetX.value = e.offsetX; + initialOffsetY.value = e.offsetY; + offsetX.value = cardElement.offsetLeft + e.offsetX; + offsetY.value = cardElement.offsetTop + e.offsetY; + translateX.value = mousePageX.value - offsetX.value; + translateY.value = mousePageY.value - offsetY.value; +} + +function leftClickDown(e: MouseEvent) { + dragStatus.value.hasClickedDown = true; + window.addEventListener("mousemove", mouseMove, false); +} + +function leftClickUpGlobal(e: MouseEvent) { + mousePageX.value = e.pageX; + mousePageY.value = e.pageY; + + if (dragStatus.value.dragging && dragStatus.value.hasClickedDown) { + dragStatus.value.dragging = false; + emit("drop", { x: e.pageX, y: e.pageY, uuid: props.card?._id }); + emit("stopMove"); + } + dragStatus.value.hasClickedDown = false; + clearTimeout(dragStatus.value.intervalEvent); + window.removeEventListener("mousemove", mouseMove, false); +} + +function leftClickUp(e: MouseEvent) { + if (dragStatus.value.dragging == false && dragStatus.value.hasClickedDown) { + dragStatus.value.hasClickedDown = false; + cardClick(); + return; + } +} + +const sensitivity = 0.5; +function mouseMove(e: MouseEvent) { + if ( + dragStatus.value.hasClickedDown && + !dragStatus.value.dragging && + Math.sqrt(Math.abs(e.movementX * e.movementY)) > sensitivity + ) { + startDrag(e); + } + + const cardElement = card.value; + if (!cardElement) { + return; + } + mousePageX.value = e.pageX; + mousePageY.value = e.pageY; + // console.log(cardElement.offsetLeft); + offsetX.value = cardElement.offsetLeft + initialOffsetX.value; + offsetY.value = cardElement.offsetTop + initialOffsetY.value; + + translateX.value = mousePageX.value - offsetX.value; + translateY.value = mousePageY.value - offsetY.value; + + // emit("move", { x: e.pageX, y: e.pageY, uuid: props.card?._id }); +} + +defineExpose({ + offsetX, + offsetY, + offsetWidth, + offsetHeight, + uuid: props.card?._id, +}); + onMounted(() => { - card.value?.style.setProperty("--random-seed", -Math.random() * 10 + "s"); + window.addEventListener("mouseup", leftClickUpGlobal, false); + const cardElement = card.value; + if (!cardElement) { + return; + } + offsetX.value = cardElement.offsetLeft; + offsetY.value = cardElement.offsetTop; + offsetWidth.value = cardElement.offsetWidth; + offsetHeight.value = cardElement.offsetHeight; + cardElement.offsetWidth; +}); + +// onRenderTriggered(() => { +// const cardElement = card.value; +// if (!cardElement) { +// return; +// } +// offsetX.value = cardElement.offsetLeft + initialOffsetX.value; +// offsetY.value = cardElement.offsetTop + initialOffsetY.value; + +// translateX.value = mousePageX.value - offsetX.value; +// translateY.value = mousePageY.value - offsetY.value; +// }); + +onUpdated(() => { + const cardElement = card.value; + if (!cardElement) { + return; + } + offsetX.value = cardElement.offsetLeft + initialOffsetX.value; + offsetY.value = cardElement.offsetTop + initialOffsetY.value; + + translateX.value = mousePageX.value - offsetX.value; + translateY.value = mousePageY.value - offsetY.value; +}); + +onUnmounted(() => { + window.removeEventListener("mouseup", leftClickUpGlobal, false); + // window.addEventListener("mousemove", mouseMove, false); }); @@ -71,25 +221,22 @@ onMounted(() => { ref="card" class="card" :class="{ + dragging: dragStatus.dragging, active: childCount > 0, wrapped, unlocked: !props.locked, zoom: isZooming, no_effects: noEffects || !props.locked, + discardable, }" @contextmenu.prevent="false" - @click.left="cardClick" @mousedown.right="rightClickDown" @mouseup.right="rightClickUp" + @mousedown.left="leftClickDown" + @mouseup.left="leftClickUp" @mouseenter="mouseenter" @mouseleave="mouseleave" > -
- -