mirror of
https://github.com/PretendoNetwork/website.git
synced 2026-08-24 09:36:43 -05:00
feat: mii editor UI
This commit is contained in:
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@@ -2,4 +2,4 @@
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { nodePolyfills } from 'vite-plugin-node-polyfills';
|
||||
|
||||
export default defineNuxtConfig({
|
||||
compatibilityDate: '2024-11-01',
|
||||
devtools: { enabled: true },
|
||||
@@ -9,6 +11,17 @@ export default defineNuxtConfig({
|
||||
}
|
||||
},
|
||||
|
||||
vite: {
|
||||
server: {
|
||||
allowedHosts: ['pretendo.network']
|
||||
},
|
||||
plugins: [
|
||||
nodePolyfills({
|
||||
include: ['buffer', 'crypto', 'stream'] // we need these for the mii editor
|
||||
})
|
||||
]
|
||||
},
|
||||
|
||||
modules: [
|
||||
'@nuxt/eslint',
|
||||
'@nuxt/fonts',
|
||||
@@ -58,6 +71,9 @@ export default defineNuxtConfig({
|
||||
strategy: 'no_prefix',
|
||||
defaultLocale: 'en-US',
|
||||
vueI18n: '../i18n.config.ts',
|
||||
bundle: {
|
||||
optimizeTranslationDirective: false
|
||||
},
|
||||
locales: [
|
||||
{ code: 'ar-AR', name: 'العربية', file: 'ar_AR.json' },
|
||||
{ code: 'ast', name: 'Asturianu', file: 'ast.json' },
|
||||
|
||||
8999
package-lock.json
generated
8999
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
12
package.json
12
package.json
@@ -9,6 +9,7 @@
|
||||
"build": "nuxt build",
|
||||
"prepare": "nuxt prepare",
|
||||
"dev": "nuxt dev",
|
||||
"dev:host": "nuxt dev --host",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix"
|
||||
},
|
||||
@@ -19,15 +20,24 @@
|
||||
"@nuxt/fonts": "^0.11.1",
|
||||
"@nuxt/icon": "^1.11.0",
|
||||
"@nuxtjs/i18n": "^9.5.3",
|
||||
"@pretendonetwork/mii-js": "^1.0.5",
|
||||
"base64-arraybuffer": "^1.0.2",
|
||||
"eslint": "^9.24.0",
|
||||
"feed": "^4.2.2",
|
||||
"node-stdlib-browser": "^1.2.0",
|
||||
"nuxt": "^3.16.2",
|
||||
"vue": "^3.5.13",
|
||||
"vue-router": "^4.5.0"
|
||||
},
|
||||
"overrides": {
|
||||
"vite": "^6.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@iconify-json/fa": "^1.2.2",
|
||||
"@iconify-json/ph": "^1.2.2",
|
||||
"@pretendonetwork/eslint-config": "^0.0.8",
|
||||
"eslint-plugin-vue": "^10.0.0",
|
||||
"sass-embedded": "^1.86.3"
|
||||
"sass-embedded": "^1.86.3",
|
||||
"vite-plugin-node-polyfills": "^0.24.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
--green-shade-0: #37a985;
|
||||
--green-shade-1: #59c9a5;
|
||||
|
||||
--red-shade-2: #ff4580;
|
||||
--red-shade-1: #a9375b;
|
||||
--yellow-shade-1: #ffd966;
|
||||
|
||||
@@ -38,7 +39,7 @@ body,
|
||||
width: 100%;
|
||||
max-width: 100vw;
|
||||
position: relative; /* This fixes overflow-x not hiding on Safari on mobile */
|
||||
overflow-x: hidden;
|
||||
overflow: hidden;
|
||||
margin: 0;
|
||||
color: var(--text-shade-3);
|
||||
justify-content: center;
|
||||
@@ -231,11 +232,11 @@ input[type="range"] {
|
||||
input[type="range"]::-webkit-slider-runnable-track {
|
||||
background: var(--bg-shade-3);
|
||||
height: 1rem;
|
||||
border-radius: 1rem;
|
||||
border-radius: .25rem;
|
||||
}
|
||||
input[type="range"]::-moz-range-track {
|
||||
background: var(--bg-shade-3);
|
||||
border-radius: 1rem;
|
||||
border-radius: .25rem;
|
||||
height: 1rem;
|
||||
}
|
||||
input[type="range"]::-webkit-slider-thumb {
|
||||
@@ -243,15 +244,15 @@ input[type="range"]::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
width: 1.5rem;
|
||||
height: 3rem;
|
||||
margin-top: -1rem;
|
||||
margin-top: -1.25rem;
|
||||
background-color: var(--accent-shade-1);
|
||||
border-radius: 0.5rem;
|
||||
border-radius: .5rem;
|
||||
}
|
||||
input[type="range"]::-moz-range-thumb {
|
||||
width: 1.5rem;
|
||||
height: 3rem;
|
||||
border: none;
|
||||
border-radius: 0.5rem;
|
||||
border-radius: .5rem;
|
||||
background-color: var(--accent-shade-1);
|
||||
}
|
||||
input[type="range"]:focus {
|
||||
|
||||
317
src/components/BirthdaySetter/BirthdaySetter.vue
Normal file
317
src/components/BirthdaySetter/BirthdaySetter.vue
Normal file
@@ -0,0 +1,317 @@
|
||||
<script lang="ts" setup>
|
||||
const { day, month } = defineProps<{ day: number; month: number }>();
|
||||
defineEmits(['change']);
|
||||
|
||||
const { t, locale } = useI18n();
|
||||
|
||||
const open = ref(false);
|
||||
const tempDay = ref(day);
|
||||
const tempMonth = ref(month === 0 ? 1 : month);
|
||||
|
||||
const validTempDate = computed(() => {
|
||||
return checkvalidDate(tempDay.value, tempMonth.value);
|
||||
});
|
||||
const daysInTempMonth = computed(() => {
|
||||
return getMaxDaysInMonth(tempMonth.value);
|
||||
});
|
||||
|
||||
/* gets the number of days in a month, in a leap year. months are 0-indexed and setting the day field to 0 returns the last day of the month prior.
|
||||
* 2004 was chosen because it's a leap year and it's my birth year :3 */
|
||||
function getMaxDaysInMonth(month: number) {
|
||||
return new Date(2004, month, 0).getDate();
|
||||
}
|
||||
|
||||
function monthToString(month: number) {
|
||||
return new Date(2004, month - 1, 15).toLocaleDateString(locale.value, {
|
||||
month: 'long'
|
||||
});
|
||||
}
|
||||
|
||||
function checkvalidDate(day: number, month: number) {
|
||||
if (month < 1 || month > 12) {
|
||||
return false;
|
||||
} else if (day < 1 || day > getMaxDaysInMonth(month)) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const dateString = computed(() => {
|
||||
if (!checkvalidDate(day, month)) {
|
||||
return t('miiEditor.clickToSet');
|
||||
}
|
||||
|
||||
const birthdate = new Date(2004, month - 1, day);
|
||||
|
||||
return birthdate.toLocaleDateString(undefined, {
|
||||
month: '2-digit',
|
||||
day: '2-digit'
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="date-selector-wrapper">
|
||||
<div
|
||||
:class="{'date-selector': true, 'open': open }"
|
||||
>
|
||||
<template v-if="open">
|
||||
<div class="header">
|
||||
<button
|
||||
:class="{
|
||||
previous: true,
|
||||
'page-btn': true,
|
||||
disabled: tempMonth === 1,
|
||||
}"
|
||||
:disabled="tempMonth === 1"
|
||||
@click.prevent="() => {
|
||||
tempMonth--;
|
||||
}"
|
||||
>
|
||||
<Icon
|
||||
name="ph:caret-left"
|
||||
size="20"
|
||||
/>
|
||||
</button>
|
||||
<span class="month-name">{{ monthToString(tempMonth) }}</span>
|
||||
<button
|
||||
:class="{
|
||||
next: true,
|
||||
'page-btn': true,
|
||||
disabled: tempMonth === 12,
|
||||
}"
|
||||
:disabled="tempMonth === 12"
|
||||
@click.prevent="() => {
|
||||
tempMonth++;
|
||||
}"
|
||||
>
|
||||
<Icon
|
||||
name="ph:caret-right"
|
||||
size="20"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<fieldset class="datepicker-day-grid">
|
||||
<template
|
||||
v-for="i in [
|
||||
...Array(daysInTempMonth)
|
||||
.keys()
|
||||
.map((j) => j + 1),
|
||||
]"
|
||||
:key="i"
|
||||
>
|
||||
<input
|
||||
:id="`datepicker-day-${i}`"
|
||||
:value="i"
|
||||
type="radio"
|
||||
:name="`datepicker-days`"
|
||||
:checked="i === tempDay && month === tempMonth"
|
||||
@click="
|
||||
() => {
|
||||
tempDay = i;
|
||||
$emit('change', { day: tempDay, month: tempMonth})
|
||||
}
|
||||
"
|
||||
>
|
||||
<label :for="`datepicker-day-${i}`"><span>{{ i }}</span></label>
|
||||
</template>
|
||||
</fieldset>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div
|
||||
:class="{ input: true, 'invalid-date': !validTempDate, open: open }"
|
||||
@click="!open && (open = true)"
|
||||
>
|
||||
<button
|
||||
class="trash action-button"
|
||||
@click.prevent.stop="() => {
|
||||
$emit('change', { day: 0, month: 0})
|
||||
open = false
|
||||
}"
|
||||
>
|
||||
<Icon
|
||||
name="ph:trash-fill"
|
||||
size="24"
|
||||
/>
|
||||
</button>
|
||||
<span class="date-string">{{ dateString }}</span>
|
||||
<Icon
|
||||
class="icon"
|
||||
name="ph:calendar-dots-fill"
|
||||
size="24"
|
||||
/>
|
||||
<button
|
||||
class="confirm action-button"
|
||||
@click.prevent.stop="() => {
|
||||
open = false
|
||||
}"
|
||||
>
|
||||
<Icon
|
||||
name="ph:check-circle-fill"
|
||||
size="24"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.date-selector-wrapper {
|
||||
position: relative;
|
||||
display: grid;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.date-selector {
|
||||
display: grid;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
max-height: 0;
|
||||
height: 0;
|
||||
overflow-y: hidden;
|
||||
box-sizing: border-box;
|
||||
bottom: 100%;
|
||||
background-color: var(--bg-shade-0);
|
||||
border: 1px solid var(--bg-shade-3);
|
||||
border-bottom: 0;
|
||||
border-radius: .5rem .5rem 0 0;
|
||||
opacity: 0;
|
||||
z-index: 2;
|
||||
transition: max-height 400ms, opacity 200ms;
|
||||
}
|
||||
|
||||
.date-selector.open {
|
||||
opacity: 1;
|
||||
height: auto;
|
||||
max-height: 24rem;
|
||||
}
|
||||
|
||||
.date-selector.open::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
display: block;
|
||||
height: 1px;
|
||||
width: 90%;
|
||||
left: 5%;
|
||||
bottom: 0;
|
||||
background: var(--bg-shade-3);
|
||||
}
|
||||
|
||||
.date-selector .header {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
text-align: center;
|
||||
padding: 1rem .75rem .25rem .75rem;
|
||||
}
|
||||
|
||||
.date-selector .header button {
|
||||
background: none;
|
||||
padding: .25rem;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.date-selector .header button.disabled {
|
||||
color: var(--text-shade-0)
|
||||
}
|
||||
|
||||
.datepicker-day-grid {
|
||||
appearance: none;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(7, 1fr);
|
||||
gap: .25rem;
|
||||
border: none;
|
||||
padding: .75rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.datepicker-day-grid input[type="radio"] {
|
||||
display: none;
|
||||
}
|
||||
.datepicker-day-grid input[type="radio"] + label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
border-radius: .25rem;
|
||||
padding: .25rem .5rem;
|
||||
background: none;
|
||||
height: fit-content;
|
||||
color: var(--text-shade-0);
|
||||
width: 1rem;
|
||||
font-size: inherit;
|
||||
aspect-ratio: 1;
|
||||
}
|
||||
.datepicker-day-grid input[type="radio"]:checked + label {
|
||||
color: var(--text-shade-3);
|
||||
font-weight: 700;
|
||||
background: var(--accent-shade-1);
|
||||
}
|
||||
|
||||
.input {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
gap: 0.5rem;
|
||||
background-color: var(--bg-shade-3);
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
padding: 12px;
|
||||
cursor: pointer;
|
||||
color: var(--text-shade-3);
|
||||
border: 0 solid var(--bg-shade-3);
|
||||
transition: background 200ms, color 200ms, border-radius 200ms;
|
||||
}
|
||||
.input.open {
|
||||
cursor: unset;
|
||||
justify-content: space-between;
|
||||
color: var(--text-shade-3);
|
||||
background-color: var(--bg-shade-0);
|
||||
border: 1px solid var(--bg-shade-3);
|
||||
border-top: 0;
|
||||
border-radius: 0 0 .5rem .5rem;
|
||||
padding: 12px 11px 11px 11px;
|
||||
}
|
||||
|
||||
.input .icon {
|
||||
position: absolute;
|
||||
right: 11px;
|
||||
}
|
||||
.input.open .icon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.input .action-button {
|
||||
display: none;
|
||||
background: none;
|
||||
padding: 0;
|
||||
height: 24px;
|
||||
}
|
||||
.input.open .action-button {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.input .action-button.trash {
|
||||
color: var(--red-shade-2);
|
||||
}
|
||||
|
||||
.input.invalid-date {
|
||||
color: var(--text-shade-1);
|
||||
}
|
||||
|
||||
/*
|
||||
.subtab.info .birthdate.monthFirst .month {
|
||||
order: 0;
|
||||
}
|
||||
.subtab.info .birthdate.monthFirst span {
|
||||
order: 1;
|
||||
}
|
||||
.subtab.info .birthdate.monthFirst .day {
|
||||
order: 2;
|
||||
}*/
|
||||
</style>
|
||||
5
src/layouts/slotOnly.vue
Normal file
5
src/layouts/slotOnly.vue
Normal file
@@ -0,0 +1,5 @@
|
||||
<template>
|
||||
<div id="root">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
@@ -408,6 +408,21 @@
|
||||
"progress": "<span>$${totd}</span> of <span>$${goald}</span>/month, <span>${perc}%</span> of the monthly goal.",
|
||||
"upgradePush": "To become a subscriber and gain access to cool perks, visit the <a href=\"/account/upgrade\">upgrade page</a>."
|
||||
},
|
||||
"miiEditor": {
|
||||
"nickname":"Nickname",
|
||||
"creator": "Creator",
|
||||
"birthday": "Birthday",
|
||||
"clickToSet": "Click to set",
|
||||
"favorite": "Favorite",
|
||||
"sharing": "Sharing",
|
||||
"copying": "Copying",
|
||||
"save": "Save",
|
||||
"saveCaption": "Saving your Mii will kill the previous one.",
|
||||
"noCanvas": "Your browser does not support the canvas element.",
|
||||
"corruptedData": "Found corrupted Mii data. Would you like to start from scratch?",
|
||||
"miiSaved": "Your Mii has been updated! Changes may take some time to reflect across all platforms and services.",
|
||||
"loading": "Loading Mii editor..."
|
||||
},
|
||||
"localizationPage": {
|
||||
"title": "Let's localize",
|
||||
"description": "Paste a link to a publicly accessible JSON locale to test it on the website",
|
||||
|
||||
1411
src/pages/account/miieditor/index.vue
Normal file
1411
src/pages/account/miieditor/index.vue
Normal file
File diff suppressed because it is too large
Load Diff
9778
src/public/assets/images/miieditor.svg
Normal file
9778
src/public/assets/images/miieditor.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 525 KiB |
4447
src/public/assets/images/miieditor_symbols.svg
Normal file
4447
src/public/assets/images/miieditor_symbols.svg
Normal file
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 459 KiB |
319
src/utils/miieditor.ts
Normal file
319
src/utils/miieditor.ts
Normal file
@@ -0,0 +1,319 @@
|
||||
export interface Slider {
|
||||
name: string;
|
||||
min: number;
|
||||
max: number;
|
||||
}
|
||||
|
||||
export interface Subtab {
|
||||
name: string;
|
||||
type?: 'color' | 'slider' | 'component';
|
||||
values?: number[][] | string[][] | boolean[][] | Slider[][];
|
||||
}
|
||||
|
||||
export interface Tab {
|
||||
name: string; subTabs?: Subtab[];
|
||||
}
|
||||
|
||||
export const miiEditorJSON: {
|
||||
tabs: Tab[];
|
||||
} = {
|
||||
tabs: [
|
||||
{
|
||||
name: 'faceType',
|
||||
subTabs: [
|
||||
{ name: 'faceType', values: [[0, 1, 8, 2, 3, 9, 4, 5, 10, 6, 7, 11]] },
|
||||
{
|
||||
name: 'makeupType',
|
||||
values: [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]]
|
||||
},
|
||||
{
|
||||
name: 'wrinklesType',
|
||||
values: [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]]
|
||||
},
|
||||
{
|
||||
name: 'skinColor',
|
||||
type: 'color',
|
||||
values: [
|
||||
['#FFCE98', '#FFBA64', '#FF7C3E', '#FFB184', '#CA5326', '#752E17 ']
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'hairType',
|
||||
subTabs: [
|
||||
{
|
||||
name: 'hairType',
|
||||
values: [
|
||||
[33, 47, 40, 37, 32, 107, 48, 51, 55, 70, 44, 66],
|
||||
[52, 50, 38, 49, 43, 31, 56, 68, 62, 115, 76, 119],
|
||||
[64, 81, 116, 121, 22, 58, 60, 87, 125, 117, 73, 75],
|
||||
[42, 89, 57, 54, 80, 34, 23, 86, 88, 118, 39, 36],
|
||||
[45, 67, 59, 65, 41, 30, 12, 16, 10, 82, 128, 129],
|
||||
[14, 95, 105, 100, 6, 20, 93, 102, 27, 4, 17, 110],
|
||||
[123, 8, 106, 72, 3, 21, 0, 98, 63, 90, 11, 120],
|
||||
[5, 74, 108, 94, 124, 25, 99, 69, 35, 13, 122, 113],
|
||||
[53, 24, 85, 83, 71, 131, 96, 101, 29, 7, 15, 112],
|
||||
[79, 1, 109, 127, 91, 26, 61, 103, 2, 77, 18, 92],
|
||||
[84, 9, 19, 130, 97, 104, 46, 78, 28, 114, 126, 111]
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'hairColor',
|
||||
type: 'color',
|
||||
values: [
|
||||
[
|
||||
'#0A0A09',
|
||||
'#562D1B',
|
||||
'#772314',
|
||||
'#9C481E',
|
||||
'#988B8D',
|
||||
'#664C1A',
|
||||
'#AA6822',
|
||||
'#FEB454'
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'eyebrowType',
|
||||
subTabs: [
|
||||
{
|
||||
name: 'eyebrowType',
|
||||
values: [
|
||||
[6, 0, 12, 1, 9, 19, 7, 21, 8, 17, 5, 4],
|
||||
[11, 10, 2, 3, 14, 20, 15, 13, 22, 18, 16, 23]
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'eyebrowPosition',
|
||||
type: 'slider',
|
||||
values: [[
|
||||
{ name: 'eyebrowYPosition', min: 3, max: 18 },
|
||||
{ name: 'eyebrowSpacing', min: 0, max: 12 },
|
||||
{ name: 'eyebrowRotation', min: 0, max: 11 },
|
||||
{ name: 'eyebrowScale', min: 0, max: 8 },
|
||||
{ name: 'eyebrowVerticalStretch', min: 0, max: 6 }
|
||||
]]
|
||||
},
|
||||
{
|
||||
name: 'eyebrowColor',
|
||||
type: 'color',
|
||||
values: [
|
||||
[
|
||||
'#0A0A09',
|
||||
'#562D1B',
|
||||
'#772314',
|
||||
'#9C481E',
|
||||
'#988B8D',
|
||||
'#664C1A',
|
||||
'#AA6822',
|
||||
'#FEB454'
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'eyeType',
|
||||
subTabs: [
|
||||
{
|
||||
name: 'eyeType',
|
||||
values: [
|
||||
[2, 4, 0, 8, 39, 17, 1, 26, 16, 15, 27, 20],
|
||||
[33, 11, 19, 32, 9, 12, 23, 34, 21, 25, 40, 35],
|
||||
[5, 41, 13, 36, 37, 6, 24, 30, 31, 18, 28, 46],
|
||||
[7, 44, 38, 42, 45, 29, 3, 43, 22, 10, 14, 47],
|
||||
[48, 49, 50, 53, 59, 56, 54, 58, 57, 55, 51, 52]
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'eyePosition',
|
||||
type: 'slider',
|
||||
values: [[
|
||||
{ name: 'eyeYPosition', min: 0, max: 18 },
|
||||
{ name: 'eyeSpacing', min: 0, max: 12 },
|
||||
{ name: 'eyeRotation', min: 0, max: 7 },
|
||||
{ name: 'eyeScale', min: 0, max: 7 },
|
||||
{ name: 'eyeVerticalStretch', min: 0, max: 6 }
|
||||
]]
|
||||
},
|
||||
{
|
||||
name: 'eyeColor',
|
||||
type: 'color',
|
||||
values: [
|
||||
['#070606', '#887E75', '#814631', '#796A34', '#565BA4', '#4C8260']
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'noseType',
|
||||
subTabs: [
|
||||
{
|
||||
name: 'noseType',
|
||||
values: [
|
||||
[1, 10, 2, 3, 6, 0, 5, 4, 8, 9, 7, 11],
|
||||
[13, 14, 12, 17, 16, 15]
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'nosePosition',
|
||||
type: 'slider',
|
||||
values: [[
|
||||
{ name: 'noseYPosition', min: 0, max: 18 },
|
||||
{ name: 'noseScale', min: 0, max: 8 }
|
||||
]]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'mouthType',
|
||||
subTabs: [
|
||||
{
|
||||
name: 'mouthType',
|
||||
values: [
|
||||
[23, 1, 19, 21, 22, 5, 0, 8, 10, 16, 6, 13],
|
||||
[7, 9, 2, 17, 3, 4, 15, 11, 20, 18, 14, 12],
|
||||
[27, 30, 24, 25, 29, 28, 26, 35, 31, 34, 33, 32]
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'mouthPosition',
|
||||
type: 'slider',
|
||||
values: [[
|
||||
{ name: 'mouthYPosition', min: 0, max: 18 },
|
||||
{ name: 'mouthScale', min: 0, max: 8 },
|
||||
{ name: 'mouthHorizontalStretch', min: 0, max: 6 }
|
||||
]]
|
||||
},
|
||||
{
|
||||
name: 'mouthColor',
|
||||
type: 'color',
|
||||
values: [['#FF5D0C', '#FF110C', '#FF524B', '#FFAA77', '#181312']]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'glassesType',
|
||||
subTabs: [
|
||||
{
|
||||
name: 'glassesType',
|
||||
values: [[0, 1, 2, 3, 4, 5, 6, 7, 8]]
|
||||
},
|
||||
{
|
||||
name: 'glassesPosition',
|
||||
type: 'slider',
|
||||
values: [[
|
||||
{ name: 'glassesYPosition', min: 0, max: 20 },
|
||||
{ name: 'glassesScale', min: 0, max: 7 }
|
||||
]]
|
||||
},
|
||||
{
|
||||
name: 'glassesColor',
|
||||
type: 'color',
|
||||
values: [
|
||||
['#000000', '#7A4011', '#D51208', '#29376E', '#D56D00', '#987F6E']
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'beardType',
|
||||
subTabs: [
|
||||
{
|
||||
name: 'beardType',
|
||||
values: [[0, 1, 2, 3, 4, 5]]
|
||||
},
|
||||
{
|
||||
name: 'mustacheType',
|
||||
values: [[0, 1, 2, 3, 4, 5]]
|
||||
},
|
||||
{
|
||||
name: 'facialHairPosition',
|
||||
type: 'slider',
|
||||
values: [[
|
||||
{ name: 'mustacheYPosition', min: 0, max: 16 },
|
||||
{ name: 'mustacheScale', min: 0, max: 8 }
|
||||
]]
|
||||
},
|
||||
{
|
||||
name: 'facialHairColor',
|
||||
type: 'color',
|
||||
values: [
|
||||
[
|
||||
'#0A0A09',
|
||||
'#562D1B',
|
||||
'#772314',
|
||||
'#9C481E',
|
||||
'#988B8D',
|
||||
'#664C1A',
|
||||
'#AA6822',
|
||||
'#FEB454'
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'moleEnabled',
|
||||
subTabs: [
|
||||
{
|
||||
name: 'moleEnabled',
|
||||
values: [[false, true]]
|
||||
},
|
||||
{
|
||||
name: 'molePosition',
|
||||
type: 'slider',
|
||||
values: [[
|
||||
{ name: 'moleYPosition', min: 0, max: 30 },
|
||||
{ name: 'moleXPosition', min: 0, max: 16 },
|
||||
{ name: 'moleScale', min: 0, max: 8 }
|
||||
]]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'miisc',
|
||||
subTabs: [
|
||||
{
|
||||
name: 'size',
|
||||
type: 'slider',
|
||||
values: [[
|
||||
{ name: 'height', min: 0, max: 127 },
|
||||
{ name: 'build', min: 0, max: 127 }
|
||||
]]
|
||||
},
|
||||
{
|
||||
name: 'gender',
|
||||
values: [[0, 1]]
|
||||
},
|
||||
{
|
||||
name: 'favoriteColor',
|
||||
type: 'color',
|
||||
values: [
|
||||
[
|
||||
'#FF2216',
|
||||
'#FF7A1A',
|
||||
'#FFED22',
|
||||
'#91F321',
|
||||
'#008332',
|
||||
'#0D50BE',
|
||||
'#49BBE4',
|
||||
'#FF6381',
|
||||
'#8B2DB2',
|
||||
'#573D18',
|
||||
'#FFFFFF',
|
||||
'#1D1A15'
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'save', subTabs: [{ name: 'info', type: 'component' }, { name: 'save', type: 'component' }]
|
||||
}
|
||||
]
|
||||
};
|
||||
Reference in New Issue
Block a user