Chore : components cleanup

This commit is contained in:
2024-08-01 17:31:09 +02:00
parent 240ab7e1d4
commit 23e5f9f432
31 changed files with 720 additions and 816 deletions
+34
View File
@@ -0,0 +1,34 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"request": "launch",
"name": "client: chrome",
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}"
},
{
"type": "node",
"request": "launch",
"name": "server: nuxt",
"outputCapture": "std",
"program": "${workspaceFolder}/node_modules/nuxi/bin/nuxi.mjs",
"args": [
"dev"
],
}
],
"compounds": [
{
"name": "fullstack: nuxt",
"configurations": [
"server: nuxt",
"client: chrome"
]
}
]
}
+2 -1
View File
@@ -4,5 +4,6 @@
"**/node_modules": true
},
"vue.server.hybridMode": true,
"editor.formatOnSave": true
"editor.formatOnSave": true,
"javascript.updateImportsOnFileMove.enabled": "never"
}
+2 -5
View File
@@ -5,7 +5,6 @@ import { getCurrentInstance } from "vue";
const nuxtApp = useNuxtApp();
const router = useRouter();
const authStore = useAuthStore();
console.log("compiling cards...");
@@ -14,16 +13,14 @@ if (!app) {
throw new Error("Couldn't bake cards: instance is null");
}
await compileCards(app);
const _cards = cards;
console.log("compiling done");
useHead({
title: "Héron Realms",
});
onMounted(()=>{
onMounted(() => {
authStore.whoami();
})
});
</script>
<template>
<div class="root_dom_div">
-1
View File
@@ -201,7 +201,6 @@ self.addEventListener("message", (e) => {
screen.height = data.screen.height;
loadShader();
} else if (data.command == "killShader") {
console.log("killShader");
self.clearInterval(interval);
self.clearTimeout(timeout);
} else if (data.command == "resumeShader") {
-23
View File
@@ -1,23 +0,0 @@
<script lang="ts">
import type { Card } from "~/netcode/interfaces";
import { cards } from "~/services/loadCards";
export default {
props: ["card", "used_effects_indexes"],
data() {
const _card = this.card as Card;
return { cards };
},
beforeCreate() {
(this as any).component = () => cards[this.card.cardId];
},
};
</script>
<template>
<Component
:is="cards[card.cardId]"
:used_effects_indexes="used_effects_indexes"
v-if="card"
/>
</template>
-51
View File
@@ -1,51 +0,0 @@
<script setup lang="ts">
import goStore from '~/netcode';
export interface Props {
card_id: number | undefined
}
const settingsStore = useSettingsStore()
const props = defineProps<Props>()
const card: Ref<Element | null> = ref(null)
const x = computed(() => {
const bounds = card.value?.getBoundingClientRect()
let offset = 1
if (!bounds) { return 0 }
if ((bounds.width + goStore.clientMouseX) > (window.visualViewport?.width ?? Infinity)) {
offset = - (bounds.width + 1)
}
return goStore.clientMouseX + offset
})
const y = computed(() => {
const bounds = card.value?.getBoundingClientRect()
let offset = 1
if (!bounds) { return 0 }
if ((bounds.height + goStore.clientMouseY) > (window.visualViewport?.height ?? Infinity)) {
offset = - (bounds.height + 1)
}
return goStore.clientMouseY + offset
})
</script>
<template>
<div :class="`card_overlay`" :style="`top: ${y}px; left: ${x}px`" ref="card">
<img :class="`card_image`" v-if="props.card_id"
:src="`/cards/${settingsStore.cardStyle}/` + props.card_id.toString().padStart(3, '0') + '.png'"
draggable="false">
<!-- <img :class="`card_image`" v-if="!props.card_id" :src="'/cards/background.png'" draggable="false"> -->
</div>
</template>
<style scoped>
.card_overlay {
/* display: none; */
position: fixed;
z-index: 999;
display: flex;
pointer-events: none;
}
</style>
-410
View File
@@ -1,410 +0,0 @@
<script setup lang="ts">
import type { Card } from "~/netcode/interfaces";
export interface Props {
card?: Card;
card_id?: number;
locked?: boolean;
wrapped?: boolean;
tilted?: boolean;
interactible?: boolean;
noEffects?: boolean;
used_effects_indexes?: number[];
discardable?: boolean;
}
const props = withDefaults(defineProps<Props>(), {
wrapped: () => false,
tilted: () => true,
locked: () => true,
interactible: () => true,
noEffects: () => false,
discardable: () => false,
});
const emit = defineEmits([
"click",
"effectClick",
"drop",
"move",
"startMove",
"stopMove",
]);
const settingsStore = useSettingsStore();
const childCount = ref<number>(0);
const card = ref<HTMLElement>();
const dragStatus = ref<{
hasClickedDown: boolean;
dragging: boolean;
intervalEvent?: ReturnType<typeof setTimeout>;
}>({
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");
}
const isZooming = ref<boolean>(false);
function mouseenter(e: MouseEvent) {
// User is Right Clicking
if ((e.buttons & 2) == 2) {
isZooming.value = true;
}
// goStore.hoveredCard = props.card_id
}
function mouseleave(e: MouseEvent) {
isZooming.value = false;
}
function rightClickDown(e: MouseEvent) {
isZooming.value = true;
}
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
&& settingsStore.enableDragging
) {
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(() => {
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);
});
</script>
<template>
<div 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" @mousedown.right="rightClickDown" @mouseup.right="rightClickUp"
@mousedown.left="leftClickDown" @mouseup.left="leftClickUp" @mouseenter="mouseenter" @mouseleave="mouseleave">
<template v-if="props.card_id">
<!-- <svg
width="180"
height="250"
viewBox="0 0 298 417"
>
<use
:xlink:href="
`/cards/${settingsStore.cardStyle}/` +
props.card_id.toString().padStart(3, '0') +
extension +
'#card' +
props.card_id
"
@activate_effect="activateEffect($event)"
></use>
</svg> -->
<CardComponent v-if="settingsStore.cardStyle == CardStyles.SVG && props.card" :card="props.card"
:used_effects_indexes="used_effects_indexes" @effectClick="emit('effectClick', $event)"></CardComponent>
<img :class="`card_image`" v-else :src="`/cards/${settingsStore.cardStyle}/` +
props.card_id.toString().padStart(3, '0') +
extension
" draggable="false" />
<div id="overlay">
<slot></slot>
</div>
</template>
<img :class="`card_image`" v-else :src="'/cards/background.png'" draggable="false" />
</div>
</template>
<style scoped>
.card.dragging {
transform: translateX(v-bind("translateX + 'px'")) translateY(v-bind("translateY + 'px'"));
cursor: grabbing;
z-index: 999;
}
.card.dragging>svg {
transform: scale(110%);
}
.card.active {
cursor: pointer;
}
.card_image {
max-height: var(--max-height);
z-index: 1;
height: var(--max-height);
}
.card.wrapped {
height: 1px;
margin: 0;
}
.card.wrapped .card_image {
filter: drop-shadow(0.5px 0.5px 0.5px gray) drop-shadow(-0.5px -0.5px 0.5px gray);
}
.card.zoom {
transform: scale(200%);
z-index: 10;
}
#contextMenuButtons {
position: absolute;
display: flex;
flex-direction: row;
flex-wrap: wrap;
word-break: break-word;
bottom: 0;
width: 99%;
transform: translateY(-0px);
transition: 0.1s transform cubic-bezier(1, 1.81, 0.59, 1.42);
}
.card.active:hover #contextMenuButtons {
transform: translateY(100%);
}
</style>
<style>
.card.no_effects svg>* {
pointer-events: none;
}
#contextMenuButtons>* {
flex: 1;
border-radius: 12px;
min-height: 50px;
}
@keyframes gelatine {
from,
to {}
25% {
transform: scale(1, 1.5);
}
50% {
transform: scale(1.5, 1);
}
75% {
transform: scale(1.1, 1.3);
}
}
.svg_resource_icon {
cursor: pointer;
animation: gelatine 0.3s normal;
transition: all 1s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
.svg_resource_icon:active {
animation: none;
}
.svg_resource_icon:hover {
transform: scale(130%);
}
.used {
opacity: 0.2;
filter: grayscale(0.6);
pointer-events: none;
}
.svg_effect text {
cursor: pointer;
}
.card {
--max-height: 250px;
--max-width: 179px;
--margin-bottom: calc(var(--max-height) * 0.05);
position: relative;
display: flex;
justify-content: center;
margin-bottom: 0px;
margin-top: var(--margin-bottom);
transition: all 0.15s cubic-bezier(0.175, 0.885, 0.32, 1.275);
pointer-events: all;
max-height: var(--max-height);
max-width: var(--max-width);
/* cursor: grab; */
}
.card:not(svg) {
cursor: grab;
}
#overlay {
position: absolute;
top: 20%;
width: calc(100% - 8%);
height: 49%;
}
.card.unlocked {
margin-top: 0px;
margin-bottom: var(--margin-bottom);
transform: translateY(calc(var(--margin-bottom) * -0.25));
filter: drop-shadow(calc(var(--margin-bottom) * 0.3) var(--margin-bottom) 1px rgba(0, 0, 0, 0.6));
cursor: pointer;
}
.card.discardable {
cursor: not-allowed;
}
.card.discardable svg {
pointer-events: none;
}
</style>
-33
View File
@@ -1,33 +0,0 @@
<script setup lang="ts">
const displayOptions = ref(false);
</script>
<template>
<div :class="`card_overlay`" ref="card">
<img
class="settings_button"
src="/img/settings.png"
alt="settings"
@click="displayOptions = true"
/>
</div>
<OptionsDialog :isVisible="displayOptions" @close="displayOptions = false" />
</template>
<style scoped>
.card_overlay {
/* display: none; */
position: fixed;
z-index: 999;
display: flex;
pointer-events: none;
/* top: left: */
top: 0;
}
.settings_button {
pointer-events: all;
width: 30px;
padding: 5px;
}
</style>
View File
-114
View File
@@ -1,114 +0,0 @@
<script setup lang="ts">
import type { Container } from '~/netcode/interfaces';
export interface Props {
container: Container
}
const props = defineProps<Props>()
</script>
<template>
<div class="cards_container" id="self_hand">
<!-- <CardPreview :card_id="c.cardId" v-for="c in container.cards "> -->
<!-- <button v-if="c && goStore.self?.turn && (goStore.self.turn.fuck_u_markers ?? 0) > 0"
@click.stop="discard(c)">DISCARD</button> -->
<!-- </CardPreview> -->
<CardsGrouped :container="container" :wrapped="false">
</CardsGrouped>
</div>
</template>
<style scoped>
.cards_container {
display: flex;
flex-direction: row-reverse;
justify-content: center;
}
.stack_and_discard {
display: flex;
flex-direction: row-reverse;
justify-content: center;
}
#play_all {
display: flex;
flex-direction: row;
align-items: center;
font-size: 10em;
}
#turn_data {
position: fixed;
bottom: 10px;
left: 50%;
right: 50%;
display: flex;
flex-direction: column;
align-items: flex-start;
z-index: 9;
}
.warning {
background-color: rgba(255, 0, 0, 0.7);
color: white;
padding: 5px;
border-radius: 5px;
width: 60px;
font-size: 0.9em;
}
#end_turn {
z-index: 10;
}
#self_hand {
position: fixed;
z-index: 1;
display: flex;
align-items: stretch;
flex-direction: row;
flex-wrap: nowrap;
left: 50%;
bottom: -50px;
max-width: 100vw;
justify-content: flex-start;
transition: 0.5s all cubic-bezier(0.075, 0.82, 0.165, 1);
transform: translate(-50%, 150px)
}
#self_hand:hover {
transform: translate(-50%, 0px);
}
#end_turn {
width: 50px;
height: 50px;
}
</style>
<style>
#self_hand .card {
transition: 0.5s all cubic-bezier(0.075, 0.82, 0.165, 1);
overflow: visible;
}
#self_hand .card #contextMenuButtons {
top: 0;
bottom: unset;
}
#self_hand .card.active:hover #contextMenuButtons {
transform: translateY(-100%);
}
#self_hand .card:hover {
transform: translateY(-40px);
}
</style>
+31
View File
@@ -0,0 +1,31 @@
<script lang="ts">
import { cards } from "~/services/loadCards";
export default {
props: {
cardId: {
required: true,
type: Number,
},
used_effects_indexes: {
default: [],
type: Array,
},
},
data() {
return { cards };
},
beforeCreate() {
console.log(cards);
(this as any).component = () => cards[this.cardId];
},
};
</script>
<template>
<Component
:is="cards[cardId]"
:cardId="cardId"
:used_effects_indexes="used_effects_indexes"
/>
</template>
@@ -7,7 +7,6 @@ import {
type Effect,
type Game,
} from "~/netcode/interfaces";
import TokenComponent from "./tokens/TokenComponent.vue";
export interface Props {
game: Game;
@@ -61,14 +60,29 @@ function tokenClick({ card, token }: { card: Card; token: Effect }) {
<template>
<div class="market">
<CardsGrouped :container="market" @cardClick="marketCardClick" :noEffects="true" :tokens="marketTokens"
@tokenClick="tokenClick">
</CardsGrouped>
<GameCardGrouped
:container="market"
@cardClick="marketCardClick"
:noEffects="true"
:tokens="marketTokens"
@tokenClick="tokenClick"
>
</GameCardGrouped>
<div class="separator"></div>
<CardsGrouped :container="fire_gems" :wrapped="true" @cardClick="fireGemCardClick" :noEffects="true"
:tokens="gemsTokens" @tokenClick="tokenClick"></CardsGrouped>
<GameCardGrouped
:container="fire_gems"
:wrapped="true"
@cardClick="fireGemCardClick"
:noEffects="true"
:tokens="gemsTokens"
@tokenClick="tokenClick"
></GameCardGrouped>
<div class="separator"></div>
<CardsGrouped :container="marketStack" :wrapped="true" :hidden="true"></CardsGrouped>
<GameCardGrouped
:container="marketStack"
:wrapped="true"
:hidden="true"
></GameCardGrouped>
</div>
</template>
@@ -8,7 +8,6 @@ import {
type Effect,
type PlayingTurn,
} from "~/netcode/interfaces";
import TokenComponent from "./tokens/TokenComponent.vue";
export interface Props {
container: Container;
@@ -138,7 +137,7 @@ function discardCardClick(card: Card) {
:class="{ wrapped, rotate: container.shuffling }"
>
<TransitionGroup name="list">
<CardPreview
<GameCardPreview
@click="$emit('cardClick', c._id)"
@effectClick="$emit('effectClick', c._id, $event)"
v-for="(c, i) in cards"
@@ -159,7 +158,7 @@ function discardCardClick(card: Card) {
:discardable="discardable"
>
<template v-for="t in tokens">
<TokenComponent
<GameToken
:token="t"
@useToken="tokenClick(t, c)"
v-if="
@@ -181,7 +180,7 @@ function discardCardClick(card: Card) {
(t.effect == CardEffects.RESTACK_DISCARDED_CHAMPION &&
c.cardType == CardType.CHAMPION)
"
></TokenComponent>
></GameToken>
</template>
<button
v-if="championsKillable && c.cardType == CardType.CHAMPION"
@@ -199,7 +198,7 @@ function discardCardClick(card: Card) {
>
Discard
</button>
</CardPreview>
</GameCardPreview>
</TransitionGroup>
<!-- <img :class="`card_image`" :src="'/cards/background.png'" draggable="false"> -->
</div>
+260
View File
@@ -0,0 +1,260 @@
<script setup lang="ts">
export interface Props {
uuid?: string;
cardId?: number;
locked?: boolean;
wrapped?: boolean;
tilted?: boolean;
interactible?: boolean;
noEffects?: boolean;
used_effects_indexes?: number[];
discardable?: boolean;
}
const props = withDefaults(defineProps<Props>(), {
wrapped: () => false,
tilted: () => true,
locked: () => true,
interactible: () => true,
noEffects: () => false,
discardable: () => false,
});
const emit = defineEmits([
"click",
"effectClick",
"drop",
"move",
"startMove",
"stopMove",
]);
const settingsStore = useSettingsStore();
const childCount = ref<number>(0);
const extension = computed(() => {
if (settingsStore.cardStyle == CardStyles.SVG) {
return ".svg";
}
return ".png";
});
function cardClick() {
if (!props.cardId) return;
emit("click");
}
const isZooming = ref<boolean>(false);
function mouseenter(e: MouseEvent) {
// User is Right Clicking
if ((e.buttons & 2) == 2) {
isZooming.value = true;
}
// goStore.hoveredCard = props.card_id
}
function mouseleave(e: MouseEvent) {
isZooming.value = false;
}
function rightClickDown(e: MouseEvent) {
isZooming.value = true;
}
function rightClickUp(e: MouseEvent) {
isZooming.value = false;
}
</script>
<template>
<div
ref="cardHTMLElement"
class="card"
:class="{
active: childCount > 0,
wrapped,
unlocked: !props.locked,
zoom: isZooming,
no_effects: noEffects || !props.locked,
discardable,
}"
@contextmenu.prevent="false"
@mousedown.right="rightClickDown"
@mouseup.right="rightClickUp"
@mouseenter="mouseenter"
@mouseleave="mouseleave"
>
<template v-if="props.cardId">
<GameCard
v-if="settingsStore.cardStyle == CardStyles.SVG"
:cardId="props.cardId"
:used_effects_indexes="used_effects_indexes"
@effectClick="emit('effectClick', $event)"
></GameCard>
<div id="overlay">
<slot></slot>
</div>
</template>
<img
:class="`card_image`"
v-else
:src="'/cards/background.png'"
draggable="false"
/>
</div>
</template>
<style scoped>
/* .card.dragging {
transform: translateX(v-bind("translateX + 'px'"))
translateY(v-bind("translateY + 'px'"));
cursor: grabbing;
z-index: 999;
} */
/* .card.dragging > svg {
transform: scale(110%);
} */
.card.active {
cursor: pointer;
}
.card_image {
max-height: var(--max-height);
z-index: 1;
height: var(--max-height);
}
.card.wrapped {
height: 1px;
margin: 0;
}
.card.wrapped .card_image {
filter: drop-shadow(0.5px 0.5px 0.5px gray)
drop-shadow(-0.5px -0.5px 0.5px gray);
}
.card.zoom {
transform: scale(200%);
z-index: 10;
}
#contextMenuButtons {
position: absolute;
display: flex;
flex-direction: row;
flex-wrap: wrap;
word-break: break-word;
bottom: 0;
width: 99%;
transform: translateY(-0px);
transition: 0.1s transform cubic-bezier(1, 1.81, 0.59, 1.42);
}
.card.active:hover #contextMenuButtons {
transform: translateY(100%);
}
</style>
<style>
.card.no_effects svg > * {
pointer-events: none;
}
#contextMenuButtons > * {
flex: 1;
border-radius: 12px;
min-height: 50px;
}
@keyframes gelatine {
from,
to {
}
25% {
transform: scale(1, 1.5);
}
50% {
transform: scale(1.5, 1);
}
75% {
transform: scale(1.1, 1.3);
}
}
.svg_resource_icon {
cursor: pointer;
animation: gelatine 0.3s normal;
transition: all 1s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
.svg_resource_icon:active {
animation: none;
}
.svg_resource_icon:hover {
transform: scale(130%);
}
.used {
opacity: 0.2;
filter: grayscale(0.6);
pointer-events: none;
}
.svg_effect text {
cursor: pointer;
}
.card {
--max-height: 250px;
--max-width: 179px;
--margin-bottom: calc(var(--max-height) * 0.05);
position: relative;
display: flex;
justify-content: center;
margin-bottom: 0px;
margin-top: var(--margin-bottom);
transition: all 0.15s cubic-bezier(0.175, 0.885, 0.32, 1.275);
pointer-events: all;
max-height: var(--max-height);
max-width: var(--max-width);
/* cursor: grab; */
}
.card:not(svg) {
cursor: grab;
}
#overlay {
position: absolute;
top: 20%;
width: calc(100% - 8%);
height: 49%;
}
.card.unlocked {
margin-top: 0px;
margin-bottom: var(--margin-bottom);
transform: translateY(calc(var(--margin-bottom) * -0.25));
filter: drop-shadow(
calc(var(--margin-bottom) * 0.3) var(--margin-bottom) 1px rgba(0, 0, 0, 0.6)
);
cursor: pointer;
}
.card.discardable {
cursor: not-allowed;
}
.card.discardable svg {
pointer-events: none;
}
</style>
@@ -8,7 +8,6 @@ import {
type Game,
type Player,
} from "~/netcode/interfaces";
import TokenComponent from "./tokens/TokenComponent.vue";
export interface Props {
game: Game;
@@ -51,7 +50,7 @@ function tokenClick({ card, token }: { card: Card; token: Effect }) {
<span>Discard of {{ player.user.username }}</span>
<div class="discard_unwrapped" @click.stop>
<CardsGrouped
<GameCardPreview
:container="discard"
:wrapped="false"
:hidden="false"
@@ -59,7 +58,7 @@ function tokenClick({ card, token }: { card: Card; token: Effect }) {
:noEffects="true"
:playingTurn="game.currentTurn"
@tokenClick="tokenClick"
></CardsGrouped>
></GameCardPreview>
</div>
</div>
</template>
@@ -1,5 +1,5 @@
<script setup lang="ts">
import type { Player } from "~/netcode/Player";
import type { Player } from "~/netcode/interfaces";
export interface Props {
isVisible: Boolean;
@@ -27,7 +27,7 @@ const close = () => {
<h3 v-else>Défaite!</h3>
</div>
<div class="dialog-body">
<PlayerIcon :player="players[0]"></PlayerIcon>
<GamePlayerIcon :player="players[0]"></GamePlayerIcon>
<p v-if="won">Vous avez gagné!</p>
<p v-else>
Vous avez perdu face à ce magnifique individu qui a très clairement
@@ -60,11 +60,12 @@ function damage() {
Prêt!
</div> -->
<div id="player_info">
<PlayerIcon :player="props.player"></PlayerIcon>
<GamePlayerIcon :player="props.player"></GamePlayerIcon>
</div>
<div id="player_stats">
<!-- <template v-if="goStore.current_game?.started"> -->
<PlayerStats :game="props.game" :player="props.player"> </PlayerStats>
<GamePlayerStats :game="props.game" :player="props.player">
</GamePlayerStats>
<!-- </template> -->
</div>
<button
+108
View File
@@ -0,0 +1,108 @@
<script setup lang="ts">
import type { Container } from "~/netcode/interfaces";
export interface Props {
container: Container;
}
const props = defineProps<Props>();
</script>
<template>
<div class="cards_container" id="self_hand">
<!-- <CardPreview :card_id="c.cardId" v-for="c in container.cards "> -->
<!-- <button v-if="c && goStore.self?.turn && (goStore.self.turn.fuck_u_markers ?? 0) > 0"
@click.stop="discard(c)">DISCARD</button> -->
<!-- </CardPreview> -->
<GameCardGrouped :container="container" :wrapped="false"> </GameCardGrouped>
</div>
</template>
<style scoped>
.cards_container {
display: flex;
flex-direction: row-reverse;
justify-content: center;
}
.stack_and_discard {
display: flex;
flex-direction: row-reverse;
justify-content: center;
}
#play_all {
display: flex;
flex-direction: row;
align-items: center;
font-size: 10em;
}
#turn_data {
position: fixed;
bottom: 10px;
left: 50%;
right: 50%;
display: flex;
flex-direction: column;
align-items: flex-start;
z-index: 9;
}
.warning {
background-color: rgba(255, 0, 0, 0.7);
color: white;
padding: 5px;
border-radius: 5px;
width: 60px;
font-size: 0.9em;
}
#end_turn {
z-index: 10;
}
#self_hand {
position: fixed;
z-index: 1;
display: flex;
align-items: stretch;
flex-direction: row;
flex-wrap: nowrap;
left: 50%;
bottom: -50px;
max-width: 100vw;
justify-content: flex-start;
transition: 0.5s all cubic-bezier(0.075, 0.82, 0.165, 1);
transform: translate(-50%, 150px);
}
#self_hand:hover {
transform: translate(-50%, 0px);
}
#end_turn {
width: 50px;
height: 50px;
}
</style>
<style>
#self_hand .card {
transition: 0.5s all cubic-bezier(0.075, 0.82, 0.165, 1);
overflow: visible;
}
#self_hand .card #contextMenuButtons {
top: 0;
bottom: unset;
}
#self_hand .card.active:hover #contextMenuButtons {
transform: translateY(-100%);
}
#self_hand .card:hover {
transform: translateY(-40px);
}
</style>
@@ -198,7 +198,7 @@ function discardCardClick(card: Card) {
</div> -->
<!-- <br /> -->
<CardsGrouped
<GameCardGrouped
:container="player.board"
:wrapped="false"
:playingTurn="props.game.currentTurn"
@@ -213,8 +213,8 @@ function discardCardClick(card: Card) {
@damageChampionClick="damageChampionClick"
@discardCardClick="discardCardClick"
>
</CardsGrouped>
<br>
</GameCardGrouped>
<br />
<!-- <div class="cards_container"> -->
<!-- HAND -->
<!-- <template v-if="isSelf">
+1 -5
View File
@@ -33,12 +33,8 @@ export default defineNuxtRouteMiddleware(async (to, from) => {
// return navigateTo('/login')
// }
// }
console.log(to.path);
if (to.path.startsWith("/game")) {
console.log(to.query.id);
// if (Array.isArray(to.query.id)) {
// return navigateTo("/lobby");
// }
return;
}
if (to.path == "/login") {
+90 -54
View File
@@ -1,5 +1,5 @@
<script setup lang="ts">
import LoadingScreen from "~/components/LoadingScreen.vue";
import LoadingScreen from "~/components/game/overlay/LoadingScreen.vue";
import { endTurn, subscribe, useToken } from "~/netcode";
import { delay } from "~/netcode/events";
import {
@@ -9,7 +9,6 @@ import {
type Player,
} from "~/netcode/interfaces";
import { playSound } from "~/helpers/audioHelpers";
import TokenComponent from "~/components/tokens/TokenComponent.vue";
const config = useRuntimeConfig();
const settingsStore = useSettingsStore();
@@ -18,19 +17,18 @@ const authStore = useAuthStore();
const route = useRoute();
const gameId = route.query.id;
const {
data: game,
pending,
error,
refresh,
execute
execute,
} = await useFetch<Game>(config.public.endpoint + `/games/${gameId}`, {
credentials: "include",
server: false
server: false,
});
const awaitGameReady = execute()
const awaitGameReady = execute();
const containers = computed<Record<string, Container>>(() => ({
[game.value!.fireGems._id]: game.value!.fireGems,
@@ -70,7 +68,7 @@ async function execAction(callback: () => Promise<any>) {
const handlers = {
start: async () => {
throw new Error("not implemented")
throw new Error("not implemented");
},
populateContainer: async (data: any) => {
const fromContainer = containers.value[data.container._id as string];
@@ -146,9 +144,7 @@ const handlers = {
await delay(settingsStore.animationSpeed);
},
unlockEffect: async (data: any, game: Game) => {
const effectIndex = game.currentTurn.lockedEffects.indexOf(
data.effect
);
const effectIndex = game.currentTurn.lockedEffects.indexOf(data.effect);
game.currentTurn.lockedEffects.splice(effectIndex, 1);
await delay(settingsStore.animationSpeed);
},
@@ -183,9 +179,7 @@ const handlers = {
},
"player.addFuckUMarker": async (data: any, game: Game) => {
console.log(`adding fuckUMarkers : ` + data.operation);
const targetPlayer = playerList.value?.find(
(p) => p._id == data.playerId
);
const targetPlayer = playerList.value?.find((p) => p._id == data.playerId);
if (!targetPlayer) {
throw new Error("Cannot add fuckU Markers : player not found");
}
@@ -193,9 +187,7 @@ const handlers = {
},
"player.removeFuckUMarker": async (data: any, game: Game) => {
console.log(`adding fuckUMarkers : ` + data.operation);
const targetPlayer = playerList.value?.find(
(p) => p._id == data.playerId
);
const targetPlayer = playerList.value?.find((p) => p._id == data.playerId);
if (!targetPlayer) {
throw new Error("Cannot remove fuckU Markers : player not found");
}
@@ -203,9 +195,7 @@ const handlers = {
},
"player.addDiscardMarker": async (data: any, game: Game) => {
console.log(`adding discardMarkers : ` + data.operation);
const targetPlayer = playerList.value?.find(
(p) => p._id == data.playerId
);
const targetPlayer = playerList.value?.find((p) => p._id == data.playerId);
if (!targetPlayer) {
throw new Error("Cannot add discard Markers : player not found");
}
@@ -213,9 +203,7 @@ const handlers = {
},
"player.removeDiscardMarker": async (data: any, game: Game) => {
console.log(`adding fuckUMarkers : ` + data.operation);
const targetPlayer = playerList.value?.find(
(p) => p._id == data.playerId
);
const targetPlayer = playerList.value?.find((p) => p._id == data.playerId);
if (!targetPlayer) {
throw new Error("Cannot remove discard Markers : player not found");
}
@@ -231,21 +219,21 @@ const handlers = {
game.teams.splice(index, 1);
},
consumeEffect: async (data: any) => {
console.warn("consumeEffect not implemented")
console.warn("consumeEffect not implemented");
},
endGame: async () => {
alert("game ended")
}
}
alert("game ended");
},
};
onMounted(async () => {
awaitGameReady.then(() => {
console.log(game.value)
console.log(game.value);
if (game.value == null) {
navigateTo("/lobby");
throw new Error("game not found");
}
focusedPlayer.value = (selfPlayer.value ?? playerList.value![0])
focusedPlayer.value = selfPlayer.value ?? playerList.value![0];
eventSource = subscribe(`/games/${gameId}/subscribe`);
eventSource.addEventListener("message", async (message) => {
@@ -255,15 +243,16 @@ onMounted(async () => {
}
const data = JSON.parse(message.data);
queueAction(async () => {
await handlers[data.type as keyof typeof handlers](data, current_game)
})
await handlers[data.type as keyof typeof handlers](data, current_game);
});
});
});
})
});
const playerList = computed(() =>
game.value && game.value.teams.reduce((acc, t) => acc.concat(t.players), [] as Player[])
const playerList = computed(
() =>
game.value &&
game.value.teams.reduce((acc, t) => acc.concat(t.players), [] as Player[])
);
const selfPlayer = computed(() =>
authStore.logged
@@ -338,48 +327,95 @@ onUnmounted(() => {
<template>
<div @contextmenu.prevent="false" id="game_board">
<AnimatedBackground @ready="loaded = true" :isTurn="isTurn ?? false"></AnimatedBackground>
<AnimatedBackground
@ready="loaded = true"
:isTurn="isTurn ?? false"
></AnimatedBackground>
<!-- <AnimatedBackground :isTurn="false"></AnimatedBackground> -->
<template v-if="game && focusedPlayer && playerList">
<Transition name="slide-left" mode="out-in">
<div id="stack_discard" :key="focusedPlayer?._id">
<div id="stack">
<CardsGrouped :container="focusedPlayer.stack" :wrapped="true" :hidden="true">
</CardsGrouped>
<GameCardGrouped
:container="focusedPlayer.stack"
:wrapped="true"
:hidden="true"
>
</GameCardGrouped>
</div>
<div id="discard" :class="{ invisible: discard_unwrapped }" @click="() => (discard_unwrapped = true)">
<CardsGrouped :container="focusedPlayer.discard" :wrapped="true" @card-click="showDiscard"
:no-effects="true">
</CardsGrouped>
<div
id="discard"
:class="{ invisible: discard_unwrapped }"
@click="() => (discard_unwrapped = true)"
>
<GameCardGrouped
:container="focusedPlayer.discard"
:wrapped="true"
@card-click="showDiscard"
:no-effects="true"
>
</GameCardGrouped>
</div>
</div>
</Transition>
<MarketCards :game="game" :market="game.market" :fire_gems="game.fireGems" :marketStack="game.marketStack">
</MarketCards>
<GameMarket
:game="game"
:market="game.market"
:fire_gems="game.fireGems"
:marketStack="game.marketStack"
>
</GameMarket>
<div>
<TokenComponent :token="t" v-for="t in game.currentTurn.tokens" @useToken="useTokenClick"></TokenComponent>
<GameToken
:token="t"
v-for="t in game.currentTurn.tokens"
@useToken="useTokenClick"
></GameToken>
</div>
<div id="player_list_container">
<div id="player_list">
<PlayerListElement v-for="p in playerList" :player="p" :game="game" @click="focusPlayer(p)"
:focused="focusedPlayer == p" :self="selfPlayer == p">
</PlayerListElement>
<GamePlayerListElement
v-for="p in playerList"
:player="p"
:game="game"
@click="focusPlayer(p)"
:focused="focusedPlayer == p"
:self="selfPlayer == p"
>
</GamePlayerListElement>
</div>
</div>
<div id="current_player">
<Transition name="slide-left" mode="out-in">
<PlayerSlot v-if="focusedPlayer" :player="focusedPlayer" :game="game" :key="focusedPlayer._id"></PlayerSlot>
<GamePlayerSlot
v-if="focusedPlayer"
:player="focusedPlayer"
:game="game"
:key="focusedPlayer._id"
></GamePlayerSlot>
</Transition>
</div>
<DiscardOverlay v-show="discard_unwrapped" :game="game" :player="focusedPlayer" :discard="focusedPlayer.discard"
@close="discard_unwrapped = false"></DiscardOverlay>
<ResultDialog :isVisible="showResults" :won="isWinner" :players="playerList" @close="showResults = false">
</ResultDialog>
<GlobalOverlay></GlobalOverlay>
<SelfView v-if="selfPlayer" :container="selfPlayer.hand"></SelfView>
<GameOverlayDiscard
v-show="discard_unwrapped"
:game="game"
:player="focusedPlayer"
:discard="focusedPlayer.discard"
@close="discard_unwrapped = false"
></GameOverlayDiscard>
<GameOverlayResultDialog
:isVisible="showResults"
:won="isWinner"
:players="playerList"
@close="showResults = false"
>
</GameOverlayResultDialog>
<GamePlayerSelf
v-if="selfPlayer"
:container="selfPlayer.hand"
></GamePlayerSelf>
</template>
<!-- <LoadingScreen v-if="!loaded"></LoadingScreen> -->
</div>
+1 -2
View File
@@ -20,7 +20,6 @@ function killErika() {
onBeforeMount(async () => {
games.value = (await getLobby()).value;
console.log(games.value);
eventSource = subscribe("/games/subscribe");
eventSource.addEventListener("message", (message) => {
const data = JSON.parse(message.data);
@@ -61,7 +60,7 @@ onUnmounted(() => {
<div v-for="g in games">
<button
v-if="g"
@click="router.push({ path: `/game`, query:{id:g._id} })"
@click="router.push({ path: `/game`, query: { id: g._id } })"
:class="
authStore.selfUser.userId == g.owner.userId ? 'own_game' : ''
"
+36 -33
View File
@@ -31,10 +31,10 @@ const router = useRouter();
<p>&#8203;</p>
<p>Et quoi de mieux pour faire ça que des cartes colorées?</p>
<div class="card-row">
<CardPreview :card_id="6" :tilted="false"></CardPreview>
<CardPreview :card_id="19" :tilted="false"></CardPreview>
<CardPreview :card_id="36" :tilted="false"></CardPreview>
<CardPreview :card_id="46" :tilted="false"></CardPreview>
<GameCardPreview :card_id="6" :tilted="false"></GameCardPreview>
<GameCardPreview :card_id="19" :tilted="false"></GameCardPreview>
<GameCardPreview :card_id="36" :tilted="false"></GameCardPreview>
<GameCardPreview :card_id="46" :tilted="false"></GameCardPreview>
</div>
<p>&#8203;</p>
<hr />
@@ -60,7 +60,10 @@ const router = useRouter();
"deck" et ce qui nous permet de le "build".
</p>
<div class="card-row">
<CardPreview :card_id="undefined" :tilted="false"></CardPreview>
<GameCardPreview
:card_id="undefined"
:tilted="false"
></GameCardPreview>
</div>
<p>&#8203;</p>
<p>
@@ -87,10 +90,10 @@ const router = useRouter();
<li>1x Dégats (2)</li>
</ul>
<div class="card-row">
<CardPreview :card_id="56" :tilted="false"></CardPreview>
<CardPreview :card_id="59" :tilted="false"></CardPreview>
<CardPreview :card_id="58" :tilted="false"></CardPreview>
<CardPreview :card_id="57" :tilted="false"></CardPreview>
<GameCardPreview :card_id="56" :tilted="false"></GameCardPreview>
<GameCardPreview :card_id="59" :tilted="false"></GameCardPreview>
<GameCardPreview :card_id="58" :tilted="false"></GameCardPreview>
<GameCardPreview :card_id="57" :tilted="false"></GameCardPreview>
</div>
<p>
La pioche est formée au hasard: on peut donc avoir une main de départ
@@ -112,15 +115,15 @@ const router = useRouter();
champions.
</p>
<div class="card-row">
<CardPreview :card_id="56" :tilted="false"></CardPreview>
<CardPreview :card_id="52" :tilted="false"></CardPreview>
<CardPreview :card_id="43" :tilted="false"></CardPreview>
<GameCardPreview :card_id="56" :tilted="false"></GameCardPreview>
<GameCardPreview :card_id="52" :tilted="false"></GameCardPreview>
<GameCardPreview :card_id="43" :tilted="false"></GameCardPreview>
</div>
<p>&#8203;</p>
<h3>Objets & actions</h3>
<div class="card-row">
<CardPreview :card_id="56" :tilted="false"></CardPreview>
<CardPreview :card_id="52" :tilted="false"></CardPreview>
<GameCardPreview :card_id="56" :tilted="false"></GameCardPreview>
<GameCardPreview :card_id="52" :tilted="false"></GameCardPreview>
</div>
<p>
Par simplicité, disons que les objets et les actions sont pareil: on
@@ -129,7 +132,7 @@ const router = useRouter();
</p>
<h3>Champions (& gardes)</h3>
<div class="card-row">
<CardPreview :card_id="43" :tilted="false"></CardPreview>
<GameCardPreview :card_id="43" :tilted="false"></GameCardPreview>
</div>
<p>
Les champions sont un peu plus complexes: ils restent sur le terrain,
@@ -150,7 +153,7 @@ const router = useRouter();
de dégats pendant un tour, et un peu le tour d'après pour les tuer.
</p>
<div class="card-row">
<CardPreview :card_id="49" :tilted="false"></CardPreview>
<GameCardPreview :card_id="49" :tilted="false"></GameCardPreview>
</div>
<p>
Par ailleurs, certains champions sont des Gardes
@@ -180,10 +183,10 @@ const router = useRouter();
exclusivement à accomplir ce but: acheter des cartes.
</p>
<div class="card-row">
<CardPreview :card_id="6" :tilted="false"></CardPreview>
<CardPreview :card_id="19" :tilted="false"></CardPreview>
<CardPreview :card_id="36" :tilted="false"></CardPreview>
<CardPreview :card_id="46" :tilted="false"></CardPreview>
<GameCardPreview :card_id="6" :tilted="false"></GameCardPreview>
<GameCardPreview :card_id="19" :tilted="false"></GameCardPreview>
<GameCardPreview :card_id="36" :tilted="false"></GameCardPreview>
<GameCardPreview :card_id="46" :tilted="false"></GameCardPreview>
</div>
<p>
Un marché est mis à disposition de tous les joueurs, mettant à
@@ -208,9 +211,9 @@ const router = useRouter();
</p>
<p>&#8203;</p>
<div class="card-row">
<CardPreview :card_id="13" :tilted="false"></CardPreview>
<CardPreview :card_id="3" :tilted="false"></CardPreview>
<CardPreview :card_id="1" :tilted="false"></CardPreview>
<GameCardPreview :card_id="13" :tilted="false"></GameCardPreview>
<GameCardPreview :card_id="3" :tilted="false"></GameCardPreview>
<GameCardPreview :card_id="1" :tilted="false"></GameCardPreview>
</div>
<p>&#8203;</p>
<p>
@@ -222,9 +225,9 @@ const router = useRouter();
</p>
<p>&#8203;</p>
<div class="card-row">
<CardPreview :card_id="39" :tilted="false"></CardPreview>
<CardPreview :card_id="34" :tilted="false"></CardPreview>
<CardPreview :card_id="40" :tilted="false"></CardPreview>
<GameCardPreview :card_id="39" :tilted="false"></GameCardPreview>
<GameCardPreview :card_id="34" :tilted="false"></GameCardPreview>
<GameCardPreview :card_id="40" :tilted="false"></GameCardPreview>
</div>
<p>&#8203;</p>
<p>
@@ -237,9 +240,9 @@ const router = useRouter();
</p>
<p>&#8203;</p>
<div class="card-row">
<CardPreview :card_id="52" :tilted="false"></CardPreview>
<CardPreview :card_id="46" :tilted="false"></CardPreview>
<CardPreview :card_id="47" :tilted="false"></CardPreview>
<GameCardPreview :card_id="52" :tilted="false"></GameCardPreview>
<GameCardPreview :card_id="46" :tilted="false"></GameCardPreview>
<GameCardPreview :card_id="47" :tilted="false"></GameCardPreview>
</div>
<p>&#8203;</p>
<p>
@@ -252,9 +255,9 @@ const router = useRouter();
</p>
<p>&#8203;</p>
<div class="card-row">
<CardPreview :card_id="24" :tilted="false"></CardPreview>
<CardPreview :card_id="25" :tilted="false"></CardPreview>
<CardPreview :card_id="19" :tilted="false"></CardPreview>
<GameCardPreview :card_id="24" :tilted="false"></GameCardPreview>
<GameCardPreview :card_id="25" :tilted="false"></GameCardPreview>
<GameCardPreview :card_id="19" :tilted="false"></GameCardPreview>
</div>
<p>&#8203;</p>
<p>
@@ -272,7 +275,7 @@ const router = useRouter();
Les effets de cartes peuvent se déclencher pour 3 raisons différentes.
</p>
<div class="card-row">
<CardPreview :card_id="14" :tilted="false"></CardPreview>
<GameCardPreview :card_id="14" :tilted="false"></GameCardPreview>
</div>
<p>Sur cette carte, on peut voir les trois en même temps.</p>
<p>La 1ère ligne s'active tout le temps.</p>
+1
View File
@@ -6,5 +6,6 @@ config.public.welcomeMessage;
<template>
<div>
{{ config.public.welcomeMessage }}
<GameCardPreview :cardId="6" :tilted="false"></GameCardPreview>
</div>
</template>
+102 -45
View File
@@ -30,17 +30,18 @@
*/
/* global define */
(function(root, factory) { // eslint-disable-line
if (typeof define === 'function' && define.amd) {
(function (root, factory) {
// eslint-disable-line
if (typeof define === "function" && define.amd) {
// AMD. Register as an anonymous module.
define([], function() {
define([], function () {
return factory.call(root);
});
} else {
// Browser globals
root.webglUtils = factory.call(root);
}
}(this, function() {
})(this, function () {
"use strict";
const topWindow = this;
@@ -53,8 +54,8 @@
}
if (!isInIFrame()) {
console.log("%c%s", 'color:blue;font-weight:bold;', 'for more about webgl-utils.js see:'); // eslint-disable-line
console.log("%c%s", 'color:blue;font-weight:bold;', 'http://webgl2fundamentals.org/webgl/lessons/webgl-boilerplate.html'); // eslint-disable-line
// console.log("%c%s", 'color:blue;font-weight:bold;', 'for more about webgl-utils.js see:'); // eslint-disable-line
// console.log("%c%s", 'color:blue;font-weight:bold;', 'http://webgl2fundamentals.org/webgl/lessons/webgl-boilerplate.html'); // eslint-disable-line
}
/**
@@ -72,23 +73,27 @@
}
const errorRE = /ERROR:\s*\d+:(\d+)/gi;
function addLineNumbersWithError(src, log = '') {
function addLineNumbersWithError(src, log = "") {
// Note: Error message formats are not defined by any spec so this may or may not work.
const matches = [...log.matchAll(errorRE)];
const lineNoToErrorMap = new Map(matches.map((m, ndx) => {
const lineNoToErrorMap = new Map(
matches.map((m, ndx) => {
const lineNo = parseInt(m[1]);
const next = matches[ndx + 1];
const end = next ? next.index : log.length;
const msg = log.substring(m.index, end);
return [lineNo - 1, msg];
}));
return src.split('\n').map((line, lineNo) => {
})
);
return src
.split("\n")
.map((line, lineNo) => {
const err = lineNoToErrorMap.get(lineNo);
return `${lineNo + 1}: ${line}${err ? `\n\n^^^ ${err}` : ''}`;
}).join('\n');
return `${lineNo + 1}: ${line}${err ? `\n\n^^^ ${err}` : ""}`;
})
.join("\n");
}
/**
* Error Callback
* @callback ErrorCallback
@@ -120,7 +125,12 @@
if (!compiled) {
// Something went wrong during compilation; get the error
const lastError = gl.getShaderInfoLog(shader);
errFn(`Error compiling shader: ${lastError}\n${addLineNumbersWithError(shaderSource, lastError)}`);
errFn(
`Error compiling shader: ${lastError}\n${addLineNumbersWithError(
shaderSource,
lastError
)}`
);
gl.deleteShader(shader);
return null;
}
@@ -139,18 +149,24 @@
* @memberOf module:webgl-utils
*/
function createProgram(
gl, shaders, opt_attribs, opt_locations, opt_errorCallback) {
gl,
shaders,
opt_attribs,
opt_locations,
opt_errorCallback
) {
const errFn = opt_errorCallback || error;
const program = gl.createProgram();
shaders.forEach(function(shader) {
shaders.forEach(function (shader) {
gl.attachShader(program, shader);
});
if (opt_attribs) {
opt_attribs.forEach(function(attrib, ndx) {
opt_attribs.forEach(function (attrib, ndx) {
gl.bindAttribLocation(
program,
opt_locations ? opt_locations[ndx] : ndx,
attrib);
attrib
);
});
}
gl.linkProgram(program);
@@ -160,13 +176,15 @@
if (!linked) {
// something went wrong with the link
const lastError = gl.getProgramInfoLog(program);
errFn(`Error in program linking: ${lastError}\n${
shaders.map(shader => {
errFn(
`Error in program linking: ${lastError}\n${shaders
.map((shader) => {
const src = addLineNumbersWithError(gl.getShaderSource(shader));
const type = gl.getShaderParameter(shader, gl.SHADER_TYPE);
return `${glEnumToString(gl, type)}:\n${src}`;
}).join('\n')
}`);
})
.join("\n")}`
);
gl.deleteProgram(program);
return null;
@@ -184,12 +202,16 @@
* @return {WebGLShader} The created shader.
*/
function createShaderFromScript(
gl, scriptId, opt_shaderType, opt_errorCallback) {
gl,
scriptId,
opt_shaderType,
opt_errorCallback
) {
let shaderSource = "";
let shaderType;
const shaderScript = document.getElementById(scriptId);
if (!shaderScript) {
throw ("*** Error: unknown script element" + scriptId);
throw "*** Error: unknown script element" + scriptId;
}
shaderSource = shaderScript.text;
@@ -198,20 +220,23 @@
shaderType = gl.VERTEX_SHADER;
} else if (shaderScript.type === "x-shader/x-fragment") {
shaderType = gl.FRAGMENT_SHADER;
} else if (shaderType !== gl.VERTEX_SHADER && shaderType !== gl.FRAGMENT_SHADER) {
throw ("*** Error: unknown shader type");
} else if (
shaderType !== gl.VERTEX_SHADER &&
shaderType !== gl.FRAGMENT_SHADER
) {
throw "*** Error: unknown shader type";
}
}
return loadShader(
gl, shaderSource, opt_shaderType ? opt_shaderType : shaderType,
opt_errorCallback);
gl,
shaderSource,
opt_shaderType ? opt_shaderType : shaderType,
opt_errorCallback
);
}
const defaultShaderType = [
"VERTEX_SHADER",
"FRAGMENT_SHADER",
];
const defaultShaderType = ["VERTEX_SHADER", "FRAGMENT_SHADER"];
/**
* Creates a program from 2 script tags.
@@ -229,13 +254,30 @@
* @memberOf module:webgl-utils
*/
function createProgramFromScripts(
gl, shaderScriptIds, opt_attribs, opt_locations, opt_errorCallback) {
gl,
shaderScriptIds,
opt_attribs,
opt_locations,
opt_errorCallback
) {
const shaders = [];
for (let ii = 0; ii < shaderScriptIds.length; ++ii) {
shaders.push(createShaderFromScript(
gl, shaderScriptIds[ii], gl[defaultShaderType[ii]], opt_errorCallback));
shaders.push(
createShaderFromScript(
gl,
shaderScriptIds[ii],
gl[defaultShaderType[ii]],
opt_errorCallback
)
);
}
return createProgram(gl, shaders, opt_attribs, opt_locations, opt_errorCallback);
return createProgram(
gl,
shaders,
opt_attribs,
opt_locations,
opt_errorCallback
);
}
/**
@@ -254,13 +296,30 @@
* @memberOf module:webgl-utils
*/
function createProgramFromSources(
gl, shaderSources, opt_attribs, opt_locations, opt_errorCallback) {
gl,
shaderSources,
opt_attribs,
opt_locations,
opt_errorCallback
) {
const shaders = [];
for (let ii = 0; ii < shaderSources.length; ++ii) {
shaders.push(loadShader(
gl, shaderSources[ii], gl[defaultShaderType[ii]], opt_errorCallback));
shaders.push(
loadShader(
gl,
shaderSources[ii],
gl[defaultShaderType[ii]],
opt_errorCallback
)
);
}
return createProgram(gl, shaders, opt_attribs, opt_locations, opt_errorCallback);
return createProgram(
gl,
shaders,
opt_attribs,
opt_locations,
opt_errorCallback
);
}
/**
@@ -273,8 +332,8 @@
*/
function resizeCanvasToDisplaySize(canvas, multiplier) {
multiplier = multiplier || 1;
const width = canvas.clientWidth * multiplier | 0;
const height = canvas.clientHeight * multiplier | 0;
const width = (canvas.clientWidth * multiplier) | 0;
const height = (canvas.clientHeight * multiplier) | 0;
if (canvas.width !== width || canvas.height !== height) {
canvas.width = width;
canvas.height = height;
@@ -289,6 +348,4 @@
createProgramFromSources: createProgramFromSources,
resizeCanvasToDisplaySize: resizeCanvasToDisplaySize,
};
}));
});
+2 -2
View File
@@ -42,7 +42,7 @@ export async function compileCards(app: App<any>) {
try {
let template: string;
if (process.dev && !process.client) {
template = (await import(k + "?raw" /* @vite-ignore */)).default;
template = (await import(/* @vite-ignore */ k + "?raw")).default;
} else {
template = await (await fetch(url)).text();
}
@@ -56,7 +56,7 @@ export async function compileCards(app: App<any>) {
defineAsyncComponent({
loader: async () =>
defineComponent({
props: ["used_effects_indexes", "card"],
props: ["used_effects_indexes", "cardId"],
methods: {
effectClick(effect: number) {
this.$emit("effectClick", effect);