All checks were successful
Build and Push Docker Image / build (push) Successful in 2m20s
801 lines
17 KiB
Vue
801 lines
17 KiB
Vue
<script setup lang="ts">
|
|
import gsap from "gsap";
|
|
import { useWindowSize } from "@vueuse/core";
|
|
|
|
const app = useAppStore();
|
|
const windowSize = useWindowSize();
|
|
const hintsContainer = useTemplateRef("hintsContainer");
|
|
|
|
const { assets } = useAssets();
|
|
|
|
const introState = reactive({
|
|
scaleMultiplier: 1,
|
|
rotateX: 0,
|
|
rotateY: 0,
|
|
opacity: 1,
|
|
});
|
|
|
|
let introPlayed = false;
|
|
|
|
onMounted(() => {
|
|
if (app.booted || app.settings.renderingMode !== "2d" || introPlayed) return;
|
|
introPlayed = true;
|
|
|
|
introState.scaleMultiplier = 0.6;
|
|
introState.rotateX = 70;
|
|
introState.rotateY = 0;
|
|
introState.opacity = 0;
|
|
|
|
assets.audio.whoosh.play();
|
|
|
|
gsap.to(introState, {
|
|
scaleMultiplier: 1,
|
|
rotateX: 0,
|
|
rotateY: 360,
|
|
opacity: 1,
|
|
duration: 2.8,
|
|
ease: "power2.inOut",
|
|
});
|
|
});
|
|
|
|
const buttonsDown = reactive(new Set<string>());
|
|
let mousePressedButton: string | null = null;
|
|
|
|
const dPadStyle = computed(() => {
|
|
const rx =
|
|
(buttonsDown.has("UP") ? -1 : 0) + (buttonsDown.has("DOWN") ? 1 : 0);
|
|
const ry =
|
|
(buttonsDown.has("LEFT") ? -1 : 0) + (buttonsDown.has("RIGHT") ? 1 : 0);
|
|
if (!rx && !ry) return {};
|
|
return { transform: `rotateX(${rx * 12}deg) rotateY(${ry * 12}deg)` };
|
|
});
|
|
|
|
const pressButton = (button: string) => {
|
|
if (mousePressedButton) {
|
|
buttonsDown.delete(mousePressedButton);
|
|
window.dispatchEvent(
|
|
new KeyboardEvent("keyup", { key: `NDS_${mousePressedButton}` }),
|
|
);
|
|
}
|
|
buttonsDown.add(button);
|
|
mousePressedButton = button;
|
|
window.dispatchEvent(new KeyboardEvent("keydown", { key: `NDS_${button}` }));
|
|
};
|
|
|
|
const releaseButton = () => {
|
|
if (!mousePressedButton) return;
|
|
buttonsDown.delete(mousePressedButton);
|
|
window.dispatchEvent(
|
|
new KeyboardEvent("keyup", { key: `NDS_${mousePressedButton}` }),
|
|
);
|
|
mousePressedButton = null;
|
|
};
|
|
|
|
useKeyDown(({ ndsButton }) => {
|
|
if (ndsButton) buttonsDown.add(ndsButton);
|
|
});
|
|
|
|
useKeyUp(({ ndsButton }) => {
|
|
if (ndsButton) buttonsDown.delete(ndsButton);
|
|
});
|
|
|
|
useMouseUp(releaseButton);
|
|
|
|
const handleTouchEnd = (event: TouchEvent) => {
|
|
releaseButton();
|
|
|
|
const touch = event.changedTouches[0];
|
|
if (!touch) return;
|
|
|
|
document.dispatchEvent(
|
|
new MouseEvent("mouseup", {
|
|
clientX: touch.clientX,
|
|
clientY: touch.clientY,
|
|
}),
|
|
);
|
|
};
|
|
|
|
const ndsScale = computed(() => {
|
|
const scaleX = (windowSize.width.value - 40) / 235;
|
|
const scaleY = (windowSize.height.value - 40) / 431;
|
|
return Math.min(scaleX, scaleY);
|
|
});
|
|
|
|
const gallery = useGalleryStore();
|
|
const TOP_SCREEN_OFFSET = 170;
|
|
|
|
const ndsStyle = computed(() => {
|
|
const scale =
|
|
ndsScale.value * gallery.zoom.scale * introState.scaleMultiplier;
|
|
const y = TOP_SCREEN_OFFSET * ndsScale.value * (gallery.zoom.scale - 1);
|
|
return {
|
|
transform: `translateY(${y}px) scale(${scale}) rotateX(${introState.rotateX}deg) rotateY(${introState.rotateY}deg)`,
|
|
opacity: introState.opacity,
|
|
};
|
|
});
|
|
|
|
const showBackFace = computed(() => {
|
|
const r = ((introState.rotateY % 360) + 360) % 360;
|
|
return r > 90 && r < 270;
|
|
});
|
|
|
|
watch(
|
|
() => app.hintsVisible,
|
|
async (show) => {
|
|
await nextTick();
|
|
if (!hintsContainer.value) return;
|
|
if (show) {
|
|
gsap.fromTo(
|
|
hintsContainer.value,
|
|
{ opacity: 0 },
|
|
{ opacity: 1, duration: 0.2, ease: "power1.out" },
|
|
);
|
|
} else {
|
|
gsap.to(hintsContainer.value, {
|
|
opacity: 0,
|
|
duration: 0.2,
|
|
ease: "power1.in",
|
|
});
|
|
}
|
|
},
|
|
);
|
|
</script>
|
|
|
|
<template>
|
|
<div class="nds2d-container">
|
|
<div class="nds2d" :style="ndsStyle">
|
|
<div v-if="showBackFace" class="nds2d-top-screen"></div>
|
|
<div v-else class="nds2d-top-screen">
|
|
<div class="nds2d-speaker-hole nds2d-sh1"></div>
|
|
<div class="nds2d-speaker-hole nds2d-sh2"></div>
|
|
<div class="nds2d-screen nds2d-screen-top">
|
|
<slot name="topScreen" />
|
|
</div>
|
|
<div class="nds2d-speaker-hole nds2d-sh3"></div>
|
|
<div class="nds2d-speaker-hole nds2d-sh4"></div>
|
|
</div>
|
|
<div class="nds2d-hinge">
|
|
<div v-if="!showBackFace" class="nds2d-mic"></div>
|
|
<div v-if="!showBackFace" class="nds2d-light"></div>
|
|
</div>
|
|
<div v-if="showBackFace" class="nds2d-bottom-screen"></div>
|
|
<div v-else class="nds2d-bottom-screen">
|
|
<div class="nds2d-screen nds2d-screen-bottom">
|
|
<slot name="bottomScreen" />
|
|
</div>
|
|
|
|
<div class="nds2d-d-pad-shadow"></div>
|
|
<div class="nds2d-d-pad">
|
|
<div class="nds2d-d-pad-inner" :style="dPadStyle">
|
|
<div class="nds2d-d-pad-base"></div>
|
|
<div class="nds2d-d-pad-light"></div>
|
|
<div
|
|
class="nds2d-d-pad-tip nds2d-tip-up"
|
|
:class="{ pressed: buttonsDown.has('UP') }"
|
|
@mousedown.prevent="pressButton('UP')"
|
|
@touchstart.prevent="pressButton('UP')"
|
|
@touchend="handleTouchEnd"
|
|
></div>
|
|
<div
|
|
class="nds2d-d-pad-tip nds2d-tip-down"
|
|
:class="{ pressed: buttonsDown.has('DOWN') }"
|
|
@mousedown.prevent="pressButton('DOWN')"
|
|
@touchstart.prevent="pressButton('DOWN')"
|
|
@touchend="handleTouchEnd"
|
|
></div>
|
|
<div
|
|
class="nds2d-d-pad-tip nds2d-tip-left"
|
|
:class="{ pressed: buttonsDown.has('LEFT') }"
|
|
@mousedown.prevent="pressButton('LEFT')"
|
|
@touchstart.prevent="pressButton('LEFT')"
|
|
@touchend="handleTouchEnd"
|
|
></div>
|
|
<div
|
|
class="nds2d-d-pad-tip nds2d-tip-right"
|
|
:class="{ pressed: buttonsDown.has('RIGHT') }"
|
|
@mousedown.prevent="pressButton('RIGHT')"
|
|
@touchstart.prevent="pressButton('RIGHT')"
|
|
@touchend="handleTouchEnd"
|
|
></div>
|
|
<div class="nds2d-d-pad-marker nds2d-dpm-up"></div>
|
|
<div class="nds2d-d-pad-marker nds2d-dpm-down"></div>
|
|
<div class="nds2d-d-pad-marker nds2d-dpm-left"></div>
|
|
<div class="nds2d-d-pad-marker nds2d-dpm-right"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
class="nds2d-button nds2d-btn-x"
|
|
:class="{ pressed: buttonsDown.has('X') }"
|
|
@mousedown.prevent="pressButton('X')"
|
|
@touchstart.prevent="pressButton('X')"
|
|
@touchend="handleTouchEnd"
|
|
>
|
|
X
|
|
</div>
|
|
<div
|
|
class="nds2d-button nds2d-btn-a"
|
|
:class="{ pressed: buttonsDown.has('A') }"
|
|
@mousedown.prevent="pressButton('A')"
|
|
@touchstart.prevent="pressButton('A')"
|
|
@touchend="handleTouchEnd"
|
|
>
|
|
A
|
|
</div>
|
|
<div
|
|
class="nds2d-button nds2d-btn-b"
|
|
:class="{ pressed: buttonsDown.has('B') }"
|
|
@mousedown.prevent="pressButton('B')"
|
|
@touchstart.prevent="pressButton('B')"
|
|
@touchend="handleTouchEnd"
|
|
>
|
|
B
|
|
</div>
|
|
<div
|
|
class="nds2d-button nds2d-btn-y"
|
|
:class="{ pressed: buttonsDown.has('Y') }"
|
|
@mousedown.prevent="pressButton('Y')"
|
|
@touchstart.prevent="pressButton('Y')"
|
|
@touchend="handleTouchEnd"
|
|
>
|
|
Y
|
|
</div>
|
|
|
|
<div
|
|
class="nds2d-small-button nds2d-start"
|
|
:class="{ pressed: buttonsDown.has('START') }"
|
|
@mousedown.prevent="pressButton('START')"
|
|
@touchstart.prevent="pressButton('START')"
|
|
@touchend="handleTouchEnd"
|
|
></div>
|
|
<div class="nds2d-small-button-label nds2d-start-label">START</div>
|
|
<div
|
|
class="nds2d-small-button nds2d-select"
|
|
:class="{ pressed: buttonsDown.has('SELECT') }"
|
|
@mousedown.prevent="pressButton('SELECT')"
|
|
@touchstart.prevent="pressButton('SELECT')"
|
|
@touchend="handleTouchEnd"
|
|
></div>
|
|
<div class="nds2d-small-button-label nds2d-select-label">SELECT</div>
|
|
|
|
<div
|
|
ref="hintsContainer"
|
|
class="nds2d-hints-container"
|
|
style="opacity: 0"
|
|
>
|
|
<div class="nds2d-hint nds2d-hint-dpad">Arrows</div>
|
|
<div class="nds2d-hint nds2d-hint-x">{{ mapNDSToKey("X") }}</div>
|
|
<div class="nds2d-hint nds2d-hint-a">{{ mapNDSToKey("A") }}</div>
|
|
<div class="nds2d-hint nds2d-hint-b">{{ mapNDSToKey("B") }}</div>
|
|
<div class="nds2d-hint nds2d-hint-y">{{ mapNDSToKey("Y") }}</div>
|
|
<div class="nds2d-hint nds2d-hint-start">
|
|
{{ mapNDSToKey("START") }}
|
|
</div>
|
|
<div class="nds2d-hint nds2d-hint-select">
|
|
{{ mapNDSToKey("SELECT") }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped lang="css">
|
|
.nds2d-container {
|
|
height: 100vh;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
text-align: center;
|
|
background: #181818;
|
|
overflow: hidden;
|
|
perspective: 800px;
|
|
}
|
|
|
|
.nds2d {
|
|
--primary: #1a1a1a;
|
|
--shadow: #111;
|
|
--black: #050505;
|
|
|
|
width: 414px;
|
|
height: 431px;
|
|
position: absolute;
|
|
}
|
|
|
|
.nds2d-top-screen {
|
|
position: absolute;
|
|
width: 100%;
|
|
height: 46.5%;
|
|
border-radius: 15px 15px 5px 5px;
|
|
background: var(--primary);
|
|
box-shadow:
|
|
inset 10px 10px 12px -2px var(--shadow),
|
|
inset -2px 5px 3px 1px var(--shadow),
|
|
inset -5px 5px 5px 2px #444,
|
|
0px -1px 2px 2px #111;
|
|
}
|
|
|
|
|
|
.nds2d-screen {
|
|
position: absolute;
|
|
width: 51.5%;
|
|
height: 83.5%;
|
|
border-radius: 3px;
|
|
top: 9.5%;
|
|
left: 24%;
|
|
box-shadow: 0px 0px 3px 0px #111;
|
|
}
|
|
|
|
.nds2d-screen :deep(canvas) {
|
|
position: absolute;
|
|
width: 91%;
|
|
height: 87%;
|
|
left: 4%;
|
|
top: 6%;
|
|
box-shadow: 0px 0px 1px 2px rgba(0, 0, 0, 0.5);
|
|
border: none !important;
|
|
}
|
|
|
|
.nds2d-speaker-hole {
|
|
position: absolute;
|
|
width: 5px;
|
|
height: 5px;
|
|
background: var(--black);
|
|
border-radius: 2.5px;
|
|
}
|
|
|
|
.nds2d-speaker-hole::after {
|
|
position: absolute;
|
|
content: "";
|
|
height: 5px;
|
|
width: 5px;
|
|
border-radius: 2.5px;
|
|
background: var(--black);
|
|
left: 16px;
|
|
}
|
|
|
|
.nds2d-speaker-hole::before {
|
|
position: absolute;
|
|
content: "";
|
|
height: 5px;
|
|
width: 5px;
|
|
border-radius: 2.5px;
|
|
background: var(--black);
|
|
left: 31px;
|
|
}
|
|
|
|
.nds2d-sh1 {
|
|
left: 30px;
|
|
top: 94px;
|
|
}
|
|
|
|
.nds2d-sh2 {
|
|
left: 30px;
|
|
top: 110px;
|
|
}
|
|
|
|
.nds2d-sh3 {
|
|
left: 346px;
|
|
top: 95px;
|
|
}
|
|
|
|
.nds2d-sh4 {
|
|
left: 346px;
|
|
top: 110px;
|
|
}
|
|
|
|
.nds2d-hinge {
|
|
position: absolute;
|
|
width: 99.5%;
|
|
top: 46.5%;
|
|
height: 28px;
|
|
border-radius: 25px;
|
|
z-index: 3;
|
|
background: linear-gradient(
|
|
0deg,
|
|
rgba(8, 8, 8) 0%,
|
|
rgba(20, 20, 20, 1) 10%,
|
|
rgba(32, 32, 32, 1) 65%,
|
|
rgba(20, 20, 20, 1) 100%
|
|
);
|
|
box-shadow: 0px 5px 10px -1px #080808;
|
|
}
|
|
|
|
.nds2d-hinge::after {
|
|
position: absolute;
|
|
content: "";
|
|
width: 2px;
|
|
height: 100%;
|
|
background: #222;
|
|
left: 49px;
|
|
}
|
|
|
|
.nds2d-hinge::before {
|
|
position: absolute;
|
|
content: "";
|
|
width: 2px;
|
|
height: 100%;
|
|
background: #222;
|
|
left: 364px;
|
|
}
|
|
|
|
.nds2d-mic {
|
|
position: absolute;
|
|
width: 4px;
|
|
height: 10px;
|
|
border-radius: 2px;
|
|
background: var(--black);
|
|
left: 49.5%;
|
|
top: 8px;
|
|
}
|
|
|
|
.nds2d-light {
|
|
position: absolute;
|
|
height: 67%;
|
|
width: 4px;
|
|
top: 12%;
|
|
border-radius: 10px;
|
|
right: 25px;
|
|
background: linear-gradient(
|
|
0deg,
|
|
rgba(40, 40, 40, 1) 0%,
|
|
rgba(80, 80, 80, 1) 65%,
|
|
rgba(40, 40, 40, 1) 100%
|
|
);
|
|
}
|
|
|
|
.nds2d-light::after {
|
|
content: "";
|
|
position: absolute;
|
|
height: 100%;
|
|
width: 4px;
|
|
top: 0;
|
|
border-radius: 10px;
|
|
left: 8px;
|
|
background: linear-gradient(
|
|
0deg,
|
|
rgba(92, 107, 73, 1) 0%,
|
|
rgba(211, 212, 183, 1) 65%,
|
|
rgba(123, 142, 98, 1) 100%
|
|
);
|
|
}
|
|
|
|
.nds2d-bottom-screen {
|
|
position: absolute;
|
|
width: 99.5%;
|
|
height: 50%;
|
|
bottom: 0;
|
|
border-radius: 3px 3px 14px 14px;
|
|
background: var(--primary);
|
|
box-shadow: 0px 1px 2px 2px #111;
|
|
}
|
|
|
|
.nds2d-bottom-screen .nds2d-screen {
|
|
top: 24px;
|
|
height: 168px;
|
|
width: 52%;
|
|
background: var(--primary);
|
|
z-index: 1;
|
|
}
|
|
|
|
.nds2d-bottom-screen .nds2d-screen::before {
|
|
content: "";
|
|
position: absolute;
|
|
width: 102%;
|
|
height: 109%;
|
|
left: -1%;
|
|
top: -7%;
|
|
z-index: -1;
|
|
border-radius: 5px;
|
|
box-shadow:
|
|
3px 4px 3px 1px var(--primary),
|
|
6px 4px 5px 2px #222,
|
|
-3px 4px 3px 1px var(--primary),
|
|
-6px 4px 5px 2px #222;
|
|
}
|
|
|
|
.nds2d-d-pad-shadow {
|
|
position: absolute;
|
|
left: 19px;
|
|
top: 61px;
|
|
width: 57px;
|
|
height: 57px;
|
|
background: var(--shadow);
|
|
filter: drop-shadow(0 3px 2px #111);
|
|
clip-path: path(
|
|
"M 22.5 0 Q 19 0 19 3.5 L 19 19 L 3.5 19 Q 0 19 0 22.5 L 0 34.5 Q 0 38 3.5 38 L 19 38 L 19 53.5 Q 19 57 22.5 57 L 34.5 57 Q 38 57 38 53.5 L 38 38 L 53.5 38 Q 57 38 57 34.5 L 57 22.5 Q 57 19 53.5 19 L 38 19 L 38 3.5 Q 38 0 34.5 0 Z"
|
|
);
|
|
}
|
|
|
|
.nds2d-d-pad {
|
|
position: absolute;
|
|
left: 20px;
|
|
top: 62px;
|
|
width: 55px;
|
|
height: 55px;
|
|
clip-path: path(
|
|
"M 22 0 Q 19 0 19 3 L 19 19 L 3 19 Q 0 19 0 22 L 0 33 Q 0 36 3 36 L 19 36 L 19 52 Q 19 55 22 55 L 33 55 Q 36 55 36 52 L 36 36 L 52 36 Q 55 36 55 33 L 55 22 Q 55 19 52 19 L 36 19 L 36 3 Q 36 0 33 0 Z"
|
|
);
|
|
}
|
|
|
|
.nds2d-d-pad-inner {
|
|
position: absolute;
|
|
width: 100%;
|
|
height: 100%;
|
|
transition: transform 0.06s ease;
|
|
}
|
|
|
|
.nds2d-d-pad-base {
|
|
position: absolute;
|
|
width: 100%;
|
|
height: 100%;
|
|
background: #333;
|
|
}
|
|
|
|
.nds2d-d-pad-light {
|
|
position: absolute;
|
|
width: 100%;
|
|
height: 100%;
|
|
box-shadow: inset 2px 2px 3px -1px #444;
|
|
}
|
|
|
|
.nds2d-d-pad-tip {
|
|
position: absolute;
|
|
cursor: pointer;
|
|
transition:
|
|
filter 0.06s ease,
|
|
box-shadow 0.06s ease;
|
|
}
|
|
|
|
.nds2d-tip-up {
|
|
left: 19px;
|
|
top: 0;
|
|
width: 17px;
|
|
height: 19px;
|
|
box-shadow: inset 0 2px 3px -1px #444;
|
|
}
|
|
|
|
.nds2d-tip-up.pressed {
|
|
filter: brightness(0.75);
|
|
box-shadow: inset 0 6px 4px -6px #222;
|
|
}
|
|
|
|
.nds2d-tip-down {
|
|
left: 19px;
|
|
bottom: 0;
|
|
width: 17px;
|
|
height: 19px;
|
|
box-shadow: inset 0 -2px 3px -1px #444;
|
|
}
|
|
|
|
.nds2d-tip-down.pressed {
|
|
filter: brightness(0.75);
|
|
box-shadow: inset 0 -6px 4px -6px #222;
|
|
}
|
|
|
|
.nds2d-tip-left {
|
|
left: 0;
|
|
top: 19px;
|
|
width: 19px;
|
|
height: 17px;
|
|
box-shadow: inset 2px 0 3px -1px #444;
|
|
}
|
|
|
|
.nds2d-tip-left.pressed {
|
|
filter: brightness(0.75);
|
|
box-shadow: inset 6px 0 4px -6px #222;
|
|
}
|
|
|
|
.nds2d-tip-right {
|
|
right: 0;
|
|
top: 19px;
|
|
width: 19px;
|
|
height: 17px;
|
|
box-shadow: inset -2px 0 3px -1px #444;
|
|
}
|
|
|
|
.nds2d-tip-right.pressed {
|
|
filter: brightness(0.75);
|
|
box-shadow: inset -6px 0 4px -6px #222;
|
|
}
|
|
|
|
.nds2d-d-pad-marker {
|
|
position: absolute;
|
|
background: #999;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.nds2d-dpm-up,
|
|
.nds2d-dpm-down {
|
|
width: 2px;
|
|
height: 11px;
|
|
left: 26px;
|
|
}
|
|
|
|
.nds2d-dpm-up {
|
|
top: 5px;
|
|
}
|
|
|
|
.nds2d-dpm-down {
|
|
bottom: 5px;
|
|
}
|
|
|
|
.nds2d-dpm-left,
|
|
.nds2d-dpm-right {
|
|
width: 11px;
|
|
height: 2px;
|
|
top: 26px;
|
|
}
|
|
|
|
.nds2d-dpm-left {
|
|
left: 5px;
|
|
}
|
|
|
|
.nds2d-dpm-right {
|
|
right: 5px;
|
|
}
|
|
|
|
/* Buttons */
|
|
|
|
.nds2d-button {
|
|
user-select: none;
|
|
cursor: pointer;
|
|
position: absolute;
|
|
width: 21px;
|
|
height: 21px;
|
|
padding-top: 1px;
|
|
border: 1px solid var(--shadow);
|
|
border-radius: 50%;
|
|
z-index: 5;
|
|
font-size: 0.7rem;
|
|
font-weight: 400;
|
|
background: #333;
|
|
color: #999;
|
|
box-shadow:
|
|
3px 2px 3px -2px #111,
|
|
inset 2px 2px 3px -1px #444;
|
|
transition:
|
|
box-shadow 0.06s ease,
|
|
transform 0.06s ease;
|
|
}
|
|
|
|
.nds2d-button.pressed {
|
|
box-shadow:
|
|
1px 1px 1px -1px #111,
|
|
inset 2px 2px 3px -1px #222;
|
|
transform: scale(0.91) translateY(1px);
|
|
}
|
|
|
|
.nds2d-btn-x {
|
|
right: 35px;
|
|
top: 45px;
|
|
}
|
|
|
|
.nds2d-btn-a {
|
|
right: 12px;
|
|
top: 69px;
|
|
}
|
|
|
|
.nds2d-btn-y {
|
|
right: 59px;
|
|
top: 69px;
|
|
}
|
|
|
|
.nds2d-btn-b {
|
|
right: 35px;
|
|
top: 92px;
|
|
}
|
|
|
|
.nds2d-small-button {
|
|
user-select: none;
|
|
cursor: pointer;
|
|
position: absolute;
|
|
width: 11px;
|
|
height: 11px;
|
|
border: 1px solid var(--shadow);
|
|
border-radius: 50%;
|
|
bottom: 53px;
|
|
right: 70px;
|
|
background: #333;
|
|
box-shadow:
|
|
3px 2px 3px -2px #111,
|
|
inset 2px 2px 3px -1px #444;
|
|
transition:
|
|
box-shadow 0.06s ease,
|
|
transform 0.06s ease;
|
|
}
|
|
|
|
.nds2d-small-button.pressed {
|
|
box-shadow:
|
|
1px 1px 1px -1px #111,
|
|
inset 1px 1px 2px -1px #222;
|
|
transform: scale(0.88) translateY(1px);
|
|
}
|
|
|
|
.nds2d-select {
|
|
bottom: 29px;
|
|
right: 70px;
|
|
}
|
|
|
|
.nds2d-small-button-label {
|
|
position: absolute;
|
|
font-size: 7px;
|
|
color: #999;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.nds2d-start-label {
|
|
bottom: 53px;
|
|
right: 44px;
|
|
}
|
|
|
|
.nds2d-select-label {
|
|
bottom: 29px;
|
|
right: 40px;
|
|
}
|
|
|
|
.nds2d-hints-container {
|
|
position: absolute;
|
|
inset: 0;
|
|
pointer-events: none;
|
|
z-index: 10;
|
|
}
|
|
|
|
.nds2d-hint {
|
|
position: absolute;
|
|
font-size: 7px;
|
|
color: #fff;
|
|
background: rgba(0, 0, 0, 0.7);
|
|
padding: 1px 3px;
|
|
border-radius: 2px;
|
|
white-space: nowrap;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.nds2d-hint-dpad {
|
|
left: 47px;
|
|
top: 46px;
|
|
transform: translateX(-50%);
|
|
}
|
|
|
|
.nds2d-hint-x,
|
|
.nds2d-hint-a,
|
|
.nds2d-hint-b,
|
|
.nds2d-hint-y {
|
|
width: 15px;
|
|
text-align: center;
|
|
}
|
|
|
|
.nds2d-hint-x {
|
|
right: 38px;
|
|
top: 32px;
|
|
}
|
|
|
|
.nds2d-hint-a {
|
|
right: 15px;
|
|
top: 56px;
|
|
}
|
|
|
|
.nds2d-hint-b {
|
|
right: 38px;
|
|
top: 79px;
|
|
}
|
|
|
|
.nds2d-hint-y {
|
|
right: 62px;
|
|
top: 56px;
|
|
}
|
|
|
|
.nds2d-hint-start {
|
|
left: 330px;
|
|
bottom: 53px;
|
|
transform: translateX(-100%);
|
|
}
|
|
|
|
.nds2d-hint-select {
|
|
left: 330px;
|
|
bottom: 28px;
|
|
transform: translateX(-100%);
|
|
}
|
|
</style>
|