feat: remove types
|
Before Width: | Height: | Size: 233 KiB After Width: | Height: | Size: 233 KiB |
|
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 97 KiB |
|
Before Width: | Height: | Size: 151 KiB After Width: | Height: | Size: 151 KiB |
|
Before Width: | Height: | Size: 184 KiB |
BIN
public/tutorial/switch/submitting/step1.jpg
Executable file
|
After Width: | Height: | Size: 247 KiB |
BIN
public/tutorial/switch/submitting/step2.jpg
Executable file
|
After Width: | Height: | Size: 74 KiB |
BIN
public/tutorial/switch/submitting/step3.jpg
Executable file
|
After Width: | Height: | Size: 142 KiB |
|
|
@ -78,7 +78,6 @@ function TableCell({ label, children }: TableCellProps) {
|
||||||
function Section({ name, instructions, children, isSubSection }: SectionProps) {
|
function Section({ name, instructions, children, isSubSection }: SectionProps) {
|
||||||
if (typeof instructions !== "object" || !instructions) return null;
|
if (typeof instructions !== "object" || !instructions) return null;
|
||||||
|
|
||||||
const type = "type" in instructions ? instructions.type : undefined;
|
|
||||||
const color = "color" in instructions ? instructions.color : undefined;
|
const color = "color" in instructions ? instructions.color : undefined;
|
||||||
const height = "height" in instructions ? instructions.height : undefined;
|
const height = "height" in instructions ? instructions.height : undefined;
|
||||||
const distance = "distance" in instructions ? instructions.distance : undefined;
|
const distance = "distance" in instructions ? instructions.distance : undefined;
|
||||||
|
|
@ -92,11 +91,6 @@ function Section({ name, instructions, children, isSubSection }: SectionProps) {
|
||||||
|
|
||||||
<table className="w-full">
|
<table className="w-full">
|
||||||
<tbody>
|
<tbody>
|
||||||
{type && (
|
|
||||||
<TableCell label="Type">
|
|
||||||
<GridPosition index={type} />
|
|
||||||
</TableCell>
|
|
||||||
)}
|
|
||||||
{color && (
|
{color && (
|
||||||
<TableCell label="Color">
|
<TableCell label="Color">
|
||||||
<ColorPosition color={color} />
|
<ColorPosition color={color} />
|
||||||
|
|
@ -129,21 +123,6 @@ export default function MiiInstructions({ instructions }: Props) {
|
||||||
{head && <Section name="Head" instructions={head}></Section>}
|
{head && <Section name="Head" instructions={head}></Section>}
|
||||||
{hair && (
|
{hair && (
|
||||||
<Section name="Hair" instructions={hair}>
|
<Section name="Hair" instructions={hair}>
|
||||||
{hair.setType && (
|
|
||||||
<TableCell label="Set Type">
|
|
||||||
<GridPosition index={hair.setType} />
|
|
||||||
</TableCell>
|
|
||||||
)}
|
|
||||||
{hair.bangsType && (
|
|
||||||
<TableCell label="Bangs Type">
|
|
||||||
<GridPosition index={hair.bangsType} />
|
|
||||||
</TableCell>
|
|
||||||
)}
|
|
||||||
{hair.backType && (
|
|
||||||
<TableCell label="Back Type">
|
|
||||||
<GridPosition index={hair.backType} />
|
|
||||||
</TableCell>
|
|
||||||
)}
|
|
||||||
{hair.subColor && (
|
{hair.subColor && (
|
||||||
<TableCell label="Sub Color">
|
<TableCell label="Sub Color">
|
||||||
<ColorPosition color={hair.subColor} />
|
<ColorPosition color={hair.subColor} />
|
||||||
|
|
|
||||||
|
|
@ -51,40 +51,37 @@ export default function SubmitForm() {
|
||||||
const [platform, setPlatform] = useState<MiiPlatform>("SWITCH");
|
const [platform, setPlatform] = useState<MiiPlatform>("SWITCH");
|
||||||
const [gender, setGender] = useState<MiiGender>("MALE");
|
const [gender, setGender] = useState<MiiGender>("MALE");
|
||||||
const instructions = useRef<SwitchMiiInstructions>({
|
const instructions = useRef<SwitchMiiInstructions>({
|
||||||
head: { type: null, skinColor: null },
|
head: { skinColor: null },
|
||||||
hair: {
|
hair: {
|
||||||
setType: null,
|
|
||||||
bangsType: null,
|
|
||||||
backType: null,
|
|
||||||
color: null,
|
color: null,
|
||||||
subColor: null,
|
subColor: null,
|
||||||
subColor2: null,
|
subColor2: null,
|
||||||
style: null,
|
style: null,
|
||||||
isFlipped: false,
|
isFlipped: false,
|
||||||
},
|
},
|
||||||
eyebrows: { type: null, color: null, height: null, distance: null, rotation: null, size: null, stretch: null },
|
eyebrows: { color: null, height: null, distance: null, rotation: null, size: null, stretch: null },
|
||||||
eyes: {
|
eyes: {
|
||||||
main: { type: null, color: null, height: null, distance: null, rotation: null, size: null, stretch: null },
|
main: { color: null, height: null, distance: null, rotation: null, size: null, stretch: null },
|
||||||
eyelashesTop: { type: null, height: null, distance: null, rotation: null, size: null, stretch: null },
|
eyelashesTop: { height: null, distance: null, rotation: null, size: null, stretch: null },
|
||||||
eyelashesBottom: { type: null, height: null, distance: null, rotation: null, size: null, stretch: null },
|
eyelashesBottom: { height: null, distance: null, rotation: null, size: null, stretch: null },
|
||||||
eyelidTop: { type: null, height: null, distance: null, rotation: null, size: null, stretch: null },
|
eyelidTop: { height: null, distance: null, rotation: null, size: null, stretch: null },
|
||||||
eyelidBottom: { type: null, height: null, distance: null, rotation: null, size: null, stretch: null },
|
eyelidBottom: { height: null, distance: null, rotation: null, size: null, stretch: null },
|
||||||
eyeliner: { type: null, color: null },
|
eyeliner: { color: null },
|
||||||
pupil: { type: null, height: null, distance: null, rotation: null, size: null, stretch: null },
|
pupil: { height: null, distance: null, rotation: null, size: null, stretch: null },
|
||||||
},
|
},
|
||||||
nose: { type: null, height: null, size: null },
|
nose: { height: null, size: null },
|
||||||
lips: { type: null, color: null, height: null, rotation: null, size: null, stretch: null, hasLipstick: false },
|
lips: { color: null, height: null, rotation: null, size: null, stretch: null, hasLipstick: false },
|
||||||
ears: { type: null, height: null, size: null },
|
ears: { height: null, size: null },
|
||||||
glasses: { type: null, ringColor: null, shadesColor: null, height: null, size: null, stretch: null },
|
glasses: { ringColor: null, shadesColor: null, height: null, size: null, stretch: null },
|
||||||
other: {
|
other: {
|
||||||
wrinkles1: { type: null, height: null, distance: null, size: null, stretch: null },
|
wrinkles1: { height: null, distance: null, size: null, stretch: null },
|
||||||
wrinkles2: { type: null, height: null, distance: null, size: null, stretch: null },
|
wrinkles2: { height: null, distance: null, size: null, stretch: null },
|
||||||
beard: { type: null, color: null },
|
beard: { color: null },
|
||||||
moustache: { type: null, color: null, height: null, isFlipped: false, size: null, stretch: null },
|
moustache: { color: null, height: null, isFlipped: false, size: null, stretch: null },
|
||||||
goatee: { type: null, color: null },
|
goatee: { color: null },
|
||||||
mole: { type: null, color: null, height: null, distance: null, size: null },
|
mole: { color: null, height: null, distance: null, size: null },
|
||||||
eyeShadow: { type: null, color: null, height: null, distance: null, size: null, stretch: null },
|
eyeShadow: { color: null, height: null, distance: null, size: null, stretch: null },
|
||||||
blush: { type: null, color: null, height: null, distance: null, size: null, stretch: null },
|
blush: { color: null, height: null, distance: null, size: null, stretch: null },
|
||||||
},
|
},
|
||||||
height: null,
|
height: null,
|
||||||
weight: null,
|
weight: null,
|
||||||
|
|
|
||||||
|
|
@ -69,8 +69,9 @@ export default function MiiEditor({ instructions }: Props) {
|
||||||
{(Object.keys(TAB_COMPONENTS) as Tab[]).map((t) => {
|
{(Object.keys(TAB_COMPONENTS) as Tab[]).map((t) => {
|
||||||
const TabComponent = TAB_COMPONENTS[t];
|
const TabComponent = TAB_COMPONENTS[t];
|
||||||
return (
|
return (
|
||||||
<div key={t} className={t === tab ? "grow flex" : "hidden"}>
|
<div key={t} className={t === tab ? "grow flex relative" : "hidden"}>
|
||||||
<TabComponent instructions={instructions} />
|
<TabComponent instructions={instructions} />
|
||||||
|
<p className="absolute top-32 left-32 z-10 text-lg font-bold w-48 text-center">Your parts screenshot should handle the types!</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import { SwitchMiiInstructions } from "@/types";
|
import { SwitchMiiInstructions } from "@/types";
|
||||||
import TypeSelector from "../type-selector";
|
|
||||||
import NumberInputs from "../number-inputs";
|
import NumberInputs from "../number-inputs";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
|
|
@ -17,17 +16,6 @@ export default function EarsTab({ instructions }: Props) {
|
||||||
<div className="flex items-center h-8">
|
<div className="flex items-center h-8">
|
||||||
<h1 className="font-bold text-xl">Ears</h1>
|
<h1 className="font-bold text-xl">Ears</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex justify-center h-74 mt-auto">
|
|
||||||
<TypeSelector
|
|
||||||
length={5}
|
|
||||||
type={type}
|
|
||||||
setType={(i) => {
|
|
||||||
setType(i);
|
|
||||||
instructions.current.ears.type = i;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="shrink-0 w-21 pb-3 flex flex-col items-center">
|
<div className="shrink-0 w-21 pb-3 flex flex-col items-center">
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import { SwitchMiiInstructions } from "@/types";
|
import { SwitchMiiInstructions } from "@/types";
|
||||||
import ColorPicker from "../color-picker";
|
import ColorPicker from "../color-picker";
|
||||||
import TypeSelector from "../type-selector";
|
|
||||||
import NumberInputs from "../number-inputs";
|
import NumberInputs from "../number-inputs";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
|
|
@ -19,18 +18,6 @@ export default function EyebrowsTab({ instructions }: Props) {
|
||||||
<div className="flex items-center h-8">
|
<div className="flex items-center h-8">
|
||||||
<h1 className="font-bold text-xl">Eyebrows</h1>
|
<h1 className="font-bold text-xl">Eyebrows</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex justify-center h-74 mt-auto">
|
|
||||||
<TypeSelector
|
|
||||||
hasNoneOption
|
|
||||||
length={48}
|
|
||||||
type={type}
|
|
||||||
setType={(i) => {
|
|
||||||
setType(i);
|
|
||||||
instructions.current.eyebrows.type = i;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="shrink-0 w-21 pb-3 flex flex-col items-center">
|
<div className="shrink-0 w-21 pb-3 flex flex-col items-center">
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import { SwitchMiiInstructions } from "@/types";
|
import { SwitchMiiInstructions } from "@/types";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import ColorPicker from "../color-picker";
|
import ColorPicker from "../color-picker";
|
||||||
import TypeSelector from "../type-selector";
|
|
||||||
import NumberInputs from "../number-inputs";
|
import NumberInputs from "../number-inputs";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|
@ -22,21 +21,10 @@ export default function OtherTab({ instructions }: Props) {
|
||||||
const [tab, setTab] = useState(0);
|
const [tab, setTab] = useState(0);
|
||||||
|
|
||||||
// One type/color state per tab
|
// One type/color state per tab
|
||||||
const [types, setTypes] = useState<number[]>([5, 0, 0, 0, 0, 0, 0]);
|
|
||||||
const [colors, setColors] = useState<number[]>(Array(TABS.length).fill(0));
|
const [colors, setColors] = useState<number[]>(Array(TABS.length).fill(0));
|
||||||
|
|
||||||
const currentTab = TABS[tab];
|
const currentTab = TABS[tab];
|
||||||
|
|
||||||
const setType = (value: number) => {
|
|
||||||
setTypes((prev) => {
|
|
||||||
const copy = [...prev];
|
|
||||||
copy[tab] = value;
|
|
||||||
return copy;
|
|
||||||
});
|
|
||||||
|
|
||||||
instructions.current.eyes[currentTab.name].type = value;
|
|
||||||
};
|
|
||||||
|
|
||||||
const setColor = (value: number) => {
|
const setColor = (value: number) => {
|
||||||
setColors((prev) => {
|
setColors((prev) => {
|
||||||
const copy = [...prev];
|
const copy = [...prev];
|
||||||
|
|
@ -69,10 +57,6 @@ export default function OtherTab({ instructions }: Props) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex justify-center h-74 mt-auto">
|
|
||||||
<TypeSelector hasNoneOption={tab === 0} length={currentTab.length} type={types[tab]} setType={setType} />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="shrink-0 w-21 pb-3 flex flex-col items-center">
|
<div className="shrink-0 w-21 pb-3 flex flex-col items-center">
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,13 @@
|
||||||
|
import { useState } from "react";
|
||||||
import { SwitchMiiInstructions } from "@/types";
|
import { SwitchMiiInstructions } from "@/types";
|
||||||
import ColorPicker from "../color-picker";
|
import ColorPicker from "../color-picker";
|
||||||
import TypeSelector from "../type-selector";
|
|
||||||
import NumberInputs from "../number-inputs";
|
import NumberInputs from "../number-inputs";
|
||||||
import { useState } from "react";
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
instructions: React.RefObject<SwitchMiiInstructions>;
|
instructions: React.RefObject<SwitchMiiInstructions>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function GlassesTab({ instructions }: Props) {
|
export default function GlassesTab({ instructions }: Props) {
|
||||||
const [type, setType] = useState(0);
|
|
||||||
const [ringColor, setRingColor] = useState(0);
|
const [ringColor, setRingColor] = useState(0);
|
||||||
const [shadesColor, setShadesColor] = useState(0);
|
const [shadesColor, setShadesColor] = useState(0);
|
||||||
|
|
||||||
|
|
@ -20,19 +18,6 @@ export default function GlassesTab({ instructions }: Props) {
|
||||||
<div className="flex items-center h-8">
|
<div className="flex items-center h-8">
|
||||||
<h1 className="font-bold text-xl">Glasses</h1>
|
<h1 className="font-bold text-xl">Glasses</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex justify-center h-74 mt-auto">
|
|
||||||
<TypeSelector
|
|
||||||
hasNoneOption
|
|
||||||
isGlassesTab
|
|
||||||
length={58}
|
|
||||||
type={type}
|
|
||||||
setType={(i) => {
|
|
||||||
setType(i);
|
|
||||||
instructions.current.glasses.type = i;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="shrink-0 w-21 pb-3 flex flex-col items-center">
|
<div className="shrink-0 w-21 pb-3 flex flex-col items-center">
|
||||||
|
|
@ -45,7 +30,6 @@ export default function GlassesTab({ instructions }: Props) {
|
||||||
/>
|
/>
|
||||||
<ColorPicker
|
<ColorPicker
|
||||||
color={shadesColor}
|
color={shadesColor}
|
||||||
disabled={type < 44}
|
|
||||||
setColor={(i) => {
|
setColor={(i) => {
|
||||||
setShadesColor(i);
|
setShadesColor(i);
|
||||||
instructions.current.glasses.shadesColor = i;
|
instructions.current.glasses.shadesColor = i;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import { SwitchMiiInstructions } from "@/types";
|
import { SwitchMiiInstructions } from "@/types";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import ColorPicker from "../color-picker";
|
import ColorPicker from "../color-picker";
|
||||||
import TypeSelector from "../type-selector";
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
instructions: React.RefObject<SwitchMiiInstructions>;
|
instructions: React.RefObject<SwitchMiiInstructions>;
|
||||||
|
|
@ -11,44 +10,14 @@ type Tab = "sets" | "bangs" | "back";
|
||||||
|
|
||||||
export default function HairTab({ instructions }: Props) {
|
export default function HairTab({ instructions }: Props) {
|
||||||
const [tab, setTab] = useState<Tab>("sets");
|
const [tab, setTab] = useState<Tab>("sets");
|
||||||
const [setsType, setSetsType] = useState<number | null>(43);
|
|
||||||
const [bangsType, setBangsType] = useState<number | null>(null);
|
|
||||||
const [backType, setBackType] = useState<number | null>(null);
|
|
||||||
const [color, setColor] = useState(0);
|
const [color, setColor] = useState(0);
|
||||||
const [subColor, setSubColor] = useState<number | null>(null);
|
const [subColor, setSubColor] = useState<number | null>(null);
|
||||||
const [subColor2, setSubColor2] = useState<number | null>(null);
|
const [subColor2, setSubColor2] = useState<number | null>(null);
|
||||||
const [style, setStyle] = useState<number | null>(null);
|
const [style, setStyle] = useState<number | null>(null);
|
||||||
const [isFlipped, setIsFlipped] = useState(false);
|
const [isFlipped, setIsFlipped] = useState(false);
|
||||||
|
|
||||||
const type = tab === "sets" ? setsType : tab === "bangs" ? bangsType : backType;
|
|
||||||
const length = tab === "sets" ? 245 : tab === "bangs" ? 83 : 111;
|
const length = tab === "sets" ? 245 : tab === "bangs" ? 83 : 111;
|
||||||
|
|
||||||
const setType = (value: number) => {
|
|
||||||
if (tab === "sets") {
|
|
||||||
setSetsType(value);
|
|
||||||
instructions.current.hair.setType = value;
|
|
||||||
// Clear bangs and back
|
|
||||||
setBangsType(null);
|
|
||||||
setBackType(null);
|
|
||||||
setSubColor2(null);
|
|
||||||
instructions.current.hair.bangsType = null;
|
|
||||||
instructions.current.hair.backType = null;
|
|
||||||
instructions.current.hair.subColor2 = null;
|
|
||||||
} else if (tab === "bangs") {
|
|
||||||
setBangsType(value);
|
|
||||||
instructions.current.hair.bangsType = value;
|
|
||||||
// Clear set
|
|
||||||
setSetsType(null);
|
|
||||||
instructions.current.hair.setType = null;
|
|
||||||
} else {
|
|
||||||
setBackType(value);
|
|
||||||
instructions.current.hair.backType = value;
|
|
||||||
// Clear set
|
|
||||||
setSetsType(null);
|
|
||||||
instructions.current.hair.setType = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative grow p-3 pb-0!">
|
<div className="relative grow p-3 pb-0!">
|
||||||
<div className="flex h-full">
|
<div className="flex h-full">
|
||||||
|
|
@ -83,10 +52,6 @@ export default function HairTab({ instructions }: Props) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex justify-center h-74 mt-auto">
|
|
||||||
<TypeSelector length={length} type={type} setType={setType} />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="shrink-0 w-21 pb-3 flex flex-col items-center">
|
<div className="shrink-0 w-21 pb-3 flex flex-col items-center">
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import ColorPicker from "../color-picker";
|
import ColorPicker from "../color-picker";
|
||||||
import { SwitchMiiInstructions } from "@/types";
|
import { SwitchMiiInstructions } from "@/types";
|
||||||
import TypeSelector from "../type-selector";
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
instructions: React.RefObject<SwitchMiiInstructions>;
|
instructions: React.RefObject<SwitchMiiInstructions>;
|
||||||
|
|
@ -20,17 +19,6 @@ export default function HeadTab({ instructions }: Props) {
|
||||||
<div className="flex items-center h-8">
|
<div className="flex items-center h-8">
|
||||||
<h1 className="font-bold text-xl">Head</h1>
|
<h1 className="font-bold text-xl">Head</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex justify-center h-74 mt-auto">
|
|
||||||
<TypeSelector
|
|
||||||
length={16}
|
|
||||||
type={type}
|
|
||||||
setType={(i) => {
|
|
||||||
setType(i);
|
|
||||||
instructions.current.head.type = i;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="shrink-0 w-21 pb-3 flex flex-col items-center">
|
<div className="shrink-0 w-21 pb-3 flex flex-col items-center">
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import { SwitchMiiInstructions } from "@/types";
|
import { SwitchMiiInstructions } from "@/types";
|
||||||
import ColorPicker from "../color-picker";
|
import ColorPicker from "../color-picker";
|
||||||
import TypeSelector from "../type-selector";
|
|
||||||
import NumberInputs from "../number-inputs";
|
import NumberInputs from "../number-inputs";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
|
|
@ -9,7 +8,6 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function LipsTab({ instructions }: Props) {
|
export default function LipsTab({ instructions }: Props) {
|
||||||
const [type, setType] = useState(1);
|
|
||||||
const [color, setColor] = useState(0);
|
const [color, setColor] = useState(0);
|
||||||
const [hasLipstick, setHasLipstick] = useState(false);
|
const [hasLipstick, setHasLipstick] = useState(false);
|
||||||
|
|
||||||
|
|
@ -20,17 +18,6 @@ export default function LipsTab({ instructions }: Props) {
|
||||||
<div className="flex items-center h-8">
|
<div className="flex items-center h-8">
|
||||||
<h1 className="font-bold text-xl">Lips</h1>
|
<h1 className="font-bold text-xl">Lips</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex justify-center h-74 mt-auto">
|
|
||||||
<TypeSelector
|
|
||||||
length={53}
|
|
||||||
type={type}
|
|
||||||
setType={(i) => {
|
|
||||||
setType(i);
|
|
||||||
instructions.current.lips.type = i;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="shrink-0 w-21 pb-3 flex flex-col items-center">
|
<div className="shrink-0 w-21 pb-3 flex flex-col items-center">
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,11 @@
|
||||||
import { SwitchMiiInstructions } from "@/types";
|
import { SwitchMiiInstructions } from "@/types";
|
||||||
import TypeSelector from "../type-selector";
|
|
||||||
import NumberInputs from "../number-inputs";
|
import NumberInputs from "../number-inputs";
|
||||||
import { useState } from "react";
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
instructions: React.RefObject<SwitchMiiInstructions>;
|
instructions: React.RefObject<SwitchMiiInstructions>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function NoseTab({ instructions }: Props) {
|
export default function NoseTab({ instructions }: Props) {
|
||||||
const [type, setType] = useState(5);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative grow p-3 pb-0!">
|
<div className="relative grow p-3 pb-0!">
|
||||||
<div className="flex h-full">
|
<div className="flex h-full">
|
||||||
|
|
@ -17,17 +13,6 @@ export default function NoseTab({ instructions }: Props) {
|
||||||
<div className="flex items-center h-8">
|
<div className="flex items-center h-8">
|
||||||
<h1 className="font-bold text-xl">Nose</h1>
|
<h1 className="font-bold text-xl">Nose</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex justify-center h-74 mt-auto">
|
|
||||||
<TypeSelector
|
|
||||||
length={32}
|
|
||||||
type={type}
|
|
||||||
setType={(i) => {
|
|
||||||
setType(i);
|
|
||||||
instructions.current.nose.type = i;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="shrink-0 w-21 pb-3 flex flex-col items-center">
|
<div className="shrink-0 w-21 pb-3 flex flex-col items-center">
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import { SwitchMiiInstructions } from "@/types";
|
import { SwitchMiiInstructions } from "@/types";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import ColorPicker from "../color-picker";
|
import ColorPicker from "../color-picker";
|
||||||
import TypeSelector from "../type-selector";
|
|
||||||
import NumberInputs from "../number-inputs";
|
import NumberInputs from "../number-inputs";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|
@ -24,21 +23,10 @@ export default function OtherTab({ instructions }: Props) {
|
||||||
const [isFlipped, setIsFlipped] = useState(false);
|
const [isFlipped, setIsFlipped] = useState(false);
|
||||||
|
|
||||||
// One type/color state per tab
|
// One type/color state per tab
|
||||||
const [types, setTypes] = useState<number[]>(Array(TABS.length).fill(0));
|
|
||||||
const [colors, setColors] = useState<number[]>(Array(TABS.length).fill(0));
|
const [colors, setColors] = useState<number[]>(Array(TABS.length).fill(0));
|
||||||
|
|
||||||
const currentTab = TABS[tab];
|
const currentTab = TABS[tab];
|
||||||
|
|
||||||
const setType = (value: number) => {
|
|
||||||
setTypes((prev) => {
|
|
||||||
const copy = [...prev];
|
|
||||||
copy[tab] = value;
|
|
||||||
return copy;
|
|
||||||
});
|
|
||||||
|
|
||||||
instructions.current.other[currentTab.name].type = value;
|
|
||||||
};
|
|
||||||
|
|
||||||
const setColor = (value: number) => {
|
const setColor = (value: number) => {
|
||||||
setColors((prev) => {
|
setColors((prev) => {
|
||||||
const copy = [...prev];
|
const copy = [...prev];
|
||||||
|
|
@ -71,10 +59,6 @@ export default function OtherTab({ instructions }: Props) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex justify-center h-74 mt-auto">
|
|
||||||
<TypeSelector length={currentTab.length} type={types[tab]} setType={setType} />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="shrink-0 w-21 pb-3 flex flex-col items-center">
|
<div className="shrink-0 w-21 pb-3 flex flex-col items-center">
|
||||||
|
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
import { Fragment } from "react/jsx-runtime";
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
hasNoneOption?: boolean;
|
|
||||||
isGlassesTab?: boolean;
|
|
||||||
length: number;
|
|
||||||
type: number | null;
|
|
||||||
setType: (type: number) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function TypeSelector({ hasNoneOption, isGlassesTab, length, type, setType }: Props) {
|
|
||||||
return (
|
|
||||||
<div className="grid grid-cols-5 gap-1 w-fit overflow-y-auto h-fit max-h-full">
|
|
||||||
{Array.from({ length }).map((_, i) => (
|
|
||||||
<Fragment key={i}>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => setType(i)}
|
|
||||||
className={`size-12 cursor-pointer hover:bg-orange-300 transition-colors duration-100 rounded-xl ${type === i ? "bg-orange-400!" : ""} ${hasNoneOption && i === 0 ? "text-md" : "text-2xl"}`}
|
|
||||||
>
|
|
||||||
{hasNoneOption ? (i === 0 ? "None" : i + 1) : i + 1}
|
|
||||||
</button>
|
|
||||||
|
|
||||||
{isGlassesTab && i === 43 && <div />}
|
|
||||||
</Fragment>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -22,7 +22,7 @@ export default function PortraitUpload({ setImage }: Props) {
|
||||||
};
|
};
|
||||||
reader.readAsDataURL(file);
|
reader.readAsDataURL(file);
|
||||||
},
|
},
|
||||||
[setImage]
|
[setImage],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -31,7 +31,7 @@ export default function PortraitUpload({ setImage }: Props) {
|
||||||
<p className="text-center text-sm">
|
<p className="text-center text-sm">
|
||||||
{!hasImage ? (
|
{!hasImage ? (
|
||||||
<>
|
<>
|
||||||
Drag and drop your Mii's portrait here
|
Drag and drop a screenshot of your Mii's parts here
|
||||||
<br />
|
<br />
|
||||||
or click to open
|
or click to open
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -24,15 +24,15 @@ export default function SwitchAddMiiTutorialButton() {
|
||||||
steps: [
|
steps: [
|
||||||
{
|
{
|
||||||
text: "1. Press X to open the menu, then select 'Add a Mii'",
|
text: "1. Press X to open the menu, then select 'Add a Mii'",
|
||||||
imageSrc: "/tutorial/switch/step1.jpg",
|
imageSrc: "/tutorial/switch/adding-mii/step1.jpg",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "2. Press 'From scratch' and choose the Male template (instructions may be slightly inaccurate if you select Female)",
|
text: "2. Press 'From scratch' and choose the Male template (instructions may be slightly inaccurate if you select Female)",
|
||||||
imageSrc: "/tutorial/switch/step2.jpg",
|
imageSrc: "/tutorial/switch/adding-mii/step2.jpg",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "3. Follow all instructions (not all instructions will be there, check next slide for more)",
|
text: "3. Follow all instructions (not all instructions will be there, check next slide for more)",
|
||||||
imageSrc: "/tutorial/switch/step3.jpg",
|
imageSrc: "/tutorial/switch/adding-mii/step3.jpg",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "4. If the instructions have height, distance, etc. the value will be relative to how many times to click the button - positive for up/left, negative for down/right",
|
text: "4. If the instructions have height, distance, etc. the value will be relative to how many times to click the button - positive for up/left, negative for down/right",
|
||||||
|
|
|
||||||
|
|
@ -18,28 +18,24 @@ export default function SubmitTutorialButton() {
|
||||||
<Tutorial
|
<Tutorial
|
||||||
tutorials={[
|
tutorials={[
|
||||||
{
|
{
|
||||||
title: "Mii Instructions",
|
title: "Submitting",
|
||||||
steps: [
|
steps: [
|
||||||
{
|
{
|
||||||
text: "1. Press X to open the menu, then select 'Add a Mii' (or 'Residents' if you're submitting an existing Mii)",
|
text: "1. Press X to open the menu, then select 'Residents'",
|
||||||
imageSrc: "/tutorial/switch/step1.jpg",
|
imageSrc: "/tutorial/switch/submitting/step1.jpg",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "2. Press 'From scratch' and choose the Male template (instructions may be slightly inaccurate if you select Female, it's fine if you change all defaults)",
|
text: "2. Find the Mii you want to submit and edit it",
|
||||||
imageSrc: "/tutorial/switch/step2.jpg",
|
imageSrc: "/tutorial/switch/submitting/step2.jpg",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "3. Customize your Mii to your liking",
|
text: "3. Press Y to open the parts list, take a screenshot then upload to this submit form",
|
||||||
imageSrc: "/tutorial/switch/step3.jpg",
|
imageSrc: "/tutorial/switch/submitting/step3.jpg",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "4. All instructions are optional but if you want to add height, distance, etc. the value will be relative to how many times you clicked the button - positive for up/left, negative for down/right",
|
text: "4. Adding Mii colors and settings is recommended. All instructions are optional; for values like height or distance, use the number of button clicks (positive for up/left, negative for down/right)",
|
||||||
imageSrc: "/tutorial/switch/step4.jpg",
|
imageSrc: "/tutorial/switch/step4.jpg",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
text: "5. Upload instructions, then screenshot the Mii for the portrait (feel free to crop it)",
|
|
||||||
imageSrc: "/tutorial/switch/step5.jpg",
|
|
||||||
},
|
|
||||||
{ type: "finish" },
|
{ type: "finish" },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
||||||
25
src/types.d.ts
vendored
|
|
@ -1,16 +1,11 @@
|
||||||
import { MiiGender, Prisma } from "@prisma/client";
|
import { MiiGender, Prisma } from "@prisma/client";
|
||||||
import { DefaultSession } from "next-auth";
|
import { DefaultSession } from "next-auth";
|
||||||
|
|
||||||
// Some types have different options disabled, we're ignoring them for now
|
|
||||||
interface SwitchMiiInstructions {
|
interface SwitchMiiInstructions {
|
||||||
head: {
|
head: {
|
||||||
type: number | null; // 16 types, default is 2
|
|
||||||
skinColor: number | null; // Additional 14 are not in color menu, default is 2
|
skinColor: number | null; // Additional 14 are not in color menu, default is 2
|
||||||
};
|
};
|
||||||
hair: {
|
hair: {
|
||||||
setType: number | null; // 245 types, default is 43
|
|
||||||
bangsType: number | null; // 83 types, default is none, if a set is selected, set bangs and back to none and vice-versa
|
|
||||||
backType: number | null; // 111 types, default is none, same here (set related)
|
|
||||||
color: number | null;
|
color: number | null;
|
||||||
subColor: number | null; // Default is none
|
subColor: number | null; // Default is none
|
||||||
subColor2: number | null; // Only used when bangs/back is selected
|
subColor2: number | null; // Only used when bangs/back is selected
|
||||||
|
|
@ -18,7 +13,6 @@ interface SwitchMiiInstructions {
|
||||||
isFlipped: boolean; // Only for sets and fringe
|
isFlipped: boolean; // Only for sets and fringe
|
||||||
};
|
};
|
||||||
eyebrows: {
|
eyebrows: {
|
||||||
type: number | null; // 1 is None, 43 types, default is 28
|
|
||||||
color: number | null;
|
color: number | null;
|
||||||
height: number | null;
|
height: number | null;
|
||||||
distance: number | null;
|
distance: number | null;
|
||||||
|
|
@ -28,7 +22,6 @@ interface SwitchMiiInstructions {
|
||||||
};
|
};
|
||||||
eyes: {
|
eyes: {
|
||||||
main: {
|
main: {
|
||||||
type: number | null; // 1 is None, 121 types default is 6
|
|
||||||
color: number | null;
|
color: number | null;
|
||||||
height: number | null;
|
height: number | null;
|
||||||
distance: number | null;
|
distance: number | null;
|
||||||
|
|
@ -37,7 +30,6 @@ interface SwitchMiiInstructions {
|
||||||
stretch: number | null;
|
stretch: number | null;
|
||||||
};
|
};
|
||||||
eyelashesTop: {
|
eyelashesTop: {
|
||||||
type: number | null; // 6 types, default is 1
|
|
||||||
height: number | null;
|
height: number | null;
|
||||||
distance: number | null;
|
distance: number | null;
|
||||||
rotation: number | null;
|
rotation: number | null;
|
||||||
|
|
@ -45,7 +37,6 @@ interface SwitchMiiInstructions {
|
||||||
stretch: number | null;
|
stretch: number | null;
|
||||||
};
|
};
|
||||||
eyelashesBottom: {
|
eyelashesBottom: {
|
||||||
type: number | null; // 2 types, default is 1
|
|
||||||
height: number | null;
|
height: number | null;
|
||||||
distance: number | null;
|
distance: number | null;
|
||||||
rotation: number | null;
|
rotation: number | null;
|
||||||
|
|
@ -53,7 +44,6 @@ interface SwitchMiiInstructions {
|
||||||
stretch: number | null;
|
stretch: number | null;
|
||||||
};
|
};
|
||||||
eyelidTop: {
|
eyelidTop: {
|
||||||
type: number | null; // 3 types, default is 1
|
|
||||||
height: number | null;
|
height: number | null;
|
||||||
distance: number | null;
|
distance: number | null;
|
||||||
rotation: number | null;
|
rotation: number | null;
|
||||||
|
|
@ -61,7 +51,6 @@ interface SwitchMiiInstructions {
|
||||||
stretch: number | null;
|
stretch: number | null;
|
||||||
};
|
};
|
||||||
eyelidBottom: {
|
eyelidBottom: {
|
||||||
type: number | null; // 3 types, default is 1
|
|
||||||
height: number | null;
|
height: number | null;
|
||||||
distance: number | null;
|
distance: number | null;
|
||||||
rotation: number | null;
|
rotation: number | null;
|
||||||
|
|
@ -69,11 +58,9 @@ interface SwitchMiiInstructions {
|
||||||
stretch: number | null;
|
stretch: number | null;
|
||||||
};
|
};
|
||||||
eyeliner: {
|
eyeliner: {
|
||||||
type: number | null; // 2 types, default is 1
|
|
||||||
color: number | null;
|
color: number | null;
|
||||||
};
|
};
|
||||||
pupil: {
|
pupil: {
|
||||||
type: number | null; // 10 types, default is 1
|
|
||||||
height: number | null;
|
height: number | null;
|
||||||
distance: number | null;
|
distance: number | null;
|
||||||
rotation: number | null;
|
rotation: number | null;
|
||||||
|
|
@ -82,12 +69,10 @@ interface SwitchMiiInstructions {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
nose: {
|
nose: {
|
||||||
type: number | null; // 1 is None, 32 types, default is 6
|
|
||||||
height: number | null;
|
height: number | null;
|
||||||
size: number | null;
|
size: number | null;
|
||||||
};
|
};
|
||||||
lips: {
|
lips: {
|
||||||
type: number | null; // 1 is None, 53 types, default is 2
|
|
||||||
color: number | null;
|
color: number | null;
|
||||||
height: number | null;
|
height: number | null;
|
||||||
rotation: number | null;
|
rotation: number | null;
|
||||||
|
|
@ -96,12 +81,10 @@ interface SwitchMiiInstructions {
|
||||||
hasLipstick: boolean;
|
hasLipstick: boolean;
|
||||||
};
|
};
|
||||||
ears: {
|
ears: {
|
||||||
type: number | null; // 5 types, default is 1
|
|
||||||
height: number | null; // Does not work for default
|
height: number | null; // Does not work for default
|
||||||
size: number | null; // Does not work for default
|
size: number | null; // Does not work for default
|
||||||
};
|
};
|
||||||
glasses: {
|
glasses: {
|
||||||
type: number | null; // NOTE: THERE IS A GAP AT 40!!! 1 is None, 58 types, default is 1
|
|
||||||
ringColor: number | null;
|
ringColor: number | null;
|
||||||
shadesColor: number | null; // Only works after gap
|
shadesColor: number | null; // Only works after gap
|
||||||
height: number | null;
|
height: number | null;
|
||||||
|
|
@ -111,25 +94,21 @@ interface SwitchMiiInstructions {
|
||||||
other: {
|
other: {
|
||||||
// names were assumed
|
// names were assumed
|
||||||
wrinkles1: {
|
wrinkles1: {
|
||||||
type: number | null; // 9 types, default is 1
|
|
||||||
height: number | null;
|
height: number | null;
|
||||||
distance: number | null;
|
distance: number | null;
|
||||||
size: number | null;
|
size: number | null;
|
||||||
stretch: number | null;
|
stretch: number | null;
|
||||||
};
|
};
|
||||||
wrinkles2: {
|
wrinkles2: {
|
||||||
type: number | null; // 15 types, default is 1
|
|
||||||
height: number | null;
|
height: number | null;
|
||||||
distance: number | null;
|
distance: number | null;
|
||||||
size: number | null;
|
size: number | null;
|
||||||
stretch: number | null;
|
stretch: number | null;
|
||||||
};
|
};
|
||||||
beard: {
|
beard: {
|
||||||
type: number | null; // 15 types, default is 1
|
|
||||||
color: number | null;
|
color: number | null;
|
||||||
};
|
};
|
||||||
moustache: {
|
moustache: {
|
||||||
type: number | null; // 16 types, default is 1
|
|
||||||
color: number | null; // is this same as hair?
|
color: number | null; // is this same as hair?
|
||||||
height: number | null;
|
height: number | null;
|
||||||
isFlipped: boolean;
|
isFlipped: boolean;
|
||||||
|
|
@ -137,18 +116,15 @@ interface SwitchMiiInstructions {
|
||||||
stretch: number | null;
|
stretch: number | null;
|
||||||
};
|
};
|
||||||
goatee: {
|
goatee: {
|
||||||
type: number | null; // 14 types, default is 1
|
|
||||||
color: number | null;
|
color: number | null;
|
||||||
};
|
};
|
||||||
mole: {
|
mole: {
|
||||||
type: number | null; // 2 types, default is 1
|
|
||||||
color: number | null; // is this same as hair?
|
color: number | null; // is this same as hair?
|
||||||
height: number | null;
|
height: number | null;
|
||||||
distance: number | null;
|
distance: number | null;
|
||||||
size: number | null;
|
size: number | null;
|
||||||
};
|
};
|
||||||
eyeShadow: {
|
eyeShadow: {
|
||||||
type: number | null; // 4 types, default is 1
|
|
||||||
color: number | null;
|
color: number | null;
|
||||||
height: number | null;
|
height: number | null;
|
||||||
distance: number | null;
|
distance: number | null;
|
||||||
|
|
@ -156,7 +132,6 @@ interface SwitchMiiInstructions {
|
||||||
stretch: number | null;
|
stretch: number | null;
|
||||||
};
|
};
|
||||||
blush: {
|
blush: {
|
||||||
type: number | null; // 8 types, default is 1
|
|
||||||
color: number | null;
|
color: number | null;
|
||||||
height: number | null;
|
height: number | null;
|
||||||
distance: number | null;
|
distance: number | null;
|
||||||
|
|
|
||||||