Map Planner: TC Blueprint backgrounds

This commit is contained in:
Kalle 2022-12-10 20:44:19 +02:00
parent a52c92808f
commit 0fd1bc0e2b
16 changed files with 63 additions and 67 deletions

View File

@ -6,9 +6,9 @@ import {
Tldraw,
type TldrawApp,
} from "@tldraw/tldraw";
import clsx from "clsx";
import randomInt from "just-random-integer";
import * as React from "react";
import invariant from "tiny-invariant";
import { useForceRefreshOnMount } from "~/hooks/useForceRefresh";
import { useTranslation } from "~/hooks/useTranslation";
import type { LanguageCode } from "~/modules/i18n";
@ -18,7 +18,6 @@ import { modesShort } from "~/modules/in-game-lists/modes";
import { semiRandomId } from "~/utils/strings";
import {
mainWeaponImageUrl,
modeImageUrl,
outlinedMainWeaponImageUrl,
stageMinimapImageUrlWithEnding,
TLDRAW_URL,
@ -26,6 +25,12 @@ import {
import { Button } from "./Button";
import { Image } from "./Image";
export type StageBackgroundStyle = ModeShort | "TCO";
const BLUEPRINTS_AVAILABLE: Partial<Record<ModeShort, Array<StageId>>> = {
TC: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
};
export default function Planner() {
const { t } = useTranslation(["common", "weapons"]);
const { i18n } = useTranslation();
@ -107,10 +112,10 @@ export default function Planner() {
);
const handleAddBackgroundImage = React.useCallback(
({ stageId, modeShort }: { stageId: StageId; modeShort: ModeShort }) => {
({ stageId, style }: { stageId: StageId; style: StageBackgroundStyle }) => {
app.resetDocument();
handleAddImage({
src: stageMinimapImageUrlWithEnding({ stageId, modeShort }),
src: stageMinimapImageUrlWithEnding({ stageId, style }),
size: [1600, 900],
isLocked: true,
point: [65, 20],
@ -156,15 +161,27 @@ function StageBackgroundSelector({
}: {
onAddBackground: ({
stageId,
modeShort,
style,
}: {
stageId: StageId;
modeShort: ModeShort;
style: StageBackgroundStyle;
}) => void;
}) {
const { t } = useTranslation(["game-misc", "common"]);
const [stageId, setStageId] = React.useState<StageId>(stageIds[0]);
const [selectedMode, setSelectedMode] = React.useState<ModeShort>("SZ");
const [backgroundStyle, setBackgroundStyle] =
React.useState<StageBackgroundStyle>("SZ");
const imgExists = () => {
// normal background image
if (backgroundStyle.length === 2) return true;
const stageIds =
BLUEPRINTS_AVAILABLE[backgroundStyle.replace("O", "") as ModeShort];
invariant(stageIds);
return stageIds.includes(stageId);
};
return (
<div className="plans__top-section">
@ -182,40 +199,38 @@ function StageBackgroundSelector({
);
})}
</select>
<div className="plans__mode-buttons">
<select
className="w-max"
value={backgroundStyle}
onChange={(e) =>
setBackgroundStyle(e.target.value as StageBackgroundStyle)
}
>
{modesShort.map((mode) => {
const selected = mode === selectedMode;
return (
<button
key={mode}
className={clsx("plans__mode-button", "outline-theme", {
selected,
})}
onClick={() => setSelectedMode(mode)}
type="button"
title={t(`game-misc:MODE_LONG_${mode}`)}
aria-pressed={selected}
>
<Image
className={clsx("plans__mode-img", {
selected,
})}
alt={t(`game-misc:MODE_LONG_${mode}`)}
path={modeImageUrl(mode)}
width={20}
height={20}
/>
</button>
<React.Fragment key={mode}>
<option value={mode}>{t(`game-misc:MODE_SHORT_${mode}`)}</option>
{Object.keys(BLUEPRINTS_AVAILABLE).includes(mode as any) ? (
<option value={`${mode}O`}>
{t(`game-misc:MODE_SHORT_${mode}`)} (
{t("common:plans.blueprint")})
</option>
) : null}
</React.Fragment>
);
})}
</div>
<Button
tiny
onClick={() => onAddBackground({ modeShort: selectedMode, stageId })}
className="w-max"
>
{t("common:actions.setBg")}
</Button>
</select>
{imgExists() ? (
<Button
tiny
onClick={() => onAddBackground({ style: backgroundStyle, stageId })}
className="w-max"
>
{t("common:actions.setBg")}
</Button>
) : (
<span className="plans__no-img-text">{t("common:plans.noImg")}</span>
)}
</div>
);
}

View File

@ -47,33 +47,6 @@ button[data-state="closed"][aria-haspopup="dialog"] {
transform: translate(-50%, -42%);
}
.plans__mode-buttons {
display: flex;
width: 100%;
align-items: center;
justify-content: center;
}
.plans__mode-button {
padding: 0;
padding: var(--s-1-5);
border: none;
border-radius: var(--rounded-full);
background-color: transparent;
color: var(--theme);
opacity: 1 !important;
outline: initial;
}
.plans__mode-button.selected {
background-color: var(--bg-mode-active);
}
.plans__mode-img:not(.selected) {
filter: var(--inactive-image-filter);
opacity: 0.6;
}
.plans__weapons-section {
position: fixed;
z-index: 10;
@ -99,3 +72,8 @@ button[data-state="closed"][aria-haspopup="dialog"] {
color: var(--text-lighter);
font-size: var(--fonts-xxxs);
}
.plans__no-img-text {
color: var(--theme-error);
font-size: var(--fonts-xs);
}

View File

@ -17,6 +17,7 @@ import type {
} from "~/modules/in-game-lists/types";
import type navItems from "~/components/layout/nav-items.json";
import { type AuthErrorCode } from "~/modules/auth";
import type { StageBackgroundStyle } from "~/components/Planner";
export const SPLATOON_2_SENDOU_IN_URL = "https://spl2.sendou.ink";
export const PLUS_SERVER_DISCORD_URL = "https://discord.gg/FW4dKrY";
@ -164,11 +165,11 @@ export const stageImageUrl = (stageId: StageId) =>
`/static-assets/img/stages/${stageId}`;
export const stageMinimapImageUrlWithEnding = ({
stageId,
modeShort,
style,
}: {
stageId: StageId;
modeShort: ModeShort;
}) => `/static-assets/img/stage-minimaps/${stageId}-${modeShort}.jpeg`;
style: StageBackgroundStyle;
}) => `/static-assets/img/stage-minimaps/${stageId}-${style}.jpeg`;
export function resolveBaseUrl(url: string) {
return new URL(url).host;

View File

@ -107,6 +107,8 @@
"weapon.category.SPLATANAS": "Splatanas",
"plans.poweredBy": "Powered by {{name}}",
"plans.blueprint": "Blueprint",
"plans.noImg": "No image available",
"articles.by": "by {{author}}",

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB